/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
1
# Copyright (C) 2009 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""An object that updates a bunch of branches based on data imported."""
18
0.82.1 by Ian Clatworthy
nicer and round-trippable mapping of git ref names to bzr branch names
19
from operator import itemgetter
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
20
0.64.258 by Ian Clatworthy
Handle multi-level branches
21
from bzrlib import bzrdir, errors, osutils, transport
0.64.322 by Jelmer Vernooij
error has been renamed to show_error.
22
from bzrlib.trace import show_error, note
0.82.1 by Ian Clatworthy
nicer and round-trippable mapping of git ref names to bzr branch names
23
0.123.1 by Jelmer Vernooij
Move pure-fastimport code into its own directory, in preparation of splitting it into a separate package.
24
from bzrlib.plugins.fastimport.helpers import (
25
    best_format_for_objects_in_a_repository,
26
    )
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
27
28
29
class BranchUpdater(object):
30
31
    def __init__(self, repo, branch, cache_mgr, heads_by_ref, last_ref, tags):
32
        """Create an object responsible for updating branches.
33
34
        :param heads_by_ref: a dictionary where
35
          names are git-style references like refs/heads/master;
36
          values are one item lists of commits marks.
37
        """
38
        self.repo = repo
39
        self.branch = branch
40
        self.cache_mgr = cache_mgr
41
        self.heads_by_ref = heads_by_ref
42
        self.last_ref = last_ref
43
        self.tags = tags
0.64.193 by Ian Clatworthy
Smarter selection of branch format based on shared repository format
44
        self._branch_format = \
0.123.1 by Jelmer Vernooij
Move pure-fastimport code into its own directory, in preparation of splitting it into a separate package.
45
            best_format_for_objects_in_a_repository(repo)
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
46
47
    def update(self):
48
        """Update the Bazaar branches and tips matching the heads.
49
50
        If the repository is shared, this routine creates branches
51
        as required. If it isn't, warnings are produced about the
52
        lost of information.
53
54
        :return: updated, lost_heads where
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
55
          updated = the list of branches updated ('trunk' is first)
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
56
          lost_heads = a list of (bazaar-name,revision) for branches that
57
            would have been created had the repository been shared
58
        """
59
        updated = []
60
        branch_tips, lost_heads = self._get_matching_branches()
61
        for br, tip in branch_tips:
62
            if self._update_branch(br, tip):
63
                updated.append(br)
64
        return updated, lost_heads
65
66
    def _get_matching_branches(self):
67
        """Get the Bazaar branches.
68
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
69
        :return: branch_tips, lost_heads where
70
          branch_tips = a list of (branch,tip) tuples for branches. The
71
            first tip is the 'trunk'.
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
72
          lost_heads = a list of (bazaar-name,revision) for branches that
73
            would have been created had the repository been shared and
74
            everything succeeded
75
        """
76
        branch_tips = []
77
        lost_heads = []
78
        ref_names = self.heads_by_ref.keys()
79
        if self.branch is not None:
80
            trunk = self.select_trunk(ref_names)
81
            default_tip = self.heads_by_ref[trunk][0]
82
            branch_tips.append((self.branch, default_tip))
83
            ref_names.remove(trunk)
84
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
85
        # Convert the reference names into Bazaar speak. If we haven't
86
        # already put the 'trunk' first, do it now.
0.112.3 by Max Bowsher
Make BranchMapper just map one name per call.
87
        git_to_bzr_map = {}
88
        for ref_name in ref_names:
0.112.4 by Max Bowsher
Store the BranchMapper in the CacheManager so it can be got from other places.
89
            git_to_bzr_map[ref_name] = self.cache_mgr.branch_mapper.git_to_bzr(ref_name)
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
90
        if ref_names and self.branch is None:
91
            trunk = self.select_trunk(ref_names)
92
            git_bzr_items = [(trunk, git_to_bzr_map[trunk])]
93
            del git_to_bzr_map[trunk]
94
        else:
95
            git_bzr_items = []
96
        git_bzr_items.extend(sorted(git_to_bzr_map.items(), key=itemgetter(1)))
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
97
98
        # Policy for locating branches
99
        def dir_under_current(name, ref_name):
100
            # Using the Bazaar name, get a directory under the current one
0.95.3 by Ian Clatworthy
Update the working tree for trunk implicitly
101
            repo_base = self.repo.bzrdir.transport.base
