Use openssl
openssl pkcs12 -in ${mycert}.pfx -out ${mycert}.txt -nodes |
Use openssl
openssl pkcs12 -in ${mycert}.pfx -out ${mycert}.txt -nodes |
{ | |
// Name of the event triggering field validation | |
validationEventTrigger: "blur", | |
// Automatically scroll viewport to the first error | |
scroll: true, | |
// Focus on the first input | |
focusFirstField: true, | |
// Show prompts, set to false to disable prompts | |
showPrompts: true, | |
// Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs) | |
validateNonVisibleFields: false, | |
// ignore the validation for fields with this specific class (Useful in cases of tabbed containers AND hidden fields we don't want to validate) | |
ignoreFieldsWithClass: 'ignoreMe', | |
// Opening box position, possible locations are: topLeft, | |
// topRight, bottomLeft, centerRight, bottomRight, inline | |
// inline gets inserted after the validated field or into an element specified in data-prompt-target | |
promptPosition: "topRight", | |
bindMethod: "bind", | |
// internal, automatically set to true when it parse a _ajax rule | |
inlineAjax: false, | |
// if set to true, the form data is sent asynchronously via ajax to the form.action url (get) | |
ajaxFormValidation: false, | |
// The url to send the submit ajax validation (default to action) | |
ajaxFormValidationURL: false, | |
// HTTP method used for ajax validation | |
ajaxFormValidationMethod: 'get', | |
// Ajax form validation callback method: boolean onComplete(form, status, errors, options) | |
// retuns false if the form.submit event needs to be canceled. | |
onAjaxFormComplete: $.noop, | |
// called right before the ajax call, may return false to cancel | |
onBeforeAjaxFormValidation: $.noop, | |
// Stops form from submitting and execute function assiciated with it | |
onValidationComplete: false, | |
// Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages | |
doNotShowAllErrosOnSubmit: false, | |
// Object where you store custom messages to override the default error messages | |
custom_error_messages: {}, | |
// true if you want to validate the input fields on blur event | |
binded: true, | |
// set to true if you want to validate the input fields on blur only if the field it's not empty | |
notEmpty: false, | |
// set to true, when the prompt arrow needs to be displayed | |
showArrow: true, | |
// set to false, determines if the prompt arrow should be displayed when validating | |
// checkboxes and radio buttons | |
showArrowOnRadioAndCheckbox: false, | |
// did one of the validation fail ? kept global to stop further ajax validations | |
isError: false, | |
// Limit how many displayed errors a field can have | |
maxErrorsPerField: false, | |
// Caches field validation status, typically only bad status are created. | |
// the array is used during ajax form validation to detect issues early and prevent an expensive submit | |
ajaxValidCache: {}, | |
// Auto update prompt position after window resize | |
autoPositionUpdate: false, | |
InvalidFields: [], | |
onFieldSuccess: false, | |
onFieldFailure: false, | |
onSuccess: false, | |
onFailure: false, | |
validateAttribute: "class", | |
addSuccessCssClassToField: "", | |
addFailureCssClassToField: "", | |
// Auto-hide prompt | |
autoHidePrompt: false, | |
// Delay before auto-hide | |
autoHideDelay: 10000, | |
// Fade out duration while hiding the validations | |
fadeDuration: 300, | |
// Use Prettify select library | |
prettySelect: false, | |
// Add css class on prompt | |
addPromptClass: "", | |
// Custom ID uses prefix | |
usePrefix: "", | |
// Custom ID uses suffix | |
useSuffix: "", | |
// Only show one message per error prompt | |
showOneMessage: false | |
} |
VBoxManage list hdds | |
VBoxManage modifyhd ${vdi_file_or_id} -compact |
find . | grep -v -f $list_file_path | xargs rm | |
find . -type d -empty -delete |
import org.tmatesoft.svn.core.SVNException; | |
import org.tmatesoft.svn.core.SVNNodeKind; | |
import org.tmatesoft.svn.core.SVNProperties; | |
import org.tmatesoft.svn.core.SVNURL; | |
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; | |
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; | |
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; | |
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; | |
import org.tmatesoft.svn.core.io.SVNRepository; | |
import org.tmatesoft.svn.core.io.SVNRepositoryFactory; | |
import org.tmatesoft.svn.core.wc.*; | |
import org.tmatesoft.svn.core.wc2.SvnOperationFactory; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
/** | |
* Diff & export | |
* Created by nanashi07 on 2016/6/29. | |
*/ | |
public class DiffWithSvnKit { | |
public static void main(String[] args) throws SVNException { | |
final String fromUrl = "https://svn.your_server.com/path_to_compare_from"; | |
final long fromRevision = 1000; | |
final String targetUrl = "https://svn.your_server.com/path_to_compare_to"; | |
final long targetRevision = 2000; | |
final String outputFolder = "/folder_to_export"; | |
final String account = "account"; | |
final String password = "password"; | |
DAVRepositoryFactory.setup(); | |
SVNRepositoryFactoryImpl.setup(); | |
FSRepositoryFactory.setup(); | |
SVNURL fromSvnUrl = SVNURL.parseURIEncoded(fromUrl); | |
SVNRevision fromSvnRevision = SVNRevision.create(fromRevision); | |
SVNURL targetSvnUrl = SVNURL.parseURIEncoded(targetUrl); | |
SVNRevision targetSvnRevision = SVNRevision.create(targetRevision); | |
final File baseFolder = new File(outputFolder); | |
final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); | |
final SVNRepository repository = SVNRepositoryFactory.create(targetSvnUrl); | |
final StringBuilder builder = new StringBuilder(); | |
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(account, password.toCharArray()); | |
svnOperationFactory.setAuthenticationManager(authManager); | |
repository.setAuthenticationManager(authManager); | |
SVNDiffClient diffClient = new SVNDiffClient(authManager, null); | |
try { | |
diffClient.doDiffStatus(fromSvnUrl, fromSvnRevision, targetSvnUrl, targetSvnRevision, org.tmatesoft.svn.core.SVNDepth.UNKNOWN, true, new ISVNDiffStatusHandler() { | |
@Override | |
public void handleDiffStatus(SVNDiffStatus diffStatus) throws SVNException { | |
builder.append(String.format("%s, %s%n", diffStatus.getModificationType(), diffStatus.getPath())); | |
if (diffStatus.getKind() == SVNNodeKind.FILE) { | |
SVNProperties p = new SVNProperties(); | |
ByteArrayOutputStream output = new ByteArrayOutputStream(); | |
repository.getFile(diffStatus.getPath(), targetRevision, p, output); | |
byte[] data = output.toByteArray(); | |
File copy = new File(baseFolder, diffStatus.getPath()); | |
if (!copy.getParentFile().exists()) copy.getParentFile().mkdirs(); | |
Files.write(copy, data); | |
} | |
} | |
}); | |
Files.write(new File(baseFolder, "diff.txt"), builder); | |
} catch (Throwable ex) { | |
ex.printStackTrace(); | |
} | |
} | |
} |
Create a anonymous object and try to serialize instance via gson. The code is below
public class SerializeJson { | |
static class ResultMessage { | |
int code; | |
String content; | |
public ResultMessage() { | |
} | |
public ResultMessage(int code, String content) { | |
this.code = code; | |
this.content = content; | |
} | |
} | |
public static void main(String[] args) { | |
ResultMessage m1 = new ResultMessage(111, "hello"); | |
ResultMessage m2 = new ResultMessage() {{ | |
code = 2323; | |
content = "hello"; | |
}}; | |
System.out.printf("m1.code : %s%n", m1.code); | |
System.out.printf("m1.content : %s%n", m1.content); | |
System.out.printf("m2.code : %s%n", m2.code); | |
System.out.printf("m2.content : %s%n", m2.content); | |
System.out.println(m1.getClass()); | |
System.out.println(m2.getClass()); | |
System.out.println("m1: " + new Gson().toJson(m1)); | |
System.out.println("m2: " + new Gson().toJson(m2)); | |
} | |
} |
Result of execution. null result when serialize a anonymous instance
m1.code : 111 | |
m1.content : hello | |
m2.code : 2323 | |
m2.content : hello | |
class com.prhythm.test.generic.http.SerializeJson$ResultMessage | |
class com.prhythm.test.generic.http.SerializeJson$1 | |
m1: {"code":111,"content":"hello"} | |
m2: null |
SVNKit version:
<dependency> | |
<groupId>org.tmatesoft.svnkit</groupId> | |
<artifactId>svnkit</artifactId> | |
<version>1.8.12</version> | |
</dependency> |
SvnCommitter.java
package com.prhythm.batch.source.control; | |
import org.tmatesoft.svn.core.*; | |
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; | |
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; | |
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; | |
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; | |
import org.tmatesoft.svn.core.io.ISVNEditor; | |
import org.tmatesoft.svn.core.io.SVNRepository; | |
import org.tmatesoft.svn.core.io.SVNRepositoryFactory; | |
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator; | |
import org.tmatesoft.svn.core.wc.SVNWCUtil; | |
import java.io.*; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.Map; | |
/** | |
* Created by nanashi07 on 2016/6/22. | |
*/ | |
@SuppressWarnings("Duplicates") | |
public class SvnCommitter implements ICommitable { | |
public static void main(String[] args) throws Throwable { | |
String url1 = "https://svn.your_server.com"; | |
String userName = "account"; | |
String userPassword = "password"; | |
DAVRepositoryFactory.setup(); | |
SVNRepositoryFactoryImpl.setup(); | |
FSRepositoryFactory.setup(); | |
new SvnCommitter().commit( | |
url1, | |
userName, | |
userPassword, | |
"Commit updates", | |
"trunk/other", | |
new File("xom/src") | |
); | |
} | |
/** | |
* 最新版本 | |
*/ | |
private int revision = -1; | |
@Override | |
public void commit(String repositoryUrl, String account, String password, String commitMessage, String pathToCommit, File... fileOrDirectory) throws Throwable { | |
// 解析網址 | |
SVNURL url = SVNURL.parseURIEncoded(repositoryUrl); | |
// 取得資源庫 | |
SVNRepository repository = SVNRepositoryFactory.create(url); | |
// 身份驗證 | |
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(account, password.toCharArray()); | |
repository.setAuthenticationManager(authManager); | |
// 檢查路徑是否存在 | |
if (pathToCommit == null) pathToCommit = ""; | |
SVNNodeKind nodeKind = repository.checkPath(pathToCommit, revision); | |
if (nodeKind == SVNNodeKind.NONE) { | |
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "No entry at URL ''{0}''", url); | |
throw new SVNException(err); | |
} else if (nodeKind == SVNNodeKind.FILE) { | |
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "Entry at URL ''{0}'' is a file while directory was expected", url); | |
throw new SVNException(err); | |
} | |
Map<String, SVNNodeKind> kinds = new HashMap<String, SVNNodeKind>(); | |
for (File file : fileOrDirectory) { | |
kinds.putAll(collect(repository, pathToCommit, file)); | |
} | |
ISVNEditor editor = repository.getCommitEditor(commitMessage, null); | |
try { | |
editor.openRoot(revision); | |
SVNDeltaGenerator svnDeltaGenerator = new SVNDeltaGenerator(); | |
for (String segment : (pathToCommit.charAt(0) == '/' ? pathToCommit.substring(1) : pathToCommit).split("[/]")) { | |
System.out.printf("開啟資料夾 %s%n", segment); | |
editor.openDir(segment, revision); | |
} | |
boolean result = false; | |
for (File file : fileOrDirectory) { | |
result = sendDelta(kinds, editor, svnDeltaGenerator, pathToCommit, file); | |
} | |
for (String segment : (pathToCommit.charAt(0) == '/' ? pathToCommit.substring(1) : pathToCommit).split("[/]")) { | |
System.out.printf("關閉資料夾 %s%n", segment); | |
editor.closeDir(); | |
} | |
if (!result) { | |
editor.abortEdit(); | |
System.out.println("無變更"); | |
} else { | |
SVNCommitInfo svnCommitInfo = editor.closeEdit(); | |
System.out.println(svnCommitInfo); | |
} | |
} catch (Throwable e) { | |
editor.abortEdit(); | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 收集版本資訊 | |
* | |
* @param repository 版本庫 | |
* @param path 路徑 | |
* @param fileOrDir 檔案 | |
* @return | |
* @throws SVNException | |
*/ | |
private Map<String, SVNNodeKind> collect(final SVNRepository repository, String path, File fileOrDir) throws SVNException, FileNotFoundException { | |
Map<String, SVNNodeKind> values = new HashMap<String, SVNNodeKind>(); | |
final String targetPath = path.endsWith("/") ? path + fileOrDir.getName() : path + "/" + fileOrDir.getName(); | |
final SVNNodeKind kind = repository.checkPath(targetPath, revision); | |
System.out.println(String.format("%s: %s", targetPath, kind)); | |
// 取得相關資料 | |
boolean ignore = false; | |
if (kind == SVNNodeKind.FILE) { | |
SVNProperties p = new SVNProperties(); | |
ByteArrayOutputStream output = new ByteArrayOutputStream(); | |
repository.getFile(targetPath, revision, p, output); | |
byte[] data = output.toByteArray(); | |
// 檔案未變更 | |
ignore = Arrays.equals(data, toByteArray(new FileInputStream(fileOrDir))); | |
} | |
// 比對版本,檔案相同時不處理 | |
if (!ignore) values.put(targetPath, kind); | |
if (fileOrDir.isDirectory()) { | |
File[] files = fileOrDir.listFiles(); | |
if (files != null) { | |
for (File file : files) { | |
values.putAll(collect(repository, targetPath, file)); | |
} | |
} | |
} | |
return values; | |
} | |
/** | |
* 處理提交的內容。 | |
* | |
* @param kindMap 版本資訊 | |
* @param editor | |
* @param deltaGenerator | |
* @param path 處理路徑 | |
* @param fileOrDir 檔案 | |
* @return | |
* @throws SVNException | |
* @throws FileNotFoundException | |
*/ | |
private boolean sendDelta(Map<String, SVNNodeKind> kindMap, ISVNEditor editor, SVNDeltaGenerator deltaGenerator, String path, File fileOrDir) throws SVNException, FileNotFoundException { | |
boolean result = false; | |
String targetPath = path.endsWith("/") ? path + fileOrDir.getName() : path + "/" + fileOrDir.getName(); | |
SVNNodeKind info = kindMap.get(targetPath); | |
if (info == SVNNodeKind.NONE) { | |
// 新增 | |
if (fileOrDir.isDirectory()) { | |
System.out.printf("加入資料夾 %s%n", fileOrDir.getName()); | |
editor.addDir(fileOrDir.getName(), null, revision); | |
File[] subFiles = fileOrDir.listFiles(); | |
if (subFiles != null) { | |
for (File subFile : subFiles) { | |
result = result || sendDelta(kindMap, editor, deltaGenerator, targetPath, subFile); | |
} | |
} | |
editor.closeDir(); | |
result = true; | |
} else if (fileOrDir.isFile()) { | |
System.out.printf("加入檔案 %s%n", fileOrDir.getName()); | |
editor.addFile(fileOrDir.getName(), null, revision); | |
editor.applyTextDelta(fileOrDir.getName(), null); | |
String checksum = deltaGenerator.sendDelta(fileOrDir.getName(), new FileInputStream(fileOrDir), editor, true); | |
editor.closeFile(fileOrDir.getName(), checksum); | |
result = true; | |
} | |
} else if (info == SVNNodeKind.DIR || info == SVNNodeKind.FILE) { | |
// 修改 | |
if (fileOrDir.isDirectory()) { | |
if (info != SVNNodeKind.DIR) | |
throw new RuntimeException(String.format("無法提交資料夾 %s 至檔案格式", fileOrDir)); | |
System.out.printf("開啟資料夾 %s%n", fileOrDir); | |
editor.openDir(fileOrDir.getName(), revision); | |
File[] subFiles = fileOrDir.listFiles(); | |
if (subFiles != null) { | |
for (File subFile : subFiles) { | |
result = result || sendDelta(kindMap, editor, deltaGenerator, targetPath, subFile); | |
} | |
} | |
editor.closeDir(); | |
} else if (fileOrDir.isFile()) { | |
if (info != SVNNodeKind.FILE) | |
throw new RuntimeException(String.format("無法提交檔案 %s 至資料夾格式", fileOrDir)); | |
System.out.printf("變更檔案 %s%n", fileOrDir.getName()); | |
editor.openFile(fileOrDir.getName(), revision); | |
editor.applyTextDelta(fileOrDir.getName(), null); | |
String checksum = deltaGenerator.sendDelta(fileOrDir.getName(), new FileInputStream(fileOrDir), editor, true); | |
editor.closeFile(fileOrDir.getName(), checksum); | |
result = true; | |
} | |
} | |
return result; | |
} | |
private byte[] toByteArray(InputStream input) { | |
if (input == null) throw new IllegalArgumentException("Input can't be null"); | |
ByteArrayOutputStream output = null; | |
try { | |
output = new ByteArrayOutputStream(); | |
byte[] buffer = new byte[128]; | |
int len; | |
while ((len = input.read(buffer)) > 0) { | |
output.write(buffer, 0, len); | |
} | |
return output.toByteArray(); | |
} catch (Throwable e) { | |
throw new RuntimeException(e.getMessage(), e); | |
} finally { | |
if (output != null) try { | |
output.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
try { | |
input.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
} |
git diff --name-only SHA1 SHA2or
git diff --name-only HEAD~10 HEAD~5
- apply plugin: 'com.android.application'
- android {
- compileSdkVersion 23
- buildToolsVersion "23.0.3"
- defaultConfig {
- applicationId "com.prhythm.myapplication"
- minSdkVersion 14
- targetSdkVersion 23
- versionCode 1
- versionName "1.0"
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
- }
- dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:23.3.0'
- }
- package com.prhythm.myapplication;
- import android.os.Bundle;
- import android.support.v7.app.AppCompatActivity;
- import android.text.TextUtils;
- import android.widget.TextView;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Enumeration;
- import java.util.List;
- import dalvik.system.DexFile;
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- TextView text = (TextView) findViewById(R.id.content);
- try {
- List<String> paths = new ArrayList<>();
- DexFile dex = new DexFile(getApplicationInfo().sourceDir);
- for (Enumeration<String> entries = dex.entries(); entries.hasMoreElements(); ) {
- paths.add(entries.nextElement());
- }
- text.append(String.format("Total entry count: %d%n", paths.size()));
- text.append("* " + TextUtils.join("\n* ", paths));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
Looks like this issue is related to the new InstantRun feature in the Android Plugin for Gradle 2.0.0. getPackageCodePath() gets a String pointing towards the base.apk file in the Android file system. If we unzip that apk we can find one or several .dex files inside its root folder. The entries obtained from the method df.entries() iterates over the .dex files found in that root folder in order to obtain all of its compiled classes. However, if we are using the new Android Plugin for Gradle, we will only find the .dex related to the android runtime and instant run (packages com.tools.android.fd.runtime, com.tools.android.fd.common and com.tools.android.tools.ir.api). Every other class will be compiled in several .dex files, zipped into a file called instant-run.zip and placed into the root folder of the apk. That's why the code posted in the question is not able to list all the classes within the app. Still, this will only affect Debug builds since the Release ones don't feature InstantRun.
- List<String> getClasses() throws IOException {
- List<String> paths = new ArrayList<>();
- File instantRunDir = new File(getBaseContext().getFilesDir(), "instant-run/dex");
- if (instantRunDir.exists()) {
- for (File dexPath : instantRunDir.listFiles()) {
- DexFile dex = new DexFile(dexPath);
- for (Enumeration<String> entries = dex.entries(); entries.hasMoreElements(); ) {
- paths.add(entries.nextElement());
- }
- }
- }
- DexFile dex = new DexFile(getApplicationInfo().sourceDir);
- for (Enumeration<String> entries = dex.entries(); entries.hasMoreElements(); ) {
- paths.add(entries.nextElement());
- }
- return paths;
- }
- class ContentLoader {
- @JavascriptInterface
- public void load(String body) {
- // do something
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- WebView webView = createWebView();
- webView.loadUrl("https://www.somedoamin.com/product.jsp");
- // enable javascript
- webView.getSettings().setJavaScriptEnabled(true);
- // add interface
- webView.addJavascriptInterface(new ContentLoader(), "ContentLoader");
- webView.setWebViewClient(new WebViewClient() {
- int action;
- @Override
- public void onPageFinished(WebView view, String url) {
- switch (action) {
- case 0:
- // fill field and submit
- view.loadUrl("javascript:{\n" +
- "\tdocument.querySelector('input[name=cgi_tel_no]').value='12345678';\n" +
- "\tdocument.querySelector('input[name=cgi_id_no]').value='abcdef';\n" +
- "\tsubmitMyForm();\n" +
- "};");
- case 1:
- // get content from 'ContentLoader' interface
- view.loadUrl("javascript:{\n" +
- "\twindow.ContentLoader.load('<body>'+document.body.innerHTML+'</body>');\t\n" +
- "};");
- break;
- }
- action++;
- }
- });
- }
- WebView createWebView() {
- WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
- WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
- params.gravity = Gravity.TOP | Gravity.LEFT;
- params.x = 0;
- params.y = 0;
- params.width = 0;
- params.height = 0;
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
- WebView view = new WebView(this);
- view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
- layout.addView(view);
- windowManager.addView(layout, params);
- return view;
- }
線上安裝,支援的 OS 有 Ubuntu、Debian、CentOS、Raspberry PI 2 on Raspbian。直接依照說明即可完成。
建議安裝時也同時下載目前安裝的版本,避免之後有移轉問題需要還原。各版本下載位址為
- # 執行備份
- gitlab-rake gitlab:backup:create
- # 複製備份檔至備份路徑
- sudo cp 1493107454_2017_04_25_9.1.0_gitlab_backup.tar /var/opt/gitlab/backups/
- # 停止服務
- sudo gitlab-ctl stop unicorn
- sudo gitlab-ctl stop sidekiq
- # 開始還原
- sudo gitlab-rake gitlab:backup:restore BACKUP=1493107454_2017_04_25_9.1.0
- # 啟動系統
- sudo gitlab-ctl start
- # 檢查還原結果
- sudo gitlab-rake gitlab:check SANITIZE=true
建立 svn 與 git 作者的 mapping 檔(author.txt)
- nanashi07 = Bruce <nanashi07@haha.com>
由 svn 簽出為 git 專案
- # clone from svn
- # with standard layout(trunk/branches/tags), "-s" argument is required
- # "author.txt" contains a list that svn accounts mapping to git authors
- git svn clone https://10.10.10.162/svn/caml/Caml.Maker --authors-file=author.txt --no-metadata -s Caml.Maker
- cd Caml.Maker
- # convert tags
- git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done
- # convert branches
- git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done
- # add remote repository
- git remote add origin http://nanashi07:password@10.10.10.222/caml/Caml.Maker.git
- # push to remote
- git push origin --all
- cd ..
- # 停止服務
- sudo gitlab-ctl stop unicorn
- sudo gitlab-ctl stop sidekiq
- sudo gitlab-ctl stop nginx
- # 備份
- sudo gitlab-rake gitlab:backup:create
- # 安裝下載的檔案
- # Ubuntu/Debian:
- sudo dpkg -i gitlab_x.x.x-omnibus.xxx.deb
- # CentOS:
- sudo rpm -Uvh gitlab-x.x.x_xxx.rpm
- # 重新設定與啟動
- sudo gitlab-ctl reconfigure
- sudo gitlab-ctl restart
- [RoutePrefix("images")]
- public class ImageController : Controller
- {
- // GET: ~/images/profile.png
- // GET: ~/images/1873429732.jpg
- [HttpGet]
- [Route("{name}.{ext}")]
- public ActionResult ReadImage(string name, string ext)
- {
- if (System.IO.File.Exists(Server.MapPath(string.Format("~/uploads/{0}.{1}", name, ext))))
- {
- byte[] data = System.IO.File.ReadAllBytes(Server.MapPath(string.Format("~/uploads/{0}.{1}", name, ext)));
- string contentType = MimeMapping.GetMimeMapping(System.IO.Path.GetFileName(string.Format("{0}.{1}", name, ext)));
- return File(data, contentType);
- }
- else
- {
- return new HttpStatusCodeResult(404);
- }
- }
- }
Then try test it, but respone 404 not found.
Add runAllManagedModulesForAllRequests="true" on modules section.
- <?xml version="1.0" encoding="utf-8"?>
- <configuration>
- ...
- <system.webServer>
- ...
- <modules runAllManagedModulesForAllRequests="true">
- <remove name="ApplicationInsightsWebTracking"/>
- <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"
- preCondition="managedHandler"/>
- </modules>
- </system.webServer>
- ...
- </configuration>
Then try it again, image rendered success.
# 安裝 package
- sudo apt-get update
# 建立 svn 資料夾
- sudo apt-get install subversion apache2 libapache2-svn apache2-utils
# 建立 svn 使用者 (apache)
- sudo mkdir -p /svn/repos/
# 建立使用者(第一次時有參數-c)
- sudo mkdir -p /svn/users/
# 刪除使用者後再重建(重設密碼)
- sudo htpasswd -cm /svn/users/svnpasswd nanashi07
# 修改 apache 設定
- #sudo htpasswd -D /svn/users/svnpasswd nanashi07
- #sudo htpasswd -m /svn/users/svnpasswd nanashi07
- sudo vi /etc/apache2/mods-enabled/dav_svn.conf
# 修改 apache 監聽埠
- <Location /svn>
- DAV svn
- SVNParentPath /svn/repos/
- AuthType Basic
- AuthName "SVN Repository"
- AuthUserFile /svn/users/svnpasswd
- Require valid-user
- </Location>
# 重新啟動 apache
- sudo vi /etc/apache2/ports.conf
# 建立資源庫
- sudo service apache2 restart
# 設定資源庫權限
- sudo svnadmin create /svn/repos/myproject
# 設定資源庫權限
- sudo chown -R www-data:www-data /svn/repos/myproject
- sudo chmod -R g+rws /svn/repos/myproject
- using Google.Apis.Auth.OAuth2;
- using Google.Apis.Drive.v2;
- using Google.Apis.Drive.v2.Data;
- using Google.Apis.Services;
- using Google.Apis.Util.Store;
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace SyncDump
- {
- class Program
- {
- /// <summary>
- /// 存取權限
- /// </summary>
- static string[] Scopes = { DriveService.Scope.Drive, DriveService.Scope.DriveFile };
- static string ApplicationName = "Drive Uploader";
- static void Main(string[] args)
- {
- // 檢查輸入參數
- if (args.Length < 1)
- {
- Console.WriteLine("No target file argument!");
- return;
- }
- // 要上傳的檔案
- string dumpPath = args[0];
- string dumpName = System.IO.Path.GetFileName(dumpPath);
- // 載入驗證資訊
- GoogleCredential credential;
- using (var stream = new System.IO.FileStream("client_secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read))
- {
- credential = GoogleCredential.FromStream(stream);
- }
- // 建立 service
- DriveService service = new DriveService(new BaseClientService.Initializer()
- {
- HttpClientInitializer = credential.CreateScoped(Scopes),
- ApplicationName = ApplicationName
- });
- // 進行上傳
- insertFile(
- service,
- dumpName,
- dumpName,
- System.Configuration.ConfigurationManager.AppSettings["drive.folder.id"],
- "application/oct-stream",
- dumpPath
- );
- }
- /// <summary>
- /// 新增檔案
- /// </summary>
- /// <param name="service">Drive API service instance.</param>
- /// <param name="title">Title of the file to insert, including the extension.</param>
- /// <param name="description">Description of the file to insert.</param>
- /// <param name="parentId">Parent folder's ID.</param>
- /// <param name="mimeType">MIME type of the file to insert.</param>
- /// <param name="filename">Filename of the file to insert.</param><br> /// <returns>Inserted file metadata, null is returned if an API error occurred.</returns>
- private static File insertFile(DriveService service, string title, string description, string parentId, string mimeType, string filename)
- {
- // 檔案資訊
- File body = new File();
- body.Title = title;
- body.Description = description;
- body.MimeType = mimeType;
- // 設定上傳位置
- if (!string.IsNullOrEmpty(parentId))
- {
- body.Parents = new List<ParentReference>() { new ParentReference() { Id = parentId } };
- }
- // 檔案內容
- byte[] byteArray = System.IO.File.ReadAllBytes(filename);
- System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
- try
- {
- FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, mimeType);
- request.Upload();
- File file = request.ResponseBody;
- Console.WriteLine("{0:yyyy/MM/dd HH:mm:ss} File {1} is uploaded to drive", DateTime.Now, file.Title);
- return file;
- }
- catch (Exception e)
- {
- Console.WriteLine("An error occurred: " + e.Message);
- return null;
- }
- }
- }
- }