Merge lp:~cjwatson/launchpad/snap-personmerge into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 17666
Proposed branch: lp:~cjwatson/launchpad/snap-personmerge
Merge into: lp:launchpad
Prerequisite: lp:~cjwatson/launchpad/snap-mail
Diff against target: 124 lines (+66/-3)
2 files modified
lib/lp/registry/personmerge.py (+22/-3)
lib/lp/registry/tests/test_personmerge.py (+44/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/snap-personmerge
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+266283@code.launchpad.net

Commit message

Handle snap packages during person merging.

Description of the change

Handle snap packages during person merging.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/personmerge.py'
2--- lib/lp/registry/personmerge.py 2015-07-23 12:56:00 +0000
3+++ lib/lp/registry/personmerge.py 2015-07-30 15:26:03 +0000
4@@ -33,6 +33,7 @@
5 )
6 from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
7 from lp.services.mail.helpers import get_email_template
8+from lp.snappy.interfaces.snap import ISnapSet
9 from lp.soyuz.enums import ArchiveStatus
10 from lp.soyuz.interfaces.archive import IArchiveSet
11 from lp.soyuz.interfaces.livefs import ILiveFSSet
12@@ -616,6 +617,24 @@
13 IStore(livefses[0]).flush()
14
15
16+def _mergeSnap(cur, from_person, to_person):
17+ # This shouldn't use removeSecurityProxy.
18+ snaps = getUtility(ISnapSet).getByPerson(from_person)
19+ existing_names = [
20+ s.name for s in getUtility(ISnapSet).getByPerson(to_person)]
21+ for snap in snaps:
22+ new_name = snap.name
23+ count = 1
24+ while new_name in existing_names:
25+ new_name = '%s-%s' % (snap.name, count)
26+ count += 1
27+ naked_snap = removeSecurityProxy(snap)
28+ naked_snap.owner = to_person
29+ naked_snap.name = new_name
30+ if not snaps.is_empty():
31+ IStore(snaps[0]).flush()
32+
33+
34 def _purgeUnmergableTeamArtifacts(from_team, to_team, reviewer):
35 """Purge team artifacts that cannot be merged, but can be removed."""
36 # A team cannot have more than one mailing list.
37@@ -713,9 +732,6 @@
38 ('latestpersonsourcepackagereleasecache', 'maintainer'),
39 # Obsolete table.
40 ('branchmergequeue', 'owner'),
41- # This needs handling before we deploy the snap code, but can be
42- # ignored for the purpose of deploying the database tables.
43- ('snap', 'owner'),
44 ]
45
46 references = list(postgresql.listReferences(cur, 'person', 'id'))
47@@ -848,6 +864,9 @@
48 _mergeLiveFS(cur, from_person, to_person)
49 skip.append(('livefs', 'owner'))
50
51+ _mergeSnap(cur, from_person, to_person)
52+ skip.append(('snap', 'owner'))
53+
54 # Sanity check. If we have a reference that participates in a
55 # UNIQUE index, it must have already been handled by this point.
56 # We can tell this by looking at the skip list.
57
58=== modified file 'lib/lp/registry/tests/test_personmerge.py'
59--- lib/lp/registry/tests/test_personmerge.py 2015-05-14 13:57:51 +0000
60+++ lib/lp/registry/tests/test_personmerge.py 2015-07-30 15:26:03 +0000
61@@ -4,6 +4,7 @@
62 """Tests for merge_people."""
63
64 from datetime import datetime
65+from operator import attrgetter
66
67 import pytz
68 from testtools.matchers import MatchesStructure
69@@ -40,6 +41,10 @@
70 EmailAddressStatus,
71 IEmailAddressSet,
72 )
73+from lp.snappy.interfaces.snap import (
74+ ISnapSet,
75+ SNAP_FEATURE_FLAG,
76+ )
77 from lp.soyuz.enums import ArchiveStatus
78 from lp.soyuz.interfaces.livefs import (
79 ILiveFSSet,
80@@ -559,6 +564,45 @@
81 self.assertEqual(['TO', 'FROM'], project_names)
82 self.assertEqual(u'foo-1', livefses[1].name)
83
84+ def test_merge_moves_snaps(self):
85+ # When person/teams are merged, snap packages owned by the from
86+ # person are moved.
87+ self.useFixture(FeatureFixture({SNAP_FEATURE_FLAG: u"on"}))
88+ duplicate = self.factory.makePerson()
89+ mergee = self.factory.makePerson()
90+ self.factory.makeSnap(registrant=duplicate, owner=duplicate)
91+ self._do_premerge(duplicate, mergee)
92+ login_person(mergee)
93+ duplicate, mergee = self._do_merge(duplicate, mergee)
94+ self.assertEqual(1, getUtility(ISnapSet).getByPerson(mergee).count())
95+
96+ def test_merge_with_duplicated_snaps(self):
97+ # If both the from and to people have snap packages with the same
98+ # name, merging renames the duplicate from the from person's side.
99+ self.useFixture(FeatureFixture({SNAP_FEATURE_FLAG: u"on"}))
100+ duplicate = self.factory.makePerson()
101+ mergee = self.factory.makePerson()
102+ branch = self.factory.makeAnyBranch()
103+ [ref] = self.factory.makeGitRefs()
104+ self.factory.makeSnap(
105+ registrant=duplicate, owner=duplicate, name=u'foo', branch=branch)
106+ self.factory.makeSnap(
107+ registrant=mergee, owner=mergee, name=u'foo', git_ref=ref)
108+ self._do_premerge(duplicate, mergee)
109+ login_person(mergee)
110+ duplicate, mergee = self._do_merge(duplicate, mergee)
111+ snaps = sorted(
112+ getUtility(ISnapSet).getByPerson(mergee), key=attrgetter("name"))
113+ self.assertEqual(2, len(snaps))
114+ self.assertIsNone(snaps[0].branch)
115+ self.assertEqual(ref.repository, snaps[0].git_repository)
116+ self.assertEqual(ref.path, snaps[0].git_path)
117+ self.assertEqual(u'foo', snaps[0].name)
118+ self.assertEqual(branch, snaps[1].branch)
119+ self.assertIsNone(snaps[1].git_repository)
120+ self.assertIsNone(snaps[1].git_path)
121+ self.assertEqual(u'foo-1', snaps[1].name)
122+
123
124 class TestMergeMailingListSubscriptions(TestCaseWithFactory):
125