iris: Add support for serialized NIR
[mesa.git] / bin / commit_in_branch.py
1 #!/usr/bin/env python3
2
3 import argparse
4 import subprocess
5 import sys
6
7
8 def print_(args: argparse.Namespace, success: bool, message: str) -> None:
9 """
10 Print function with extra coloring when supported and/or requested,
11 and with a "quiet" switch
12 """
13
14 COLOR_SUCCESS = '\033[32m'
15 COLOR_FAILURE = '\033[31m'
16 COLOR_RESET = '\033[0m'
17
18 if args.quiet:
19 return
20
21 if args.color == 'auto':
22 use_colors = sys.stdout.isatty()
23 else:
24 use_colors = args.color == 'always'
25
26 s = ''
27 if use_colors:
28 if success:
29 s += COLOR_SUCCESS
30 else:
31 s += COLOR_FAILURE
32
33 s += message
34
35 if use_colors:
36 s += COLOR_RESET
37
38 print(s)
39
40
41 def is_commit_valid(commit: str) -> bool:
42 ret = subprocess.call(['git', 'cat-file', '-e', commit],
43 stdout=subprocess.DEVNULL,
44 stderr=subprocess.DEVNULL)
45 return ret == 0
46
47
48 def branch_has_commit(upstream: str, branch: str, commit: str) -> bool:
49 """
50 Returns True if the commit is actually present in the branch
51 """
52 ret = subprocess.call(['git', 'merge-base', '--is-ancestor',
53 commit, upstream + '/' + branch],
54 stdout=subprocess.DEVNULL,
55 stderr=subprocess.DEVNULL)
56 return ret == 0
57
58
59 def branch_has_backport_of_commit(upstream: str, branch: str, commit: str) -> str:
60 """
61 Returns the commit hash if the commit has been backported to the branch,
62 or an empty string if is hasn't
63 """
64 out = subprocess.check_output(['git', 'log', '--format=%H',
65 branch + '-branchpoint..' + upstream + '/' + branch,
66 '--grep', 'cherry picked from commit ' + commit],
67 stderr=subprocess.DEVNULL)
68 return out.decode().strip()
69
70
71 def canonicalize_commit(commit: str) -> str:
72 """
73 Takes a commit-ish and returns a commit sha1 if the commit exists
74 """
75
76 # Make sure input is valid first
77 if not is_commit_valid(commit):
78 raise argparse.ArgumentTypeError('invalid commit identifier: ' + commit)
79
80 out = subprocess.check_output(['git', 'rev-parse', commit],
81 stderr=subprocess.DEVNULL)
82 return out.decode().strip()
83
84
85 def validate_branch(branch: str) -> str:
86 if '/' not in branch:
87 raise argparse.ArgumentTypeError('must be in the form `remote/branch`')
88
89 out = subprocess.check_output(['git', 'remote', '--verbose'],
90 stderr=subprocess.DEVNULL)
91 remotes = out.decode().splitlines()
92 (upstream, _) = branch.split('/')
93 valid_remote = False
94 for line in remotes:
95 if line.startswith(upstream + '\t'):
96 valid_remote = True
97
98 if not valid_remote:
99 raise argparse.ArgumentTypeError('Invalid remote: ' + upstream)
100
101 if not is_commit_valid(branch):
102 raise argparse.ArgumentTypeError('Invalid branch: ' + branch)
103
104 return branch
105
106
107 if __name__ == "__main__":
108 parser = argparse.ArgumentParser(description="""
109 Returns 0 if the commit is present in the branch,
110 1 if it's not,
111 and 2 if it couldn't be determined (eg. invalid commit)
112 """)
113 parser.add_argument('commit',
114 type=canonicalize_commit,
115 help='commit sha1')
116 parser.add_argument('branch',
117 type=validate_branch,
118 help='branch to check, in the form `remote/branch`')
119 parser.add_argument('--quiet',
120 action='store_true',
121 help='suppress all output; exit code can still be used')
122 parser.add_argument('--color',
123 choices=['auto', 'always', 'never'],
124 default='auto',
125 help='colorize output (default: true if stdout is a terminal)')
126 args = parser.parse_args()
127
128 (upstream, branch) = args.branch.split('/')
129
130 if branch_has_commit(upstream, branch, args.commit):
131 print_(args, True, 'Commit ' + args.commit + ' is in branch ' + branch)
132 exit(0)
133
134 backport = branch_has_backport_of_commit(upstream, branch, args.commit)
135 if backport:
136 print_(args, True,
137 'Commit ' + args.commit + ' was backported to branch ' + branch + ' as commit ' + backport)
138 exit(0)
139
140 print_(args, False, 'Commit ' + args.commit + ' is NOT in branch ' + branch)
141 exit(1)