← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/remove-branch-distro into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/remove-branch-distro into lp:launchpad.

Commit message:
Remove branch-distro, which we haven't used for some time.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/remove-branch-distro/+merge/342065

With git-ubuntu building up steam, it seems unlikely that this will be resurrected, so we probably don't need to keep this around.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/remove-branch-distro into lp:launchpad.
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg	2017-05-25 17:22:38 +0000
+++ database/schema/security.cfg	2018-03-25 15:48:42 +0000
@@ -715,30 +715,6 @@
 public.xref                               = SELECT, INSERT, DELETE
 type=user
 
-[branch-distro]
-public.accessartifact            = SELECT, INSERT, DELETE
-public.accesspolicy              = SELECT
-public.accesspolicyartifact      = SELECT, INSERT, DELETE
-public.accesspolicygrant         = SELECT
-public.accessartifactgrant       = SELECT
-public.branch                    = SELECT, INSERT, UPDATE
-public.branchrevision            = SELECT, INSERT
-public.branchsubscription        = SELECT, INSERT
-public.distribution              = SELECT
-public.distributionsourcepackage = SELECT, INSERT, UPDATE, DELETE
-public.distributionsourcepackagecache = SELECT, INSERT
-public.distroseries              = SELECT
-public.karma                     = SELECT, INSERT
-public.karmaaction               = SELECT
-public.person                    = SELECT
-public.product                   = SELECT
-public.revision                  = SELECT
-public.seriessourcepackagebranch = SELECT, INSERT, DELETE
-public.sourcepackagename         = SELECT
-public.teamparticipation         = SELECT
-public.validpersoncache          = SELECT
-type=user
-
 [targetnamecacheupdater]
 groups=script
 public.binarypackagename                        = SELECT

