2012-06-14 106 views
6

有没有一种方法可以中途克服克隆操作? 我将只使用克隆来验证存储库? 是否有任何其他方式来测试远程URL /存储库是否有效?JGIT验证存储库是否有效

+0

你可以看看[这个答案](http://stackoverflow.com/a/13606879/640012)。我认为这正是你想要的。 – Abhishek

+0

您可以使用JGIT调用'git ls-remote '。请参阅(http://superuser.com/questions/227509/git-ping-check-if-remote-repository-exists) – Muco

回答

1

我看了一下JGit的源代码,似乎没有提供检查远程回购有效性的方法。

这是CloneCommandcall方法:

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无效,捕当JGitInternalExceptione你可能会得到与e.getCause()实际原因,寻找InvalidRemoteException甚至URISyntaxException ,但正如你所指出的那样,如果它实际上是有效的,那么你最终会得到克隆;该库不允许您中断操作。

钻研更深入地进入JGit代码中,TransportLocal类有你可能会用来检查一个InvalidRemoteException抛出的open(URIsh,Repository,String)方法,但它的构造是不公开的。一个自己动手的解决方案是必需的,唉。你可以从我提到的TransportLocal.open方法的内容开始。

0

AFAIK JGit尚未实现git fsck。我使用下面的启发式

3

(有待进一步提高):

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创建URI时,主机不是空的,而是空字符串! URIish.isRemote()然而返回true,如果主机字段不为空...

编辑:增加了对isValidRemoteRepository()方法的ssh支持。

+1

用于检测本地回购有效或无效的代码在所有情况下都不正确即使对于处于无效状态的部分克隆回购,它也会返回true。看到[这](http://stackoverflow.com/questions/13586502/how-to-check-if-a-git-clone-has-been-done-already-with-jgit)回答一些代码,将处理这个场景也是。 – Adam

0

对于任何正在寻找的人,我使用以下更通用的方法来验证远程存储库(代码使用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; 
} 
2

您可以使用JGIT调用'git ls-remote'。看到如下here

示例代码:

final LsRemoteCommand lsCmd = new LsRemoteCommand(null); 
    final List<String> repos = Arrays.asList(
      "https://github.com/MuchContact/java.git", 
      "[email protected]:MuchContact/java.git"); 
    for (String gitRepo: repos){ 
     lsCmd.setRemote(gitRepo); 
     System.out.println(lsCmd.call().toString()); 
    } 
+0

只有代码组成的答案永远不会是答案。请详细说明。 – SubliemeSiem

+0

明白了。谢谢! @SubliemeSiem – Muco

0

JGit正在对git fsck命令的执行,但是这并没有得到至于我可以看到发布mvnrepository.com

示例如何,请检查此test case

@Test 
public void testHealthyRepo() throws Exception { 
    RevCommit commit0 = git.commit().message("0").create(); 
    RevCommit commit1 = git.commit().message("1").parent(commit0).create(); 
    git.update("master", commit1); 

    DfsFsck fsck = new DfsFsck(repo); 
    FsckError errors = fsck.check(null); 

    assertEquals(errors.getCorruptObjects().size(), 0); 
    assertEquals(errors.getMissingObjects().size(), 0); 
    assertEquals(errors.getCorruptIndices().size(), 0); 
} 
0

API用于验证远程存储库

public boolean validateRepository(String repositoryURL, String username, String password) throws Exception { 
    boolean result = false; 
    Repository db = FileRepositoryBuilder.create(new File("/tmp")); 
    Git git = Git.wrap(db); 
    final LsRemoteCommand lsCmd = git.lsRemote(); 
    lsCmd.setRemote(repositoryURL); 
    if (username != null && password != null) { 
     lsCmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)); 
    } 
    if (null != lsCmd.call()){ 
     result = true; 
    } 
    return result; 
} 

注:jgit的LS-远程API抛出其已知错误NPE。所以添加了错误评论中提到的解决方法。
https://bugs.eclipse.org/bugs/show_bug.cgi?id=436695