def getInvisibleArtifacts(self, person, branches=None, bugs=None): """See `ISharingService`.""" bugs_by_id = {} branches_by_id = {} for bug in bugs or []: bugs_by_id[bug.id] = bug for branch in branches or []: branches_by_id[branch.id] = branch # Load the bugs. visible_bug_ids = set() if bugs_by_id: param = BugTaskSearchParams( user=person, bug=any(*bugs_by_id.keys())) visible_bug_ids = set(getUtility(IBugTaskSet).searchBugIds(param)) invisible_bug_ids = set(bugs_by_id.keys()).difference(visible_bug_ids) invisible_bugs = [bugs_by_id[bug_id] for bug_id in invisible_bug_ids] # Load the branches. invisible_branches = [] if branches_by_id: all_branches = getUtility(IAllBranches) visible_branch_ids = all_branches.visibleByUser(person).withIds( *branches_by_id.keys()).getBranchIds() invisible_branch_ids = ( set(branches_by_id.keys()).difference(visible_branch_ids)) invisible_branches = [ branches_by_id[branch_id] for branch_id in invisible_branch_ids] return invisible_bugs, invisible_branches
def buglinks(self): """Return a list of dict with bug, title and can_see_bug keys for the linked bugs. It makes the Right Thing(tm) with private bug. """ # Do a regular search to get the bugtasks so that visibility is # evaluated and eager loading is performed. bug_ids = map(attrgetter("bugID"), self.context.bug_links) if not bug_ids: return [] bugtask_set = getUtility(IBugTaskSet) query = BugTaskSearchParams(user=self.user, bug=any(*bug_ids)) bugtasks = list(bugtask_set.search(query)) # collate by bug bugs = defaultdict(list) for task in bugtasks: bugs[task.bug].append(task) badges = bugtask_set.getBugTaskBadgeProperties(bugtasks) links = [] columns_to_show = ["id", "summary", "bugtargetdisplayname", "importance", "status"] for bug, tasks in bugs.items(): navigator = BugListingBatchNavigator( tasks, self.request, columns_to_show=columns_to_show, size=config.malone.buglist_batch_size ) get_property_cache(navigator).bug_badge_properties = badges links.append( {"bug": bug, "title": bug.title, "can_view_bug": True, "tasks": tasks, "batch_navigator": navigator} ) return links
def duplicates(self): """Return a list of dicts of duplicates. Each dict contains the title that should be shown and the bug object itself. This allows us to protect private bugs using a title like 'Private Bug'. """ duplicate_bugs = list(self.context.duplicates) current_task = self.current_bugtask dupes_in_current_context = dict( (bugtask.bug, bugtask) for bugtask in current_task.target.searchTasks( BugTaskSearchParams(self.user, bug=any(*duplicate_bugs)))) dupes = [] for bug in duplicate_bugs: dupe = {} try: dupe['title'] = bug.title except Unauthorized: dupe['title'] = 'Private Bug' dupe['id'] = bug.id # If the dupe has the same context as the one we're in, link # to that bug task directly. if bug in dupes_in_current_context: dupe['url'] = canonical_url(dupes_in_current_context[bug]) else: dupe['url'] = canonical_url(bug) dupes.append(dupe) return dupes
def getSharedArtifacts(self, pillar, person, user, include_bugs=True, include_branches=True, include_specifications=True): """See `ISharingService`.""" bug_ids = set() branch_ids = set() specification_ids = set() for artifact in self.getArtifactGrantsForPersonOnPillar( pillar, person): if artifact.bug_id and include_bugs: bug_ids.add(artifact.bug_id) elif artifact.branch_id and include_branches: branch_ids.add(artifact.branch_id) elif artifact.specification_id and include_specifications: specification_ids.add(artifact.specification_id) # Load the bugs. bugtasks = [] if bug_ids: param = BugTaskSearchParams(user=user, bug=any(*bug_ids)) param.setTarget(pillar) bugtasks = list(getUtility(IBugTaskSet).search(param)) # Load the branches. branches = [] if branch_ids: all_branches = getUtility(IAllBranches) wanted_branches = all_branches.visibleByUser(user).withIds( *branch_ids) branches = list(wanted_branches.getBranches()) specifications = [] if specification_ids: specifications = load(Specification, specification_ids) return bugtasks, branches, specifications
def linked_bugtasks(self): """Return a list of bugtasks linked to the branch.""" if self.context.is_series_branch: status_filter = searchbuilder.any(*UNRESOLVED_BUGTASK_STATUSES) else: status_filter = None return list(self.context.getLinkedBugTasks( self.user, status_filter))
def setSourcePackage(self, sourcepackage): """Set the sourcepackage context on which to filter the search.""" # Import this here to avoid circular dependencies from lp.registry.interfaces.sourcepackage import (ISourcePackage) if isinstance(sourcepackage, any): # Unwrap the source package. self.sourcepackagename = any( *[pkg.sourcepackagename for pkg in sourcepackage.query_values]) distroseries = any(*[ pkg.distroseries for pkg in sourcepackage.query_values if ISourcePackage.providedBy(pkg) ]) distributions = any(*[ pkg.distribution for pkg in sourcepackage.query_values if not ISourcePackage.providedBy(pkg) ]) if distroseries.query_values and not distributions.query_values: self.distroseries = distroseries elif not distroseries.query_values and distributions.query_values: self.distributions = distributions else: # At this point we have determined that either we have both # distroseries and distributions, or we have neither of them. # We will set both. Doing so will give us the cross-product, # because searching source packages is # sourcepackagename-specific rather than actually # context-specific. This is not ideal but is tolerable given # no actual use of mixed-type any() exists today. self.distroseries = distroseries self.distributions = distributions return if ISourcePackage.providedBy(sourcepackage): # This is a sourcepackage in a distro series. self.distroseries = sourcepackage.distroseries else: # This is a sourcepackage in a distribution. self.distribution = sourcepackage.distribution self.sourcepackagename = sourcepackage.sourcepackagename
def _anyfy(cls, value): """If value is a sequence, wrap its items with the `any` combinator. Otherwise, return value as is, or None if it's a zero-length sequence. """ if zope_isinstance(value, (list, tuple)): if len(value) > 1: return any(*value) elif len(value) == 1: return value[0] else: return None else: return value
def setSourcePackage(self, sourcepackage): """Set the sourcepackage context on which to filter the search.""" # Import this here to avoid circular dependencies from lp.registry.interfaces.sourcepackage import ( ISourcePackage) if isinstance(sourcepackage, any): # Unwrap the source package. self.sourcepackagename = any(*[ pkg.sourcepackagename for pkg in sourcepackage.query_values]) distroseries = any(*[pkg.distroseries for pkg in sourcepackage.query_values if ISourcePackage.providedBy(pkg)]) distributions = any(*[pkg.distribution for pkg in sourcepackage.query_values if not ISourcePackage.providedBy(pkg)]) if distroseries.query_values and not distributions.query_values: self.distroseries = distroseries elif not distroseries.query_values and distributions.query_values: self.distributions = distributions else: # At this point we have determined that either we have both # distroseries and distributions, or we have neither of them. # We will set both. Doing so will give us the cross-product, # because searching source packages is # sourcepackagename-specific rather than actually # context-specific. This is not ideal but is tolerable given # no actual use of mixed-type any() exists today. self.distroseries = distroseries self.distributions = distributions return if ISourcePackage.providedBy(sourcepackage): # This is a sourcepackage in a distro series. self.distroseries = sourcepackage.distroseries else: # This is a sourcepackage in a distribution. self.distribution = sourcepackage.distribution self.sourcepackagename = sourcepackage.sourcepackagename
def getVisibleArtifacts(self, person, branches=None, bugs=None, specifications=None, ignore_permissions=False): """See `ISharingService`.""" bugs_by_id = {} branches_by_id = {} for bug in bugs or []: if (not ignore_permissions and not check_permission('launchpad.View', bug)): raise Unauthorized bugs_by_id[bug.id] = bug for branch in branches or []: if (not ignore_permissions and not check_permission('launchpad.View', branch)): raise Unauthorized branches_by_id[branch.id] = branch for spec in specifications or []: if (not ignore_permissions and not check_permission('launchpad.View', spec)): raise Unauthorized # Load the bugs. visible_bug_ids = [] if bugs_by_id: param = BugTaskSearchParams( user=person, bug=any(*bugs_by_id.keys())) visible_bug_ids = set(getUtility(IBugTaskSet).searchBugIds(param)) visible_bugs = [bugs_by_id[bug_id] for bug_id in visible_bug_ids] # Load the branches. visible_branches = [] if branches_by_id: all_branches = getUtility(IAllBranches) wanted_branches = all_branches.visibleByUser(person).withIds( *branches_by_id.keys()) visible_branches = list(wanted_branches.getBranches()) visible_specs = [] if specifications: visible_private_spec_ids = self._getVisiblePrivateSpecificationIDs( person, specifications) visible_specs = [ spec for spec in specifications if spec.id in visible_private_spec_ids or not spec.private] return visible_bugs, visible_branches, visible_specs
def getInvisibleArtifacts(self, person, bugs=None, branches=None, gitrepositories=None): """See `ISharingService`.""" bug_ids = list(map(attrgetter("id"), bugs or [])) branch_ids = list(map(attrgetter("id"), branches or [])) gitrepository_ids = list(map(attrgetter("id"), gitrepositories or [])) # Load the bugs. invisible_bugs = [] if bug_ids: param = BugTaskSearchParams(user=person, bug=any(*bug_ids)) visible_bug_ids = set(getUtility(IBugTaskSet).searchBugIds(param)) invisible_bugs = [ bug for bug in bugs if bug.id not in visible_bug_ids ] # Load the branches. invisible_branches = [] if branch_ids: all_branches = getUtility(IAllBranches) visible_branch_ids = all_branches.visibleByUser(person).withIds( *branch_ids).getBranchIds() invisible_branches = [ branch for branch in branches if branch.id not in visible_branch_ids ] # Load the Git repositories. invisible_gitrepositories = [] if gitrepository_ids: all_gitrepositories = getUtility(IAllGitRepositories) visible_gitrepository_ids = all_gitrepositories.visibleByUser( person).withIds(*gitrepository_ids).getRepositoryIds() invisible_gitrepositories = [ gitrepository for gitrepository in gitrepositories if gitrepository.id not in visible_gitrepository_ids ] return invisible_bugs, invisible_branches, invisible_gitrepositories
def test_tags_with_any_and_all(self): # If the tags are bundled in a c.l.searchbuilder.any or .all, the # find_any_tags attribute will also be updated. bug_subscription_filter = BugSubscriptionFilter() self.assertEqual(frozenset(), bug_subscription_filter.tags) self.assertFalse(bug_subscription_filter.find_all_tags) bug_subscription_filter.tags = searchbuilder.all(u"foo") self.assertEqual(frozenset((u"foo",)), bug_subscription_filter.tags) self.assertTrue(bug_subscription_filter.find_all_tags) # Not using `searchbuilder.any` or `.all` leaves find_all_tags # unchanged. bug_subscription_filter.tags = [u"-bar"] self.assertEqual(frozenset((u"-bar",)), bug_subscription_filter.tags) self.assertTrue(bug_subscription_filter.find_all_tags) bug_subscription_filter.tags = searchbuilder.any(u"baz") self.assertEqual(frozenset((u"baz",)), bug_subscription_filter.tags) self.assertFalse(bug_subscription_filter.find_all_tags)
def test_tags_with_any_and_all(self): # If the tags are bundled in a c.l.searchbuilder.any or .all, the # find_any_tags attribute will also be updated. bug_subscription_filter = BugSubscriptionFilter() self.assertEqual(frozenset(), bug_subscription_filter.tags) self.assertFalse(bug_subscription_filter.find_all_tags) bug_subscription_filter.tags = searchbuilder.all(u"foo") self.assertEqual(frozenset((u"foo", )), bug_subscription_filter.tags) self.assertTrue(bug_subscription_filter.find_all_tags) # Not using `searchbuilder.any` or `.all` leaves find_all_tags # unchanged. bug_subscription_filter.tags = [u"-bar"] self.assertEqual(frozenset((u"-bar", )), bug_subscription_filter.tags) self.assertTrue(bug_subscription_filter.find_all_tags) bug_subscription_filter.tags = searchbuilder.any(u"baz") self.assertEqual(frozenset((u"baz", )), bug_subscription_filter.tags) self.assertFalse(bug_subscription_filter.find_all_tags)
def buglinks(self): """Return a list of dict with bug, title and can_see_bug keys for the linked bugs. It makes the Right Thing(tm) with private bug. """ # Do a regular search to get the bugtasks so that visibility is # evaluated and eager loading is performed. bug_ids = [bug.id for bug in self.context.bugs] if not bug_ids: return [] bugtask_set = getUtility(IBugTaskSet) query = BugTaskSearchParams(user=self.user, bug=any(*bug_ids)) bugtasks = list(bugtask_set.search(query)) # collate by bug bugs = defaultdict(list) for task in bugtasks: bugs[task.bug].append(task) badges = bugtask_set.getBugTaskBadgeProperties(bugtasks) tags = bugtask_set.getBugTaskTags(bugtasks) people = bugtask_set.getBugTaskPeople(bugtasks) links = [] columns_to_show = [ "id", "summary", "bugtargetdisplayname", "importance", "status" ] for bug, tasks in bugs.items(): navigator = BugListingBatchNavigator( tasks, self.request, columns_to_show=columns_to_show, size=config.malone.buglist_batch_size) get_property_cache(navigator).bug_badge_properties = badges get_property_cache(navigator).tags_for_batch = tags get_property_cache(navigator).bugtask_people = people links.append({ 'bug': bug, 'title': bug.title, 'can_view_bug': True, 'tasks': tasks, 'batch_navigator': navigator, }) return links
def check_bug_links(self, links): """Checks links of the form /bugs/100""" invalid_links = {} valid_links = {} user = self.user # List of all the bugs we are checking. bugs_ids = set([int(link[len('/bugs/'):]) for link in links]) if bugs_ids: params = BugTaskSearchParams( user=user, status=None, bug=any(*bugs_ids)) bugtasks = getUtility(IBugTaskSet).search(params) for task in bugtasks: valid_links['/bugs/' + str(task.bug.id)] = task.bug.title # Remove valid bugs from the list of all the bugs. if task.bug.id in bugs_ids: bugs_ids.remove(task.bug.id) # We should now have only invalid bugs in bugs list for bug in bugs_ids: invalid_links['/bugs/%d' % bug] = ( "Bug %s cannot be found" % bug) return {'valid': valid_links, 'invalid': invalid_links}
def fromSearchForm(cls, user, order_by=('-importance', ), search_text=None, status=list(UNRESOLVED_BUGTASK_STATUSES), importance=None, assignee=None, bug_reporter=None, bug_supervisor=None, bug_commenter=None, bug_subscriber=None, owner=None, affected_user=None, affects_me=False, has_patch=None, has_cve=None, distribution=None, tags=None, tags_combinator=BugTagsSearchCombinator.ALL, omit_duplicates=True, omit_targeted=None, status_upstream=None, milestone=None, component=None, nominated_for=None, sourcepackagename=None, has_no_package=None, hardware_bus=None, hardware_vendor_id=None, hardware_product_id=None, hardware_driver_name=None, hardware_driver_package_name=None, hardware_owner_is_bug_reporter=None, hardware_owner_is_affected_by_bug=False, hardware_owner_is_subscribed_to_bug=False, hardware_is_linked_to_bug=False, linked_branches=None, linked_blueprints=None, structural_subscriber=None, modified_since=None, created_since=None, created_before=None, information_type=None): """Create and return a new instance using the parameter list.""" search_params = cls(user=user, orderby=order_by) search_params.searchtext = search_text search_params.status = cls._anyfy(status) search_params.importance = cls._anyfy(importance) search_params.assignee = assignee search_params.bug_reporter = bug_reporter search_params.bug_supervisor = bug_supervisor search_params.bug_commenter = bug_commenter search_params.subscriber = bug_subscriber search_params.owner = owner search_params.affected_user = affected_user search_params.distribution = distribution if has_patch: # Import this here to avoid circular imports from lp.bugs.interfaces.bugattachment import ( BugAttachmentType) search_params.attachmenttype = BugAttachmentType.PATCH search_params.has_cve = has_cve if zope_isinstance(tags, (list, tuple)): if len(tags) > 0: if tags_combinator == BugTagsSearchCombinator.ALL: search_params.tag = all(*tags) else: search_params.tag = any(*tags) elif zope_isinstance(tags, str): search_params.tag = tags elif tags is None: pass # tags not supplied else: raise AssertionError( 'Tags can only be supplied as a list or a string.') search_params.omit_dupes = omit_duplicates search_params.omit_targeted = omit_targeted if status_upstream is not None: if 'pending_bugwatch' in status_upstream: search_params.pending_bugwatch_elsewhere = True if 'resolved_upstream' in status_upstream: search_params.resolved_upstream = True if 'open_upstream' in status_upstream: search_params.open_upstream = True if 'hide_upstream' in status_upstream: search_params.has_no_upstream_bugtask = True search_params.milestone = cls._anyfy(milestone) search_params.component = cls._anyfy(component) search_params.sourcepackagename = sourcepackagename if has_no_package: search_params.sourcepackagename = NULL search_params.nominated_for = nominated_for search_params.hardware_bus = hardware_bus search_params.hardware_vendor_id = hardware_vendor_id search_params.hardware_product_id = hardware_product_id search_params.hardware_driver_name = hardware_driver_name search_params.hardware_driver_package_name = ( hardware_driver_package_name) search_params.hardware_owner_is_bug_reporter = ( hardware_owner_is_bug_reporter) search_params.hardware_owner_is_affected_by_bug = ( hardware_owner_is_affected_by_bug) search_params.hardware_owner_is_subscribed_to_bug = ( hardware_owner_is_subscribed_to_bug) search_params.hardware_is_linked_to_bug = ( hardware_is_linked_to_bug) search_params.linked_branches = linked_branches search_params.linked_blueprints = linked_blueprints search_params.structural_subscriber = structural_subscriber search_params.modified_since = modified_since search_params.created_since = created_since search_params.created_before = created_before search_params.information_type = information_type return search_params
def fromSearchForm(cls, user, order_by=('-importance', ), search_text=None, status=list(UNRESOLVED_BUGTASK_STATUSES), importance=None, assignee=None, bug_reporter=None, bug_supervisor=None, bug_commenter=None, bug_subscriber=None, owner=None, affected_user=None, affects_me=False, has_patch=None, has_cve=None, distribution=None, tags=None, tags_combinator=BugTagsSearchCombinator.ALL, omit_duplicates=True, omit_targeted=None, status_upstream=None, milestone=None, component=None, nominated_for=None, sourcepackagename=None, has_no_package=None, hardware_bus=None, hardware_vendor_id=None, hardware_product_id=None, hardware_driver_name=None, hardware_driver_package_name=None, hardware_owner_is_bug_reporter=None, hardware_owner_is_affected_by_bug=False, hardware_owner_is_subscribed_to_bug=False, hardware_is_linked_to_bug=False, linked_branches=None, linked_merge_proposals=None, linked_blueprints=None, structural_subscriber=None, modified_since=None, created_since=None, created_before=None, information_type=None): """Create and return a new instance using the parameter list.""" search_params = cls(user=user, orderby=order_by) search_params.searchtext = search_text search_params.status = cls._anyfy(status) search_params.importance = cls._anyfy(importance) search_params.assignee = assignee search_params.bug_reporter = bug_reporter search_params.bug_supervisor = bug_supervisor search_params.bug_commenter = bug_commenter search_params.subscriber = bug_subscriber search_params.owner = owner search_params.affected_user = affected_user search_params.distribution = distribution if has_patch: # Import this here to avoid circular imports from lp.bugs.interfaces.bugattachment import (BugAttachmentType) search_params.attachmenttype = BugAttachmentType.PATCH search_params.has_cve = has_cve if zope_isinstance(tags, (list, tuple)): if len(tags) > 0: if tags_combinator == BugTagsSearchCombinator.ALL: search_params.tag = all(*tags) else: search_params.tag = any(*tags) elif zope_isinstance(tags, str): search_params.tag = tags elif tags is None: pass # tags not supplied else: raise AssertionError( 'Tags can only be supplied as a list or a string.') search_params.omit_dupes = omit_duplicates search_params.omit_targeted = omit_targeted if status_upstream is not None: if 'pending_bugwatch' in status_upstream: search_params.pending_bugwatch_elsewhere = True if 'resolved_upstream' in status_upstream: search_params.resolved_upstream = True if 'open_upstream' in status_upstream: search_params.open_upstream = True if 'hide_upstream' in status_upstream: search_params.has_no_upstream_bugtask = True search_params.milestone = cls._anyfy(milestone) search_params.component = cls._anyfy(component) search_params.sourcepackagename = sourcepackagename if has_no_package: search_params.sourcepackagename = NULL search_params.nominated_for = nominated_for search_params.hardware_bus = hardware_bus search_params.hardware_vendor_id = hardware_vendor_id search_params.hardware_product_id = hardware_product_id search_params.hardware_driver_name = hardware_driver_name search_params.hardware_driver_package_name = ( hardware_driver_package_name) search_params.hardware_owner_is_bug_reporter = ( hardware_owner_is_bug_reporter) search_params.hardware_owner_is_affected_by_bug = ( hardware_owner_is_affected_by_bug) search_params.hardware_owner_is_subscribed_to_bug = ( hardware_owner_is_subscribed_to_bug) search_params.hardware_is_linked_to_bug = (hardware_is_linked_to_bug) search_params.linked_branches = linked_branches search_params.linked_merge_proposals = linked_merge_proposals search_params.linked_blueprints = linked_blueprints search_params.structural_subscriber = structural_subscriber search_params.modified_since = modified_since search_params.created_since = created_since search_params.created_before = created_before search_params.information_type = information_type return search_params
def getExtendedRevisionDetails(self, user, revisions): """See `IBranchCollection`.""" if not revisions: return [] branch = revisions[0].branch def make_rev_info(branch_revision, merge_proposal_revs, linked_bugtasks): rev_info = { 'revision': branch_revision, 'linked_bugtasks': None, 'merge_proposal': None, } merge_proposal = merge_proposal_revs.get(branch_revision.sequence) rev_info['merge_proposal'] = merge_proposal if merge_proposal is not None: rev_info['linked_bugtasks'] = linked_bugtasks.get( merge_proposal.source_branch.id) return rev_info rev_nos = [revision.sequence for revision in revisions] merge_proposals = self.getMergeProposals( target_branch=branch, merged_revnos=rev_nos, statuses=[BranchMergeProposalStatus.MERGED]) merge_proposal_revs = dict([(mp.merged_revno, mp) for mp in merge_proposals]) source_branch_ids = [mp.source_branch.id for mp in merge_proposals] linked_bugtasks = defaultdict(list) if source_branch_ids: # We get the bugtasks for our merge proposal branches # First, the bug ids params = BugTaskSearchParams( user=user, status=None, linked_branches=any(*source_branch_ids)) bug_ids = getUtility(IBugTaskSet).searchBugIds(params) # Then the bug tasks and branches store = IStore(BugBranch) rs = store.using( BugBranch, Join(BugTask, BugTask.bugID == BugBranch.bugID), ).find((BugTask, BugBranch), BugBranch.bugID.is_in(bug_ids), BugBranch.branchID.is_in(source_branch_ids)) # Build up a collection of bugtasks for each branch bugtasks_for_branch = defaultdict(list) for bugtask, bugbranch in rs: bugtasks_for_branch[bugbranch.branch].append(bugtask) # Now filter those down to one bugtask per branch for branch, tasks in bugtasks_for_branch.iteritems(): linked_bugtasks[branch.id].extend( filter_bugtasks_by_context(branch.target.context, tasks)) return [ make_rev_info(rev, merge_proposal_revs, linked_bugtasks) for rev in revisions ]
def getExtendedRevisionDetails(self, user, revisions): """See `IBranchCollection`.""" if not revisions: return [] branch = revisions[0].branch def make_rev_info( branch_revision, merge_proposal_revs, linked_bugtasks): rev_info = { 'revision': branch_revision, 'linked_bugtasks': None, 'merge_proposal': None, } merge_proposal = merge_proposal_revs.get(branch_revision.sequence) rev_info['merge_proposal'] = merge_proposal if merge_proposal is not None: rev_info['linked_bugtasks'] = linked_bugtasks.get( merge_proposal.source_branch.id) return rev_info rev_nos = [revision.sequence for revision in revisions] merge_proposals = self.getMergeProposals( target_branch=branch, merged_revnos=rev_nos, statuses=[BranchMergeProposalStatus.MERGED]) merge_proposal_revs = dict( [(mp.merged_revno, mp) for mp in merge_proposals]) source_branch_ids = [mp.source_branch.id for mp in merge_proposals] linked_bugtasks = defaultdict(list) if source_branch_ids: # We get the bugtasks for our merge proposal branches # First, the bug ids params = BugTaskSearchParams( user=user, status=None, linked_branches=any(*source_branch_ids)) bug_ids = getUtility(IBugTaskSet).searchBugIds(params) # Then the bug tasks and branches store = IStore(BugBranch) rs = store.using( BugBranch, Join(BugTask, BugTask.bugID == BugBranch.bugID), ).find( (BugTask, BugBranch), BugBranch.bugID.is_in(bug_ids), BugBranch.branchID.is_in(source_branch_ids) ) # Build up a collection of bugtasks for each branch bugtasks_for_branch = defaultdict(list) for bugtask, bugbranch in rs: bugtasks_for_branch[bugbranch.branch].append(bugtask) # Now filter those down to one bugtask per branch for branch, tasks in bugtasks_for_branch.iteritems(): linked_bugtasks[branch.id].extend( filter_bugtasks_by_context(branch.target.context, tasks)) return [make_rev_info(rev, merge_proposal_revs, linked_bugtasks) for rev in revisions]
def getVisibleArtifacts(self, person, bugs=None, branches=None, gitrepositories=None, specifications=None, ignore_permissions=False): """See `ISharingService`.""" bug_ids = [] branch_ids = [] gitrepository_ids = [] for bug in bugs or []: if (not ignore_permissions and not check_permission('launchpad.View', bug)): raise Unauthorized bug_ids.append(bug.id) for branch in branches or []: if (not ignore_permissions and not check_permission('launchpad.View', branch)): raise Unauthorized branch_ids.append(branch.id) for gitrepository in gitrepositories or []: if (not ignore_permissions and not check_permission('launchpad.View', gitrepository)): raise Unauthorized gitrepository_ids.append(gitrepository.id) for spec in specifications or []: if (not ignore_permissions and not check_permission('launchpad.View', spec)): raise Unauthorized # Load the bugs. visible_bugs = [] if bug_ids: param = BugTaskSearchParams(user=person, bug=any(*bug_ids)) visible_bug_ids = set(getUtility(IBugTaskSet).searchBugIds(param)) visible_bugs = [bug for bug in bugs if bug.id in visible_bug_ids] # Load the branches. visible_branches = [] if branch_ids: all_branches = getUtility(IAllBranches) wanted_branches = all_branches.visibleByUser(person).withIds( *branch_ids) visible_branches = list(wanted_branches.getBranches()) # Load the Git repositories. visible_gitrepositories = [] if gitrepository_ids: all_gitrepositories = getUtility(IAllGitRepositories) wanted_gitrepositories = all_gitrepositories.visibleByUser( person).withIds(*gitrepository_ids) visible_gitrepositories = list( wanted_gitrepositories.getRepositories()) # Load the specifications. visible_specs = [] if specifications: visible_private_spec_ids = self._getVisiblePrivateSpecificationIDs( person, specifications) visible_specs = [ spec for spec in specifications if spec.id in visible_private_spec_ids or not spec.private ] return (visible_bugs, visible_branches, visible_gitrepositories, visible_specs)