[Launchpad-reviewers] [Merge] lp:~cjwatson/launchpad/codeimport-git-webservice into lp:launchpad

2016-10-13 Thread Colin Watson
Colin Watson has proposed merging 
lp:~cjwatson/launchpad/codeimport-git-webservice into lp:launchpad with 
lp:~cjwatson/launchpad/codeimport-git-edit-views as a prerequisite.

Commit message:
Allow creating Git-targeted code imports on the webservice.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1469459 in Launchpad itself: "import external code into a LP git repo 
(natively)"
  https://bugs.launchpad.net/launchpad/+bug/1469459

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/codeimport-git-webservice/+merge/308399

The branch_name parameter is slightly unfortunate now, but it's probably better 
than introducing a new endpoint or having a mostly-duplicate repository_name 
parameter.

I need to do penance for not unittestifying the doctests, but I ran out of time.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~cjwatson/launchpad/codeimport-git-webservice into lp:launchpad.
=== modified file 'lib/lp/code/errors.py'
--- lib/lp/code/errors.py	2016-10-05 09:29:41 +
+++ lib/lp/code/errors.py	2016-10-13 15:58:50 +
@@ -27,7 +27,9 @@
 'CannotUpgradeNonHosted',
 'CodeImportAlreadyRequested',
 'CodeImportAlreadyRunning',
+'CodeImportInvalidTargetType',
 'CodeImportNotInReviewedState',
+'CodeImportGitTargetFeatureDisabled',
 'ClaimReviewFailed',
 'DiffNotFound',
 'GitDefaultConflict',
@@ -488,6 +490,25 @@
 
 
 @error_status(httplib.BAD_REQUEST)
+class CodeImportInvalidTargetType(Exception):
+"""Raised for code imports with an invalid target for their type."""
+
+def __init__(self, target, target_rcs_type):
+super(CodeImportInvalidTargetType, self).__init__(
+"Objects of type %s do not support code imports targeting %s." %
+(target.__class__.__name__, target_rcs_type))
+
+
+@error_status(httplib.UNAUTHORIZED)
+class CodeImportGitTargetFeatureDisabled(Exception):
+"""Only certain users can create new Git-targeted code imports."""
+
+def __init__(self):
+super(CodeImportGitTargetFeatureDisabled, self).__init__(
+"You do not have permission to create Git-targeted code imports.")
+
+
+@error_status(httplib.BAD_REQUEST)
 class TooNewRecipeFormat(Exception):
 """The format of the recipe supplied was too new."""
 

=== modified file 'lib/lp/code/interfaces/codeimport.py'
--- lib/lp/code/interfaces/codeimport.py	2016-10-13 15:58:50 +
+++ lib/lp/code/interfaces/codeimport.py	2016-10-13 15:58:50 +
@@ -6,6 +6,7 @@
 __metaclass__ = type
 
 __all__ = [
+'CODE_IMPORT_GIT_TARGET_FEATURE_FLAG',
 'ICodeImport',
 'ICodeImportSet',
 ]
@@ -51,6 +52,9 @@
 )
 
 
+CODE_IMPORT_GIT_TARGET_FEATURE_FLAG = u'code.import.git_target'
+
+
 def validate_cvs_root(cvsroot):
 try:
 root = CVSRoot(cvsroot)

=== modified file 'lib/lp/code/interfaces/hasbranches.py'
--- lib/lp/code/interfaces/hasbranches.py	2016-09-07 02:46:20 +
+++ lib/lp/code/interfaces/hasbranches.py	2016-10-13 15:58:50 +
@@ -7,6 +7,8 @@
 __all__ = [
 'IHasBranches',
 'IHasCodeImports',
+'IHasCodeImportsToBazaar',
+'IHasCodeImportsToGit',
 'IHasMergeProposals',
 'IHasRequestedReviews',
 ]
@@ -35,6 +37,7 @@
 BranchLifecycleStatus,
 BranchMergeProposalStatus,
 RevisionControlSystems,
+TargetRevisionControlSystems,
 )
 
 
