2012-02-07 92 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()