2016-04-05 52 views
4

我是GitPython的新手,我试图在提交中获取文件的内容。我可以从特定的提交中获取每个文件,但每次运行该命令时都会收到错误消息。现在,我知道,在文件中GitPython存在,但每次我运行我的程序时,我收到以下错误:GitPython:我如何访问GitPython中的提交文件的内容

returned non-zero exit status 1 

我使用Python的2.7.6Ubuntu Linux操作系统的14.04。

我知道该文件存在,因为我也直接从命令行进入git,检查相应的提交,搜索文件并找到它。我还运行了cat命令,并显示文件内容。很多时候,当出现错误时,它说相关文件不存在。我正在试图通过每次使用GitPython进行提交,从每个单独提交中获取每个blob或文件,并对该文件的内容运行外部Java程序。 Java程序旨在将字符串返回给Python。要捕获从我的Java代码返回的字符串,我也使用subprocess.check_output。任何帮助将不胜感激。

我试图在命令传递的列表:

cmd = ['java', '-classpath', '/home/rahkeemg/workspace/CSCI499_Java/bin/:/usr/local/lib/*:', 'java_gram.mainJava','absolute/path/to/file'] 
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False) 

而且我自己也尝试将命令传递作为字符串:

subprocess.check_output('java -classpath /home/rahkeemg/workspace/CSCI499_Java/bin/:/usr/local/lib/*: java_gram.mainJava {file}'.format(file=entry.abspath.strip()), shell=True) 

是否有可能访问文件的内容来自GitPython? 例如,假设有一个承诺,它有一个文件foo.java 在该文件中是以下几行代码:

foo.java

import java.io.FileInputStream; 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 

    public class foo{ 
     public static void main(String[] args) throws Exception{} 
    } 

我想访问文件中的所有内容并在其上运行外部程序。 任何帮助将不胜感激。下面是我使用的一段代码

#! usr/bin/env python 

__author__ = 'rahkeemg' 

from git import * 
import git, json, subprocess, re 


git_dir = '/home/rahkeemg/Documents/GitRepositories/WhereHows' 


# make an instance of the repository from specified path 
repo = Repo(path=git_dir) 

heads = repo.heads # obtain the differnet repositories 
master = heads.master # get the master repository 

print master 

# get all of the commits on the master branch 
commits = list(repo.iter_commits(master)) 

cmd = ['java', '-classpath', '/home/rahkeemg/workspace/CSCI499_Java/bin/:/usr/local/lib/*:', 'java_gram.mainJava'] 

# start at the very 1st commit, or start at commit 0 
for i in range(len(commits) - 1, 0, -1): 
    commit = commits[i] 
    commit_num = len(commits) - 1 - i 
    print commit_num, ": ", commit.hexsha, '\n', commit.message, '\n' 

    for entry in commit.tree.traverse(): 
     if re.search(r'\.java', entry.path): 

      current_file = str(entry.abspath.strip()) 

      #add the current file, or blob, to the list for the command to run 
      cmd.append(current_file) 
      print entry.abspath 

      try: 

       #This is scenario where I pass arguments into command as a string 
       print subprocess.check_output('java -classpath /home/rahkeemg/workspace/CSCI499_Java/bin/:/usr/local/lib/*: java_gram.mainJava {file}'.format(file=entry.abspath.strip()), shell=True) 


       # scenario where I pass arguments into command as a list 
       j_response = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False) 

      except subprocess.CalledProcessError as e: 
       print "Error on file: ", current_file 

      #Use pop on list to remove the last string, which is the selected file at the moment, to make place for the next file. 
      cmd.pop() 
+0

*“我也直接进入git的命令行,看看各自的承诺,搜索文件,并发现它” * - 您的问题是,当您迭代提交**时,不会执行签出** * GitPython *。 – totoro

+0

提示1:因为Python是魔术,你可以对commit_num进行commit操作,使用反序列表(list(enumerate(commits))):而不是使用'i','len','commitits [i]'等等。 ... – mbdevpl

+0

提示2:'re.search(r'\。java',entry.path)'也会匹配像'my.name.is.java.txt'这样的字符串,它不一定是Java源文件。为什么不简单地执行'entry.path.endswith('。java')'? – mbdevpl

回答

4

首先,当您像这样遍历提交历史记录时,文件将不会被签出。你所得到的只是文件名,可能是文件或可能不是,但肯定不会导致文件与当前签出的版本不同。

但是,有一个解决方案。请记住,原则上,您可以使用一些git命令执行任何操作,您可以使用GitPython。

要想从特定修订文件的内容,你可以做到以下几点,这I've taken from that page

git show <treeish>:<file> 

因此,在GitPython:

file_contents = repo.git.show('{}:{}'.format(commit.hexsha, entry.path)) 

然而,这仍然不会使文件出现在磁盘上。如果你需要一些真实路径的文件,你可以使用tempfile

f = tempfile.NamedTemporaryFile(delete=False) 
f.write(file_contents) 
f.close() 

# at this point file with name f.name contains contents of 
# the file from path entry.path at revision commit.hexsha 
# your program launch goes here, use f.name as filename to be read 

os.unlink(f.name) # delete the temp file