From 09b06a601c22d9ca3cbbb90a3da7bc3d6809139e Mon Sep 17 00:00:00 2001 From: Rob Cutmore Date: Fri, 12 Aug 2016 09:53:06 -0400 Subject: [PATCH] Git: Determine if remote URL is being changed (#4243) * Git: Determine if remote URL is being changed Ansible reported there were no changes when only the remote URL for a repo was changed. This properly tracks and reports when the remote URL for a repo changes. Fixes #4006 * Fix handling of local repo paths * Git: Use newer method for fetching remote URL * Git: use ls-remote to fetch remote URL Using ls-remote to fetch remote URL is supported in earlier versions of Git compared to using remote command. * Maintain previous behavior for older Git versions Previously whether or not the remote URL changed was not factored into command's changed status. Git versions prior to 1.7.5 lack the functionality used for fetching a repo's remote URL so these versions will update the remote URL without affecting the changed status. --- lib/ansible/modules/source_control/git.py | 44 +++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/ansible/modules/source_control/git.py b/lib/ansible/modules/source_control/git.py index 1e9b89df079..c3d09c6421a 100644 --- a/lib/ansible/modules/source_control/git.py +++ b/lib/ansible/modules/source_control/git.py @@ -206,6 +206,7 @@ EXAMPLES = ''' import re import tempfile +from ansible.utils.path import unfrackpath from distutils.version import LooseVersion def get_submodule_update_params(module, git_path, cwd): @@ -521,14 +522,32 @@ def get_head_branch(git_path, module, dest, remote, bare=False): f.close() return branch +def get_remote_url(git_path, module, dest, remote): + '''Return URL of remote source for repo.''' + command = [git_path, 'ls-remote', '--get-url', remote] + (rc, out, err) = module.run_command(command, cwd=dest) + if rc != 0: + # There was an issue getting remote URL, most likely + # command is not available in this version of Git. + return None + return out.rstrip('\n') + def set_remote_url(git_path, module, repo, dest, remote): ''' updates repo from remote sources ''' - commands = [("set a new url %s for %s" % (repo, remote), [git_path, 'remote', 'set-url', remote, repo])] + # Return if remote URL isn't changing. + remote_url = get_remote_url(git_path, module, dest, remote) + if remote_url == repo or remote_url == unfrackpath(repo): + return False - for (label,command) in commands: - (rc,out,err) = module.run_command(command, cwd=dest) - if rc != 0: - module.fail_json(msg="Failed to %s: %s %s" % (label, out, err)) + command = [git_path, 'remote', 'set-url', remote, repo] + (rc, out, err) = module.run_command(command, cwd=dest) + if rc != 0: + label = "set a new url %s for %s" % (repo, remote) + module.fail_json(msg="Failed to %s: %s %s" % (label, out, err)) + + # Return False if remote_url is None to maintain previous bevhavior + # for Git versions prior to 1.7.5 that lack required functionality. + return remote_url is not None def fetch(git_path, module, repo, dest, version, remote, depth, bare, refspec): ''' updates repo from remote sources ''' @@ -859,7 +878,14 @@ def main(): reset(git_path, module, dest) # exit if already at desired sha version - set_remote_url(git_path, module, repo, dest, remote) + if module.check_mode: + remote_url = get_remote_url(git_path, module, dest, remote) + remote_url_changed = remote_url and remote_url != repo and remote_url != unfrackpath(repo) + else: + remote_url_changed = set_remote_url(git_path, module, repo, dest, remote) + if remote_url_changed: + result.update(remote_url_changed=True) + remote_head = get_remote_head(git_path, module, dest, version, remote, bare) if result['before'] == remote_head: if local_mods: @@ -908,9 +934,7 @@ def main(): if module.check_mode: if submodules_updated: result.update(changed=True, after=remote_head) - else: - result.update(changed=False, after=remote_head) - module.exit_json(**result) + module.exit_json(**result) if submodules_updated: # Switch to version specified @@ -920,7 +944,7 @@ def main(): result['after'] = get_version(module, git_path, dest) result.update(changed=False) - if result['before'] != result['after'] or local_mods or submodules_updated: + if result['before'] != result['after'] or local_mods or submodules_updated or remote_url_changed: result.update(changed=True) if module._diff: diff = get_diff(module, git_path, dest, repo, remote, depth, bare, result['before'], result['after'])