2015-10-23 2 views
2

Я пытаюсь использовать Process Builder для выполнения команды git. Но он, похоже, не работает никакой командой.ProcessBuilder с командой GIT не дает результата

git log дает мне правильный результат.

git shortlog -s но заканчивается на TimeOut!

Обе команды, запущенные на терминале, обеспечивают правильный результат! Я тестировал Win и Mac.

Кто-нибудь есть идеи, как я могу отладить это, или где моя ошибка?

Или, может быть, другое решение? Цель состоит в том, чтобы прочитать коммиттер определенного файла в репозитории git.

Фактическая команда Git: git shortlog -s -p FeilePath?

Мой Тест Код:

@Test 
    public void testCommandListDir() { 

     File execDir = new File("./"); 
     String returnValue = ""; 

     try { 
      returnValue = runCommand(execDir, 10, TimeUnit.SECONDS, "git", "log"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     assertTrue(returnValue.contains("+ try and error for git shortlog")); 
    } 


    @Test 
    public void testCommandGitShortlog() { 

     File execDir = new File("./"); 
     String returnValue = ""; 

     try { 
      returnValue = runCommand(execDir, 10, TimeUnit.SECONDS, "git", "shortlog", "-s"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     assertTrue(returnValue.equals("")); 
    } 

    public static String runCommand(File directory, long timeout, TimeUnit unit, String... command) throws IOException, InterruptedException { 

     StringBuilder sb = new StringBuilder(); 

     ProcessBuilder pb = new ProcessBuilder(command) 
       .redirectErrorStream(true).directory(directory); 


     Process p = pb.start(); 

     InputStream is = p.getInputStream(); 
     InputStream es = p.getErrorStream(); 
     BufferedReader br = new BufferedReader(new InputStreamReader(is)); 
     BufferedReader bre = new BufferedReader(new InputStreamReader(es)); 
     String in; 

     boolean timeOut = false; 


     if (!p.waitFor(timeout, unit)) { 
      //timeout - kill the process. 
      p.destroy(); // consider using destroyForcibly instead 
      timeOut = true; 
     } 

     if (timeOut) { 
      //write time out msg 
      sb.append("RunCommand time out! after " + timeout + " " + unit.toString() + "\n"); 
      sb.append("  directory: " + directory.getAbsolutePath() + "\n"); 
      sb.append("  command: " + command + "\n"); 
     } else { 
      while ((in = br.readLine()) != null) { 
       sb.append(in + "\n"); 
      } 

      while ((in = bre.readLine()) != null) { 
       sb.append(in + "\n"); 
      } 
     } 
     return sb.toString(); 
    } 

ответ

0

Если я правильно понял, вы пытаетесь ваша цель состоит git blame <filepath>.

Я бы предложил Git API для Java (JGit). В этом cookbook есть несколько примеров того, как начать работу.

Более конкретно, вы можете обвинить данный файл в данный коммит, как это:

private BlameResult blameCommit(String path, RevCommit commitToBlame) throws GitAPIException { 
    BlameCommand blamer = new BlameCommand(<yourRepository>); 
    ObjectId commitToBlameID = commitToBlame.getId(); 
    blamer.setStartCommit(commitToBlameID); 
    blamer.setFilePath(path); 
    return blamer.call(); 
} 

... или рекурсивно в заданном временном диапазоне, например:

public List<Blame> recuriveBlame(String path, RevCommit beginRevision, RevCommit endRevision) throws IOException, GitAPIException { 
    if (path == null 
      || beginRevision == null 
      || endRevision == null) { 
     return null; 
    } 

    List<Blame> result = new ArrayList<Blame>(); 
    try (RevWalk rw = new RevWalk(this.repo)) { 
     rw.markStart(rw.parseCommit(this.beginRevision)); 
     rw.markUninteresting(rw.parseCommit(this.endRevision)); 
     for (RevCommit curr; (curr = rw.next()) != null;){ 
      result.add(new Blame(curr, blameCommit(path, curr))); 
     } 
    } 

    return result; 
} 

. .. и получить коммиттер данной строки данного файла в данном обязательство, как this:

public void printCommitter(Repository repo, ObjectID commitID, String filename){ 
    int lines = countFiles(repos, commitID, filename); 
    for (int i = 0; i < lines; i++) { 
     PersonIdent committer = blame.getSourceCommitter(i); 
     System.out.println("Committer of the line: " + i + ": " + committer.getName()); 
    } 
} 

пса: Имейте в виду, что вам может потребоваться внести небольшие изменения для запуска этого кода. Например, countFiles(...) - here.