Merge lp:~rockstar/launchpad/no-recipe-dupes into lp:launchpad

Proposed by Paul Hummer
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merge reported by: Paul Hummer
Merged at revision: not available
Proposed branch: lp:~rockstar/launchpad/no-recipe-dupes
Merge into: lp:launchpad
Diff against target: 111 lines (+60/-0)
5 files modified
lib/lp/code/browser/sourcepackagerecipe.py (+7/-0)
lib/lp/code/browser/tests/test_sourcepackagerecipe.py (+25/-0)
lib/lp/code/interfaces/sourcepackagerecipe.py (+3/-0)
lib/lp/code/model/sourcepackagerecipe.py (+13/-0)
lib/lp/code/model/tests/test_sourcepackagerecipe.py (+12/-0)
To merge this branch: bzr merge lp:~rockstar/launchpad/no-recipe-dupes
Reviewer Review Type Date Requested Status
Curtis Hovey (community) rc + code Approve
Review via email: mp+26212@code.launchpad.net

Description of the change

This branch makes it so that the UI can't create a recipe owned by the same person with the same name. There's a database patch to go along with this.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for reworking the implementation and providing the extra test.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/browser/sourcepackagerecipe.py'
--- lib/lp/code/browser/sourcepackagerecipe.py 2010-05-18 20:29:30 +0000
+++ lib/lp/code/browser/sourcepackagerecipe.py 2010-05-27 20:23:27 +0000
@@ -321,6 +321,13 @@
321 'recipe_text',321 'recipe_text',
322 'The recipe text is not a valid bzr-builder recipe.')322 'The recipe text is not a valid bzr-builder recipe.')
323323
324 if getUtility(ISourcePackageRecipeSource).exists(
325 self.user, data['name']):
326 self.setFieldError(
327 'name',
328 'There is already a recipe owned by %s with this name.' %
329 self.user.displayname)
330
324331
325class SourcePackageRecipeAddView(RecipeTextValidatorMixin, LaunchpadFormView):332class SourcePackageRecipeAddView(RecipeTextValidatorMixin, LaunchpadFormView):
326 """View for creating Source Package Recipes."""333 """View for creating Source Package Recipes."""
327334
=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2010-05-26 12:11:31 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2010-05-27 20:23:27 +0000
@@ -127,6 +127,31 @@
127 extract_text(find_tags_by_class(browser.contents, 'message')[1]),127 extract_text(find_tags_by_class(browser.contents, 'message')[1]),
128 'The recipe text is not a valid bzr-builder recipe.')128 'The recipe text is not a valid bzr-builder recipe.')
129129
130 def test_create_dupe_recipe(self):
131 # You shouldn't be able to create a duplicate recipe owned by the same
132 # person with the same name.
133 recipe = self.factory.makeSourcePackageRecipe(owner=self.chef)
134
135 product = self.factory.makeProduct(
136 name='ratatouille', displayname='Ratatouille')
137 branch = self.factory.makeBranch(
138 owner=self.chef, product=product, name='veggies')
139 self.factory.makeSourcePackage(sourcepackagename='ratatouille')
140
141 # A new recipe can be created from the branch page.
142 browser = self.getUserBrowser(canonical_url(branch), user=self.chef)
143 browser.getLink('Create packaging recipe').click()
144
145 browser.getControl(name='field.name').value = recipe.name
146 browser.getControl('Description').value = 'Make some food!'
147 browser.getControl('Source Package Name').value = 'ratatouille'
148 browser.getControl('Secret Squirrel').click()
149 browser.getControl('Create Recipe').click()
150
151 self.assertEqual(
152 extract_text(find_tags_by_class(browser.contents, 'message')[1]),
153 'There is already a recipe owned by Master Chef with this name.')
154
130155
131class TestSourcePackageRecipeEditView(TestCaseForRecipe):156class TestSourcePackageRecipeEditView(TestCaseForRecipe):
132 """Test the editing behaviour of a source package recipe."""157 """Test the editing behaviour of a source package recipe."""
133158
=== modified file 'lib/lp/code/interfaces/sourcepackagerecipe.py'
--- lib/lp/code/interfaces/sourcepackagerecipe.py 2010-05-18 20:29:30 +0000
+++ lib/lp/code/interfaces/sourcepackagerecipe.py 2010-05-27 20:23:27 +0000
@@ -186,3 +186,6 @@
186 def new(registrant, owner, distroseries, sourcepackagename, name,186 def new(registrant, owner, distroseries, sourcepackagename, name,
187 builder_recipe, description):187 builder_recipe, description):
188 """Create an `ISourcePackageRecipe`."""188 """Create an `ISourcePackageRecipe`."""
189
190 def exists(owner, name):
191 """Check to see if a recipe by the same name and owner exists."""
189192
=== modified file 'lib/lp/code/model/sourcepackagerecipe.py'
--- lib/lp/code/model/sourcepackagerecipe.py 2010-05-26 19:23:20 +0000
+++ lib/lp/code/model/sourcepackagerecipe.py 2010-05-27 20:23:27 +0000
@@ -134,6 +134,19 @@
134 store.add(sprecipe)134 store.add(sprecipe)
135 return sprecipe135 return sprecipe
136136
137 @staticmethod
138 def exists(owner, name):
139 """See `ISourcePackageRecipeSource.new`."""
140 store = IMasterStore(SourcePackageRecipe)
141 recipe = store.find(
142 SourcePackageRecipe,
143 SourcePackageRecipe.owner == owner,
144 SourcePackageRecipe.name == name).one()
145 if recipe:
146 return True
147 else:
148 return False
149
137 def destroySelf(self):150 def destroySelf(self):
138 store = Store.of(self)151 store = Store.of(self)
139 self.distroseries.clear()152 self.distroseries.clear()
140153
=== modified file 'lib/lp/code/model/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-05-18 19:14:16 +0000
+++ lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-05-27 20:23:27 +0000
@@ -85,6 +85,18 @@
85 (recipe.registrant, recipe.owner, set(recipe.distroseries),85 (recipe.registrant, recipe.owner, set(recipe.distroseries),
86 recipe.sourcepackagename, recipe.name))86 recipe.sourcepackagename, recipe.name))
8787
88 def test_exists(self):
89 # Test ISourcePackageRecipeSource.exists
90 recipe = self.factory.makeSourcePackageRecipe()
91
92 self.assertTrue(
93 getUtility(ISourcePackageRecipeSource).exists(
94 recipe.owner, recipe.name))
95
96 self.assertFalse(
97 getUtility(ISourcePackageRecipeSource).exists(
98 recipe.owner, u'daily'))
99
88 def test_source_implements_interface(self):100 def test_source_implements_interface(self):
89 # The SourcePackageRecipe class implements ISourcePackageRecipeSource.101 # The SourcePackageRecipe class implements ISourcePackageRecipeSource.
90 self.assertProvides(102 self.assertProvides(