JGIT如何验证代码仓库是否有效。

8

有没有办法在克隆操作进行中停止它? 我只是想使用克隆来验证存储库? 还有其他方法可以测试远程URL /存储库是否有效吗?


你能看一下这个答案吗?我认为这正是你所需要的。 - Abhishek
您可以使用JGIT调用“git ls-remote <REPO_URL>”命令。请参见(http://superuser.com/questions/227509/git-ping-check-if-remote-repository-exists)。 - Muco
7个回答

5

您可以使用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());
    }

答案仅包含代码是不够的,需要进一步阐述。 - SubliemeSiem
明白了,谢谢!@SubliemeSiem - Muco

4

我正在使用以下启发式方法(需要进一步改进):

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...
编辑:已将ssh支持添加到isValidRemoteRepository() 方法中。

2
用于检测本地仓库是否有效的代码并不在所有情况下都正确,即使是处于无效状态的部分克隆仓库也会返回true。请参考答案,获取一些可以处理这种情况的代码。 - Adam
这段代码将返回 true: new URIish(new File("/tmp").toURI().toURL()).isRemote(),因此至少应该执行 repoUri.isRemote() && !repoUri.getScheme().equals("file") - Daniel C. Sobral

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是否无效,在捕获JGitInternalException e时,您可以使用e.getCause()获取实际原因,查找InvalidRemoteException或者URISyntaxException,但正如您所指出的,如果它实际上是有效的,您最终会克隆;该库不允许您中断操作。
深入研究JGit代码后,TransportLocal类具有open(URIsh,Repository,String)方法,您可以使用该方法检查是否抛出InvalidRemoteException,但其构造函数不是公共的。不幸的是,需要自己动手解决。您可以从我提到的TransportLocal.open方法的内容开始。

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-remote API会抛出NPE异常,这是已知的错误。因此,按照错误的注释添加了解决方法。
https://bugs.eclipse.org/bugs/show_bug.cgi?id=436695

0
JGit正在实现git fsck命令,但据我所知,这还没有在mvnrepository.com上发布。
查看此测试用例以了解其外观示例。
@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
据我所知,JGit目前还没有实现git fsck

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接