=== removed file 'lib/lp/codehosting/branchdistro.py'
--- lib/lp/codehosting/branchdistro.py	2013-06-20 05:50:00 +0000
+++ lib/lp/codehosting/branchdistro.py	1970-01-01 00:00:00 +0000
@@ -1,385 +0,0 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Opening a new DistroSeries for branch based development.
-
-Intended to be run just after a new distro series has been completed, this
-script will create an official package branch in the new series for every one
-in the old.  The old branch will become stacked on the new, to avoid a using
-too much disk space whilst retaining best performance for the new branch.
-"""
-
-__metaclass__ = type
-__all__ = [
-    'DistroBrancher',
-    'switch_branches',
-    ]
-
-import os
-
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import (
-    NotBranchError,
-    NotStacked,
-    )
-from bzrlib.revision import NULL_REVISION
-import transaction
-from zope.component import getUtility
-
-from lp.code.enums import (
-    BranchLifecycleStatus,
-    BranchType,
-    )
-from lp.code.errors import BranchExists
-from lp.code.interfaces.branchcollection import IAllBranches
-from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
-from lp.code.interfaces.seriessourcepackagebranch import (
-    IFindOfficialBranchLinks,
-    )
-from lp.code.model.branchrevision import BranchRevision
-from lp.codehosting.vfs import branch_id_to_path
-from lp.registry.interfaces.distribution import IDistributionSet
-from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.services.config import config
-from lp.services.database.interfaces import IMasterStore
-
-
-def switch_branches(prefix, scheme, old_db_branch, new_db_branch):
-    """Move bzr data from an old to a new branch, leaving old stacked on new.
-
-    This function is intended to be used just after Ubuntu is released to
-    create (at the bzr level) a new trunk branch for a source package for the
-    next release of the distribution.  We move the bzr data to the location
-    for the new branch and replace the trunk branch for the just released
-    version with a stacked branch pointing at the new branch.
-
-    The procedure is to complicated to be carried out atomically, so if this
-    function is interrupted things may be a little inconsistent (e.g. there
-    might be a branch in the old location, but not stacked on the new location
-    yet).  There should be no data loss though.
-
-    :param prefix: The non-branch id dependent part of the physical path to
-        the branches on disk.
-    :param scheme: The branches should be open-able at a URL of the form
-        ``scheme + :/// + unique_name``.
-    :param old_db_branch: The branch that currently has the trunk bzr data.
-    :param old_db_branch: The new trunk branch.  This should not have any
-        presence on disk yet.
-    """
-    # Move .bzr directory from old to new location, crashing through the
-    # abstraction we usually hide our branch locations behind.
-    old_underlying_path = os.path.join(
-        prefix, branch_id_to_path(old_db_branch.id))
-    new_underlying_path = os.path.join(
-        prefix, branch_id_to_path(new_db_branch.id))
-    os.makedirs(new_underlying_path)
-    os.rename(
-        os.path.join(old_underlying_path, '.bzr'),
-        os.path.join(new_underlying_path, '.bzr'))
-
-    # Create branch at old location -- we use the "clone('null:')" trick to
-    # preserve the format.  We have to open at the logical, unique_name-based,
-    # location so that it works to set the stacked on url to '/' + a
-    # unique_name.
-    new_location_bzrdir = BzrDir.open(
-        scheme + ':///' + new_db_branch.unique_name)
-    old_location_bzrdir = new_location_bzrdir.clone(
-        scheme + ':///' + old_db_branch.unique_name, revision_id='null:')
-
-    # Set the stacked on url for old location.
-    old_location_branch = old_location_bzrdir.open_branch()
-    old_location_branch.set_stacked_on_url('/' + new_db_branch.unique_name)
-
-    # Pull from new location to old -- this won't actually transfer any
-    # revisions, just update the last revision pointer.
-    old_location_branch.pull(new_location_bzrdir.open_branch())
-
-
-class DistroBrancher:
-    """Open a new distroseries for branch based development.
-
-    `makeNewBranches` will create an official package branch in the new series
-    for every one in the old.  `checkNewBranches` will check that a previous
-    run of this script completed successfully -- this is only likely to be
-    really useful if a script run died halfway through or had to be killed.
-    """
-
-    def __init__(self, logger, old_distroseries, new_distroseries):
-        """Construct a `DistroBrancher`.
-
-        The old and new distroseries must be from the same distribution, but
-        not the same distroseries.
-
-        :param logger: A Logger.  Problems will be logged to this object at
-            the WARNING level or higher; progress reports will be logged at
-            the DEBUG level.
-        :param old_distroseries: The distroseries that will be examined to
-            find existing source package branches.
-        :param new_distroseries: The distroseries that will have new official
-            source branches made for it.
-        """
-        self.logger = logger
-        if old_distroseries.distribution != new_distroseries.distribution:
-            raise AssertionError(
-                "%s and %s are from different distributions!" %
-                (old_distroseries, new_distroseries))
-        if old_distroseries == new_distroseries:
-            raise AssertionError(
-                "New and old distributions must be different!")
-        self.old_distroseries = old_distroseries
-        self.new_distroseries = new_distroseries
-
-    @classmethod
-    def fromNames(cls, logger, distribution_name, old_distroseries_name,
-                  new_distroseries_name):
-        """Make a `DistroBrancher` from the names of a distro and two series.
-        """
-        distribution = getUtility(IDistributionSet).getByName(
-            distribution_name)
-        new_distroseries = distribution.getSeries(new_distroseries_name)
-        old_distroseries = distribution.getSeries(old_distroseries_name)
-        return cls(logger, old_distroseries, new_distroseries)
-
-    def _existingOfficialBranches(self):
-        """Return the collection of official branches in the old distroseries.
-        """
-        branches = getUtility(IAllBranches)
-        distroseries_branches = branches.inDistroSeries(self.old_distroseries)
-        return distroseries_branches.officialBranches().getBranches(
-            eager_load=False)
-
-    def checkConsistentOfficialPackageBranch(self, db_branch):
-        """Check that `db_branch` is a consistent official package branch.
-
-        'Consistent official package branch' means:
-
-         * It's a package branch (rather than a personal or junk branch).
-         * It's official for its SourcePackage and no other.
-
-        This function simply returns True or False -- any problems will be
-        logged to ``self.logger``.
-
-        :param db_branch: The `IBranch` to check.
-        :return: ``True`` if the branch is a consistent official package
-            branch, ``False`` otherwise.
-        """
-        if db_branch.product:
-            self.logger.warning(
-                "Encountered unexpected product branch %r",
-                db_branch.unique_name)
-            return False
-        if not db_branch.distroseries:
-            self.logger.warning(
-                "Encountered unexpected personal branch %s",
-                db_branch.unique_name)
-            return False
-        find_branch_links = getUtility(IFindOfficialBranchLinks)
-        links = list(find_branch_links.findForBranch(db_branch))
-        if len(links) == 0:
-            self.logger.warning(
-                "%s is not an official branch", db_branch.unique_name)
-            return False
-        elif len(links) > 1:
-            series_text = ', '.join([
-                link.sourcepackage.path for link in links])
-            self.logger.warning(
-                "%s is official for multiple series: %s",
-                db_branch.unique_name, series_text)
-            return False
-        elif links[0].sourcepackage != db_branch.sourcepackage:
-            self.logger.warning(
-                "%s is the official branch for %s but not its "
-                "sourcepackage", db_branch.unique_name,
-                links[0].sourcepackage.path)
-            return False
-        return True
-
-    def makeNewBranches(self):
-        """Make official branches in the new distroseries."""
-        for db_branch in self._existingOfficialBranches():
-            self.logger.debug("Processing %s" % db_branch.unique_name)
-            try:
-                self.makeOneNewBranch(db_branch)
-            except BranchExists:
-                pass
-
-    def checkNewBranches(self):
-        """Check the branches in the new distroseries are present and correct.
-
-        This function checks that every official package branch in the old
-        distroseries has a matching branch in the new distroseries and that
-        stacking is set up as we expect on disk.
-
-        Every branch will be checked, even if some fail.
-
-        This function simply returns True or False -- any problems will be
-        logged to ``self.logger``.
-
-        :return: ``True`` if every branch passes the check, ``False``
-            otherwise.
-        """
-        ok = True
-        for db_branch in self._existingOfficialBranches():
-            self.logger.debug("Checking %s" % db_branch.unique_name)
-            try:
-                if not self.checkOneBranch(db_branch):
-                    ok = False
-            except:
-                ok = False
-                self.logger.exception(
-                    "Unexpected error checking %s!", db_branch)
-        return ok
-
-    def checkOneBranch(self, old_db_branch):
-        """Check a branch in the old distroseries has been copied to the new.
-
-        This function checks that `old_db_branch` has a matching branch in the
-        new distroseries and that stacking is set up as we expect on disk.
-
-        This function simply returns True or False -- any problems will be
-        logged to ``self.logger``.
-
-        :param old_db_branch: The branch to check.
-        :return: ``True`` if the branch passes the check, ``False`` otherwise.
-        """
-        ok = self.checkConsistentOfficialPackageBranch(old_db_branch)
-        if not ok:
-            return ok
-        new_sourcepackage = self.new_distroseries.getSourcePackage(
-            old_db_branch.sourcepackagename)
-        new_db_branch = new_sourcepackage.getBranch(
-            PackagePublishingPocket.RELEASE)
-        if new_db_branch is None:
-            self.logger.warning(
-                "No official branch found for %s",
-                new_sourcepackage.path)
-            return False
-        ok = self.checkConsistentOfficialPackageBranch(new_db_branch)
-        if not ok:
-            return ok
-        # the branch in the new distroseries is unstacked
-        new_location = 'lp-internal:///' + new_db_branch.unique_name
-        try:
-            new_bzr_branch = Branch.open(new_location)
-        except NotBranchError:
-            self.logger.warning(
-                "No bzr branch at new location %s", new_location)
-            ok = False
-        else:
-            try:
-                new_stacked_on_url = new_bzr_branch.get_stacked_on_url()
-                ok = False
-                self.logger.warning(
-                    "New branch at %s is stacked on %s, should be "
-                    "unstacked.", new_location, new_stacked_on_url)
-            except NotStacked:
-                pass
-        # The branch in the old distroseries is stacked on that in the
-        # new.
-        old_location = 'lp-internal:///' + old_db_branch.unique_name
-        try:
-            old_bzr_branch = Branch.open(old_location)
-        except NotBranchError:
-            self.logger.warning(
-                "No bzr branch at old location %s", old_location)
-            ok = False
-        else:
-            try:
-                old_stacked_on_url = old_bzr_branch.get_stacked_on_url()
-                if old_stacked_on_url != '/' + new_db_branch.unique_name:
-                    self.logger.warning(
-                        "Old branch at %s is stacked on %s, should be "
-                        "stacked on %s", old_location, old_stacked_on_url,
-                        '/' + new_db_branch.unique_name)
-                    ok = False
-            except NotStacked:
-                self.logger.warning(
-                    "Old branch at %s is not stacked, should be stacked "
-                    "on %s", old_location,
-                    '/' + new_db_branch.unique_name)
-                ok = False
-            # The branch in the old distroseries has no revisions in its
-            # repository.  We open the repository independently of the
-            # branch because the branch's repository has had its fallback
-            # location activated. Note that this check might fail if new
-            # revisions get pushed to the branch in the old distroseries,
-            # which shouldn't happen but isn't totally impossible.
-            old_repo = BzrDir.open(old_location).open_repository()
-            if len(old_repo.all_revision_ids()) > 0:
-                self.logger.warning(
-                    "Repository at %s has %s revisions.",
-                    old_location, len(old_repo.all_revision_ids()))
-                ok = False
-            # The branch in the old distroseries has at least some
-            # history.  (We can't check that the tips are the same because
-            # the branch in the new distroseries might have new revisons).
-            if old_bzr_branch.last_revision() == 'null:':
-                self.logger.warning(
-                    "Old branch at %s has null tip revision.",
-                    old_location)
-                ok = False
-        return ok
-
-    def makeOneNewBranch(self, old_db_branch):
-        """Copy a branch to the new distroseries.
-
-        This function makes a new database branch for the same source package
-        as old_db_branch but in the new distroseries and then uses
-        `switch_branches` to move the underlying bzr branch to the new series
-        and replace the old branch with a branch stacked on the new series'
-        branch.
-
-        :param old_db_branch: The branch to copy into the new distroseries.
-        :raises BranchExists: This will be raised if old_db_branch has already
-            been copied to the new distroseries (in the database, at least).
-        """
-        if not self.checkConsistentOfficialPackageBranch(old_db_branch):
-            self.logger.warning("Skipping branch")
-            return
-        new_namespace = getUtility(IBranchNamespaceSet).get(
-            person=old_db_branch.owner, product=None,
-            distroseries=self.new_distroseries,
-            sourcepackagename=old_db_branch.sourcepackagename)
-        new_db_branch = new_namespace.createBranch(
-            BranchType.HOSTED, self.new_distroseries.name,
-            old_db_branch.registrant)
-        new_db_branch.sourcepackage.setBranch(
-            PackagePublishingPocket.RELEASE, new_db_branch,
-            new_db_branch.owner)
-        old_db_branch.lifecycle_status = BranchLifecycleStatus.MATURE
-        # switch_branches *moves* the data to locations dependent on the
-        # new_branch's id, so if the transaction was rolled back we wouldn't
-        # know the branch id and thus wouldn't be able to find the branch data
-        # again.  So commit before doing that.
-        transaction.commit()
-        switch_branches(
-            config.codehosting.mirrored_branches_root,
-            'lp-internal', old_db_branch, new_db_branch)
-        # Directly copy the branch revisions from the old branch to the new
-        # branch.
-        store = IMasterStore(BranchRevision)
-        store.execute(
-            """
-            INSERT INTO BranchRevision (branch, revision, sequence)
-            SELECT %s, BranchRevision.revision, BranchRevision.sequence
-            FROM BranchRevision
-            WHERE branch = %s
-            """ % (new_db_branch.id, old_db_branch.id))
-
-        # Update the scanned details first, that way when hooking into
-        # branchChanged, it won't try to create a new scan job.
-        tip_revision = old_db_branch.getTipRevision()
-        new_db_branch.updateScannedDetails(
-            tip_revision, old_db_branch.revision_count)
-        tip_revision_id = (
-            tip_revision.revision_id if tip_revision is not None else
-            NULL_REVISION)
-        new_db_branch.branchChanged(
-            '', tip_revision_id,
-            old_db_branch.control_format,
-            old_db_branch.branch_format,
-            old_db_branch.repository_format)
-        old_db_branch.stacked_on = new_db_branch
-        transaction.commit()
-        return new_db_branch

=== removed file 'lib/lp/codehosting/tests/test_branchdistro.py'
--- lib/lp/codehosting/tests/test_branchdistro.py	2017-11-06 09:32:45 +0000
+++ lib/lp/codehosting/tests/test_branchdistro.py	1970-01-01 00:00:00 +0000
@@ -1,642 +0,0 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Tests for making new source package branches just after a distro release.
-"""
-
-__metaclass__ = type
-
-import os
-import re
-from StringIO import StringIO
-from subprocess import (
-    PIPE,
-    Popen,
-    STDOUT,
-    )
-import textwrap
-
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import NotStacked
-from bzrlib.tests import TestCaseWithTransport
-from bzrlib.transport import get_transport
-from bzrlib.transport.chroot import ChrootServer
-from lazr.uri import URI
-import transaction
-from zope.component import getUtility
-from zope.security.proxy import removeSecurityProxy
-
-from lp.code.enums import BranchLifecycleStatus
-from lp.code.interfaces.branchjob import IBranchScanJobSource
-from lp.codehosting.branchdistro import (
-    DistroBrancher,
-    switch_branches,
-    )
-from lp.codehosting.vfs import branch_id_to_path
-from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.services.config import config
-from lp.services.log.logger import (
-    BufferLogger,
-    FakeLogger,
-    )
-from lp.services.osutils import override_environ
-from lp.testing import TestCaseWithFactory
-from lp.testing.dbuser import switch_dbuser
-from lp.testing.layers import LaunchpadZopelessLayer
-
-# We say "RELEASE" often enough to not want to say "PackagePublishingPocket."
-# each time.
-RELEASE = PackagePublishingPocket.RELEASE
-
-
-class FakeBranch:
-    """Just enough of a Branch to pass `test_switch_branches`."""
-
-    def __init__(self, id):
-        self.id = id
-
-    @property
-    def unique_name(self):
-        return branch_id_to_path(self.id)
-
-
-class TestSwitchBranches(TestCaseWithTransport):
-    """Tests for `switch_branches`."""
-
-    def test_switch_branches(self):
-        # switch_branches moves a branch to the new location and places a
-        # branch (with no revisions) stacked on the new branch in the old
-        # location.
-
-        chroot_server = ChrootServer(self.get_transport())
-        chroot_server.start_server()
-        self.addCleanup(chroot_server.stop_server)
-        scheme = chroot_server.get_url().rstrip('/:')
-
-        old_branch = FakeBranch(1)
-        self.get_transport(old_branch.unique_name).create_prefix()
-        tree = self.make_branch_and_tree(old_branch.unique_name)
-        # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
-        # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
-            tree.commit(message='.')
-
-        new_branch = FakeBranch(2)
-
-        switch_branches('.', scheme, old_branch, new_branch)
-
-        # Post conditions:
-        # 1. unstacked branch in new_branch's location
-        # 2. stacked branch with no revisions in repo at old_branch
-        # 3. last_revision() the same for two branches
-
-        old_location_bzrdir = BzrDir.open(str(URI(
-            scheme=scheme, host='', path='/' + old_branch.unique_name)))
-        new_location_bzrdir = BzrDir.open(str(URI(
-            scheme=scheme, host='', path='/' + new_branch.unique_name)))
-
-        old_location_branch = old_location_bzrdir.open_branch()
-        new_location_branch = new_location_bzrdir.open_branch()
-
-        # 1. unstacked branch in new_branch's location
-        self.assertRaises(NotStacked, new_location_branch.get_stacked_on_url)
-
-        # 2. stacked branch with no revisions in repo at old_branch
-        self.assertEqual(
-            '/' + new_branch.unique_name,
-            old_location_branch.get_stacked_on_url())
-        self.assertEqual(
-            [], old_location_bzrdir.open_repository().all_revision_ids())
-
-        # 3. last_revision() the same for two branches
-        self.assertEqual(
-            old_location_branch.last_revision(),
-            new_location_branch.last_revision())
-
-
-class TestDistroBrancher(TestCaseWithFactory):
-    """Tests for `DistroBrancher`."""
-
-    layer = LaunchpadZopelessLayer
-
-    def setUp(self):
-        TestCaseWithFactory.setUp(self)
-        self.useBzrBranches(direct_database=True)
-
-    def makeOfficialPackageBranch(self, distroseries=None,
-                                  make_revisions=True):
-        """Make an official package branch with an underlying bzr branch."""
-        db_branch = self.factory.makePackageBranch(distroseries=distroseries)
-        db_branch.sourcepackage.setBranch(RELEASE, db_branch, db_branch.owner)
-        if make_revisions:
-            self.factory.makeRevisionsForBranch(db_branch, count=1)
-
-        transaction.commit()
-
-        _, tree = self.create_branch_and_tree(
-            tree_location=self.factory.getUniqueString(), db_branch=db_branch)
-        # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
-        # required to generate the revision-id.
-        if make_revisions:
-            with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
-                tree.commit('')
-
-        return db_branch
-
-    def makeNewSeriesAndBrancher(self, distroseries=None):
-        """Make a DistroBrancher.
-
-        Any messages logged by this DistroBrancher can be checked by calling
-        `assertLogMessages` below.
-        """
-        if distroseries is None:
-            distroseries = self.factory.makeDistroSeries()
-        self._log_file = StringIO()
-        new_distroseries = self.factory.makeDistroSeries(
-            distribution=distroseries.distribution)
-        switch_dbuser('branch-distro')
-        return DistroBrancher(
-            FakeLogger(self._log_file), distroseries, new_distroseries)
-
-    def clearLogMessages(self):
-        """Forget about all logged messages seen so far."""
-        self._log_file.seek(0, 0)
-        self._log_file.truncate()
-
-    def assertLogMessages(self, patterns):
-        """Assert that the messages logged meet expectations.
-
-        :param patterns: A list of regular expressions.  The length must match
-            the number of messages logged, and then each pattern must match
-            the messages logged in order.
-        """
-        log_messages = self._log_file.getvalue().splitlines()
-        if len(log_messages) > len(patterns):
-            self.fail(
-                "More log messages (%s) than expected (%s)" %
-                (log_messages, patterns))
-        elif len(log_messages) < len(patterns):
-            self.fail(
-                "Fewer log messages (%s) than expected (%s)" %
-                (log_messages, patterns))
-        for pattern, message in zip(patterns, log_messages):
-            if not re.match(pattern, message):
-                self.fail("%r does not match %r" % (pattern, message))
-
-    def test_DistroBrancher_same_distro_check(self):
-        # DistroBrancher.__init__ raises AssertionError if the two
-        # distroseries passed are not from the same distribution.
-        self.assertRaises(
-            AssertionError, DistroBrancher, None,
-            self.factory.makeDistroSeries(),
-            self.factory.makeDistroSeries())
-
-    def test_DistroBrancher_same_distroseries_check(self):
-        # DistroBrancher.__init__ raises AssertionError if passed the same
-        # distroseries twice.
-        distroseries = self.factory.makeDistroSeries()
-        self.assertRaises(
-            AssertionError, DistroBrancher, None, distroseries, distroseries)
-
-    def test_fromNames(self):
-        # DistroBrancher.fromNames constructs a DistroBrancher from the names
-        # of a distribution and two distroseries within it.
-        distribution = self.factory.makeDistribution()
-        distroseries1 = self.factory.makeDistroSeries(
-            distribution=distribution)
-        distroseries2 = self.factory.makeDistroSeries(
-            distribution=distribution)
-        brancher = DistroBrancher.fromNames(
-            None, distribution.name, distroseries1.name, distroseries2.name)
-        self.assertEqual(
-            [distroseries1, distroseries2],
-            [brancher.old_distroseries, brancher.new_distroseries])
-
-    # A word on testing strategy: we don't directly test the post conditions
-    # of makeOneNewBranch, but we do test that it satisfies checkOneBranch and
-    # the tests for checkOneBranch verify that this function rejects various
-    # ways in which makeOneNewBranch could conceivably fail.
-
-    def test_makeOneNewBranch(self):
-        # makeOneNewBranch creates an official package branch in the new
-        # distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-
-        new_branch = brancher.new_distroseries.getSourcePackage(
-            db_branch.sourcepackage.name).getBranch(RELEASE)
-
-        self.assertIsNot(None, new_branch)
-        # The branch owner is the same, the source package name is the same,
-        # the distroseries is the new one and the branch name is the name of
-        # the new distroseries.
-        self.assertEqual(
-            [db_branch.owner, db_branch.distribution,
-             db_branch.sourcepackagename, brancher.new_distroseries.name],
-            [new_branch.owner, new_branch.distribution,
-             new_branch.sourcepackagename, new_branch.name])
-        # The new branch is set in the development state, and the old one is
-        # mature.
-        self.assertEqual(
-            BranchLifecycleStatus.DEVELOPMENT, new_branch.lifecycle_status)
-        self.assertEqual(
-            BranchLifecycleStatus.MATURE, db_branch.lifecycle_status)
-
-    def test_makeOneNewBranch_avoids_need_for_scan(self):
-        # makeOneNewBranch sets the appropriate properties of the new branch
-        # so a scan is unnecessary.  This can be done because we are making a
-        # copy of the source branch.
-        db_branch = self.makeOfficialPackageBranch()
-        self.factory.makeRevisionsForBranch(db_branch, count=10)
-        tip_revision_id = db_branch.last_mirrored_id
-        self.assertIsNot(None, tip_revision_id)
-        # The makeRevisionsForBranch will create a scan job for the db_branch.
-        # We don't really care about that, but what we do care about is that
-        # no new jobs are created.
-        existing_scan_job_count = len(
-            list(getUtility(IBranchScanJobSource).iterReady()))
-
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        new_branch = brancher.new_distroseries.getSourcePackage(
-            db_branch.sourcepackage.name).getBranch(RELEASE)
-
-        self.assertEqual(tip_revision_id, new_branch.last_mirrored_id)
-        self.assertEqual(tip_revision_id, new_branch.last_scanned_id)
-        # Make sure that the branch revisions have been copied.
-        old_ancestry, old_history = removeSecurityProxy(
-            db_branch).getScannerData()
-        new_ancestry, new_history = removeSecurityProxy(
-            new_branch).getScannerData()
-        self.assertEqual(old_ancestry, new_ancestry)
-        self.assertEqual(old_history, new_history)
-        self.assertIs(None, new_branch.stacked_on)
-        self.assertEqual(new_branch, db_branch.stacked_on)
-        # The script doesn't have permission to create branch jobs, but just
-        # to be insanely paranoid.
-        switch_dbuser('launchpad')
-        self.assertFalse(new_branch.pending_writes)
-        scan_jobs = list(getUtility(IBranchScanJobSource).iterReady())
-        self.assertEqual(existing_scan_job_count, len(scan_jobs))
-
-    def test_makeOneNewBranch_inconsistent_branch(self):
-        # makeOneNewBranch skips over an inconsistent official package branch
-        # (see `checkConsistentOfficialPackageBranch` for precisely what an
-        # "inconsistent official package branch" is).
-        unofficial_branch = self.factory.makePackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(
-            unofficial_branch.distroseries)
-        brancher.makeOneNewBranch(unofficial_branch)
-
-        new_branch = brancher.new_distroseries.getSourcePackage(
-            unofficial_branch.sourcepackage.name).getBranch(RELEASE)
-        self.assertIs(None, new_branch)
-        self.assertLogMessages(
-            ['^WARNING .* is not an official branch$',
-             '^WARNING Skipping branch$'])
-
-    def test_makeOnewNewBranch_empty_branch(self):
-        # Branches with no commits work.
-        db_branch = self.makeOfficialPackageBranch(make_revisions=False)
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-
-    def test_makeNewBranches(self):
-        # makeNewBranches calls makeOneNewBranch for each official branch in
-        # the old distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-        db_branch2 = self.makeOfficialPackageBranch(
-            distroseries=db_branch.distroseries)
-
-        new_distroseries = self.factory.makeDistroSeries(
-            distribution=db_branch.distribution)
-
-        brancher = DistroBrancher(
-            BufferLogger(), db_branch.distroseries, new_distroseries)
-
-        brancher.makeNewBranches()
-
-        new_sourcepackage = new_distroseries.getSourcePackage(
-            db_branch.sourcepackage.name)
-        new_branch = new_sourcepackage.getBranch(RELEASE)
-        new_sourcepackage2 = new_distroseries.getSourcePackage(
-            db_branch2.sourcepackage.name)
-        new_branch2 = new_sourcepackage2.getBranch(RELEASE)
-
-        self.assertIsNot(None, new_branch)
-        self.assertIsNot(None, new_branch2)
-
-    def test_makeNewBranches_idempotent(self):
-        # makeNewBranches is idempotent in the sense that if a branch in the
-        # old distroseries already has a counterpart in the new distroseries,
-        # it is silently ignored.
-        db_branch = self.makeOfficialPackageBranch()
-
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeNewBranches()
-        brancher.makeNewBranches()
-
-        new_branch = brancher.new_distroseries.getSourcePackage(
-            db_branch.sourcepackage.name).getBranch(RELEASE)
-
-        self.assertIsNot(new_branch, None)
-
-    def test_makeOneNewBranch_checks_ok(self):
-        # After calling makeOneNewBranch for a branch, calling checkOneBranch
-        # returns True for that branch.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        self.clearLogMessages()
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertLogMessages([])
-        self.assertTrue(ok)
-
-    def test_checkConsistentOfficialPackageBranch_product_branch(self):
-        # checkConsistentOfficialPackageBranch returns False when passed a
-        # product branch.
-        db_branch = self.factory.makeProductBranch()
-        brancher = self.makeNewSeriesAndBrancher()
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Encountered unexpected product branch .*/.*/.*$'])
-        self.assertFalse(ok)
-
-    def test_checkConsistentOfficialPackageBranch_personal_branch(self):
-        # checkConsistentOfficialPackageBranch returns False when passed a
-        # personal branch.
-        db_branch = self.factory.makePersonalBranch()
-        brancher = self.makeNewSeriesAndBrancher()
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Encountered unexpected personal branch .*/.*/.*$'])
-        self.assertFalse(ok)
-
-    def test_checkConsistentOfficialPackageBranch_no_official_branch(self):
-        # checkConsistentOfficialPackageBranch returns False when passed a
-        # branch which is not official for any package.
-        db_branch = self.factory.makePackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages(
-            ['^WARNING .*/.*/.* is not an official branch$'])
-        self.assertFalse(ok)
-
-    def test_checkConsistentOfficialPackageBranch_official_elsewhere(self):
-        # checkConsistentOfficialPackageBranch returns False when passed a
-        # branch which is official for a sourcepackage that it is not a branch
-        # for.
-        db_branch = self.factory.makePackageBranch()
-        self.factory.makeSourcePackage().setBranch(
-            RELEASE, db_branch, db_branch.owner)
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages(
-            ['^WARNING .*/.*/.* is the official branch for .*/.*/.* but not '
-             'its sourcepackage$'])
-        self.assertFalse(ok)
-
-    def test_checkConsistentOfficialPackageBranch_official_twice(self):
-        # checkConsistentOfficialPackageBranch returns False when passed a
-        # branch that is official for two sourcepackages.
-        db_branch = self.factory.makePackageBranch()
-        db_branch.sourcepackage.setBranch(RELEASE, db_branch, db_branch.owner)
-        self.factory.makeSourcePackage().setBranch(
-            RELEASE, db_branch, db_branch.owner)
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING .*/.*/.* is official for multiple series: .*/.*/.*, '
-            '.*/.*/.*$'])
-        self.assertFalse(ok)
-
-    def test_checkConsistentOfficialPackageBranch_ok(self):
-        # checkConsistentOfficialPackageBranch returns True when passed a
-        # branch that is official for its sourcepackage and no other.
-        db_branch = self.factory.makePackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        db_branch.sourcepackage.setBranch(RELEASE, db_branch, db_branch.owner)
-        ok = brancher.checkConsistentOfficialPackageBranch(db_branch)
-        self.assertLogMessages([])
-        self.assertTrue(ok)
-
-    def test_checkOneBranch_inconsistent_old_package_branch(self):
-        # checkOneBranch returns False when passed a branch that is not a
-        # consistent official package branch.
-        db_branch = self.factory.makePackageBranch()
-        brancher = self.makeNewSeriesAndBrancher()
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertFalse(ok)
-        self.assertLogMessages(
-            ['^WARNING .*/.*/.* is not an official branch$'])
-
-    def test_checkOneBranch_no_new_official_branch(self):
-        # checkOneBranch returns False when there is no corresponding official
-        # package branch in the new distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertFalse(ok)
-        self.assertLogMessages(
-            ['^WARNING No official branch found for .*/.*/.*$'])
-
-    def test_checkOneBranch_inconsistent_new_package_branch(self):
-        # checkOneBranch returns False when the corresponding official package
-        # branch in the new distroseries is not consistent.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        new_db_branch = brancher.makeOneNewBranch(db_branch)
-        switch_dbuser('launchpad')
-        new_db_branch.setTarget(
-            new_db_branch.owner,
-            source_package=self.factory.makeSourcePackage())
-        switch_dbuser('branch-distro')
-        ok = brancher.checkOneBranch(new_db_branch)
-        self.assertFalse(ok)
-        self.assertLogMessages(
-            ['^WARNING .*/.*/.* is the official branch for .*/.*/.* but not '
-             'its sourcepackage$'])
-
-    def test_checkOneBranch_new_branch_missing(self):
-        # checkOneBranch returns False when there is no bzr branch for the
-        # database branch in the new distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        new_db_branch = brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + new_db_branch.unique_name
-        get_transport(url).delete_tree('.bzr')
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertFalse(ok)
-        # Deleting the new branch will break the old branch, as that's stacked
-        # on the new one.
-        self.assertLogMessages([
-            '^WARNING No bzr branch at new location '
-            'lp-internal:///.*/.*/.*/.*$',
-            '^WARNING No bzr branch at old location '
-            'lp-internal:///.*/.*/.*/.*$',
-            ])
-
-    def test_checkOneBranch_old_branch_missing(self):
-        # checkOneBranch returns False when there is no bzr branchfor the
-        # database branch in old distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + db_branch.unique_name
-        get_transport(url).delete_tree('.bzr')
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertFalse(ok)
-        self.assertLogMessages([
-            '^WARNING No bzr branch at old location '
-            'lp-internal:///.*/.*/.*/.*$'
-            ])
-
-    def test_checkOneBranch_new_stacked(self):
-        # checkOneBranch returns False when the bzr branch for the database
-        # branch in new distroseries is stacked.
-        db_branch = self.makeOfficialPackageBranch()
-        b, _ = self.create_branch_and_tree(self.factory.getUniqueString())
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        new_db_branch = brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + new_db_branch.unique_name
-        Branch.open(url).set_stacked_on_url('/' + b.unique_name)
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertFalse(ok)
-        self.assertLogMessages([
-            '^WARNING New branch at lp-internal:///.*/.*/.*/.* is stacked on '
-            '/.*/.*/.*, should be unstacked.$',
-            ])
-
-    def test_checkOneBranch_old_unstacked(self):
-        # checkOneBranch returns False when the bzr branch for the database
-        # branch in old distroseries is not stacked.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + db_branch.unique_name
-        old_bzr_branch = Branch.open(url)
-        old_bzr_branch.set_stacked_on_url(None)
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Old branch at lp-internal:///.*/.*/.*/.* is not '
-            'stacked, should be stacked on /.*/.*/.*.$',
-            '^.*has .* revisions.*$',
-            ])
-        self.assertFalse(ok)
-
-    def test_checkOneBranch_old_misstacked(self):
-        # checkOneBranch returns False when the bzr branch for the database
-        # branch in old distroseries stacked on some other branch than the
-        # branch in the new distroseries.
-        db_branch = self.makeOfficialPackageBranch()
-        b, _ = self.create_branch_and_tree(self.factory.getUniqueString())
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + db_branch.unique_name
-        Branch.open(url).set_stacked_on_url('/' + b.unique_name)
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Old branch at lp-internal:///.*/.*/.*/.* is stacked on '
-            '/.*/.*/.*, should be stacked on /.*/.*/.*.$',
-            ])
-        self.assertFalse(ok)
-
-    def test_checkOneBranch_old_has_revisions(self):
-        # checkOneBranch returns False when the bzr branch for the database
-        # branch in old distroseries has a repository that contains revisions.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + db_branch.unique_name
-        old_bzr_branch = Branch.open(url)
-        # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
-        # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
-            old_bzr_branch.create_checkout(
-                self.factory.getUniqueString()).commit('')
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Repository at lp-internal:///.*/.*/.*/.* has 1 '
-            'revisions.'
-            ])
-        self.assertFalse(ok)
-
-    def test_checkOneBranch_old_has_null_tip(self):
-        # checkOneBranch returns False when the bzr branch for the database
-        # branch in old distroseries has tip revision of 'null:'.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeOneNewBranch(db_branch)
-        url = 'lp-internal:///' + db_branch.unique_name
-        old_bzr_branch = Branch.open(url)
-        old_bzr_branch.set_last_revision_info(0, 'null:')
-        ok = brancher.checkOneBranch(db_branch)
-        self.assertLogMessages([
-            '^WARNING Old branch at lp-internal:///.*/.*/.*/.* has null tip '
-            'revision.'
-            ])
-        self.assertFalse(ok)
-
-    def runBranchDistroScript(self, args):
-        """Run the branch-distro.py script with the given arguments.
-
-        ;param args: The arguments to pass to the branch-distro.py script.
-        :return: A tuple (returncode, output).  stderr and stdout are both
-            contained in the output.
-        """
-        script_path = os.path.join(config.root, 'scripts', 'branch-distro.py')
-        process = Popen([script_path] + args, stdout=PIPE, stderr=STDOUT)
-        output, error = process.communicate()
-        return process.returncode, output
-
-    def test_makeNewBranches_script(self):
-        # Running the script with the arguments 'distro old-series new-series'
-        # makes new branches in the new series.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        returncode, output = self.runBranchDistroScript(
-            ['-v', db_branch.distribution.name,
-             brancher.old_distroseries.name, brancher.new_distroseries.name])
-        self.assertEqual(0, returncode)
-        self.assertEqual(
-            'DEBUG   Processing ' + db_branch.unique_name + '\n', output)
-        brancher.checkOneBranch(db_branch)
-
-    def test_checkNewBranches_script_success(self):
-        # Running the script with the arguments '--check distro old-series
-        # new-series' checks that the branches in the new series are as
-        # expected.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        brancher.makeNewBranches()
-        returncode, output = self.runBranchDistroScript(
-            ['-v', '--check', db_branch.distribution.name,
-             brancher.old_distroseries.name, brancher.new_distroseries.name])
-        self.assertEqual(0, returncode)
-        self.assertEqual(
-            'DEBUG   Checking ' + db_branch.unique_name + '\n', output)
-        brancher.checkOneBranch(db_branch)
-
-    def test_checkNewBranches_script_failure(self):
-        # Running the script with the arguments '--check distro old-series
-        # new-series' checks that the branches in the new series are as
-        # expected and logs warnings and exits with code 1 is things are not
-        # as expected.
-        db_branch = self.makeOfficialPackageBranch()
-        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
-        returncode, output = self.runBranchDistroScript(
-            ['-v', '--check', db_branch.distribution.name,
-             brancher.old_distroseries.name, brancher.new_distroseries.name])
-        sp_path = brancher.new_distroseries.getSourcePackage(
-            db_branch.sourcepackagename).path
-        expected = '''\
-        DEBUG   Checking %(branch_name)s
-        WARNING No official branch found for %(sp_path)s
-        ERROR   Check failed
-        ''' % {'branch_name': db_branch.unique_name, 'sp_path': sp_path}
-        self.assertEqual(
-            textwrap.dedent(expected), output)
-        self.assertEqual(1, returncode)

