2012-06-07 47 views
2

我在Git仓库上运行Gitolite,并且我有用Python编写的post-receive钩子。我需要在git repository目录下执行“git”命令。有几行代码:通过git钩子执行python子进程

proc = subprocess.Popen(['git', 'log', '-n1'], cwd='/home/git/repos/testing.git' stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
proc.communicate() 

后,我作出新的承诺,并推到库,脚本执行,并说

fatal: Not a git repository: '.' 

如果我运行

proc = subprocess.Popen(['pwd'], cwd='/home/git/repos/testing.git' stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

它说,如预期,正确的路径到git仓库(/home/git/repos/testing.git)

如果我从bash手动运行这个脚本,它工作正常并显示正确的“git log”输出。我做错了什么?

回答

4

你可以尝试使用命令行开关来设置Git仓库:

proc = subprocess.Popen(['git', '--git-dir', '/home/git/repos/testing.git', 'log', '-n1'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

--git-dir需要指向一个实际git目录(工作树中的.git)。请注意,对于某些命令,您还需要也设置--work-tree选项。

另一种方式来设置目录使用GIT_DIR环境变量:

import os 
env = os.environ.copy() 
env['GIT_DIR'] = '/home/git/repos/testing.git' 
proc = subprocess.Popen((['git', 'log', '-n1', stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) 

显然已经的钩设置GIT_DIR,但显然这是不正确的你的情况(也可能是相对的);上面的代码将其设置为完整的显式路径。

请参阅git manpage

编辑:显然,它同时指定一个CWD和重写GIT_DIR VAR时,仅适用于在OP:

import os 
repo = '/home/git/repos/testing.git' 
env = os.environ.copy() 
env['GIT_DIR'] = repo 
proc = subprocess.Popen((['git', 'log', '-n1', stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=repo) 
+1

钩子已经设置好环境变量'$ GIT_DIR',所以如果你想把git指向不同的目录,你必须重写它。请注意,一般情况下,钩子也运行'GIT_DIR = .'(即它是*相对*,这对我来说是一个惊喜)。最好完全清除它或将其设置为你想要的。 – torek

+0

@torek:有趣的是,这可能是OP的错误。更新了答案,因为'env.update(os.environ)'会抹掉我们试图设置的自定义'GIT_DIR' var。 –

+0

呵呵,我没有仔细阅读你的第二部分答案,以至于你意识到你正在使用'.update'。无论如何,是的,我怀疑这是OP的真正问题。 (实验告诉我,' - git-dir'覆盖了'$ GIT_DIR',所以你的第一个答案应该可以工作。) – torek

0

有一个逗号CWD争吵后失踪:

proc = subprocess.Popen(['git', 'log', '-n1'], cwd='/home/git/repos/testing.git', stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
+1

这很难吧;这会产生一个SyntaxError,而不是用户看到的错误。在SO上发布时,可以避免转换错误。 –