Merge ~racb/git-ubuntu:applied-enum into git-ubuntu:master

Proposed by Robie Basak
Status: Merged
Approved by: Robie Basak
Approved revision: 369f645c6b1c80cb3d243b8fcea51ce76de9102d
Merged at revision: 2c4581202eac146cd0b39e0d6e285e24f4dafa87
Proposed branch: ~racb/git-ubuntu:applied-enum
Merge into: git-ubuntu:master
Diff against target: 369 lines (+110/-73)
4 files modified
gitubuntu/git_repository.py (+46/-35)
gitubuntu/importer.py (+54/-37)
gitubuntu/importer_test.py (+7/-1)
gitubuntu/patch_state.py (+3/-0)
Reviewer Review Type Date Requested Status
Bryce Harrington Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+378522@code.launchpad.net

Commit message

Make Jenkins happy

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:369f645c6b1c80cb3d243b8fcea51ce76de9102d
https://jenkins.ubuntu.com/server/job/git-ubuntu-ci/460/
Executed test runs:
    SUCCESS: VM Setup
    SUCCESS: Build
    SUCCESS: Unit Tests
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/git-ubuntu-ci/460//rebuild

review: Approve (continuous-integration)
Revision history for this message
Bryce Harrington (bryce) wrote :

Looks good, I see what you mean about how much code this touches, but a solid refactoring.

I don't know if it matters, and probably wouldn't ever in practice, but as python doesn't type check function parameters, the anonymous dict is going to be a bit brittle if incorrect values are passed.

However, I don't think it's worth going out of the way to prevent. If someone does louse up the code and pass a non-enum in, it'll error a bit cryptically but shouldn't be too hard to figure out.

