summaryrefslogtreecommitdiffstats
path: root/test/runner/lib/git.py
blob: f195f9596391d55134f749ff7c883804bec6268c (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Wrapper around git command-line tools."""

from __future__ import absolute_import, print_function

try:
    # noinspection PyUnresolvedReferences
    from typing import (
        Optional,
    )
except ImportError:
    pass

from lib.util import (
    SubprocessError,
    raw_command,
)


class Git(object):
    """Wrapper around git command-line tools."""
    def __init__(self, root=None):  # type: (Optional[str]) -> None
        self.git = 'git'
        self.root = root

    def get_diff(self, args, git_options=None):
        """
        :type args: list[str]
        :type git_options: list[str] | None
        :rtype: list[str]
        """
        cmd = ['diff'] + args
        if git_options is None:
            git_options = ['-c', 'core.quotePath=']
        return self.run_git_split(git_options + cmd, '\n', str_errors='replace')

    def get_diff_names(self, args):
        """
        :type args: list[str]
        :rtype: list[str]
        """
        cmd = ['diff', '--name-only', '--no-renames', '-z'] + args
        return self.run_git_split(cmd, '\0')

    def get_file_names(self, args):
        """
        :type args: list[str]
        :rtype: list[str]
        """
        cmd = ['ls-files', '-z'] + args
        return self.run_git_split(cmd, '\0')

    def get_branches(self):
        """
        :rtype: list[str]
        """
        cmd = ['for-each-ref', 'refs/heads/', '--format', '%(refname:strip=2)']
        return self.run_git_split(cmd)

    def get_branch(self):
        """
        :rtype: str
        """
        cmd = ['symbolic-ref', '--short', 'HEAD']
        return self.run_git(cmd).strip()

    def get_rev_list(self, commits=None, max_count=None):
        """
        :type commits: list[str] | None
        :type max_count: int | None
        :rtype: list[str]
        """
        cmd = ['rev-list']

        if commits:
            cmd += commits
        else:
            cmd += ['HEAD']

        if max_count:
            cmd += ['--max-count', '%s' % max_count]

        return self.run_git_split(cmd)

    def get_branch_fork_point(self, branch):
        """
        :type branch: str
        :rtype: str
        """
        cmd = ['merge-base', '--fork-point', branch]
        return self.run_git(cmd).strip()

    def is_valid_ref(self, ref):
        """
        :type ref: str
        :rtype: bool
        """
        cmd = ['show', ref]
        try:
            self.run_git(cmd, str_errors='replace')
            return True
        except SubprocessError:
            return False

    def run_git_split(self, cmd, separator=None, str_errors='strict'):
        """
        :type cmd: list[str]
        :type separator: str | None
        :type str_errors: str
        :rtype: list[str]
        """
        output = self.run_git(cmd, str_errors=str_errors).strip(separator)

        if not output:
            return []

        return output.split(separator)

    def run_git(self, cmd, str_errors='strict'):
        """
        :type cmd: list[str]
        :type str_errors: str
        :rtype: str
        """
        return raw_command([self.git] + cmd, cwd=self.root, capture=True, str_errors=str_errors)[0]