blob: 426406bd42209597a15f4f473c71a14430b885d8 [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