$ python3
Python 3.7.6 (default, Jan 16 2020, 18:23:42)
[GCC 9.2.1 20200110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import enum
>>> PatchState = enum.Enum('PatchState', ['APPLIED', 'UNAPPLIED'])
>>> def test_enum(patch_state=PatchState.UNAPPLIED):
... print({ PatchState.UNAPPLIED: 'import', PatchState.APPLIED: 'applied', }[patch_state])
...
>>> test_enum(PatchState.APPLIED)
applied
>>> test_enum(PatchState.UNAPPLIED)
import
>>> test_enum(PatchState.NOTHING)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/enum.py", line 349, in __getattr__
    raise AttributeError(name) from None
AttributeError: NOTHING
>>> test_enum(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test_enum
KeyError: -1
>>> test_enum(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test_enum
KeyError: 0
>>> import typing
>>> def test_enum(patch_state: PatchState = PatchState.UNAPPLIED):
... print({ PatchState.UNAPPLIED: 'import', PatchState.APPLIED: 'applied', }[patch_state])
...
>>> test_enum(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test_enum
KeyError: 0
>>> test_enum(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test_enum
KeyError: -1
>>> test_enum(PatchState.APPLIED)
applied

review: Approve
Revision history for this message
Bryce Harrington (bryce) wrote :

I almost hate to mention it, but I notice the import_tag() and reimport_tag_prefix() functions could be condensed to one routine pretty easily by using a '/'.join() on the parts. IOW:

def import_tag(version, namespace, patch_state=PatchState.UNAPPLIED, reimport=False):
    elements = [ namespace ]
    if reimport:
        elements.append('reimport')
    elements.append('applied' if patch_state==PatchState.APPLIED else 'import')
    elements.append(git_dep14_tag(version))
    return '/'.join(elements)

>>> import_tag('ver', 'ns')
'ns/import/dep14.ver'
>>> import_tag('ver', 'ns', PatchState.APPLIED, True)
'ns/reimport/applied/dep14.ver'

(There's probably simpler ways to build the list than append(), and obviously the reimport bool would be better done as an enum like patch state, but I think that gives the basic idea.)

Frankly, though, I kind of like having two distinct routines here like you've done, because they're conceptually different and will make the code calling them a bit more clear as to what's going on. However, sometimes unifying to a single function can open other refactoring possibilities later, so figure it's worth mentioning as an option.

Revision history for this message
Robie Basak (racb) wrote :

> because they're conceptually different and will make the code calling them a bit more clear as to what's going on

Agreed. I prefer leaving this as-is, especially because it's difficult to define the semantics of a combined function from the perspective of callers.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/gitubuntu/git_repository.py b/gitubuntu/git_repository.py
2index bce4573..6dfddd9 100644
3--- a/gitubuntu/git_repository.py
4+++ b/gitubuntu/git_repository.py
5@@ -22,6 +22,7 @@ import gitubuntu.lint
6 from gitubuntu.__main__ import top_level_defaults
7 import gitubuntu.build
8 from gitubuntu.dsc import component_tarball_matches
9+from gitubuntu.patch_state import PatchState
10 from gitubuntu.run import (
11 decode_binary,
12 run,
13@@ -736,36 +737,37 @@ def git_dep14_tag(version):
14 version = pre + '.#lock'
15 return version
16
17-def import_tag(version, namespace):
18- return '%s/import/%s' % (namespace, git_dep14_tag(version))
19-
20-def reimport_tag_prefix(version, namespace):
21- return '%s/reimport/import/%s' % (
22+def import_tag(version, namespace, patch_state=PatchState.UNAPPLIED):
23+ return '%s/%s/%s' % (
24 namespace,
25+ {
26+ PatchState.UNAPPLIED: 'import',
27+ PatchState.APPLIED: 'applied',
28+ }[patch_state],
29 git_dep14_tag(version),
30 )
31
32-def applied_reimport_tag_prefix(version, namespace):
33- return '%s/reimport/applied/%s' % (
34+def reimport_tag_prefix(version, namespace, patch_state=PatchState.UNAPPLIED):
35+ return '%s/reimport/%s/%s' % (
36 namespace,
37+ {
38+ PatchState.UNAPPLIED: 'import',
39+ PatchState.APPLIED: 'applied',
40+ }[patch_state],
41 git_dep14_tag(version),
42 )
43
44-def reimport_tag(version, namespace, reimport):
45- return '%s/%s' % (
46- reimport_tag_prefix(version, namespace),
47- reimport,
48- )
49-
50-def applied_reimport_tag(version, namespace, reimport):
51+def reimport_tag(
52+ version,
53+ namespace,
54+ reimport,
55+ patch_state=PatchState.UNAPPLIED,
56+):
57 return '%s/%s' % (
58- applied_reimport_tag_prefix(version, namespace),
59+ reimport_tag_prefix(version, namespace, patch_state=patch_state),
60 reimport,
61 )
62
63-def applied_tag(version, namespace):
64- return '%s/applied/%s' % (namespace, git_dep14_tag(version))
65-
66 def upload_tag(version, namespace):
67 return '%s/upload/%s' % (namespace, git_dep14_tag(version))
68
69@@ -1676,32 +1678,41 @@ class GitUbuntuRepository:
70 except (KeyError, ValueError):
71 return None
72
73- def get_import_tag(self, version, namespace):
74- return self.get_tag_reference(import_tag(version, namespace))
75-
76- def get_reimport_tag(self, version, namespace, reimport):
77+ def get_import_tag(
78+ self,
79+ version,
80+ namespace,
81+ patch_state=PatchState.UNAPPLIED,
82+ ):
83 return self.get_tag_reference(
84- reimport_tag(version, namespace, reimport)
85+ import_tag(version, namespace, patch_state)
86 )
87
88- def get_applied_reimport_tag(self, version, namespace, reimport):
89+ def get_reimport_tag(
90+ self,
91+ version,
92+ namespace,
93+ reimport,
94+ patch_state=PatchState.UNAPPLIED,
95+ ):
96 return self.get_tag_reference(
97- applied_reimport_tag(version, namespace, reimport)
98- )
99-
100- def get_all_reimport_tags(self, version, namespace):
101- return self.references_with_prefix(
102- 'refs/tags/%s' % reimport_tag_prefix(version, namespace)
103+ reimport_tag(version, namespace, reimport, patch_state)
104 )
105
106- def get_all_applied_reimport_tags(self, version, namespace):
107+ def get_all_reimport_tags(
108+ self,
109+ version,
110+ namespace,
111+ patch_state=PatchState.UNAPPLIED,
112+ ):
113 return self.references_with_prefix(
114- 'refs/tags/%s' % applied_reimport_tag_prefix(version, namespace)
115+ 'refs/tags/%s' % reimport_tag_prefix(
116+ version,
117+ namespace,
118+ patch_state,
119+ )
120 )
121
122- def get_applied_tag(self, version, namespace):
123- return self.get_tag_reference(applied_tag(version, namespace))
124-
125 def get_upload_tag(self, version, namespace):
126 return self.get_tag_reference(upload_tag(version, namespace))
127
128diff --git a/gitubuntu/importer.py b/gitubuntu/importer.py
129index c6bfea9..98a0997 100644
130--- a/gitubuntu/importer.py
131+++ b/gitubuntu/importer.py
132@@ -46,14 +46,13 @@ from gitubuntu.git_repository import (
133 GitUbuntuRepository,
134 GitUbuntuRepositoryFetchError,
135 orphan_tag,
136- applied_tag,
137 import_tag,
138 reimport_tag,
139- applied_reimport_tag,
140 upstream_tag,
141 PristineTarError,
142 is_dir_3_0_quilt,
143 )
144+from gitubuntu.patch_state import PatchState
145 from gitubuntu.run import (
146 decode_binary,
147 run,
148@@ -980,30 +979,24 @@ def parse_parentfile(parentfile, pkgname):
149 return parent_overrides
150
151
152-def get_existing_import_tags(repo, version, namespace):
153- existing_import_tag = repo.get_import_tag(version, namespace)
154+def get_existing_import_tags(
155+ repo,
156+ version,
157+ namespace,
158+ patch_state=PatchState.UNAPPLIED,
159+):
160+ existing_import_tag = repo.get_import_tag(version, namespace, patch_state)
161 if existing_import_tag:
162 # check if there are reimports
163- existing_reimport_tags = repo.get_all_reimport_tags(version, namespace)
164- if existing_reimport_tags:
165- return existing_reimport_tags
166- else:
167- return [existing_import_tag]
168- return []
169-
170-
171-def get_existing_applied_tags(repo, version, namespace):
172- existing_applied_tag = repo.get_applied_tag(version, namespace)
173- if existing_applied_tag:
174- # check if there are reimports
175- existing_applied_reimport_tags = repo.get_all_applied_reimport_tags(
176+ existing_reimport_tags = repo.get_all_reimport_tags(
177 version,
178 namespace,
179+ patch_state,
180 )
181- if existing_applied_reimport_tags:
182- return existing_applied_reimport_tags
183+ if existing_reimport_tags:
184+ return existing_reimport_tags
185 else:
186- return [existing_applied_tag]
187+ return [existing_import_tag]
188 return []
189
190
191@@ -1019,11 +1012,13 @@ def override_parents(parent_overrides, repo, version, namespace):
192
193 unapplied_changelog_parent_tag = repo.get_import_tag(
194 parent_overrides[version]['changelog_parent'],
195- namespace
196+ namespace,
197+ PatchState.UNAPPLIED,
198 )
199- applied_changelog_parent_tag = repo.get_applied_tag(
200+ applied_changelog_parent_tag = repo.get_import_tag(
201 parent_overrides[version]['changelog_parent'],
202- namespace
203+ namespace,
204+ PatchState.APPLIED,
205 )
206 if unapplied_changelog_parent_tag is not None:
207 # sanity check that version from d/changelog of the
208@@ -1188,12 +1183,17 @@ def get_import_tag_msg():
209 def create_applied_tag(repo, commit_hash, version, namespace):
210 tag_msg = get_import_tag_msg()
211
212- existing_applied_tag = repo.get_applied_tag(version, namespace)
213+ existing_applied_tag = repo.get_import_tag(
214+ version,
215+ namespace,
216+ PatchState.APPLIED,
217+ )
218 if existing_applied_tag:
219- base_applied_reimport_tag = repo.get_applied_reimport_tag(
220+ base_applied_reimport_tag = repo.get_reimport_tag(
221 version,
222 namespace,
223 reimport=0,
224+ patch_state=PatchState.APPLIED,
225 )
226 if base_applied_reimport_tag:
227 assert (
228@@ -1203,44 +1203,55 @@ def create_applied_tag(repo, commit_hash, version, namespace):
229 else:
230 repo.create_tag(
231 str(existing_applied_tag.peel(pygit2.Commit).id),
232- applied_reimport_tag(version, namespace, reimport=0),
233+ reimport_tag(
234+ version,
235+ namespace,
236+ reimport=0,
237+ patch_state=PatchState.APPLIED,
238+ ),
239 tag_msg,
240 )
241 num_existing_applied_reimports = len(
242- repo.get_all_applied_reimport_tags(version, namespace)
243+ repo.get_all_reimport_tags(version, namespace, PatchState.APPLIED)
244 )
245- assert not repo.get_applied_reimport_tag(
246+ assert not repo.get_reimport_tag(
247 version,
248 namespace,
249 reimport=num_existing_applied_reimports,
250+ patch_state=PatchState.APPLIED,
251 )
252 repo.create_tag(
253 commit_hash,
254- applied_reimport_tag(
255+ reimport_tag(
256 version,
257 namespace,
258 reimport=num_existing_applied_reimports,
259+ patch_state=PatchState.APPLIED,
260 ),
261 tag_msg,
262 )
263- return repo.get_applied_reimport_tag(
264+ return repo.get_reimport_tag(
265 version,
266 namespace,
267 reimport=num_existing_applied_reimports,
268+ patch_state=PatchState.APPLIED,
269 )
270 else:
271 repo.create_tag(
272 commit_hash,
273- applied_tag(version, namespace),
274+ import_tag(version, namespace, PatchState.APPLIED),
275 tag_msg,
276 )
277- return repo.get_applied_tag(version, namespace)
278+ return repo.get_import_tag(version, namespace, PatchState.APPLIED)
279
280
281 def create_import_tag(repo, commit_hash, version, namespace):
282 tag_msg = get_import_tag_msg()
283
284- existing_import_tag = repo.get_import_tag(version, namespace)
285+ existing_import_tag = repo.get_import_tag(
286+ version,
287+ namespace,
288+ )
289 if existing_import_tag:
290 base_reimport_tag = repo.get_reimport_tag(
291 version,
292@@ -1311,14 +1322,16 @@ def get_changelog_parent_commit(
293
294 for version in import_tree_versions:
295 if patches_applied:
296- changelog_parent_tag = repo.get_applied_tag(
297+ changelog_parent_tag = repo.get_import_tag(
298 version,
299 namespace,
300+ PatchState.APPLIED,
301 )
302 else:
303 changelog_parent_tag = repo.get_import_tag(
304 version,
305 namespace,
306+ PatchState.UNAPPLIED,
307 ) or repo.get_orphan_tag(
308 version,
309 namespace,
310@@ -1744,7 +1757,11 @@ def import_applied_dsc(
311 patches_applied=True,
312 )
313
314- existing_applied_tag = repo.get_applied_tag(version, namespace)
315+ existing_applied_tag = repo.get_import_tag(
316+ version,
317+ namespace,
318+ PatchState.APPLIED,
319+ )
320 if existing_applied_tag:
321 # XXX: What should be checked here? The result of pushing all
322 # the patches? How to do it most non-destructively? (Might be
323@@ -1822,9 +1839,9 @@ def import_applied_dsc(
324 )
325
326 tag = None
327- if repo.get_applied_tag(version, namespace) is None:
328+ if repo.get_import_tag(version, namespace, PatchState.APPLIED) is None:
329 # Not imported before
330- tag = applied_tag(version, namespace)
331+ tag = import_tag(version, namespace, PatchState.APPLIED)
332 elif (
333 applied_changelog_parent_commit is None and
334 unapplied_parent_commit is None and
335diff --git a/gitubuntu/importer_test.py b/gitubuntu/importer_test.py
336index 90412d4..b1dcdc3 100644
337--- a/gitubuntu/importer_test.py
338+++ b/gitubuntu/importer_test.py
339@@ -12,6 +12,7 @@ import tempfile
340
341 import pygit2
342
343+from gitubuntu.patch_state import PatchState
344 import gitubuntu.repo_builder as repo_builder
345 from gitubuntu.repo_builder import Placeholder
346 import gitubuntu.repo_comparator as repo_comparator
347@@ -218,7 +219,12 @@ def test_get_existing_applied_tags(repo, input_repo, expected):
348
349 assert [
350 ref.name for ref in
351- target.get_existing_applied_tags(repo, '1-1', 'importer')
352+ target.get_existing_import_tags(
353+ repo,
354+ '1-1',
355+ 'importer',
356+ PatchState.APPLIED,
357+ )
358 ] == expected
359
360
361diff --git a/gitubuntu/patch_state.py b/gitubuntu/patch_state.py
362new file mode 100644
363index 0000000..b2a9cfe
364--- /dev/null
365+++ b/gitubuntu/patch_state.py
366@@ -0,0 +1,3 @@
367+import enum
368+
369+PatchState = enum.Enum('PatchState', ['APPLIED', 'UNAPPLIED'])

Subscribers

People subscribed via source and target branches