102
            return osutils.pathjoin(repo_base, "..", name)
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
103
        def dir_sister_branch(name, ref_name):
104
            # Using the Bazaar name, get a sister directory to the branch
105
            return osutils.pathjoin(self.branch.base, "..", name)
106
        if self.branch is not None:
107
            dir_policy = dir_sister_branch
108
        else:
109
            dir_policy = dir_under_current
110
111
        # Create/track missing branches
112
        shared_repo = self.repo.is_shared()
0.82.1 by Ian Clatworthy
nicer and round-trippable mapping of git ref names to bzr branch names
113
        for ref_name, name in git_bzr_items:
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
114
            tip = self.heads_by_ref[ref_name][0]
115
            if shared_repo:
116
                location = dir_policy(name, ref_name)
117
                try:
118
                    br = self.make_branch(location)
119
                    branch_tips.append((br,tip))
120
                    continue
121
                except errors.BzrError, ex:
0.64.322 by Jelmer Vernooij
error has been renamed to show_error.
122
                    show_error("ERROR: failed to create branch %s: %s",
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
123
                        location, ex)
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
124
            lost_head = self.cache_mgr.lookup_committish(tip)
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
125
            lost_info = (name, lost_head)
126
            lost_heads.append(lost_info)
127
        return branch_tips, lost_heads
128
129
    def select_trunk(self, ref_names):
130
        """Given a set of ref names, choose one as the trunk."""
131
        for candidate in ['refs/heads/master']:
132
            if candidate in ref_names:
133
                return candidate
134
        # Use the last reference in the import stream
135
        return self.last_ref
136
137
    def make_branch(self, location):
138
        """Make a branch in the repository if not already there."""
0.64.258 by Ian Clatworthy
Handle multi-level branches
139
        to_transport = transport.get_transport(location)
140
        to_transport.create_prefix()
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
141
        try:
142
            return bzrdir.BzrDir.open(location).open_branch()
143
        except errors.NotBranchError, ex:
0.64.193 by Ian Clatworthy
Smarter selection of branch format based on shared repository format
144
            return bzrdir.BzrDir.create_branch_convenience(location,
0.64.258 by Ian Clatworthy
Handle multi-level branches
145
                format=self._branch_format,
146
                possible_transports=[to_transport])
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
147
148
    def _update_branch(self, br, last_mark):
149
        """Update a branch with last revision and tag information.
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
150
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
151
        :return: whether the branch was changed or not
152
        """
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
153
        from fastimport.helpers import single_plural
0.129.2 by Jelmer Vernooij
Use lookup functions for committish.
154
        last_rev_id = self.cache_mgr.lookup_committish(last_mark)
0.64.324 by Jelmer Vernooij
Avoid deprecated Repository.iter_reverse_revision_history.
155
        self.repo.lock_read()
156
        try:
157
            graph = self.repo.get_graph()
158
            revno = graph.find_distance_to_null(last_rev_id, [])
159
        finally:
160
            self.repo.unlock()
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
161
        existing_revno, existing_last_rev_id = br.last_revision_info()
162
        changed = False
163
        if revno != existing_revno or last_rev_id != existing_last_rev_id:
164
            br.set_last_revision_info(revno, last_rev_id)
165
            changed = True
166
        # apply tags known in this branch
167
        my_tags = {}
168
        if self.tags:
0.64.248 by Ian Clatworthy
Merge fix for tags off the mainline
169
            ancestry = self.repo.get_ancestry(last_rev_id)
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
170
            for tag,rev in self.tags.items():
0.108.1 by Max Bowsher
Store tags on entire branch ancestry, not just left-hand ancestry.
171
                if rev in ancestry:
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
172
                    my_tags[tag] = rev
173
            if my_tags:
174
                br.tags._set_tag_dict(my_tags)
175
                changed = True
176
        if changed:
177
            tagno = len(my_tags)
178
            note("\t branch %s now has %d %s and %d %s", br.nick,
0.123.1 by Jelmer Vernooij
Move pure-fastimport code into its own directory, in preparation of splitting it into a separate package.
179
                revno, single_plural(revno, "revision", "revisions"),
180
                tagno, single_plural(tagno, "tag", "tags"))
0.78.4 by Ian Clatworthy
move GenericBranchUpdater into its own module
181
        return changed