Exemplo n.º 1
0
    def execute(self, bug, current_event):
        """See IEmailCommand."""
        if isinstance(bug, CreateBugParams):
            # Return the input because there is not yet a bug to
            # unsubscribe too.
            return bug, current_event

        string_args = list(self.string_args)
        if len(string_args) == 1:
            person = get_person_or_team(string_args.pop())
        elif len(string_args) == 0:
            # Subscribe the sender of the email.
            person = getUtility(ILaunchBag).user
        else:
            raise EmailProcessingError(
                get_error_message('unsubscribe-too-many-arguments.txt',
                                  error_templates=error_templates))

        if bug.isSubscribed(person):
            try:
                bug.unsubscribe(person, getUtility(ILaunchBag).user)
            except UserCannotUnsubscribePerson:
                raise EmailProcessingError(
                    get_error_message('user-cannot-unsubscribe.txt',
                                      error_templates=error_templates,
                                      person=person.displayname))
        if bug.isSubscribedToDupes(person):
            bug.unsubscribeFromDupes(person, person)

        return bug, current_event
Exemplo n.º 2
0
    def execute(self, context):
        """Extract the vote and tags from the args."""
        if len(self.string_args) == 0:
            raise EmailProcessingError(
                get_error_message('num-arguments-mismatch.txt',
                                  command_name='review',
                                  num_arguments_expected='one or more',
                                  num_arguments_got='0'))

        vote_string = self.string_args[0]
        vote_tag_list = self.string_args[1:]
        try:
            context.vote = CodeReviewVote.items[vote_string.upper()]
        except KeyError:
            # If the word doesn't match, check aliases that we allow.
            context.vote = self._vote_alias.get(vote_string)
            if context.vote is None:
                # Replace the _ with - in the names of the items.
                # Slightly easier to type and read.
                valid_votes = ', '.join(
                    sorted(v.name.lower().replace('_', '-')
                           for v in CodeReviewVote.items.items))
                raise EmailProcessingError(
                    get_error_message('dbschema-command-wrong-argument.txt',
                                      command_name='review',
                                      arguments=valid_votes,
                                      example_argument='needs-fixing'))

        if len(vote_tag_list) > 0:
            context.vote_tags = ' '.join(vote_tag_list)
Exemplo n.º 3
0
    def execute(self, context, current_event):
        """See IEmailCommand."""
        if isinstance(context, CreateBugParams):
            # No one intentially reports a duplicate bug. Bug email commands
            # support CreateBugParams, so in this case, just return.
            return context, current_event
        self._ensureNumberOfArguments()
        [bug_id] = self.string_args

        if bug_id != 'no':
            try:
                bug = getUtility(IBugSet).getByNameOrID(bug_id)
            except NotFoundError:
                raise EmailProcessingError(
                    get_error_message('no-such-bug.txt',
                                      error_templates=error_templates,
                                      bug_id=bug_id))
        else:
            # 'no' is a special value for unmarking a bug as a duplicate.
            bug = None

        duplicate_field = IBug['duplicateof'].bind(context)
        try:
            duplicate_field.validate(bug)
        except ValidationError as error:
            raise EmailProcessingError(error.doc())

        context_snapshot = Snapshot(context, providing=providedBy(context))
        context.markAsDuplicate(bug)
        current_event = ObjectModifiedEvent(context, context_snapshot,
                                            'duplicateof')
        notify(current_event)
        return bug, current_event
Exemplo n.º 4
0
 def execute(self, context):
     """Update the status of the merge proposal."""
     # Only accepts approved, and rejected for now.
     self._ensureNumberOfArguments()
     new_status = self.string_args[0].lower()
     # Grab the latest rev_id from the source branch.
     # This is what the browser code does right now.
     rev_id = context.merge_proposal.source_branch.last_scanned_id
     try:
         if new_status in ('approved', 'approve'):
             if context.vote is None:
                 context.vote = CodeReviewVote.APPROVE
             context.merge_proposal.approveBranch(context.user, rev_id)
         elif new_status in ('rejected', 'reject'):
             if context.vote is None:
                 context.vote = CodeReviewVote.DISAPPROVE
             context.merge_proposal.rejectBranch(context.user, rev_id)
         else:
             raise EmailProcessingError(
                 get_error_message('dbschema-command-wrong-argument.txt',
                                   command_name=self.name,
                                   arguments='approved, rejected',
                                   example_argument='approved'))
     except (UserNotBranchReviewer, Unauthorized):
         raise EmailProcessingError(
             get_error_message(
                 'user-not-reviewer.txt',
                 error_templates=error_templates,
                 command_name=self.name,
                 target=context.merge_proposal.target_branch.bzr_identity))
