summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndré Draszik <andre.draszik@linaro.org>2024-02-16 16:25:01 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-02-19 12:00:59 +0000
commite6892bc47a5aa52ab640d74cf4729fe52c46fd81 (patch)
tree004c1245a483ab6f25fba880d7022464e59ecc7f
parent577e73606acc34263d1e1eb1c76e2794d77a86cb (diff)
downloadpoky-e6892bc47a5aa52ab640d74cf4729fe52c46fd81.tar.gz
bitbake: git-make-shallow: support git's safe.bareRepository
When git is configured with safe.bareRepository=explicit [1], the git-make-shallow fails miserably. LWN has an article about the problem that this configuration option addresses and why it is useful in [2]. It also seems that it is being rolled out in some environments as a default for users. In order to allow having this configuration turned on for a user's environment in general, the fetcher has to be tought to use --git-dir= for all relevent git operations. The alternative, implemented here, is to forcibly turn off that option for all git operations. In the future, we could look into converting these to using the --git-dir= command line argument instead. Link: https://git.kernel.org/pub/scm/git/git.git/tree/Documentation/config/safe.txt#n1 [1] Link: https://lwn.net/Articles/892755/ [2] (Bitbake rev: 7c63989db4590564516ed150930f4e2fa503e98f) Signed-off-by: André Draszik <andre.draszik@linaro.org> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rwxr-xr-xbitbake/bin/git-make-shallow34
1 files changed, 18 insertions, 16 deletions
diff --git a/bitbake/bin/git-make-shallow b/bitbake/bin/git-make-shallow
index d0532c5ab8..9de557c10e 100755
--- a/bitbake/bin/git-make-shallow
+++ b/bitbake/bin/git-make-shallow
@@ -24,15 +24,17 @@ warnings.simplefilter("default")
24version = 1.0 24version = 1.0
25 25
26 26
27git_cmd = ['git', '-c', 'safe.bareRepository=all']
28
27def main(): 29def main():
28 if sys.version_info < (3, 4, 0): 30 if sys.version_info < (3, 4, 0):
29 sys.exit('Python 3.4 or greater is required') 31 sys.exit('Python 3.4 or greater is required')
30 32
31 git_dir = check_output(['git', 'rev-parse', '--git-dir']).rstrip() 33 git_dir = check_output(git_cmd + ['rev-parse', '--git-dir']).rstrip()
32 shallow_file = os.path.join(git_dir, 'shallow') 34 shallow_file = os.path.join(git_dir, 'shallow')
33 if os.path.exists(shallow_file): 35 if os.path.exists(shallow_file):
34 try: 36 try:
35 check_output(['git', 'fetch', '--unshallow']) 37 check_output(git_cmd + ['fetch', '--unshallow'])
36 except subprocess.CalledProcessError: 38 except subprocess.CalledProcessError:
37 try: 39 try:
38 os.unlink(shallow_file) 40 os.unlink(shallow_file)
@@ -41,21 +43,21 @@ def main():
41 raise 43 raise
42 44
43 args = process_args() 45 args = process_args()
44 revs = check_output(['git', 'rev-list'] + args.revisions).splitlines() 46 revs = check_output(git_cmd + ['rev-list'] + args.revisions).splitlines()
45 47
46 make_shallow(shallow_file, args.revisions, args.refs) 48 make_shallow(shallow_file, args.revisions, args.refs)
47 49
48 ref_revs = check_output(['git', 'rev-list'] + args.refs).splitlines() 50 ref_revs = check_output(git_cmd + ['rev-list'] + args.refs).splitlines()
49 remaining_history = set(revs) & set(ref_revs) 51 remaining_history = set(revs) & set(ref_revs)
50 for rev in remaining_history: 52 for rev in remaining_history:
51 if check_output(['git', 'rev-parse', '{}^@'.format(rev)]): 53 if check_output(git_cmd + ['rev-parse', '{}^@'.format(rev)]):
52 sys.exit('Error: %s was not made shallow' % rev) 54 sys.exit('Error: %s was not made shallow' % rev)
53 55
54 filter_refs(args.refs) 56 filter_refs(args.refs)
55 57
56 if args.shrink: 58 if args.shrink:
57 shrink_repo(git_dir) 59 shrink_repo(git_dir)
58 subprocess.check_call(['git', 'fsck', '--unreachable']) 60 subprocess.check_call(git_cmd + ['fsck', '--unreachable'])
59 61
60 62
61def process_args(): 63def process_args():
@@ -72,12 +74,12 @@ def process_args():
72 args = parser.parse_args() 74 args = parser.parse_args()
73 75
74 if args.refs: 76 if args.refs:
75 args.refs = check_output(['git', 'rev-parse', '--symbolic-full-name'] + args.refs).splitlines() 77 args.refs = check_output(git_cmd + ['rev-parse', '--symbolic-full-name'] + args.refs).splitlines()
76 else: 78 else:
77 args.refs = get_all_refs(lambda r, t, tt: t == 'commit' or tt == 'commit') 79 args.refs = get_all_refs(lambda r, t, tt: t == 'commit' or tt == 'commit')
78 80
79 args.refs = list(filter(lambda r: not r.endswith('/HEAD'), args.refs)) 81 args.refs = list(filter(lambda r: not r.endswith('/HEAD'), args.refs))
80 args.revisions = check_output(['git', 'rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines() 82 args.revisions = check_output(git_cmd + ['rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines()
81 return args 83 return args
82 84
83 85
@@ -95,7 +97,7 @@ def make_shallow(shallow_file, revisions, refs):
95 97
96def get_all_refs(ref_filter=None): 98def get_all_refs(ref_filter=None):
97 """Return all the existing refs in this repository, optionally filtering the refs.""" 99 """Return all the existing refs in this repository, optionally filtering the refs."""
98 ref_output = check_output(['git', 'for-each-ref', '--format=%(refname)\t%(objecttype)\t%(*objecttype)']) 100 ref_output = check_output(git_cmd + ['for-each-ref', '--format=%(refname)\t%(objecttype)\t%(*objecttype)'])
99 ref_split = [tuple(iter_extend(l.rsplit('\t'), 3)) for l in ref_output.splitlines()] 101 ref_split = [tuple(iter_extend(l.rsplit('\t'), 3)) for l in ref_output.splitlines()]
100 if ref_filter: 102 if ref_filter:
101 ref_split = (e for e in ref_split if ref_filter(*e)) 103 ref_split = (e for e in ref_split if ref_filter(*e))
@@ -113,7 +115,7 @@ def filter_refs(refs):
113 all_refs = get_all_refs() 115 all_refs = get_all_refs()
114 to_remove = set(all_refs) - set(refs) 116 to_remove = set(all_refs) - set(refs)
115 if to_remove: 117 if to_remove:
116 check_output(['xargs', '-0', '-n', '1', 'git', 'update-ref', '-d', '--no-deref'], 118 check_output(['xargs', '-0', '-n', '1'] + git_cmd + ['update-ref', '-d', '--no-deref'],
117 input=''.join(l + '\0' for l in to_remove)) 119 input=''.join(l + '\0' for l in to_remove))
118 120
119 121
@@ -126,7 +128,7 @@ def follow_history_intersections(revisions, refs):
126 if rev in seen: 128 if rev in seen:
127 continue 129 continue
128 130
129 parents = check_output(['git', 'rev-parse', '%s^@' % rev]).splitlines() 131 parents = check_output(git_cmd + ['rev-parse', '%s^@' % rev]).splitlines()
130 132
131 yield rev 133 yield rev
132 seen.add(rev) 134 seen.add(rev)
@@ -134,12 +136,12 @@ def follow_history_intersections(revisions, refs):
134 if not parents: 136 if not parents:
135 continue 137 continue
136 138
137 check_refs = check_output(['git', 'merge-base', '--independent'] + sorted(refs)).splitlines() 139 check_refs = check_output(git_cmd + ['merge-base', '--independent'] + sorted(refs)).splitlines()
138 for parent in parents: 140 for parent in parents:
139 for ref in check_refs: 141 for ref in check_refs:
140 print("Checking %s vs %s" % (parent, ref)) 142 print("Checking %s vs %s" % (parent, ref))
141 try: 143 try:
142 merge_base = check_output(['git', 'merge-base', parent, ref]).rstrip() 144 merge_base = check_output(git_cmd + ['merge-base', parent, ref]).rstrip()
143 except subprocess.CalledProcessError: 145 except subprocess.CalledProcessError:
144 continue 146 continue
145 else: 147 else:
@@ -159,14 +161,14 @@ def iter_except(func, exception, start=None):
159 161
160def shrink_repo(git_dir): 162def shrink_repo(git_dir):
161 """Shrink the newly shallow repository, removing the unreachable objects.""" 163 """Shrink the newly shallow repository, removing the unreachable objects."""
162 subprocess.check_call(['git', 'reflog', 'expire', '--expire-unreachable=now', '--all']) 164 subprocess.check_call(git_cmd + ['reflog', 'expire', '--expire-unreachable=now', '--all'])
163 subprocess.check_call(['git', 'repack', '-ad']) 165 subprocess.check_call(git_cmd + ['repack', '-ad'])
164 try: 166 try:
165 os.unlink(os.path.join(git_dir, 'objects', 'info', 'alternates')) 167 os.unlink(os.path.join(git_dir, 'objects', 'info', 'alternates'))
166 except OSError as exc: 168 except OSError as exc:
167 if exc.errno != errno.ENOENT: 169 if exc.errno != errno.ENOENT:
168 raise 170 raise
169 subprocess.check_call(['git', 'prune', '--expire', 'now']) 171 subprocess.check_call(git_cmd + ['prune', '--expire', 'now'])
170 172
171 173
172if __name__ == '__main__': 174if __name__ == '__main__':