Add diff mode support to git module (#3364)

* Add diffmode support to git module

This patch adds missing diffmode support to the git module.

* Remodel get_diff() and calls to it

As proposed by @abadger

* Ensure we fetch the required object before performing a diff

Also we handle the return code ourselves, so don't leave this up to run_command().
reviewable/pr18780/r1
Dag Wieers 8 years ago committed by jctanner
parent 23ebb98570
commit f5f1ec65e4

@ -375,6 +375,25 @@ def reset(git_path, module, dest):
cmd = "%s reset --hard HEAD" % (git_path,) cmd = "%s reset --hard HEAD" % (git_path,)
return module.run_command(cmd, check_rc=True, cwd=dest) return module.run_command(cmd, check_rc=True, cwd=dest)
def get_diff(module, git_path, dest, repo, remote, depth, bare, before, after):
''' Return the difference between 2 versions '''
if before == None:
return { 'prepared': '>> Newly checked out %s' % after }
elif before != after:
# Ensure we have the object we are referring to during git diff !
fetch(git_path, module, repo, dest, after, remote, depth, bare, '')
cmd = '%s diff %s %s' % (git_path, before, after)
(rc, out, err) = module.run_command(cmd, cwd=dest)
if rc == 0 and out:
return { 'prepared': out }
elif rc == 0:
return { 'prepared': '>> No visual differences between %s and %s' % (before, after) }
elif err:
return { 'prepared': '>> Failed to get proper diff between %s and %s:\n>> %s' % (before, after, err) }
else:
return { 'prepared': '>> Failed to get proper diff between %s and %s' % (before, after) }
return {}
def get_remote_head(git_path, module, dest, version, remote, bare): def get_remote_head(git_path, module, dest, version, remote, bare):
cloning = False cloning = False
cwd = None cwd = None
@ -761,8 +780,7 @@ def main():
key_file = module.params['key_file'] key_file = module.params['key_file']
ssh_opts = module.params['ssh_opts'] ssh_opts = module.params['ssh_opts']
return_values = {} result = dict( warnings=list() )
return_values['warnings'] = []
# We screenscrape a huge amount of git commands so use C locale anytime we # We screenscrape a huge amount of git commands so use C locale anytime we
# call run_command() # call run_command()
@ -796,13 +814,13 @@ def main():
git_version_used = git_version(git_path, module) git_version_used = git_version(git_path, module)
if depth is not None and git_version_used < LooseVersion('1.9.1'): if depth is not None and git_version_used < LooseVersion('1.9.1'):
return_values['warnings'].append("Your git version is too old to fully support the depth argument. Falling back to full checkouts.") result['warnings'].append("Your git version is too old to fully support the depth argument. Falling back to full checkouts.")
depth = None depth = None
recursive = module.params['recursive'] recursive = module.params['recursive']
track_submodules = module.params['track_submodules'] track_submodules = module.params['track_submodules']
before = None result.update(before=None)
local_mods = False local_mods = False
repo_updated = None repo_updated = None
if (dest and not os.path.exists(gitconfig)) or (not dest and not allow_clone): if (dest and not os.path.exists(gitconfig)) or (not dest and not allow_clone):
@ -812,7 +830,12 @@ def main():
# In those cases we do an ls-remote # In those cases we do an ls-remote
if module.check_mode or not allow_clone: if module.check_mode or not allow_clone:
remote_head = get_remote_head(git_path, module, dest, version, repo, bare) remote_head = get_remote_head(git_path, module, dest, version, repo, bare)
module.exit_json(changed=True, before=before, after=remote_head, **return_values) result.update(changed=True, after=remote_head)
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
if diff:
result['diff'] = diff
module.exit_json(**result)
# there's no git config, so clone # there's no git config, so clone
clone(git_path, module, repo, dest, remote, depth, version, bare, reference, refspec, verify_commit) clone(git_path, module, repo, dest, remote, depth, version, bare, reference, refspec, verify_commit)
repo_updated = True repo_updated = True
@ -820,16 +843,17 @@ def main():
# Just return having found a repo already in the dest path # Just return having found a repo already in the dest path
# this does no checking that the repo is the actual repo # this does no checking that the repo is the actual repo
# requested. # requested.
before = get_version(module, git_path, dest) result['before'] = get_version(module, git_path, dest)
module.exit_json(changed=False, before=before, after=before, **return_values) result.update(changed=False, after=result['before'])
module.exit_json(**result)
else: else:
# else do a pull # else do a pull
local_mods = has_local_mods(module, git_path, dest, bare) local_mods = has_local_mods(module, git_path, dest, bare)
before = get_version(module, git_path, dest) result['before'] = get_version(module, git_path, dest)
if local_mods: if local_mods:
# failure should happen regardless of check mode # failure should happen regardless of check mode
if not force: if not force:
module.fail_json(msg="Local modifications exist in repository (force=no).", **return_values) module.fail_json(msg="Local modifications exist in repository (force=no).", **result)
# if force and in non-check mode, do a reset # if force and in non-check mode, do a reset
if not module.check_mode: if not module.check_mode:
reset(git_path, module, dest) reset(git_path, module, dest)
@ -837,10 +861,14 @@ def main():
# exit if already at desired sha version # exit if already at desired sha version
set_remote_url(git_path, module, repo, dest, remote) set_remote_url(git_path, module, repo, dest, remote)
remote_head = get_remote_head(git_path, module, dest, version, remote, bare) remote_head = get_remote_head(git_path, module, dest, version, remote, bare)
if before == remote_head: if result['before'] == remote_head:
if local_mods: if local_mods:
module.exit_json(changed=True, before=before, after=remote_head, result.update(changed=True, after=remote_head, msg='Local modifications exist')
msg="Local modifications exist", **return_values) if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
if diff:
result['diff'] = diff
module.exit_json(**result)
elif version == 'HEAD': elif version == 'HEAD':
# If the remote and local match and we're using the default of # If the remote and local match and we're using the default of
# HEAD (It's not a real tag) then exit early # HEAD (It's not a real tag) then exit early
@ -856,7 +884,12 @@ def main():
if repo_updated is None: if repo_updated is None:
if module.check_mode: if module.check_mode:
module.exit_json(changed=True, before=before, after=remote_head, **return_values) result.update(changed=(result['before']!=remote_head), after=remote_head)
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
if diff:
result['diff'] = diff
module.exit_json(**result)
fetch(git_path, module, repo, dest, version, remote, depth, bare, refspec) fetch(git_path, module, repo, dest, version, remote, depth, bare, refspec)
repo_updated = True repo_updated = True
@ -872,20 +905,25 @@ def main():
if module.check_mode: if module.check_mode:
if submodules_updated: if submodules_updated:
module.exit_json(changed=True, before=before, after=remote_head, submodules_changed=True, **return_values) result.update(changed=True, after=remote_head, submodules_changed=True)
else: else:
module.exit_json(changed=False, before=before, after=remote_head, **return_values) result.update(changed=False, after=remote_head)
module.exit_json(**result)
if submodules_updated: if submodules_updated:
# Switch to version specified # Switch to version specified
submodule_update(git_path, module, dest, track_submodules) submodule_update(git_path, module, dest, track_submodules)
# determine if we changed anything # determine if we changed anything
after = get_version(module, git_path, dest) result['after'] = get_version(module, git_path, dest)
changed = False result.update(changed=False)
if before != after or local_mods or submodules_updated: if result['before'] != result['after'] or local_mods or submodules_updated:
changed = True result.update(changed=True)
if module._diff:
diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])
if diff:
result['diff'] = diff
# cleanup the wrapper script # cleanup the wrapper script
if ssh_wrapper: if ssh_wrapper:
@ -895,7 +933,7 @@ def main():
# No need to fail if the file already doesn't exist # No need to fail if the file already doesn't exist
pass pass
module.exit_json(changed=changed, before=before, after=after, **return_values) module.exit_json(**result)
# import module snippets # import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *

Loading…
Cancel
Save