2012-06-14 9 views
6

¿Existe algún método para matar una operación de clonación a mitad de camino? ¿Usaré la clonación para validar el repositorio? ¿Hay alguna otra forma de comprobar si el URL/repositorio remoto es válido?JGIT validate si el repositorio es válido

+0

¿Podría echar un vistazo a [esta respuesta] (http://stackoverflow.com/a/13606879/640012). Creo que esto es exactamente lo que estabas buscando. – Abhishek

+0

puede invocar 'git ls-remote ' usando JGIT. ver en (http://superuser.com/questions/227509/git-ping-check-if-remote-repository-exists) – Muco

Respuesta

1

Eché un vistazo a las fuentes de JGit y no parece haber un método presente para verificar la validez del repositorio remoto.

Este es el método de 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); 
    } 
} 

Con el fin de conseguir si el URL remota no es válido, cuando la captura de un JGitInternalExceptione puede obtener la causa real con e.getCause() para buscar InvalidRemoteException o incluso URISyntaxException , pero como señaló, termina clonando si es realmente válido; la biblioteca no le permite interrumpir la operación.

Profundizando más profundamente en el código JGit, la clase TransportLocal tiene el método open(URIsh,Repository,String) se podría haber utilizado para comprobar si un InvalidRemoteException se lanza, pero su constructor no es pública. Se requiere una solución de hágalo usted mismo, ¡ay! Tal vez podría comenzar desde el contenido del método TransportLocal.open que mencioné.

0

AFAIK JGit todavía no tiene una implementación de git fsck.

3

estoy usando la siguiente heurística (que debe mejorar aún más):

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

Esto funciona bien con los repositorios de desnudos y no desnudos.

Tenga en cuenta que parece haber un problema con el método URIish.isRemote(). Cuando creas un URIish a partir de un archivo-URL, ¡el host no es nulo sino una cadena vacía! URIish.isRemote() sin embargo devuelve verdadero, si el campo de host no es nulo ...

EDITAR: Se agregó el soporte de ssh al método isValidRemoteRepository().

+1

el código utilizado para detectar si un repositorio local es válido o no no es correcto en todos los casos , devolverá verdadero incluso para un repositorio parcialmente clonado en un estado inválido. Vea [this] (http://stackoverflow.com/questions/13586502/how-to-check-if-a-git-clone-has-been-done-already-with-jgit) answer para algún código que maneje este escenario también – Adam

0

Para cualquiera que esté buscando, estoy usando el siguiente enfoque, más genérico, para validar un repositorio remoto (el código está en C#, pero no debería ser difícil convertirlo a 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

puede invocar 'git ls-remote' utilizando JGIT. ver en here

Código de la muestra de la siguiente manera:

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

Una respuesta que consiste en solo código nunca es una respuesta. Por favor elabora. – SubliemeSiem

+0

Lo tengo. ¡Gracias! @SubliemeSiem – Muco

0

JGit está trabajando en una aplicación del comando git fsck, pero esto no se ha lanzado en mvnrepository.com por lo que yo puedo ver.

Ejemplo de cómo se verá, marque 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 para validar repositorios remotos

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

Nota: API-ls remota de jgit lanza NPE que se conoce de errores.Así que agregó la solución como se menciona en los comentarios del error.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=436695

Cuestiones relacionadas