Merge ~nacc/git-ubuntu:refactor-import-pristine-tarv2 into git-ubuntu:master
- Git
- lp:~nacc/git-ubuntu
- refactor-import-pristine-tarv2
- Merge into master
Status: | Merged |
---|---|
Approved by: | Nish Aravamudan |
Approved revision: | 29e03d74bfa4a708c9e0cf4a57683ea7d08dca3b |
Merge reported by: | Nish Aravamudan |
Merged at revision: | 29e03d74bfa4a708c9e0cf4a57683ea7d08dca3b |
Proposed branch: | ~nacc/git-ubuntu:refactor-import-pristine-tarv2 |
Merge into: | git-ubuntu:master |
Prerequisite: | ~nacc/git-ubuntu:refactor-before-build-2v2 |
Diff against target: |
343 lines (+204/-62) 2 files modified
gitubuntu/git_repository.py (+149/-0) gitubuntu/importer.py (+55/-62) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robie Basak | Approve | ||
Server Team CI bot | continuous-integration | Needs Fixing | |
Review via email:
|
This proposal supersedes a proposal from 2017-08-25.
Commit message
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:32ba12fd7c4
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Tests
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:76ce4ba27f3
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Tests
SUCCESS: Build
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:29e03d74bfa
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Tests
SUCCESS: Build
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Robie Basak (racb) : | # |
Preview Diff
1 | diff --git a/gitubuntu/git_repository.py b/gitubuntu/git_repository.py |
2 | index 335a14c..91b865a 100644 |
3 | --- a/gitubuntu/git_repository.py |
4 | +++ b/gitubuntu/git_repository.py |
5 | @@ -2,6 +2,7 @@ |
6 | ### XXX: is any of this data in lp already? |
7 | |
8 | import collections |
9 | +from contextlib import contextmanager |
10 | from copy import copy |
11 | from functools import lru_cache |
12 | import itertools |
13 | @@ -361,6 +362,15 @@ def test_changelog_utf8(): |
14 | class GitUbuntuChangelogError(Exception): |
15 | pass |
16 | |
17 | +class PristineTarError(Exception): |
18 | + pass |
19 | + |
20 | +class PristineTarNotFoundError(PristineTarError): |
21 | + pass |
22 | + |
23 | +class MultiplePristineTarFoundError(PristineTarError): |
24 | + pass |
25 | + |
26 | |
27 | def git_dep14_tag(version): |
28 | """Munge a version string according to taken from |
29 | @@ -469,6 +479,145 @@ class GitUbuntuRepository: |
30 | 'Initial Debian pristine-tar branch.' |
31 | ) |
32 | |
33 | + @contextmanager |
34 | + def pristine_tar_branches(self, dist, namespace='pkg', move=False): |
35 | + """Context manager wrapping pristine-tar branch manipulation |
36 | + |
37 | + In this context, the repository pristine-tar branch will point to |
38 | + the pristine-tar branch for @dist distribution in @namespace. |
39 | + If a local branch named pristine-tar exists already, it will be |
40 | + moved to a (hopefully) safe name. |
41 | + If @move is True, then the pristine-tar branch will be moved |
42 | + rather than simply started from the parameter-specified point. |
43 | + """ |
44 | + pt_branch = '%s/importer/%s/pristine-tar' % (namespace, dist) |
45 | + old_pt_branch = self.raw_repo.lookup_branch('pristine-tar') |
46 | + if old_pt_branch: |
47 | + self.git_run(['branch', '-M', 'pristine-tar', 'pristine-tar.bak']) |
48 | + cmd = ['branch'] |
49 | + if move: |
50 | + cmd.extend(['-M', pt_branch, 'pristine-tar']) |
51 | + else: |
52 | + cmd.extend(['pristine-tar', pt_branch]) |
53 | + self.git_run(cmd) |
54 | + yield |
55 | + cmd = ['branch'] |
56 | + if move: |
57 | + cmd.extend(['-M', 'pristine-tar', pt_branch]) |
58 | + else: |
59 | + cmd.extend(['-D', 'pristine-tar']) |
60 | + self.git_run(cmd) |
61 | + if old_pt_branch: |
62 | + self.git_run(['branch', '-M', 'pristine-tar.bak', 'pristine-tar']) |
63 | + |
64 | + def pristine_tar_list(self, dist, namespace='pkg'): |
65 | + with self.pristine_tar_branches(dist, namespace): |
66 | + cp = run(['pristine-tar', 'list']) |
67 | + return decode_binary(cp.stdout).strip().splitlines() |
68 | + |
69 | + def pristine_tar_extract(self, pkgname, version, dist=None, namespace='pkg'): |
70 | + '''Extract orig tarballs for a given package and upstream version |
71 | + |
72 | + returns: list of tarball paths that are now present on the filesystem |
73 | + throws: |
74 | + - PristineTarNotFoundError if no suitable tarballs are found |
75 | + - MultiplePristineTarFoundError if multiple distinct suitable tarballs |
76 | + are found |
77 | + |
78 | + ''' |
79 | + dists = [dist] if dist else ['debian', 'ubuntu'] |
80 | + for dist in dists: |
81 | + main_tarball = '%s_%s.orig.tar' % (pkgname, version) |
82 | + |
83 | + all_tarballs = self.pristine_tar_list(dist, namespace) |
84 | + |
85 | + potential_main_tarballs = [tarball for tarball |
86 | + in all_tarballs if tarball.startswith(main_tarball)] |
87 | + if len(potential_main_tarballs) == 0: |
88 | + continue |
89 | + if len(potential_main_tarballs) > 1: |
90 | + # This will need some extension/flag for the case of there |
91 | + # being multiple imports with varying compression |
92 | + raise MultiplePristineTarFoundError( |
93 | + 'More than one pristine-tar tarball found for %s: %s' % |
94 | + (version, potential_main_tarballs) |
95 | + ) |
96 | + ext = os.path.splitext(potential_main_tarballs[0])[1] |
97 | + tarballs = [] |
98 | + tarballs.append(os.path.join('..', potential_main_tarballs[0])) |
99 | + cmd = ['gbp', 'buildpackage', '--git-builder=/bin/true', |
100 | + '--git-pristine-tar', '--git-ignore-branch', |
101 | + '--git-upstream-tag=%s/upstream/%s/%%(version)s%s' % |
102 | + (namespace, dist, ext)] |
103 | + orig_re = re.compile( |
104 | + r'^%s_%s\.orig-(?P<component>[^.]+)\.tar\.[^.]+$' % |
105 | + (re.escape(pkgname), re.escape(version)) |
106 | + ) |
107 | + # This will probably break if the component tarballs get |
108 | + # compressed differently, as each component tarball will show up |
109 | + # multiple times |
110 | + # Breaks may be too strong -- we will 'over cache' tarballs, and |
111 | + # then it's up to dpkg-buildpackage to use the 'correct' one |
112 | + potential_component_tarballs = { |
113 | + orig_re.match(tarball).group('component') : tarball for tarball |
114 | + in all_tarballs if orig_re.match(tarball) |
115 | + } |
116 | + tarballs.extend(map(lambda x : os.path.join('..', x), |
117 | + list(potential_component_tarballs.values())) |
118 | + ) |
119 | + cmd.extend(map(lambda x : '--git-component=%s' % x, |
120 | + list(potential_component_tarballs.keys())) |
121 | + ) |
122 | + with self.pristine_tar_branches(dist, namespace): |
123 | + run(cmd) |
124 | + return tarballs |
125 | + |
126 | + raise PristineTarNotFoundError( |
127 | + 'No pristine-tar tarball found for %s' % version |
128 | + ) |
129 | + |
130 | + def pristine_tar_exists(self, pkgname, version, namespace='pkg'): |
131 | + '''Report distributions that contain pristine-tar data for @version |
132 | + ''' |
133 | + results = [] |
134 | + for dist in ('debian', 'ubuntu'): |
135 | + main_tarball = '%s_%s.orig.tar' % (pkgname, version) |
136 | + |
137 | + all_tarballs = self.pristine_tar_list(dist, namespace) |
138 | + |
139 | + potential_main_tarballs = [tarball for tarball |
140 | + in all_tarballs if tarball.startswith(main_tarball)] |
141 | + if len(potential_main_tarballs) == 0: |
142 | + continue |
143 | + if len(potential_main_tarballs) > 1: |
144 | + # This will need some extension/flag for the case of there |
145 | + # being multiple imports with varying compression |
146 | + raise MultiplePristineTarFoundError( |
147 | + 'More than one pristine-tar tarball found for %s: %s' % |
148 | + (version, potential_main_tarballs) |
149 | + ) |
150 | + results.append(dist) |
151 | + |
152 | + return results |
153 | + |
154 | + def verify_pristine_tar(self, tarball_paths, dist, namespace='pkg'): |
155 | + '''Verify the pristine-tar data matches for a set of paths |
156 | + ''' |
157 | + all_tarballs = self.pristine_tar_list(dist, namespace) |
158 | + for path in tarball_paths: |
159 | + if os.path.basename(path) not in all_tarballs: |
160 | + break |
161 | + try: |
162 | + with self.pristine_tar_branches(dist, namespace): |
163 | + # need to handle this not existing |
164 | + run(['pristine-tar', 'verify', path]) |
165 | + except CalledProcessError as e: |
166 | + raise PristineTarError('Tarball at %s failed to verify') |
167 | + else: |
168 | + return True |
169 | + |
170 | + return False |
171 | + |
172 | def set_git_attributes(self): |
173 | git_attr_path = os.path.join(self.raw_repo.path, |
174 | 'info', |
175 | diff --git a/gitubuntu/importer.py b/gitubuntu/importer.py |
176 | index 7667ed2..3f4125a 100644 |
177 | --- a/gitubuntu/importer.py |
178 | +++ b/gitubuntu/importer.py |
179 | @@ -36,7 +36,10 @@ import sys |
180 | import tempfile |
181 | import time |
182 | from gitubuntu.cache import CACHE_PATH |
183 | -from gitubuntu.dsc import GitUbuntuDsc |
184 | +from gitubuntu.dsc import ( |
185 | + GitUbuntuDsc, |
186 | + GitUbuntuDscError, |
187 | +) |
188 | from gitubuntu.git_repository import ( |
189 | GitUbuntuRepository, |
190 | GitUbuntuRepositoryFetchError, |
191 | @@ -44,6 +47,7 @@ from gitubuntu.git_repository import ( |
192 | applied_tag, |
193 | import_tag, |
194 | upstream_tag, |
195 | + PristineTarError, |
196 | ) |
197 | from gitubuntu.run import decode_binary, run, runq |
198 | from gitubuntu.source_information import GitUbuntuSourceInformation, NoPublicationHistoryException, SourceExtractionException, launchpad_login_auth |
199 | @@ -341,14 +345,19 @@ class GitUbuntuImport: |
200 | |
201 | self.local_repo.clean_repository_state() |
202 | |
203 | - def orig_imported(self, orig_tarball): |
204 | - """Determines if a given tarball has already been imported |
205 | + def orig_imported(self, orig_tarball_paths, dist): |
206 | + """Determines if a list of paths to tarballs have already been imported to @dist |
207 | |
208 | Assumes that the pristine-tar branch exists |
209 | """ |
210 | - cp = run(['pristine-tar', 'list']) |
211 | - tarballs = decode_binary(cp.stdout).strip() |
212 | - return orig_tarball in tarballs |
213 | + try: |
214 | + return self.local_repo.verify_pristine_tar(orig_tarball_paths, dist, |
215 | + self.namespace |
216 | + ) |
217 | + except PristineTarError as e: |
218 | + raise GitUbuntuImportOrigError('Tarball has already been imported to ' |
219 | + '%s with different contents: %s' % (dist, e) |
220 | + ) |
221 | |
222 | def import_orig(self, spi): |
223 | """Imports the orig-tarball using gbp import-org --pristine-tar |
224 | @@ -361,23 +370,13 @@ class GitUbuntuImport: |
225 | version = str(spi.version) |
226 | dist = spi.distribution.name.lower() |
227 | |
228 | - # adapted from ubuntutools.SourcePackage.verify_orig |
229 | - orig_tarball = None |
230 | - components = [] |
231 | - orig_re = re.compile(r'.*\.orig(-(?P<component>[^.]+))?\.tar\.[^.]+$') |
232 | - for entry in dsc['Files']: |
233 | - m = orig_re.match(entry['name']) |
234 | - if m is not None: |
235 | - if m.group('component') is not None: |
236 | - components.append(m.group('component')) |
237 | - else: |
238 | - if orig_tarball is None: |
239 | - orig_tarball = entry['name'] |
240 | - else: |
241 | - raise GitUbuntuImportOrigError('Multiple base orig ' |
242 | - 'tarballs in DSC for version %s' % version) |
243 | + try: |
244 | + orig_tarball_path = dsc.orig_tarball_path |
245 | + except GitUbuntuDscError as e: |
246 | + raise GitUbuntuImportOrigError('Multiple base orig ' |
247 | + 'tarballs in DSC for version %s' % version) from e |
248 | |
249 | - if orig_tarball is None: |
250 | + if orig_tarball_path is None: |
251 | # native packages only have a .tar.* |
252 | native_re = re.compile(r'.*\.tar\.[^.]+$') |
253 | for entry in dsc['Files']: |
254 | @@ -386,41 +385,42 @@ class GitUbuntuImport: |
255 | raise GitUbuntuImportOrigError('No orig tarball in ' |
256 | 'DSC for version %s.' % version) |
257 | |
258 | - # update the branch name so that gbp is happy |
259 | - self.local_repo.git_run(['branch', '-M', |
260 | - '%s/importer/%s/pristine-tar' % (self.namespace, dist), |
261 | - 'pristine-tar' |
262 | - ] |
263 | - ) |
264 | + try: |
265 | + orig_component_paths = dsc.component_tarball_paths |
266 | + except GitUbuntuDscError as e: |
267 | + raise GitUbuntuImportOrigError('Unable to import component ' |
268 | + 'tarballs in DSC for version %s' % version) from e |
269 | + |
270 | + orig_paths = [orig_tarball_path] + list(orig_component_paths.values()) |
271 | + if (not orig_tarball_path or |
272 | + self.orig_imported(orig_paths, dist)): |
273 | + return |
274 | + if not all(map(os.path.exists, orig_paths)): |
275 | + raise GitUbuntuImportOrigError('Unable to find tarball: ' |
276 | + '%s' % [p for p in orig_paths if not os.path.exists(p)]) |
277 | |
278 | try: |
279 | - oldcwd = os.getcwd() |
280 | - # gbp fails if the tag already exist |
281 | - if (not orig_tarball or |
282 | - self.orig_imported(orig_tarball)): |
283 | - return |
284 | - if not os.path.exists(dsc.orig_tarball_path): |
285 | - raise GitUbuntuImportOrigError('Unable to find tarball: ' |
286 | - '%s' % dsc.orig_tarball_path) |
287 | - |
288 | - # gbp does not support running from arbitrary git trees or |
289 | - # working directories |
290 | - # https://github.com/agx/git-buildpackage/pull/16 |
291 | - os.chdir(self.local_repo.local_dir) |
292 | - |
293 | - ext = os.path.splitext(dsc.orig_tarball_path)[1] |
294 | - |
295 | - # make this non-fatal if upstream already exist as tagged? |
296 | - cmd = ['gbp', 'import-orig', '--no-merge', |
297 | - '--upstream-branch', 'do-not-push', |
298 | - '--pristine-tar', '--no-interactive', |
299 | - '--no-symlink-orig', |
300 | - '--upstream-tag=%s/upstream/%s/%%(version)s%s' % |
301 | - (self.namespace, dist, ext)] |
302 | - if len(components) > 0: |
303 | - cmd.extend(map(lambda x: '--component=%s' % x, components)) |
304 | - cmd.extend([dsc.orig_tarball_path,]) |
305 | - run(cmd, env=self.local_repo.env) |
306 | + with self.local_repo.pristine_tar_branches(dist, self.namespace, move=True): |
307 | + oldcwd = os.getcwd() |
308 | + # gbp does not support running from arbitrary git trees or |
309 | + # working directories |
310 | + # https://github.com/agx/git-buildpackage/pull/16 |
311 | + os.chdir(self.local_repo.local_dir) |
312 | + |
313 | + ext = os.path.splitext(dsc.orig_tarball_path)[1] |
314 | + |
315 | + # make this non-fatal if upstream already exist as tagged? |
316 | + cmd = ['gbp', 'import-orig', '--no-merge', |
317 | + '--upstream-branch', 'do-not-push', |
318 | + '--pristine-tar', '--no-interactive', |
319 | + '--no-symlink-orig', |
320 | + '--upstream-tag=%s/upstream/%s/%%(version)s%s' % |
321 | + (self.namespace, dist, ext)] |
322 | + cmd.extend(map(lambda x: '--component=%s' % x, |
323 | + list(orig_component_paths.keys())) |
324 | + ) |
325 | + cmd.extend([orig_tarball_path,]) |
326 | + run(cmd, env=self.local_repo.env) |
327 | except CalledProcessError as e: |
328 | raise GitUbuntuImportOrigError('Unable to import tarballs: ' |
329 | '%s' % orig_paths) from e |
330 | @@ -429,13 +429,6 @@ class GitUbuntuImport: |
331 | |
332 | self.local_repo.clean_repository_state() |
333 | |
334 | - # update the branch name so that the importer is happy |
335 | - self.local_repo.git_run(['branch', '-M', |
336 | - 'pristine-tar', |
337 | - '%s/importer/%s/pristine-tar' % (self.namespace, dist), |
338 | - ] |
339 | - ) |
340 | - |
341 | def import_patches_unapplied_tree(self, dsc_pathname): |
342 | """Imports the patches-unapplied source package and writes the |
343 | corresponding working tree for a given srcpkg |
FAILED: Continuous integration, rev:3ba561d5c68 16954393999a27e 6487b5b31c4fe7 /code.launchpad .net/~nacc/ usd-importer/ +git/usd- importer/ +merge/ 329554/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
https:/ /jenkins. ubuntu. com/server/ job/git- ubuntu- ci/9/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Tests
SUCCESS: Build
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/git- ubuntu- ci/9/rebuild
https:/