656
655
"""See `IBugTarget`."""
657
656
return get_bug_tags("BugTask.distribution = %s" % sqlvalues(self))
659
def getBranchTips(self, user=None, since=None):
658
def getBranchTips(self, since=None):
660
659
"""See `IDistribution`."""
661
# This, ignoring privacy issues, is what we want.
663
SELECT Branch.unique_name,
664
Branch.last_scanned_id,
665
SPBDS.name AS distro_series_name,
671
ON Branch.distroseries = DistroSeries.id
672
LEFT OUTER JOIN SeriesSourcePackageBranch
673
ON Branch.id = SeriesSourcePackageBranch.branch
674
LEFT OUTER JOIN DistroSeries SPBDS
675
-- (SPDBS stands for Source Package Branch Distro Series)
676
ON SeriesSourcePackageBranch.distroseries = SPBDS.id
677
WHERE DistroSeries.distribution = %s
678
""" % sqlvalues(self.id)
661
SELECT unique_name, last_scanned_id, SPBDS.name FROM Branch
663
ON Branch.distroseries = DistroSeries.id
664
LEFT OUTER JOIN SeriesSourcePackageBranch
665
ON Branch.id = SeriesSourcePackageBranch.branch
666
LEFT OUTER JOIN DistroSeries SPBDS
667
-- (SPDBS stands for Source Package Branch Distro Series)
668
ON SeriesSourcePackageBranch.distroseries = SPBDS.id
669
WHERE DistroSeries.distribution = %s""" % sqlvalues(self.id)
679
671
if since is not None:
680
# If "since" was provided, take into account.
682
' AND branch.last_scanned > %s\n' % sqlvalues(since))
684
# Now we see just a touch of privacy concerns.
685
# If the current user is anonymous, they cannot see any private
687
base_query += (' AND NOT Branch.private\n')
688
# We want to order the results, in part for easier grouping at the
690
base_query += 'ORDER BY unique_name, last_scanned_id'
692
user.inTeam(getUtility(ILaunchpadCelebrities).admin)):
693
# Anonymous is already handled above; admins can see everything.
694
# In both cases, we can just use the query as it already stands.
697
# Otherwise (an authenticated, non-admin user), we need to do some
698
# more sophisticated privacy dances. Note that the one thing we
699
# are ignoring here is stacking. See the discussion in comment 1
700
# of https://bugs.launchpad.net/launchpad/+bug/812335 . Often, we
701
# use unions for this kind of work. The WITH statement can give
702
# us a similar approach with more flexibility. In both cases,
703
# we're essentially declaring that we have a better idea of a good
704
# high-level query plan than Postgres will.
708
FROM TeamParticipation
709
WHERE TeamParticipation.person = %(user)s
714
), private_branches AS (
722
), owned_branch_ids AS (
723
SELECT private_branches.id
724
FROM private_branches
725
JOIN principals ON private_branches.owner = principals.id
726
), subscribed_branch_ids AS (
727
SELECT private_branches.id
728
FROM private_branches
729
JOIN BranchSubscription
730
ON BranchSubscription.branch = private_branches.id
732
ON BranchSubscription.person = principals.id
734
SELECT unique_name, last_scanned_id, distro_series_name
737
id IN (SELECT id FROM owned_branch_ids) OR
738
id IN (SELECT id FROM subscribed_branch_ids)
739
""" % dict(base_query=base_query, user=quote(user.id))
741
data = Store.of(self).execute(query + ';')
673
' AND branch.last_scanned > %s' % sqlvalues(since))
675
query += ' ORDER BY unique_name, last_scanned_id;'
677
data = Store.of(self).execute(query)
744
680
# Group on location (unique_name) and revision (last_scanned_id).