Update git module to use module magic and other changes

Convert git module to module magic.
Drop cruft no longer needed.
Standardize indent to 4 spaces in methods switchLocalBranch, reset,
clone, and get_version.
Update is_local_branch to also handle '* branch' format.
Add is_current branch method()
Update pull() method to use is_current_branch()
This commit is contained in:
Stephen Fromm 2012-07-29 22:33:16 -07:00
commit 87b3e1ecdc

View file

@ -22,136 +22,98 @@
# tag. Latest is not supported, you should not be doing # tag. Latest is not supported, you should not be doing
# that. Contribs welcome! -- MPD # that. Contribs welcome! -- MPD
try:
import json
except ImportError:
import simplejson as json
import os import os
import re import re
import sys
import shlex
import subprocess import subprocess
import syslog
# ===========================================
# Basic support methods
def exit_json(rc=0, **kwargs):
print json.dumps(kwargs)
sys.exit(rc)
def fail_json(**kwargs):
kwargs['failed'] = True
exit_json(**kwargs)
# ===========================================
# convert arguments of form a=b c=d
# to a dictionary
# FIXME: make more idiomatic
if len(sys.argv) == 1:
fail_json(msg="the command module requires arguments (-a)")
argfile = sys.argv[1]
if not os.path.exists(argfile):
fail_json(msg="Argument file not found")
args = open(argfile, 'r').read()
items = shlex.split(args)
syslog.openlog('ansible-%s' % os.path.basename(__file__))
syslog.syslog(syslog.LOG_NOTICE, 'Invoked with %s' % args)
if not len(items):
fail_json(msg="the command module requires arguments (-a)")
params = {}
for x in items:
(k, v) = x.split("=")
params[k] = v
dest = params['dest']
repo = params['repo']
version = params.get('version', 'HEAD')
remote = params.get('remote', 'origin')
# ===========================================
def get_version(dest): def get_version(dest):
''' samples the version of the git repo ''' ''' samples the version of the git repo '''
os.chdir(dest) os.chdir(dest)
cmd = "git show --abbrev-commit" cmd = "git show --abbrev-commit"
sha = os.popen(cmd).read().split("\n") sha = os.popen(cmd).read().split("\n")
sha = sha[0].split()[1] sha = sha[0].split()[1]
return sha return sha
def clone(repo, dest): def clone(repo, dest):
''' makes a new git repo if it does not already exist ''' ''' makes a new git repo if it does not already exist '''
try: try:
os.makedirs(os.path.dirname(dest)) os.makedirs(os.path.dirname(dest))
except: except:
pass pass
cmd = "git clone %s %s" % (repo, dest) cmd = "git clone %s %s" % (repo, dest)
cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate() (out, err) = cmd.communicate()
rc = cmd.returncode rc = cmd.returncode
return (rc, out, err) return (rc, out, err)
def reset(dest): def reset(dest):
''' '''
Resets the index and working tree to HEAD. Resets the index and working tree to HEAD.
Discards any changes to tracked files in working Discards any changes to tracked files in working
tree since that commit. tree since that commit.
''' '''
os.chdir(dest) os.chdir(dest)
cmd = "git reset --hard HEAD" cmd = "git reset --hard HEAD"
cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate() (out, err) = cmd.communicate()
rc = cmd.returncode rc = cmd.returncode
return (rc, out, err) return (rc, out, err)
def switchLocalBranch( branch ): def switchLocalBranch( branch ):
cmd = "git checkout %s" % branch cmd = "git checkout %s" % branch
cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return cmd.communicate() return cmd.communicate()
def get_branches(dest): def get_branches(module, dest):
os.chdir(dest) os.chdir(dest)
branches = [] branches = []
cmd = "git branch -a" cmd = "git branch -a"
cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = cmd.communicate() out, err = cmd.communicate()
if cmd.returncode != 0: if cmd.returncode != 0:
fail_json(msg="Could not determine branch data - received %s" % out) module.fail_json(msg="Could not determine branch data - received %s" % out)
for line in out.split('\n'): for line in out.split('\n'):
branches.append(line.strip()) branches.append(line.strip())
return branches return branches
def is_remote_branch(dest, remote, branch): def is_remote_branch(module, dest, remote, branch):
branches = get_branches(dest) branches = get_branches(module, dest)
rbranch = 'remotes/%s/%s' % (remote, branch) rbranch = 'remotes/%s/%s' % (remote, branch)
if rbranch in branches: if rbranch in branches:
return True return True
else: else:
return False return False
def is_local_branch(dest, branch): def is_local_branch(module, dest, branch):
branches = get_branches(dest) branches = get_branches(module, dest)
lbranch = '%s' % branch lbranch = '%s' % branch
if lbranch in branches: if lbranch in branches:
return True return True
elif '* %s' % branch in branches:
return True
else: else:
return False return False
def pull(repo, dest, version): def is_current_branch(module, dest, branch):
branches = get_branches(module, dest)
for b in branches:
if b.startswith('* '):
cur_branch = b
if branch == cur_branch or '* %s' % branch == cur_branch:
return True
else:
return True
def pull(module, repo, dest, version):
''' updates repo from remote sources ''' ''' updates repo from remote sources '''
os.chdir(dest) os.chdir(dest)
branches = get_branches(dest) branches = get_branches(module, dest)
cur_branch = '' cur_branch = ''
for b in branches: for b in branches:
if b.startswith('* '): if b.startswith('* '):
cur_branch = b cur_branch = b
if is_local_branch(dest, version) and version != cur_branch: if is_local_branch(module, dest, version) and not is_current_branch(module, dest, version):
(out, err) = switchLocalBranch(version) (out, err) = switch_version(module, dest, remote, version)
cmd = "git pull -u origin" cmd = "git pull -u origin"
cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -159,12 +121,12 @@ def pull(repo, dest, version):
rc = cmd.returncode rc = cmd.returncode
return (rc, out, err) return (rc, out, err)
def switch_version(dest, remote, version): def switch_version(module, dest, remote, version):
''' once pulled, switch to a particular SHA or tag ''' ''' once pulled, switch to a particular SHA, tag, or branch '''
os.chdir(dest) os.chdir(dest)
cmd = '' cmd = ''
if version != 'HEAD': if version != 'HEAD':
if not is_local_branch(dest, version) and is_remote_branch(dest, remote, version): if not is_local_branch(module, dest, version) and is_remote_branch(module, dest, remote, version):
cmd = "git checkout --track -b %s %s/%s" % (version, remote, version) cmd = "git checkout --track -b %s %s/%s" % (version, remote, version)
else: else:
cmd = "git checkout --force %s" % version cmd = "git checkout --force %s" % version
@ -175,46 +137,62 @@ def switch_version(dest, remote, version):
(out, err) = cmd.communicate() (out, err) = cmd.communicate()
rc = cmd.returncode rc = cmd.returncode
return (rc, out, err) return (rc, out, err)
gitconfig = os.path.join(dest, '.git', 'config') # ===========================================
out, err, status = (None, None, None) def main():
module = AnsibleModule(
argument_spec = dict(
dest=dict(required=True),
repo=dict(required=True),
version=dict(default='HEAD'),
remote=dict(default='origin')
)
)
# if there is no git configuration, do a clone operation dest = module.params['dest']
# else pull and switch the version repo = module.params['repo']
version = module.params['version']
remote = module.params['remote']
before = None gitconfig = os.path.join(dest, '.git', 'config')
if not os.path.exists(gitconfig):
(rc, out, err) = clone(repo, dest)
if rc != 0:
fail_json(out=out, err=err, rc=rc)
else:
# else do a pull
before = get_version(dest)
(rc, out, err) = reset(dest)
if rc != 0:
fail_json(out=out, err=err, rc=rc)
(rc, out, err) = pull(repo, dest, version)
# handle errors from clone or pull out, err, status = (None, None, None)
if out.find('error') != -1 or err.find('ERROR') != -1: # if there is no git configuration, do a clone operation
fail_json(out=out, err=err) # else pull and switch the version
before = None
if not os.path.exists(gitconfig):
(rc, out, err) = clone(repo, dest)
if rc != 0:
module.fail_json(out=out, err=err, rc=rc)
else:
# else do a pull
before = get_version(dest)
(rc, out, err) = reset(dest)
if rc != 0:
module.fail_json(out=out, err=err, rc=rc)
(rc, out, err) = pull(module, repo, dest, version)
# switch to version specified regardless of whether # handle errors from clone or pull
# we cloned or pulled if out.find('error') != -1 or err.find('ERROR') != -1:
module.fail_json(out=out, err=err)
(rc, out, err) = switch_version(dest, remote, version) # switch to version specified regardless of whether
if err.find('error') != -1: # we cloned or pulled
fail_json(out=out, err=err) (rc, out, err) = switch_version(module, dest, remote, version)
if err.find('error') != -1:
module.fail_json(out=out, err=err)
# determine if we changed anything # determine if we changed anything
after = get_version(dest)
changed = False
after = get_version(dest) if before != after:
changed = False changed = True
if before != after: module.exit_json(changed=changed, before=before, after=after)
changed = True
exit_json(changed=changed, before=before, after=after) # include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()