1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
"""Pure git tools for managing local folder Git.
"""
import logging
from git import Repo, GitCommandError
_LOGGER = logging.getLogger(__name__)
def checkout_and_create_branch(repo, name):
"""Checkout branch. Create it if necessary"""
local_branch = repo.branches[name] if name in repo.branches else None
if not local_branch:
if name in repo.remotes.origin.refs:
# If origin branch exists but not local, git.checkout is the fatest way
# to create local branch with origin link automatically
msg = repo.git.checkout(name)
_LOGGER.debug(msg)
return
# Create local branch, will be link to origin later
local_branch = repo.create_head(name)
local_branch.checkout()
def checkout_create_push_branch(repo, name):
"""Checkout this branch. Create it if necessary, and push it to origin."""
try:
repo.git.checkout(name)
_LOGGER.info("Checkout %s success", name)
except GitCommandError:
_LOGGER.info("Checkout %s was impossible (branch does not exist). Creating it and push it.", name)
checkout_and_create_branch(repo, name)
repo.git.push("origin", name, set_upstream=True)
def do_commit(repo, message_template, branch_name, hexsha):
"Do a commit if modified/untracked files"
repo.git.add(repo.working_tree_dir)
if not repo.git.diff(staged=True):
_LOGGER.warning("No modified files in this Autorest run")
return False
checkout_and_create_branch(repo, branch_name)
msg = message_template.format(hexsha=hexsha)
commit = repo.index.commit(msg)
_LOGGER.info("Commit done: %s", msg)
return commit.hexsha
def get_repo_hexsha(git_folder):
"""Get the SHA1 of the current repo"""
repo = Repo(str(git_folder))
if repo.bare:
not_git_hexsha = "notgitrepo"
_LOGGER.warning("Not a git repo, SHA1 used will be: %s", not_git_hexsha)
return not_git_hexsha
hexsha = repo.head.commit.hexsha
_LOGGER.info("Found REST API repo SHA1: %s", hexsha)
return hexsha
def checkout_with_fetch(git_folder, refspec, repository="origin"):
"""Fetch the refspec, and checkout FETCH_HEAD.
Beware that you will ne in detached head mode.
"""
_LOGGER.info("Trying to fetch and checkout %s", refspec)
repo = Repo(str(git_folder))
repo.git.fetch(repository, refspec) # FETCH_HEAD should be set
repo.git.checkout("FETCH_HEAD")
_LOGGER.info("Fetch and checkout success for %s", refspec)
def clone_to_path(https_authenticated_url, folder, branch_or_commit=None):
"""Clone the given URL to the folder.
:param str branch_or_commit: If specified, switch to this branch. Branch must exist.
"""
_LOGGER.info("Cloning repo")
repo = Repo.clone_from(https_authenticated_url, str(folder))
# Do NOT clone and set branch at the same time, since we allow branch to be a SHA1
# And you can't clone a SHA1
if branch_or_commit:
_LOGGER.info("Checkout branch_or_commit %s", branch_or_commit)
repo.git.checkout(branch_or_commit)
_LOGGER.info("Clone success")
def get_files_in_commit(git_folder, commit_id="HEAD"):
"""List of files in HEAD commit."""
repo = Repo(str(git_folder))
output = repo.git.diff("--name-only", commit_id + "^", commit_id)
return output.splitlines()
def get_diff_file_list(git_folder):
"""List of unstaged files."""
repo = Repo(str(git_folder))
output = repo.git.diff("--name-only")
return output.splitlines()
def get_add_diff_file_list(git_folder):
"""List of new files."""
repo = Repo(str(git_folder))
repo.git.add("sdk")
output = repo.git.diff("HEAD", "--name-only")
return output.splitlines()
|