Exemplo n.º 5
0
    def execute(self, bug, current_event):
        """See `IEmailCommand`."""
        # Tags are always lowercase.
        string_args = [arg.lower() for arg in self.string_args]
        if bug.tags is None:
            tags = []
        else:
            tags = list(bug.tags)
        for arg in string_args:
            # Are we adding or removing a tag?
            if arg.startswith('-'):
                remove = True
                tag = arg[1:]
            else:
                remove = False
                tag = arg
            # Tag must be a valid name.
            if not valid_name(tag):
                raise EmailProcessingError(
                    get_error_message('invalid-tag.txt',
                                      error_templates=error_templates,
                                      tag=tag))
            if remove:
                try:
                    tags.remove(tag)
                except ValueError:
                    raise EmailProcessingError(
                        get_error_message('unassigned-tag.txt',
                                          error_templates=error_templates,
                                          tag=tag))
            else:
                tags.append(arg)
        bug.tags = tags

        return bug, current_event
Exemplo n.º 6
0
    def execute(self, parsed_msg, filealias):
        """See IBugEmailCommand."""
        self._ensureNumberOfArguments()
        bugid = self.string_args[0]

        if bugid == 'new':
            message = getUtility(IMessageSet).fromEmail(
                parsed_msg.as_string(),
                owner=getUtility(ILaunchBag).user,
                filealias=filealias,
                parsed_message=parsed_msg)
            description = message.text_contents
            if description.strip() == '':
                # The report for a new bug must contain an affects command,
                # since the bug must have at least one task
                raise EmailProcessingError(get_error_message(
                    'no-affects-target-on-submit.txt',
                    error_templates=error_templates),
                                           stop_processing=True)

            # Check the message validator.
            validator = IBugAddForm['comment'].validate
            try:
                validator(description)
            except TooLong:
                raise EmailProcessingError(
                    'The description is too long. If you have lots of '
                    'text to add, use an attachment instead.',
                    stop_processing=True)
            except ValidationError as e:
                # More a just in case than any real expectation of getting
                # something.
                raise EmailProcessingError(str(e), stop_processing=True)

            params = CreateBugParams(msg=message,
                                     title=message.title,
                                     owner=getUtility(ILaunchBag).user)
            return params, None
        else:
            try:
                bugid = int(bugid)
            except ValueError:
                raise EmailProcessingError(
                    get_error_message('bug-argument-mismatch.txt',
                                      error_templates=error_templates))

            try:
                bug = getUtility(IBugSet).get(bugid)
            except NotFoundError:
                bug = None
            if bug is None or not check_permission('launchpad.View', bug):
                raise EmailProcessingError(
                    get_error_message('no-such-bug.txt',
                                      error_templates=error_templates,
                                      bug_id=bugid))
            return bug, None
Exemplo n.º 7
0
    def execute(self, bug, current_event):
        """See IEmailCommand."""
        if bug is None:
            raise EmailProcessingError(get_error_message(
                'command-with-no-bug.txt', error_templates=error_templates),
                                       stop_processing=True)

        # Do a manual control of the number of arguments, in order to
        # provide a better error message than the default one.
        if len(self.string_args) > 1:
            raise EmailProcessingError(
                get_error_message('summary-too-many-arguments.txt',
                                  error_templates=error_templates))

        if isinstance(bug, CreateBugParams):
            bug.title = self.string_args[0]
            return bug, current_event

        return EditEmailCommand.execute(self, bug, current_event)
Exemplo n.º 8
0
    def setAttributeValue(self, context, attr_name, attr_value):
        """See EmailCommand."""
        user = getUtility(ILaunchBag).user

        if not context.canTransitionToStatus(attr_value, user):
            raise EmailProcessingError(
                'The status cannot be changed to %s because you are not '
                'the maintainer, driver or bug supervisor for %s.' %
                (attr_value.name.lower(), context.pillar.displayname))

        context.transitionToStatus(attr_value, user)
Exemplo n.º 9
0
    def execute(self, bug, current_event):
        """See IEmailCommand."""
        [cve_sequence] = self.string_args
        cve = getUtility(ICveSet)[cve_sequence]
        if cve is None:
            raise EmailProcessingError('Launchpad can\'t find the CVE "%s".' %
                                       cve_sequence)
        if isinstance(bug, CreateBugParams):
            bug.cve = cve
            return bug, current_event

        bug.linkCVE(cve, getUtility(ILaunchBag).user)
        return bug, current_event
Exemplo n.º 10
0
    def _ensureNumberOfArguments(self):
        """Check that the number of arguments is correct.

        Raise an EmailProcessingError
        """
        if self._numberOfArguments is not None:
            num_arguments_got = len(self.string_args)
            if self._numberOfArguments != num_arguments_got:
                raise EmailProcessingError(
                    get_error_message(
                        'num-arguments-mismatch.txt',
                        command_name=self.name,
                        num_arguments_expected=self._numberOfArguments,
                        num_arguments_got=num_arguments_got))
