File: git_tools.py

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (110 lines) | stat: -rw-r--r-- 3,756 bytes parent folder | download | duplicates (2)
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()