途中でクローン操作を強制終了する方法はありますか?クローンを使用してリポジトリを検証しますか?リモートURL/リポジトリが有効かどうかをテストする他の方法はありますか?
7 に答える
JGIT を使用して「git ls-remote」を呼び出すことができます。ここを見て
サンプルコードは次のとおりです。
final LsRemoteCommand lsCmd = new LsRemoteCommand(null);
final List<String> repos = Arrays.asList(
"https://github.com/MuchContact/java.git",
"git@github.com:MuchContact/java.git");
for (String gitRepo: repos){
lsCmd.setRemote(gitRepo);
System.out.println(lsCmd.call().toString());
}
次のヒューリスティックを使用しています(さらに改善する必要があります):
private final static String INFO_REFS_PATH = "info/refs";
public static boolean isValidRepository(URIish repoUri) {
if (repoUri.isRemote()) {
return isValidRemoteRepository(repoUri);
} else {
return isValidLocalRepository(repoUri);
}
}
private static boolean isValidLocalRepository(URIish repoUri) {
boolean result;
try {
result = new FileRepository(repoUri.getPath()).getObjectDatabase().exists();
} catch (IOException e) {
result = false;
}
return result;
}
private static boolean isValidRemoteRepository(URIish repoUri) {
boolean result;
if (repoUri.getScheme().toLowerCase().startsWith("http") ) {
String path = repoUri.getPath();
String newPath = path.endsWith("/")? path + INFO_REFS_PATH : path + "/" + INFO_REFS_PATH;
URIish checkUri = repoUri.setPath(newPath);
InputStream ins = null;
try {
URLConnection conn = new URL(checkUri.toString()).openConnection();
conn.setReadTimeout(NETWORK_TIMEOUT_MSEC);
ins = conn.getInputStream();
result = true;
} catch (Exception e) {
result = false;
} finally {
try { ins.close(); } catch (Exception e) { /* ignore */ }
}
} else if (repoUri.getScheme().toLowerCase().startsWith("ssh") ) {
RemoteSession ssh = null;
Process exec = null;
try {
ssh = SshSessionFactory.getInstance().getSession(repoUri, null, FS.detect(), 5000);
exec = ssh.exec("cd " + repoUri.getPath() +"; git rev-parse --git-dir", 5000);
Integer exitValue = null;
do {
try {
exitValue = exec.exitValue();
} catch (Exception e) {
try{Thread.sleep(1000);}catch(Exception ee){}
}
} while (exitValue == null);
result = exitValue == 0;
} catch (Exception e) {
result = false;
} finally {
try { exec.destroy(); } catch (Exception e) { /* ignore */ }
try { ssh.disconnect(); } catch (Exception e) { /* ignore */ }
}
} else {
// TODO need to implement tests for other schemas
result = true;
}
return result;
}
これは、裸および非裸のリポジトリでうまく機能します。
URIish.isRemote() メソッドに問題があるようです。ファイル URL から URIish を作成すると、ホストは null ではなく空の文字列になります! ただし、ホスト フィールドが null でない場合、URIish.isRemote() は true を返します...
編集: isValidRemoteRepository() メソッドに ssh サポートを追加しました。
JGit のソースを調べたところ、リモート リポジトリの有効性を確認する方法がないようです。
これは次のcall
方法ですCloneCommand
。
public Git call() throws JGitInternalException {
try {
URIish u = new URIish(uri);
Repository repository = init(u);
FetchResult result = fetch(repository, u);
if (!noCheckout)
checkout(repository, result);
return new Git(repository);
} catch (IOException ioe) {
throw new JGitInternalException(ioe.getMessage(), ioe);
} catch (InvalidRemoteException e) {
throw new JGitInternalException(e.getMessage(), e);
} catch (URISyntaxException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
リモート URL が無効かどうかを取得するために、 a をキャッチすると、またはを検索しJGitInternalException
e
て実際の原因を取得できますが、指摘したように、実際に有効な場合はクローンを作成します。ライブラリでは、操作を中断することはできません。e.getCause()
InvalidRemoteException
URISyntaxException
JGit コードをさらに深く掘り下げると、TransportLocal
クラスにはがスローopen(URIsh,Repository,String)
されたかどうかを確認するために使用できるメソッドがありますがInvalidRemoteException
、そのコンストラクターはパブリックではありません。残念ながら、日曜大工のソリューションが必要です。TransportLocal.open
私が言及した方法の内容から始めることができるかもしれません。
AFAIK JGitにはgit fsck
まだ実装がありません。
見ている人には、次のより一般的なアプローチを使用して、リモート リポジトリを検証しています (コードは C# ですが、Java に変換するのは難しくありません)。
public static bool IsValidRemoteRepository(URIish repoUri, CredentialsProvider credentialsProvider = null)
{
var repoPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
Directory.CreateDirectory(repoPath);
var git = Git.Init().SetBare(true).SetDirectory(repoPath).Call();
var config = git.GetRepository().GetConfig();
config.SetString("remote", "origin", "url", repoUri.ToString());
config.Save();
try
{
var cmd = git.LsRemote();
if (credentialsProvider != null)
{
cmd.SetCredentialsProvider(credentialsProvider);
}
cmd.SetRemote("origin").Call();
}
catch (TransportException e)
{
LastException = e;
return false;
}
return true;
}