Exemplo n.º 11
0
    def execute(self, context, current_event):
        """See `IEmailCommand`.

        Much of this method was lifted from
        `EditEmailCommand.execute`.
        """
        # Parse args.
        self._ensureNumberOfArguments()
        [security_flag] = self.string_args
        if security_flag == 'yes':
            security_related = True
        elif security_flag == 'no':
            security_related = False
        else:
            raise EmailProcessingError(get_error_message(
                'security-parameter-mismatch.txt',
                error_templates=error_templates),
                                       stop_processing=True)

        if isinstance(context, CreateBugParams):
            if security_related:
                context.information_type = InformationType.PRIVATESECURITY
            return context, current_event

        # Take a snapshot.
        edited = False
        edited_fields = set()
        if IObjectModifiedEvent.providedBy(current_event):
            context_snapshot = current_event.object_before_modification
            edited_fields.update(current_event.edited_fields)
        else:
            context_snapshot = Snapshot(context, providing=providedBy(context))

        # Apply requested changes.
        user = getUtility(ILaunchBag).user
        if security_related:
            if context.setPrivate(True, user):
                edited = True
                edited_fields.add('private')
        if context.security_related != security_related:
            context.setSecurityRelated(security_related, user)
            edited = True
            edited_fields.add('security_related')

        # Update the current event.
        if edited and not IObjectCreatedEvent.providedBy(current_event):
            current_event = ObjectModifiedEvent(context, context_snapshot,
                                                list(edited_fields))

        return context, current_event
Exemplo n.º 12
0
    def convertArguments(self, context):
        """See EmailCommand."""
        user = getUtility(ILaunchBag).user
        milestone_name = self.string_args[0]

        if milestone_name == '-':
            # Remove milestone
            return {self.name: None}
        elif context.userHasBugSupervisorPrivileges(user):
            milestone = context.pillar.getMilestone(milestone_name)
            if milestone is None:
                raise EmailProcessingError(
                    "The milestone %s does not exist for %s. Note that "
                    "milestones are not automatically created from emails; "
                    "they must be created on the website." %
                    (milestone_name, context.pillar.title))
            else:
                return {self.name: milestone}
        else:
            raise EmailProcessingError(
                "You do not have permission to set the milestone for %s. "
                "Only owners, drivers and bug supervisors may assign "
                "milestones." % (context.pillar.title, ))
Exemplo n.º 13
0
    def parseReviewRequest(klass, op_name, string_args):
        if len(string_args) == 0:
            raise EmailProcessingError(
                get_error_message('num-arguments-mismatch.txt',
                                  command_name=op_name,
                                  num_arguments_expected='one or more',
                                  num_arguments_got='0'))

        # Pop the first arg as the reviewer.
        reviewer = get_person_or_team(string_args.pop(0))
        if len(string_args) > 0:
            review_tags = ' '.join(string_args)
        else:
            review_tags = None
        return (reviewer, review_tags)
Exemplo n.º 14
0
    def execute(self, context, current_event):
        """See `IEmailCommand`. Much of this method has been lifted from
        `EditEmailCommand.execute`.
        """
        # Parse args.
        self._ensureNumberOfArguments()
        private_arg = self.string_args[0]
        if private_arg == 'yes':
            private = True
        elif private_arg == 'no':
            private = False
        else:
            raise EmailProcessingError(get_error_message(
                'private-parameter-mismatch.txt',
                error_templates=error_templates),
                                       stop_processing=True)

        if isinstance(context, CreateBugParams):
            if private:
                # "private yes" forces it to Private if it isn't already.
                if (context.information_type is None or
                        context.information_type in PUBLIC_INFORMATION_TYPES):
                    context.information_type = InformationType.USERDATA
            elif context.information_type != InformationType.PRIVATESECURITY:
                # "private no" forces it to Public, except we always
                # force new security bugs to be private.
                context.information_type = InformationType.PUBLIC
            return context, current_event

        # Snapshot.
        edited_fields = set()
        if IObjectModifiedEvent.providedBy(current_event):
            context_snapshot = current_event.object_before_modification
            edited_fields.update(current_event.edited_fields)
        else:
            context_snapshot = Snapshot(context, providing=providedBy(context))

        # Apply requested changes.
        edited = context.setPrivate(private, getUtility(ILaunchBag).user)

        # Update the current event.
        if edited and not IObjectCreatedEvent.providedBy(current_event):
            edited_fields.add('private')
            current_event = ObjectModifiedEvent(context, context_snapshot,
                                                list(edited_fields))

        return context, current_event
