blob: 0c8e51f12e2b68724249a0e02bba0afc24bf4d03 [file] [log] [blame]
Kuang-che Wue41e0062017-09-01 19:04:14 +08001# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""Git utility."""
5
6from __future__ import print_function
7import logging
8import re
9import subprocess
10
11from bisect_kit import cli
12from bisect_kit import util
13
14logger = logging.getLogger(__name__)
15
16GIT_FULL_COMMIT_ID_LENGTH = 40
17
18# Minimal acceptable length of git commit id.
19#
20# For chromium, hash collision rate over number of digits:
21# - 6 digits: 4.85%
22# - 7 digits: 0.32%
23# - 8 digits: 0.01%
24# As foolproof check, 7 digits should be enough.
25GIT_MIN_COMMIT_ID_LENGTH = 7
26
27
28def is_git_rev(s):
29 """Is a git hash-like version string.
30
31 It accepts shortened hash with at least 7 digits.
32 """
33 if not GIT_MIN_COMMIT_ID_LENGTH <= len(s) <= GIT_FULL_COMMIT_ID_LENGTH:
34 return False
35 return bool(re.match(r'^[0-9a-f]+$', s))
36
37
38def argtype_git_rev(s):
39 """Validates git hash."""
40 if not is_git_rev(s):
41 msg = 'should be git hash, at least %d digits' % GIT_MIN_COMMIT_ID_LENGTH
42 raise cli.ArgTypeError(msg, '1a2b3c4d5e')
43 return s
44
45
46def checkout_version(git_repo, rev):
47 """git checkout.
48
49 Args:
50 git_repo: path of git repo.
51 rev: git commit revision to checkout.
52 """
53 util.check_call('git', 'checkout', '-q', '-f', rev, cwd=git_repo)
54
55
56def is_containing_commit(git_repo, rev):
57 """Determines given commit exists.
58
59 Args:
60 git_repo: path of git repo.
61 rev: git commit revision in query.
62 """
63 try:
64 return util.check_output(
65 'git', 'cat-file', '-t', rev, cwd=git_repo) == 'commit\n'
66 except subprocess.CalledProcessError:
67 return False
68
69
70def get_revlist(git_repo, old, new):
71 """Enumerates git commit between two revisions (inclusive).
72
73 Args:
74 git_repo: path of git repo.
75 old: git commit revision.
76 new: git commit revision.
77
78 Returns:
79 list of git revisions. The list contains the input revisions, old and new.
80 """
81 assert old
82 assert new
83 cmd = ['git', 'rev-list', '--reverse', '%s^..%s' % (old, new)]
84 revlist = util.check_output(*cmd, cwd=git_repo).splitlines()
85 return revlist
Kuang-che Wue2563ea2018-01-05 20:30:28 +080086
87
88def get_commit_log(git_repo, rev):
89 """Get git commit log.
90
91 Args:
92 git_repo: path of git repo.
93 rev: git commit revision.
94
95 Returns:
96 commit log message
97 """
98 cmd = ['git', 'log', '-1', '--format=%B', rev]
99 msg = util.check_output(*cmd, cwd=git_repo)
100 return msg
101
102
103def get_commit_hash(git_root, rev):
104 """Get git commit hash.
105
106 Args:
107 git_repo: path of git repo.
108 rev: could be git tag, branch, or (shortened) commit hash
109
110 Returns:
111 full git commit hash
112 """
113 cmd = ['git', 'rev-parse', rev]
114 git_rev = util.check_output(*cmd, cwd=git_root).strip()
115 assert git_rev
116 return git_rev