@@ -154,13 +157,14 @@
 This interface defines the common methods that for working with them.
 """
 
-# In order to minimise dependancies the returns_collection is defined as
+# In order to minimise dependencies the returns_collection is defined as
 # Interface here and defined fully in the circular imports file.
 
 @operation_parameters(
 branch_name=TextLine(
 title=_('Name of branch to create'), required=True),
 rcs_type=Choice(vocabulary=RevisionControlSystems, required=True),
+target_rcs_type=Choice(vocabulary=TargetRevisionControlSystems),
 url=TextLine(title=_('Foreign VCS URL')),
 cvs_root=TextLine(title=_('CVS root URL')),
 cvs_module=TextLine(title=_('CVS module to import')),
@@ -170,19 +174,31 @@
 @call_with(registrant=REQUEST_USER)
 @export_factory_operation(Interface, [])  # Really ICodeImport.
 @operation_for_version('beta')
-def newCodeImport(registrant=None, branch_name=None, rcs_type=None,
-  url=None, cvs_root=None, cvs_module=None, owner=None):
+def newCodeImport(registrant=None, branch_name=None,
+  rcs_type=None, target_rcs_type=None, url=None,
+  cvs_root=None, cvs_module=None, owner=None):
 """Create a new code import.
 
 :param registrant: The IPerson to record as the registrant of the
-import
-:param branch_name: The name of the branch to create.
+import.
+:param branch_name: The name of the branch or repository to 

[Launchpad-reviewers] [Merge] lp:~cjwatson/launchpad/codeimport-git-edit-views into lp:launchpad

2016-10-13 Thread Colin Watson
Colin Watson has proposed merging 
lp:~cjwatson/launchpad/codeimport-git-edit-views into lp:launchpad with 
lp:~cjwatson/launchpad/codeimport-list-git as a prerequisite.

Commit message:
Add GitRepository:+edit-import, GitRepository:+request-import, and 
GitRepository:+try-again views.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1469459 in Launchpad itself: "import external code into a LP git repo 
(natively)"
  https://bugs.launchpad.net/launchpad/+bug/1469459

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/codeimport-git-edit-views/+merge/308398
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~cjwatson/launchpad/codeimport-git-edit-views into lp:launchpad.
=== modified file 'lib/lp/code/browser/codeimport.py'
--- lib/lp/code/browser/codeimport.py	2016-10-13 15:49:56 +
+++ lib/lp/code/browser/codeimport.py	2016-10-13 15:49:57 +
@@ -207,15 +207,16 @@
 canonical_url(code_import.target),
 code_import.target.unique_name))
 
-def _validateURL(self, url, rcs_type, existing_import=None,
- field_name='url'):
+def _validateURL(self, url, rcs_type, target_rcs_type,
+ existing_import=None, field_name='url'):
 """If the user has specified a url, we need to make sure that there
 isn't already an import with that url."""
 if url is None:
 self.setSecondaryFieldError(
 field_name, 'Enter the URL of a foreign VCS branch.')
 else:
-reason = validate_import_url(url, rcs_type, existing_import)
+reason = validate_import_url(
+url, rcs_type, target_rcs_type, existing_import)
 if reason:
 self.setFieldError(field_name, reason)
 
@@ -445,20 +446,22 @@
 % product.displayname)
 
 rcs_type = data['rcs_type']
+target_rcs_type = TargetRevisionControlSystems.BZR
 # Make sure fields for unselected revision control systems
 # are blanked out:
 if rcs_type == RevisionControlSystems.CVS:
 self._validateCVS(data.get('cvs_root'), data.get('cvs_module'))
 elif rcs_type == RevisionControlSystems.BZR_SVN:
 self._validateURL(
-data.get('svn_branch_url'), rcs_type,
+data.get('svn_branch_url'), rcs_type, target_rcs_type,
 field_name='svn_branch_url')
 elif rcs_type == RevisionControlSystems.GIT:
 self._validateURL(
-data.get('git_repo_url'), rcs_type, field_name='git_repo_url')
+data.get('git_repo_url'), rcs_type, target_rcs_type,
+field_name='git_repo_url')
 elif rcs_type == RevisionControlSystems.BZR:
 self._validateURL(
-data.get('bzr_branch_url'), rcs_type,
+data.get('bzr_branch_url'), rcs_type, target_rcs_type,
 field_name='bzr_branch_url')
 else:
 raise AssertionError(
@@ -592,7 +595,8 @@
 self.code_import)
 elif self.code_import.rcs_type in NON_CVS_RCS_TYPES:
 self._validateURL(
-data.get('url'), self.code_import.rcs_type, self.code_import)
+data.get('url'), self.code_import.rcs_type,
+self.code_import.target_rcs_type, self.code_import)
 else:
 raise AssertionError('Unknown rcs_type for code import.')
 
