~launchpad-pqm/launchpad/devel

9678.4.1 by Max Bowsher
[r=barry][ui=none] Update Makefile PYTHON_VERSION variables and most script #! lines to python2.5.
1
#!/usr/bin/python2.5
8687.15.22 by Karl Fogel
Add the copyright header block to the remaining .py files.
2
#
3
# Copyright 2009 Canonical Ltd.  This software is licensed under the
4
# GNU Affero General Public License version 3 (see the file LICENSE).
5
7109.3.10 by Jonathan Lange
Disable lint.
6
# pylint: disable-msg=W0403
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
7
8
"""Update stacked_on_location for all Bazaar branches.
9
7109.3.3 by Jonathan Lange
Docstrings.
10
Expects standard input of:
11
    '<id> <branch_type> <unique_name> <stacked_on_unique_name>\n'.
12
13
Such input can be provided using "get-stacked-on-branches.py".
14
15
This script makes the stacked_on_location variables in all Bazaar branches
16
match the stacked_on column in the Launchpad database. This is useful for
17
updating stacked branches when their stacked-on branch has been moved or
18
renamed.
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
19
"""
20
21
__metaclass__ = type
22
23
import _pythonpath
24
import sys
25
import xmlrpclib
26
27
from bzrlib.bzrdir import BzrDir
28
from bzrlib.config import TransportConfig
29
from bzrlib import errors
30
8486.12.1 by Celso Providelo
Fixing the 'fixable' scripts and adding a checker with the really-broken ones blacklisted.
31
from lp.codehosting.vfs.branchfs import LaunchpadInternalServer
8426.6.1 by Michael Hudson
bzr ls --versioned --recursive --kind=file | xargs sed -i -e 's,from canonical.codehosting,from lp.codehosting,'
32
from lp.codehosting.vfs import BlockingProxy
33
from lp.codehosting.vfs.transport import (
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
34
    get_chrooted_transport, get_readonly_transport, _MultiServer)
8426.6.1 by Michael Hudson
bzr ls --versioned --recursive --kind=file | xargs sed -i -e 's,from canonical.codehosting,from lp.codehosting,'
35
from lp.codehosting.bzrutils import get_branch_stacked_on_url
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
36
from canonical.config import config
8356.1.9 by Leonard Richardson
Renamed the base script module in scripts/, which module_rename.py didn't touch because it wasn't under lib/.
37
from lp.services.scripts.base import LaunchpadScript
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
38
39
7109.3.5 by Jonathan Lange
Use the regular option framework to handle dry-run, rather than a global.
40
def get_server(read_only):
7109.3.3 by Jonathan Lange
Docstrings.
41
    """Get a server that can write to both hosted and mirrored areas."""
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
42
    proxy = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)
43
    authserver = BlockingProxy(proxy)
44
    hosted_transport = get_chrooted_transport(
7732.1.2 by Jonathan Lange
Change the name of the config variable for the hosted area from
45
        config.codehosting.hosted_branches_root)
7109.3.5 by Jonathan Lange
Use the regular option framework to handle dry-run, rather than a global.
46
    if read_only:
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
47
        hosted_transport = get_readonly_transport(hosted_transport)
48
    mirrored_transport = get_chrooted_transport(
7732.1.3 by Jonathan Lange
Get rid of the branchesdest config variable.
49
        config.codehosting.mirrored_branches_root)
7109.3.5 by Jonathan Lange
Use the regular option framework to handle dry-run, rather than a global.
50
    if read_only:
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
51
        mirrored_transport = get_readonly_transport(mirrored_transport)
52
    hosted_server = LaunchpadInternalServer(
53
        'lp-hosted:///', authserver, hosted_transport)
54
    mirrored_server = LaunchpadInternalServer(
55
        'lp-mirrored:///', authserver, mirrored_transport)
56
    return _MultiServer(hosted_server, mirrored_server)
57
58
59
def get_hosted_url(unique_name):
7109.3.3 by Jonathan Lange
Docstrings.
60
    """Return the hosted URL for the branch with 'unique_name'."""
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
61
    return 'lp-hosted:///%s' % unique_name
62
63
64
def get_mirrored_url(unique_name):
7109.3.3 by Jonathan Lange
Docstrings.
65
    """Return the mirrored URL for the branch with 'unique_name'."""
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
66
    return 'lp-mirrored:///%s' % unique_name
67
68
69
def set_branch_stacked_on_url(bzrdir, stacked_on_url):
7109.3.3 by Jonathan Lange
Docstrings.
70
    """Set the stacked_on_location for the branch at 'bzrdir'.
71
72
    We cannot use Branch.set_stacked_on, since that requires us to first open
73
    the branch. Opening the branch requires a working stacked_on_url:
74
    something we don't yet have.
75
    """
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
76
    branch_transport = bzrdir.get_branch_transport(None)
77
    branch_config = TransportConfig(branch_transport, 'branch.conf')
