GitPython:如何在GitPython的提交中访问文件的内容 [英] GitPython: How can I access the contents of a file in a commit in GitPython

查看:90
本文介绍了GitPython:如何在GitPython的提交中访问文件的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是GitPython的新手,我正在尝试在一次提交中获取文件的内容.我可以从特定的提交中获取每个文件,但是每次运行命令时都会出错.现在,我知道该文件存在于GitPython中,但是每次运行程序时,都会出现以下错误:

I am new to GitPython and I am trying to get the content of a file within a commit. I am able to get each file from a specific commit, but I am getting an error each time I run the command. Now, I know that the file exist in GitPython, but each time I run my program, I am getting the following error:

 returned non-zero exit status 1

我正在使用 Python 2.7.6 Ubuntu Linux 14.04.

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

I know that the file exist, since I also go directly into git from the command line, check out the respective commit, search for the file, and find it. I also run the cat command on it and the file content are displayed. Many times when the error shows up, it says that the file in question does not exist. What I am trying to do it to go through each commit with GitPython, get every blob, or file, from each individual commit, and run an external Java program on the content of that file. The Java program is designed to return a string to Python. To capture the string returned from my Java code, I am also using subprocess.check_output. Any help will be greatly appreciated.

我尝试将命令作为列表传递:

I tried passing in the command as a list:

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)

我还尝试过将命令作为字符串传递:

And I have also tried passing the command as a string:

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 该文件中包含以下代码行:

Is it possible to access the contents of a file from GitPython? For example, say there is a commit and it has one file foo.java In that file is the following lines of code:

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

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

I want to access everything in the file and run an external program on it. Any help would be greatly appreciated. Below is a piece of the code I am using to do so

 #! 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()

推荐答案

首先,当您遍历这样的提交历史记录时,将不会检出该文件.您所获得的只是文件名,可能导致文件出现,也可能不会导致文件出现,但是肯定不会导致文件版本不同于当前签出的版本.

First of all, when you traverse the commit history like this, the file will not be checked out. All you get is the filename, maybe leading to the file or maybe not, but certainly it will not lead to the file from different revision than currently checked-out.

但是,有一个解决方案.请记住,原则上,只要使用 git 命令可以执行的任何操作,都可以使用GitPython.

However, there is a solution to this. Remember that in principle, anything you could do with some git command, you can do with GitPython.

要从特定版本获取文件内容,可以执行以下操作,其中

To get file contents from specific revision, you can do the following, which I've taken from that page:

git show <treeish>:<file>

因此,在GitPython中:

therefore, in GitPython:

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

但是,那仍然不能使文件显示在磁盘上.如果您需要文件的真实路径,则可以使用 tempfile :

However, that still wouldn't make the file appear on disk. If you need some real path for the file, you can use 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

这篇关于GitPython:如何在GitPython的提交中访问文件的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