@@ -608,23 +612,25 @@
 return getUtility(ICodeImportMachineSet).getAll()
 
 
-def validate_import_url(url, rcs_type, existing_import=None):
+def validate_import_url(url, rcs_type, target_rcs_type, existing_import=None):
 """Validate the given import URL."""
-# XXX cjwatson 2015-06-12: Once we have imports into Git, this should be
-# extended to prevent Git-to-Git self-imports as well.
-if (rcs_type == RevisionControlSystems.BZR and
+if (rcs_type.name == target_rcs_type.name and
 urlparse(url).netloc.endswith('launchpad.net')):
 return (
-"You cannot create imports for Bazaar branches that are hosted by "
-"Launchpad.")
+"You cannot create same-VCS imports for branches or repositories "
+"that are hosted by Launchpad.")
 code_import = getUtility(ICodeImportSet).getByURL(url)
 if code_import is not None:
 if existing_import and code_import == existing_import:
 return None
+if code_import.target_rcs_type == TargetRevisionControlSystems.BZR:
+target_type = "branch"
+else:
+target_type = "repository"
 return structured(
 "This foreign branch URL is already specified for the imported "
-"branch %s.", canonical_url(code_import.branch),
-code_import.branch.unique_name)
+"%s %s.", target_type,
+

[Launchpad-reviewers] [Merge] lp:~cjwatson/launchpad/codeimport-list-git into lp:launchpad

2016-10-13 Thread Colin Watson
Colin Watson has proposed merging lp:~cjwatson/launchpad/codeimport-list-git 
into lp:launchpad with lp:~cjwatson/launchpad/codeimport-git-read-only-views as 
a prerequisite.

Commit message:
Extend CodeImportSet:+index to support different target types.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1469459 in Launchpad itself: "import external code into a LP git repo 
(natively)"
  https://bugs.launchpad.net/launchpad/+bug/1469459

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/codeimport-list-git/+merge/308387
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~cjwatson/launchpad/codeimport-list-git into lp:launchpad.
=== modified file 'lib/lp/code/browser/codeimport.py'
--- lib/lp/code/browser/codeimport.py	2016-10-13 14:25:08 +
+++ lib/lp/code/browser/codeimport.py	2016-10-13 14:25:09 +
@@ -123,12 +123,19 @@
 review_status_field = copy_field(
 ICodeImport['review_status'], required=False, default=None)
 self.review_status_widget = CustomWidgetFactory(DropdownWidgetWithAny)
-setUpWidget(self, 'review_status',  review_status_field, IInputWidget)
+setUpWidget(self, 'review_status', review_status_field, IInputWidget)
 
 rcs_type_field = copy_field(
 ICodeImport['rcs_type'], required=False, default=None)
 self.rcs_type_widget = CustomWidgetFactory(DropdownWidgetWithAny)
-setUpWidget(self, 'rcs_type',  rcs_type_field, IInputWidget)
+setUpWidget(self, 'rcs_type', rcs_type_field, IInputWidget)
+
+target_rcs_type_field = copy_field(
+ICodeImport['target_rcs_type'], required=False, default=None)
+self.target_rcs_type_widget = CustomWidgetFactory(
+DropdownWidgetWithAny)
+setUpWidget(
+self, 'target_rcs_type', target_rcs_type_field, IInputWidget)
 
 # status should be None if either (a) there were no query arguments
 # supplied, i.e. the user browsed directly to this page (this is when