=== removed file 'scripts/branch-distro.py'
--- scripts/branch-distro.py	2012-01-01 03:13:08 +0000
+++ scripts/branch-distro.py	1970-01-01 00:00:00 +0000
@@ -1,42 +0,0 @@
-#!/usr/bin/python -S
-#
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-import _pythonpath
-
-from lp.codehosting.branchdistro import DistroBrancher
-from lp.codehosting.vfs import get_rw_server
-from lp.services.scripts.base import (
-    LaunchpadScript,
-    LaunchpadScriptFailure,
-    )
-
-
-class BranchDistroScript(LaunchpadScript):
-
-    usage = "%prog distro old-series new-series"
-
-    def add_my_options(self):
-        self.parser.add_option(
-            '--check', dest="check", action="store_true", default=False,
-            help=("Check that the new distro series has its official "
-                  "branches set up correctly."))
-
-    def main(self):
-        if len(self.args) != 3:
-            self.parser.error("Wrong number of arguments.")
-        brancher = DistroBrancher.fromNames(self.logger, *self.args)
-        server = get_rw_server(direct_database=True)
-        server.start_server()
-        try:
-            if self.options.check:
-                if not brancher.checkNewBranches():
-                    raise LaunchpadScriptFailure("Check failed")
-            else:
-                brancher.makeNewBranches()
-        finally:
-            server.stop_server()
-
-if __name__ == '__main__':
-    BranchDistroScript("branch-distro", dbuser='branch-distro').run()


Follow ups