0

I'm writing a CLI-based web server control panel in Python 3 as a replacement for Plesk. One of the functions of the application is to create and configure Git repositories in existing project directories. Interestingly, I can perform all Git functions using os.system() except for git push -u origin master. Here is the relevant code:

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

This is the result:

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

However, running the exact same command on the CLI results in success:

$ 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.

What might be the cause of this issue? How should I proceed to troubleshoot? Note that the command in question is the last command run so the issue cannot be that other steps have yet to complete. The entire relevant function is add_dir_to_git() in this file (Github link), copied here as well:

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 Answer 1

1

Use the python sh module.. It allows you to import commands as functions. This is better than using os.system and more foolproof. https://pypi.python.org/pypi/sh

Then you can simply do:

from sh import git, cd
cd(dir_name)
git("push -u origin master")
Sign up to request clarification or add additional context in comments.

5 Comments

Is it more foolproof than subprocess? How does it split the command into arguments?
I'm not the developer for this plugin but yes it should be more foolproof. I quote from the docs: "Note that these aren’t Python functions, these are running the binary commands on your system dynamically by resolving your $PATH, much like Bash does. In this way, all the programs on your system are easily available to you from within Python."
If I cannot find a way to resolve the issue by running the commands via os.system() and os.popen() then I will try sh. Thanks.
@dotancohen, I'll recommend using the subprocess module rather than os.system().. It's dedicated and meant for executing system commands.
This answer did not resolve the issue of fatal: 'origin' does not appear to be a git repository, and the subprocess did not help. either. I'm stumped.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.