78
    stacked_on_url = branch_config.set_option(
79
        stacked_on_url, 'stacked_on_location')
80
81
7109.3.6 by Jonathan Lange
Use the LaunchpadScript structure to give us power.
82
class UpdateStackedBranches(LaunchpadScript):
83
    """Update stacked branches so their stacked_on_location matches the db."""
84
85
    def __init__(self):
86
        super(UpdateStackedBranches, self).__init__('update-stacked-on')
87
88
    def add_my_options(self):
89
        self.parser.add_option(
90
            '-n', '--dry-run', default=False, action="store_true",
91
            dest="dry_run",
92
            help=("Don't change anything on disk, just go through the "
93
                  "motions."))
94
95
    def main(self):
96
        server = get_server(self.options.dry_run)
97
        server.setUp()
98
        if self.options.dry_run:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
99
            self.logger.debug('Running read-only')
100
        self.logger.debug('Beginning processing')
7109.3.6 by Jonathan Lange
Use the LaunchpadScript structure to give us power.
101
        try:
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
102
            self.updateBranches(self.parseFromStream(sys.stdin))
7109.3.6 by Jonathan Lange
Use the LaunchpadScript structure to give us power.
103
        finally:
104
            server.tearDown()
7109.3.8 by Jonathan Lange
Use the real logger, not print.
105
        self.logger.info('Done')
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
106
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
107
    def updateStackedOn(self, branch_id, bzr_branch_url, stacked_on_location):
108
        """Stack the Bazaar branch at 'bzr_branch_url' on the given URL.
109
110
        :param branch_id: The database ID of the branch. This is only used for
111
            logging.
112
        :param bzr_branch_url: The URL of the Bazaar branch. Normally this is
113
            of the form lp-mirrored:/// or lp-hosted:///.
114
        :param stacked_on_location: The location to store in the branch's
115
            stacked_on_location configuration variable.
116
        """
117
        try:
118
            bzrdir = BzrDir.open(bzr_branch_url)
119
        except errors.NotBranchError:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
120
            self.logger.warn(
121
                "No bzrdir for %r at %r" % (branch_id, bzr_branch_url))
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
122
            return
123
124
        try:
125
            current_stacked_on_location = get_branch_stacked_on_url(bzrdir)
126
        except errors.NotBranchError:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
127
            self.logger.warn(
128
                "No branch for %r at %r" % (branch_id, bzr_branch_url))
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
129
        except errors.NotStacked:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
130
            self.logger.warn(
131
                "Branch for %r at %r is not stacked at all. Giving up."
132
                % (branch_id, bzr_branch_url))
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
133
        except errors.UnstackableBranchFormat:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
134
            self.logger.error(
135
                "Branch for %r at %r is unstackable. Giving up."
136
                % (branch_id, bzr_branch_url))
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
137
        else:
138
            if current_stacked_on_location != stacked_on_location:
7109.3.8 by Jonathan Lange
Use the real logger, not print.
139
                self.logger.info(
140
                    'Branch for %r at %r stacked on %r, should be on %r.'
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
141
                    % (branch_id, bzr_branch_url, current_stacked_on_location,
142
                       stacked_on_location))
143
                if not self.options.dry_run:
144
                    set_branch_stacked_on_url(bzrdir, stacked_on_location)
145
146
    def parseFromStream(self, stream):
147
        """Parse branch input from the given stream.
148
7109.3.9 by Jonathan Lange
78 cols and vws
149
        Expects the stream to be populated only by blank lines or by lines
150
        with whitespace-separated fields. Such lines are yielded as tuples.
151
        Blank lines are ignored.
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
152
        """
153
        for line in stream.readlines():
154
            if not line.strip():
155
                continue
7109.3.9 by Jonathan Lange
78 cols and vws
156
            yield line.split()
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
157
158
    def updateBranches(self, branches):
159
        """Update the stacked_on_location for all branches in 'branches'.
160
161
        :param branches: An iterator yielding (branch_id, branch_type,
162
            unique_name, stacked_on_unique_name).
163
        """
164
        for branch_info in branches:
7109.3.9 by Jonathan Lange
78 cols and vws
165
            (branch_id, branch_type, unique_name,
166
             stacked_on_name) = branch_info
7109.3.7 by Jonathan Lange
Bring some methods into the fold.
167
            stacked_on_location = '/' + stacked_on_name
168
            if branch_type == 'HOSTED':
169
                self.updateStackedOn(
170
                    branch_id, get_hosted_url(unique_name),
171
                    stacked_on_location)
172
            self.updateStackedOn(
173
                branch_id, get_mirrored_url(unique_name), stacked_on_location)
174
175
7109.3.1 by Jonathan Lange
Initial version of stacking update scripts.
176
if __name__ == '__main__':
7109.3.6 by Jonathan Lange
Use the LaunchpadScript structure to give us power.
177
    UpdateStackedBranches().lock_and_run()