@@ -138,13 +145,17 @@
 review_status = None
 if self.review_status_widget.hasValidInput():
 review_status = self.review_status_widget.getInputValue()
-# Similar for 'type'
+# Similar for 'rcs_type' and 'target_rcs_type'.
 rcs_type = None
 if self.rcs_type_widget.hasValidInput():
 rcs_type = self.rcs_type_widget.getInputValue()
+target_rcs_type = None
+if self.target_rcs_type_widget.hasValidInput():
+target_rcs_type = self.target_rcs_type_widget.getInputValue()
 
 imports = self.context.search(
-review_status=review_status, rcs_type=rcs_type)
+review_status=review_status, rcs_type=rcs_type,
+target_rcs_type=target_rcs_type)
 
 self.batchnav = BatchNavigator(imports, self.request)
 

=== modified file 'lib/lp/code/interfaces/codeimport.py'
--- lib/lp/code/interfaces/codeimport.py	2016-10-13 14:25:08 +
+++ lib/lp/code/interfaces/codeimport.py	2016-10-13 14:25:09 +
@@ -267,11 +267,14 @@
 def delete(id):
 """Delete a CodeImport given its id."""
 
-def search(review_status=None, rcs_type=None):
+def search(review_status=None, rcs_type=None, target_rcs_type=None):
 """Find the CodeImports of the given status and type.
 
 :param review_status: An entry from the `CodeImportReviewStatus`
 schema, or None, which signifies 'any status'.
 :param rcs_type: An entry from the `RevisionControlSystems`
 schema, or None, which signifies 'any type'.
+:param target_rcs_type: An entry from the
+`TargetRevisionControlSystems` schema, or None, which signifies
+'any type'.
 """

=== modified file 'lib/lp/code/model/codeimport.py'
--- lib/lp/code/model/codeimport.py	2016-10-13 14:25:08 +
+++ lib/lp/code/model/codeimport.py	2016-10-13 14:25:09 +
@@ -364,11 +364,15 @@
 def getByGitRepository(self, repository):
 return CodeImport.selectOneBy(git_repository=repository)
 
-def search(self, review_status=None, rcs_type=None):
+def search(self, review_status=None, rcs_type=None, target_rcs_type=None):
 """See `ICodeImportSet`."""
 clauses = []
 if review_status is not None:
 clauses.append(CodeImport.review_status == review_status)
 if rcs_type is not None:
 clauses.append(CodeImport.rcs_type == rcs_type)
+if target_rcs_type == TargetRevisionControlSystems.BZR:
+clauses.append(CodeImport.branch != None)
+elif target_rcs_type == TargetRevisionControlSystems.GIT:
+clauses.append(CodeImport.git_repository != None)
 return IStore(CodeImport).find(CodeImport, *clauses)

=== modified file 'lib/lp/code/stories/codeimport/xx-codeimport-view.txt'
--- lib/lp/code/stories/codeimport/xx-codeimport-view.txt	

[Launchpad-reviewers] [Merge] lp:~cjwatson/launchpad/codeimport-git-read-only-views into lp:launchpad

2016-10-13 Thread Colin Watson
Colin Watson has proposed merging 
lp:~cjwatson/launchpad/codeimport-git-read-only-views into lp:launchpad with 
lp:~cjwatson/launchpad/git-code-import-security-deletion as a prerequisite.

Commit message:
Add read-only views for Git-targeted code imports.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1469459 in Launchpad itself: "import external code into a LP git repo 
(natively)"
  https://bugs.launchpad.net/launchpad/+bug/1469459

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/codeimport-git-read-only-views/+merge/308374

We don't have much in the way of tests for this yet, but that will be easier to 
bring up once we have creation webservice/view handling in place.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~cjwatson/launchpad/codeimport-git-read-only-views into lp:launchpad.
=== modified file 'lib/lp/code/browser/branch.py'
--- lib/lp/code/browser/branch.py	2016-05-07 00:40:18 +
+++ lib/lp/code/browser/branch.py	2016-10-13 12:55:20 +
@@ -89,12 +89,12 @@
 latest_proposals_for_each_branch,
 )
 from lp.code.browser.branchref import BranchRef
