launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #16314
[Merge] lp:~cprov/launchpad/private-branches-tips into lp:launchpad
Celso Providelo has proposed merging lp:~cprov/launchpad/private-branches-tips into lp:launchpad.
Requested reviews:
William Grant (wgrant)
For more details, see:
https://code.launchpad.net/~cprov/launchpad/private-branches-tips/+merge/200530
Refactoring IDistribution.getBranchTips() to deal with branch privacy properly.
--
https://code.launchpad.net/~cprov/launchpad/private-branches-tips/+merge/200530
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2013-08-29 10:49:29 +0000
+++ lib/lp/registry/model/distribution.py 2014-01-06 13:28:59 +0000
@@ -10,7 +10,6 @@
]
import itertools
-from operator import itemgetter
from sqlobject import (
BoolCol,
@@ -23,6 +22,7 @@
Desc,
Exists,
Join,
+ LeftJoin,
Max,
Not,
Or,
@@ -632,101 +632,61 @@
def getBranchTips(self, user=None, since=None):
"""See `IDistribution`."""
- # This, ignoring privacy issues, is what we want.
- base_query = """
- SELECT Branch.unique_name,
- Branch.last_scanned_id,
- SPBDS.name AS distro_series_name,
- Branch.id,
- Branch.information_type,
- Branch.owner
- FROM Branch
- JOIN DistroSeries
- ON Branch.distroseries = DistroSeries.id
- LEFT OUTER JOIN SeriesSourcePackageBranch
- ON Branch.id = SeriesSourcePackageBranch.branch
- LEFT OUTER JOIN DistroSeries SPBDS
- -- (SPDBS stands for Source Package Branch Distro Series)
- ON SeriesSourcePackageBranch.distroseries = SPBDS.id
- WHERE DistroSeries.distribution = %s
- """ % sqlvalues(self.id)
+ from lp.code.model.branch import (
+ Branch, get_branch_privacy_filter)
+ from lp.code.model.seriessourcepackagebranch import (
+ SeriesSourcePackageBranch)
+
+ clauses = [
+ DistroSeries.distribution == self.id,
+ get_branch_privacy_filter(user),
+ ]
+
if since is not None:
# If "since" was provided, take into account.
- base_query += (
- ' AND branch.last_scanned > %s\n' % sqlvalues(since))
- if user is None:
- # Now we see just a touch of privacy concerns.
- # If the current user is anonymous, they cannot see any private
- # branches.
- base_query += (
- ' AND Branch.information_type in %s\n'
- % sqlvalues(PUBLIC_INFORMATION_TYPES))
- # We want to order the results, in part for easier grouping at the
- # end.
- base_query += 'ORDER BY unique_name, last_scanned_id'
- if (user is None or
- user.inTeam(getUtility(ILaunchpadCelebrities).admin)):
- # Anonymous is already handled above; admins can see everything.
- # In both cases, we can just use the query as it already stands.
- query = base_query
- else:
- # Otherwise (an authenticated, non-admin user), we need to do some
- # more sophisticated privacy dances. Note that the one thing we
- # are ignoring here is stacking. See the discussion in comment 1
- # of https://bugs.launchpad.net/launchpad/+bug/812335 . Often, we
- # use unions for this kind of work. The WITH statement can give
- # us a similar approach with more flexibility. In both cases,
- # we're essentially declaring that we have a better idea of a good
- # high-level query plan than Postgres will.
- query = """
- WITH principals AS (
- SELECT team AS id
- FROM TeamParticipation
- WHERE TeamParticipation.person = %(user)s
- UNION
- SELECT %(user)s
- ), all_branches AS (
- %(base_query)s
- ), private_branches AS (
- SELECT unique_name,
- last_scanned_id,
- distro_series_name,
- id,
- owner
- FROM all_branches
- WHERE information_type in %(private_branches)s
- ), owned_branch_ids AS (
- SELECT private_branches.id
- FROM private_branches
- JOIN principals ON private_branches.owner = principals.id
- ), subscribed_branch_ids AS (
- SELECT private_branches.id
- FROM private_branches
- JOIN BranchSubscription
- ON BranchSubscription.branch = private_branches.id
- JOIN principals
- ON BranchSubscription.person = principals.id
- )
- SELECT unique_name, last_scanned_id, distro_series_name
- FROM all_branches
- WHERE information_type in %(public_branches)s OR
- id IN (SELECT id FROM owned_branch_ids) OR
- id IN (SELECT id FROM subscribed_branch_ids)
- """ % dict(
- base_query=base_query,
- user=quote(user.id),
- private_branches=quote(PRIVATE_INFORMATION_TYPES),
- public_branches=quote(PUBLIC_INFORMATION_TYPES))
-
- data = Store.of(self).execute(query + ';')
-
+ clauses.append(Branch.last_scanned > since)
+
+ OfficialSeries = ClassAlias(DistroSeries)
+ branches = IStore(self).using(
+ Branch,
+ Join(DistroSeries,
+ DistroSeries.id == Branch.distroseriesID),
+ LeftJoin(
+ SeriesSourcePackageBranch,
+ SeriesSourcePackageBranch.branchID == Branch.id),
+ LeftJoin(
+ OfficialSeries,
+ OfficialSeries.id == SeriesSourcePackageBranch.distroseriesID),
+ ).find(
+ # XXX cprov 20140106: Storm query specs with LeftJoin does not
+ # allow loading only specific fields ('Branch.unique_name',
+ # 'Branch.last_scanned_id', 'OfficialSeries.name') which could
+ # the load on DB.
+ (Branch, OfficialSeries),
+ And(*clauses)
+ ).order_by(
+ Branch.unique_name,
+ Branch.last_scanned_id
+ )
+
+ # Group/filter helpers.
+ def get_branch_key(item):
+ (branch, series) = item
+ return (branch.unique_name, branch.last_scanned_id)
+
+ def get_series_name(item):
+ (branch, series) = item
+ if series:
+ return series.name
+
+ # Group on location (unique_name) and revision (last_scanned_id).
result = []
- # Group on location (unique_name) and revision (last_scanned_id).
- for key, group in itertools.groupby(data, itemgetter(0, 1)):
+ for key, group in itertools.groupby(branches, get_branch_key):
result.append(list(key))
# Pull out all the official series names and append them as a list
- # to the end of the current record, removing Nones from the list.
- result[-1].append(filter(None, map(itemgetter(2), group)))
+ # to the end of the current record.
+ result[-1].append(filter(None, map(get_series_name, group)))
+
return result
def getMirrorByName(self, name):
Follow ups