2012-02-07 94 views
5

我有一个脚本,可以自动将作者重写到一些git存储库上。为Python子进程打印执行命令.Popen

def filter_history(old, new, name, repoPath): 

command = """--env-filter ' 
     an="$GIT_AUTHOR_NAME" 
     am="$GIT_AUTHOR_EMAIL" 
     cn="$GIT_COMMITTER_NAME" 
     cm="$GIT_COMMITTER_EMAIL" 

     if [[ "$GIT_COMMITTER_NAME" = "|old|" ]] 
     then 
      cn="|name|" 
      cm="|new|" 
     fi 

     if [[ "$GIT_AUTHOR_NAME" = "|old|" ]] 
     then 
      an="|name|" 
      am="|new|" 
     fi 

     export GIT_AUTHOR_NAME="$an" 
     export GIT_AUTHOR_EMAIL="$am" 
     export GIT_COMMITTER_NAME="$cn" 
     export GIT_COMMITTER_EMAIL="$cm" 
' 
""" 

#DO string replace 
command = command.replace("|old|", old) 
command = command.replace("|new|", new) 
command = command.replace("|name|", name) 

print "git filter-branch -f " + command 

process = subprocess.Popen(['git filter-branch -f', command],cwd=os.path.dirname(repoPath), shell=True) 
process.wait() 

该命令执行得很好,但告诉我没有任何变化的回购历史。但是,如果我将打印出的命令(应该是正在执行的命令)放到shell脚本中并执行它,它会更改历史记录。我认为这个命令不能正确执行。有什么办法可以看到子进程模块正在执行什么命令?

回答

5

当您使用shell = True时,subprocess.Popen需要一个字符串作为其第一个参数。最好不要使用shell = True,因为它可以是security risk (see the Warning

当您省略shell = True或使用shell = False时,subprocess.Popen需要参数列表。您可以使用shlex.split生成一个参数列表:

import shlex 
import subprocess 

def filter_history(old, new, name, repoPath): 
    """Change author info 
    """ 
    # http://help.github.com/change-author-info/ 
    # http://stackoverflow.com/a/3880493/190597 
    command = """git filter-branch -f --env-filter ' 
     an="$GIT_AUTHOR_NAME" 
     am="$GIT_AUTHOR_EMAIL" 
     cn="$GIT_COMMITTER_NAME" 
     cm="$GIT_COMMITTER_EMAIL" 

     if [[ "$GIT_COMMITTER_NAME" = "{old}" ]] 
     then 
      cn="{name}" 
      cm="{new}" 
     fi 

     if [[ "$GIT_AUTHOR_NAME" = "{old}" ]] 
     then 
      an="{name}" 
      am="{new}" 
     fi 

     export GIT_AUTHOR_NAME="$an" 
     export GIT_AUTHOR_EMAIL="$am" 
     export GIT_COMMITTER_NAME="$cn" 
     export GIT_COMMITTER_EMAIL="$cm" 
     ' 
     """.format(old = old, new = new, name = name) 

    process = subprocess.Popen(
     shlex.split(command), 
     cwd = os.path.dirname(repoPath)) 
    process.communicate()