Exemplo n.º 15
0
def get_person_or_team(person_name_or_email):
    """Get the `Person` from the vocabulary.

    :raises: EmailProcessingError if person not found.
    """
    # Avoid circular import problems.
    from lp.registry.vocabularies import ValidPersonOrTeamVocabulary
    valid_person_vocabulary = ValidPersonOrTeamVocabulary()
    try:
        person_term = valid_person_vocabulary.getTermByToken(
            person_name_or_email)
    except LookupError:
        raise EmailProcessingError(
            get_error_message(
                'no-such-person.txt',
                name_or_email=person_name_or_email))
    return person_term.value
Exemplo n.º 16
0
    def execute(self, bug, current_event):
        """See IEmailCommand."""
        string_args = list(self.string_args)
        # preserve compatibility with the original command that let you
        # specify a subscription type
        if len(string_args) == 2:
            # Remove the subscription_name
            string_args.pop()

        user = getUtility(ILaunchBag).user

        if len(string_args) == 1:
            person = get_person_or_team(string_args.pop())
        elif len(string_args) == 0:
            # Subscribe the sender of the email.
            person = user
        else:
            raise EmailProcessingError(
                get_error_message('subscribe-too-many-arguments.txt',
                                  error_templates=error_templates))

        if isinstance(bug, CreateBugParams):
            if len(bug.subscribers) == 0:
                bug.subscribers = [person]
            else:
                bug.subscribers.append(person)
            return bug, current_event

        if bug.isSubscribed(person):
            # but we still need to find the subscription
            for bugsubscription in bug.subscriptions:
                if bugsubscription.person == person:
                    break

        else:
            bugsubscription = bug.subscribe(person, user)
            notify(ObjectCreatedEvent(bugsubscription))

        return bug, current_event
Exemplo n.º 17
0
    def convertArguments(self, context):
        """See EmailCommand."""
        item_name = self.string_args[0]
        dbschema = self.dbschema
        try:
            dbitem = dbschema.items[item_name.upper()]
        except KeyError:
            dbitem = None

        if dbitem is None or dbitem.name == 'UNKNOWN':
            possible_items = [
                item.name.lower() for item in dbschema.items
                if item.name != 'UNKNOWN'
            ]
            possible_values = ', '.join(possible_items)
            raise EmailProcessingError(
                get_error_message('dbschema-command-wrong-argument.txt',
                                  command_name=self.name,
                                  arguments=possible_values,
                                  example_argument=possible_items[0]))

        return {self.name: dbitem}
Exemplo n.º 18
0
    def execute(self, bug, bug_event):
        """See IEmailCommand."""
        if bug is None:
            raise EmailProcessingError(get_error_message(
                'command-with-no-bug.txt', error_templates=error_templates),
                                       stop_processing=True)

        string_args = list(self.string_args)
        try:
            path = string_args.pop(0)
        except IndexError:
            raise EmailProcessingError(get_error_message(
                'affects-no-arguments.txt', error_templates=error_templates),
                                       stop_processing=True)
        try:
            bug_target = self.getBugTarget(path)
        except BugTargetNotFound as error:
            raise EmailProcessingError(unicode(error), stop_processing=True)
        event = None

        if isinstance(bug, CreateBugParams):
            # Enough information has been gathered to create a new bug.
            # If a series task is requested, create the non-series
            # equivalent here. The series will be nominated/targeted in
            # the remainder of the method.
            if ISeriesBugTarget.providedBy(bug_target):
                bug.target = bug_target.bugtarget_parent
            else:
                bug.target = bug_target
            bug, bug_event = getUtility(IBugSet).createBug(bug,
                                                           notify_event=False)
            event = ObjectCreatedEvent(bug.bugtasks[0])
            # Continue because the bug_target may be a subordinate bugtask.

        bugtask = bug.getBugTask(bug_target)
        if (bugtask is None
                and IDistributionSourcePackage.providedBy(bug_target)):
            # If there's a distribution task with no source package, use
            # that one.
            bugtask = bug.getBugTask(bug_target.distribution)
            if bugtask is not None:
                bugtask_before_edit = Snapshot(bugtask, providing=IBugTask)
                bugtask.transitionToTarget(bug_target,
                                           getUtility(ILaunchBag).user)
                event = ObjectModifiedEvent(bugtask, bugtask_before_edit,
                                            ['sourcepackagename'])

        if bugtask is None:
            try:
                bugtask = self._create_bug_task(bug, bug_target)
            except IllegalTarget as e:
                raise EmailProcessingError(get_error_message(
                    'cannot-add-task.txt',
                    error_templates=error_templates,
                    bug_id=bug.id,
                    target_name=bug_target.name,
                    reason=e[0]),
                                           stop_processing=True)
            event = ObjectCreatedEvent(bugtask)

        return bugtask, event, bug_event
Exemplo n.º 19
0
 def execute(self, context, current_event):
     raise EmailProcessingError(
         get_error_message('bug-importance.txt',
                           error_templates=error_templates,
                           argument=self.name))