diff options
author | André Draszik <andre.draszik@linaro.org> | 2024-02-16 16:25:01 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-02-19 12:00:59 +0000 |
commit | e6892bc47a5aa52ab640d74cf4729fe52c46fd81 (patch) | |
tree | 004c1245a483ab6f25fba880d7022464e59ecc7f | |
parent | 577e73606acc34263d1e1eb1c76e2794d77a86cb (diff) | |
download | poky-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-x | bitbake/bin/git-make-shallow | 34 |
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") | |||
24 | version = 1.0 | 24 | version = 1.0 |
25 | 25 | ||
26 | 26 | ||
27 | git_cmd = ['git', '-c', 'safe.bareRepository=all'] | ||
28 | |||
27 | def main(): | 29 | def 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 | ||
61 | def process_args(): | 63 | def 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 | ||
96 | def get_all_refs(ref_filter=None): | 98 | def 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 | ||
160 | def shrink_repo(git_dir): | 162 | def 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 | ||
172 | if __name__ == '__main__': | 174 | if __name__ == '__main__': |