+from lp.code.browser.codeimport import CodeImportTargetMixin
 from lp.code.browser.decorations import DecoratedBranch
 from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
 from lp.code.browser.widgets.branchtarget import BranchTargetWidget
 from lp.code.enums import (
 BranchType,
-CodeImportResultStatus,
 CodeImportReviewStatus,
 )
 from lp.code.errors import (
@@ -403,7 +403,7 @@
 
 
 class BranchView(InformationTypePortletMixin, FeedsMixin, BranchMirrorMixin,
- LaunchpadView, HasSnapsViewMixin):
+ LaunchpadView, HasSnapsViewMixin, CodeImportTargetMixin):
 
 feed_types = (
 BranchFeedLink,
@@ -596,31 +596,6 @@
 return collection.getExtendedRevisionDetails(
 self.user, self.context.latest_revisions)
 
-@cachedproperty
-def latest_code_import_results(self):
-"""Return the last 10 CodeImportResults."""
-return list(self.context.code_import.results[:10])
-
-def iconForCodeImportResultStatus(self, status):
-"""The icon to represent the `CodeImportResultStatus` `status`."""
-if status == CodeImportResultStatus.SUCCESS_PARTIAL:
-return "/@@/yes-gray"
-elif status in CodeImportResultStatus.successes:
-return "/@@/yes"
-else:
-return "/@@/no"
-
-@property
-def url_is_web(self):
-"""True if an imported branch's URL is HTTP or HTTPS."""
-# You should only be calling this if it's an SVN, BZR or GIT code
-# import
-assert self.context.code_import
-url = self.context.code_import.url
-assert url
-# https starts with http too!
-return url.startswith("http")
-
 @property
 def show_merge_links(self):
 """Return whether or not merge proposal links should be shown.
@@ -799,7 +774,7 @@
 target is not None and target != self.context.target):
 try:
 self.context.setTarget(self.user, project=target)
-except BranchTargetError, e:
+except BranchTargetError as e:
 self.setFieldError('target', e.message)
 return
 

=== modified file 'lib/lp/code/browser/codeimport.py'
--- lib/lp/code/browser/codeimport.py	2016-10-06 15:59:34 +
+++ lib/lp/code/browser/codeimport.py	2016-10-13 12:55:20 +
@@ -12,6 +12,7 @@
 'CodeImportSetBreadcrumb',
 'CodeImportSetNavigation',
 'CodeImportSetView',
+'CodeImportTargetMixin',
 'validate_import_url',
 ]
 
@@ -49,6 +50,7 @@
 from lp.code.enums import (
 BranchSubscriptionDiffSize,
 BranchSubscriptionNotificationLevel,
+CodeImportResultStatus,
 CodeImportReviewStatus,
 CodeReviewNotificationLevel,
 NON_CVS_RCS_TYPES,
@@ -191,8 +193,8 @@
 self.addError(structured("""
 Those CVS details are already specified for
 the imported branch %s.""",
-canonical_url(code_import.branch),
-code_import.branch.unique_name))
+canonical_url(code_import.target),
+code_import.target.unique_name))
 
 def _validateURL(self, url, rcs_type, existing_import=None,
  field_name='url'):
@@ -495,12 +497,12 @@
 class CodeImportEditView(CodeImportBaseView):
 """View for editing code imports.
 
-This view is registered against the branch, but mostly edits the code
-import for that branch -- the exception being that it also allows the
-editing of the branch whiteboard.  If the branch has no associated code
-import, then the result is a 404.  If the branch does have a code import,
-then the adapters property allows the form internals 

[Launchpad-reviewers] [Merge] lp:~cjwatson/launchpad/codeimport-git-worker into lp:launchpad

2016-10-13 Thread noreply
The proposal to merge lp:~cjwatson/launchpad/codeimport-git-worker into 
lp:launchpad has been updated.

Status: Needs review => Merged

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/codeimport-git-worker/+merge/308142
-- 
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.

___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp