From 472fc8bd779f1f6203136c09cfdf2803466398af Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Wed, 12 May 2021 18:24:04 +0300 Subject: [PATCH] Always use checkout for git_requirements library Despite git reset gets correct state of the repo `git status` will be misleading, since it will always be master with changes. Instead we should checkout to tags/branches/SHAs so that `git status` will be explicitly showing what version of the role we're using We shouldn't also fetch tags for every scenario, but only when we suspect that we need to checkout on tag. Change-Id: I1a5568487f2bb8a8c3f9affa04112ded16a17126 --- playbooks/library/git_requirements.py | 80 +++++++++++++-------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/playbooks/library/git_requirements.py b/playbooks/library/git_requirements.py index cbe39f9401..71a006b11b 100644 --- a/playbooks/library/git_requirements.py +++ b/playbooks/library/git_requirements.py @@ -85,17 +85,12 @@ def init_signal(): def check_out_version(repo, version, pull=False, force=False, - refspec=None, depth=10): + refspec=None, tag=False, depth=10): try: - repo.git.fetch(force=force, refspec=refspec, depth=depth) + repo.git.fetch(tags=tag, force=force, refspec=refspec, depth=depth) except Exception as e: return ["Failed to fetch %s\n%s" % (repo.working_dir, str(e))] - try: - repo.git.fetch(tags=True, force=force, refspec=refspec, depth=depth) - except Exception as e: - return ["Failed to fetch tags for %s\n%s" % (repo.working_dir, str(e))] - try: repo.git.checkout(version, force=force) except Exception as e: @@ -103,6 +98,14 @@ def check_out_version(repo, version, pull=False, force=False, "Failed to check out version %s for %s\n%s" % (version, repo.working_dir, str(e))] + if repo.is_dirty(untracked_files=True) and force: + try: + repo.git.clean(force=force) + except Exception as e: + return [ + "Failed to clean up repository% s\n%s" % + (repo.working_dir, str(e))] + if pull: try: repo.git.pull(force=force, refspec=refspec, depth=depth) @@ -111,23 +114,6 @@ def check_out_version(repo, version, pull=False, force=False, return [] -def reset_to_version(path, version, reset_type='--hard', force=False, - refspec=None, depth=10): - """Function to reset to a specific hash commit""" - modify_repo = git.Repo(path) - try: - modify_repo.git.fetch(force=force, refspec=refspec, depth=depth) - except Exception as e: - return ["Failed to fetch %s\n%s" % (modify_repo.working_dir, str(e))] - - try: - modify_repo.git.reset(reset_type, version, refspec=refspec) - except Exception as e: - return ["Failed to reset %s\n%s" % (modify_repo.working_dir, str(e))] - - return [] - - def pull_wrapper(info): role_info = info retries = info[1]["retries"] @@ -153,17 +139,21 @@ def pull_role(info): if len(required_version) == 40: version_hash = True - # if repo exists - if os.path.exists(role["dest"]): + def get_repo(dest): try: - repo = git.Repo(role["dest"]) + return git.Repo(dest) except Exception: failtxt = "Role in {0} is broken/not a git repo.".format( role["dest"]) failtxt += "Please delete or fix it manually" failures.append(failtxt) - return False # go to next role + return False + # if repo exists + if os.path.exists(role["dest"]): + repo = get_repo(role["dest"]) + if not repo: + return False # go to next role repo_url = list(repo.remote().urls)[0] if repo_url != role["src"]: repo.remote().set_url(role["src"]) @@ -178,11 +168,10 @@ def pull_role(info): # If we have a hash then reset it to elif version_hash: - fail = reset_to_version(role["dest"], - required_version, - force=config["force"], - refspec=role["refspec"], - depth=role["depth"]) + fail = check_out_version(repo, required_version, + force=config["force"], + refspec=role["refspec"], + depth=role["depth"]) else: # describe can fail in some cases so be careful: try: @@ -196,25 +185,30 @@ def pull_role(info): fail = check_out_version(repo, required_version, force=config["force"], refspec=role["refspec"], - depth=role["depth"]) + depth=role["depth"], + tag=True) else: try: # If we have a hash id then treat this a little differently - if not version_hash: + if version_hash: + git.Repo.clone_from(role["src"], role["dest"], + branch='master', + no_single_branch=True, + depth=role["depth"]) + repo = get_repo(role["dest"]) + if not repo: + return False # go to next role + fail = check_out_version(repo, required_version, + force=config["force"], + refspec=role["refspec"], + depth=role["depth"]) + else: git.Repo.clone_from(role["src"], role["dest"], branch=required_version, depth=role["depth"], no_single_branch=True) fail = [] - else: - git.Repo.clone_from(role["src"], role["dest"], - branch='master', - no_single_branch=True, - depth=role["depth"]) - fail = reset_to_version(role["dest"], required_version, - refspec=role["refspec"], - depth=role["depth"]) except Exception as e: fail = ('Failed cloning repo %s\n%s' % (role["dest"], str(e)))