2015-02-24 68 views
0

我在Python 3中編寫了CLI-based web server control panel以代替Plesk。該應用程序的功能之一是在現有項目目錄中創建和配置Git存儲庫。有趣的是,除了git push -u origin master之外,我可以使用os.system()執行所有Git功能。下面是相關代碼:無法在Python中推git倉庫

external_command = " cd %s ; " % (dir_name,) 
external_command+= " git push -u origin master " 
os.system(external_command) 

這是結果:

fatal: 'origin' does not appear to be a git repository 
fatal: The remote end hung up unexpectedly 

然而,在CLI結果在成功運行相同的指令:

$ cd /var/www/foobar.com ; git push -u origin master 
Counting objects: 190, done. 
Delta compression using up to 4 threads. 
Compressing objects: 100% (185/185), done. 
Writing objects: 100% (190/190), 1.36 MiB, done. 
Total 190 (delta 131), reused 0 (delta 0) 
To ssh://alpha/var/git/foobar.com.git 
* [new branch]  master -> master 
Branch master set up to track remote branch master from origin. 

可能是什麼這個問題的原因?我應該如何着手解決問題?請注意,有問題的命令是最後一個命令運行,所以問題不可能是其他步驟尚未完成。整個相關的功能是在this file (Github link)add_dir_to_git(),這裏複製的,以及:

def add_dir_to_git(): 

    print('\nAdd Git repo.\n') 

    dir_name = input('Directory path to add' + environment.prompt) 
    git_name = input('Git repo path' + environment.prompt) 
    # TODO: Validate input 

    if not dir_name.endswith('/'): 
     dir_name += '/' 

    if not os.path.isdir(dir_name): 
     print('The specified directory does not seem to exist: %s' % (dir_name,)) 
     print('Aborting operation.') 
     return False 

    external_command = "cd %s ; " % (dir_name,) 
    external_command+= " git status 2>&1 " 

    git_check = os.popen(external_command).read().strip() 

    if not 'Not a git repository' in git_check: 
     print('The specified directory is already in a Git repository: %s' % (dir_name,)) 
     print('Aborting operation.') 
     return False 

    external_command = " find %s -name '.git' -type d " % (dir_name,) 
    subdirectory_git = os.popen(external_command).read().strip().split('\n') 
    subdirectory_git = [x for x in subdirectory_git if x!=''] 

    if len(subdirectory_git)>0: 
     print("Git directories were found in the following subdirectories:") 
     for dirname in subdirectory_git: 
      print(" * %s" % (dirname,)) 

     continue_install = input("Continue? [y/N]" + environment.prompt).lower() 

     if not continue_install=='y' and not continue_install=='yes': 
      print('Aborting operation.') 
      return False 

    git_version = os.popen("git --version | awk '{print $3}'").read().strip().split('.') 

    if git_version[0]=='1' and git_version[1]=='9': 
     push_default = " git config push.default simple ; " 
    else: 
     push_default = '' 

    external_command = "cd %s ; " % (dir_name,) 
    external_command+= " git init ; " 
    external_command+= " git config user.name 'Do not work on the server' ; " 
    external_command+= " git config user.email '[email protected]' ; " 
    external_command+= push_default 
    external_command+= " git add . ; " 
    external_command+= " git commit -am 'Initial commit' 2>&1 " 

    create_repo = os.popen(external_command).read().strip() 

    #TODO: Check! 

    git_config_file = dir_name + '.git/config' 
    git_config = open(git_config_file, 'a') 

    git_append = """ 
[remote "origin"] 
     fetch = +refs/heads/*:refs/remotes/origin/* 
     url = %s 
[branch "master"] 
     remote = origin 
     merge = refs/heads/master 
""" % (git_name,) 

    git_config.write(git_append) 

    # TODO: Check that the steps completed properly. 

    print('Done! If connecting to A NEW PUBLIC REPO then you must do an initial branch-configuration push. Would you like to do that now?') 
    initial_push = input('[y/N]' + environment.prompt).lower() 

    if initial_push=='y' or initial_push=='yes': 
     external_command = " cd %s ; " % (dir_name,) 
     external_command+= " git push -u origin master " 
     os.system(external_command) 

    return True 

回答

1

使用Python SH模塊。它可以讓你輸入命令的功能。這比使用os.system更安全。 https://pypi.python.org/pypi/sh

然後,你可以簡單地做:

from sh import git, cd 
cd(dir_name) 
git("push -u origin master") 
+0

它比'subprocess'更萬無一失?它如何將命令分解爲參數? – Kos 2015-02-24 12:14:02

+0

我不是這個插件的開發者,但是它應該更加簡單。我引用了這些文檔:「請注意,這些不是Python函數,它們通過解析$ PATH動態地在系統上運行二進制命令,就像Bash所做的那樣。這樣,系統中的所有程序都可以輕鬆獲得來自Python內部的你。「 – geekpradd 2015-02-24 12:15:33

+0

如果我通過'os.system()'和'os.popen()'運行命令找不到解決問題的方法,那麼我會嘗試'sh'。謝謝。 – dotancohen 2015-02-24 12:40:52