/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
1
# Copyright (C) 2009 by Jelmer Vernooij <jelmer@samba.org>
0.436.177 by Jelmer Vernooij
Remove trailing whitespace.
2
#
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
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
"""Revision pseudonyms."""
18
19
from collections import defaultdict
20
7406.3.2 by Jelmer Vernooij
Update for breezy.
21
from breezy import (
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
22
    errors,
23
    foreign,
24
    ui,
7406.3.3 by Jelmer Vernooij
Fix python3 compatibility.
25
    urlutils,
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
26
    )
27
28
0.436.174 by Jelmer Vernooij
Support git-svn-id.
29
def parse_git_svn_id(text):
0.436.221 by Jelmer Vernooij
Add deb-md5 support in pseudonyms.
30
    """Parse a git svn id string.
31
32
    :param text: git svn id
33
    :return: URL, revision number, uuid
34
    """
0.436.174 by Jelmer Vernooij
Support git-svn-id.
35
    (head, uuid) = text.rsplit(" ", 1)
36
    (full_url, rev) = head.rsplit("@", 1)
0.436.175 by Jelmer Vernooij
Cache repo root for svn URLs.
37
    return (full_url.encode("utf-8"), int(rev), uuid.encode("utf-8"))
38
39
40
class SubversionBranchUrlFinder(object):
41
42
    def __init__(self):
43
        self._roots = defaultdict(set)
44
45
    def find_root(self, uuid, url):
46
        for root in self._roots[uuid]:
47
            if url.startswith(root):
48
                return root
49
        try:
50
            from subvertpy.ra import RemoteAccess
51
        except ImportError:
52
            return None
53
        c = RemoteAccess(url)
54
        root = c.get_repos_root()
55
        self._roots[uuid].add(root)
56
        return root
57
58
    def find_branch_path(self, uuid, url):
59
        root = self.find_root(uuid, url)
60
        if root is None:
61
            return None
62
        assert url.startswith(root)
63
        return url[len(root):].strip("/")
64
65
66
svn_branch_path_finder = SubversionBranchUrlFinder()
0.436.174 by Jelmer Vernooij
Support git-svn-id.
67
68
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
69
def _extract_converted_from_revid(rev):
7406.3.5 by Jelmer Vernooij
Fix formatting.
70
    if "converted-from" not in rev.properties:
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
71
        return
72
73
    for line in rev.properties.get("converted-from", "").splitlines():
74
        (kind, serialized_foreign_revid) = line.split(" ", 1)
75
        yield (kind, serialized_foreign_revid)
76
77
78
def _extract_cscvs(rev):
79
    """Older-style launchpad-cscvs import."""
7406.3.5 by Jelmer Vernooij
Fix formatting.
80
    if "cscvs-svn-branch-path" not in rev.properties:
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
81
        return
7406.3.5 by Jelmer Vernooij
Fix formatting.
82
    yield (
83
        "svn", "%s:%s:%s" % (
84
            rev.properties["cscvs-svn-repository-uuid"],
85
            rev.properties["cscvs-svn-revision-number"],
86
            urlutils.quote(rev.properties["cscvs-svn-branch-path"].strip("/"))))
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
87
88
89
def _extract_git_svn_id(rev):
7406.3.5 by Jelmer Vernooij
Fix formatting.
90
    if "git-svn-id" not in rev.properties:
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
91
        return
92
    (full_url, revnum, uuid) = parse_git_svn_id(rev.properties['git-svn-id'])
93
    branch_path = svn_branch_path_finder.find_branch_path(uuid, full_url)
94
    if branch_path is not None:
7406.3.3 by Jelmer Vernooij
Fix python3 compatibility.
95
        yield ("svn", "%s:%d:%s" % (uuid, revnum, urlutils.quote(branch_path)))
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
96
0.436.186 by Jelmer Vernooij
Add test for cscvs foreign revids
97
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
98
def _extract_foreign_revision(rev):
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
99
    # Perhaps 'rev' is a foreign revision ?
100
    if getattr(rev, "foreign_revid", None) is not None:
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
101
        yield ("svn", rev.mapping.vcs.serialize_foreign_revid(rev.foreign_revid))
102
103
104
def _extract_foreign_revid(rev):
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
105
    # Try parsing the revision id
106
    try:
107
        foreign_revid, mapping = \
108
            foreign.foreign_vcs_registry.parse_revision_id(rev.revision_id)
109
    except errors.InvalidRevisionId:
110
        pass
111
    else:
7406.3.5 by Jelmer Vernooij
Fix formatting.
112
        yield (
113
            mapping.vcs.abbreviation,
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
114
            mapping.vcs.serialize_foreign_revid(foreign_revid))
115
116
0.436.221 by Jelmer Vernooij
Add deb-md5 support in pseudonyms.
117
def _extract_debian_md5sum(rev):
118
    if 'deb-md5' in rev.properties:
119
        yield ("debian-md5sum", rev.properties["deb-md5"])
120
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
121
122
_foreign_revid_extractors = [
123
    _extract_converted_from_revid,
124
    _extract_cscvs,
125
    _extract_git_svn_id,
126
    _extract_foreign_revision,
127
    _extract_foreign_revid,
0.436.221 by Jelmer Vernooij
Add deb-md5 support in pseudonyms.
128
    _extract_debian_md5sum,
0.436.184 by Jelmer Vernooij
split up pseudonyms function.
129
    ]
130
131
132
def extract_foreign_revids(rev):
133
    """Find ids of semi-equivalent revisions in foreign VCS'es.
134
135
    :param: Bazaar revision object
136
    :return: Set with semi-equivalent revisions.
137
    """
138
    ret = set()
139
    for extractor in _foreign_revid_extractors:
140
        ret.update(extractor(rev))
0.436.169 by Jelmer Vernooij
Add 'pseudonyms' command.
141
    return ret
142
143
144
def find_pseudonyms(repository, revids):
145
    """Find revisions that are pseudonyms of each other.
146
147
    :param repository: Repository object
148
    :param revids: Sequence of revision ids to check
149
    :return: Iterable over sets of pseudonyms
150
    """
151
    # Where have foreign revids ended up?
152
    conversions = defaultdict(set)
153
    # What are native revids conversions of?
154
    conversion_of = defaultdict(set)
155
    revs = repository.get_revisions(revids)
156
    pb = ui.ui_factory.nested_progress_bar()
157
    try:
158
        for i, rev in enumerate(revs):
159
            pb.update("finding pseudonyms", i, len(revs))
160
            for foreign_revid in extract_foreign_revids(rev):
161
                conversion_of[rev.revision_id].add(foreign_revid)
162
                conversions[foreign_revid].add(rev.revision_id)
163
    finally:
164
        pb.finished()
165
    done = set()
166
    for foreign_revid in conversions.keys():
167
        ret = set()
168
        check = set(conversions[foreign_revid])
169
        while check:
170
            x = check.pop()
171
            extra = set()
172
            for frevid in conversion_of[x]:
173
                extra.update(conversions[frevid])
174
                del conversions[frevid]
175
            del conversion_of[x]
176
            check.update(extra)
177
            ret.add(x)
178
        if len(ret) > 1:
179
            yield ret
0.436.170 by Jelmer Vernooij
Add convenience function for creating a pseudonym dictionary.
180
181
182
def pseudonyms_as_dict(l):
183
    """Convert an iterable over pseudonyms to a dictionary.
184
185
    :param l: Iterable over sets of pseudonyms
186
    :return: Dictionary with pseudonyms for each revid.
187
    """
188
    ret = {}
189
    for pns in l:
190
        for pn in pns:
191
            ret[pn] = pns - set([pn])
192
    return ret
0.436.172 by Jelmer Vernooij
Split up code for generating rebase map.
193
194
195
def generate_rebase_map_from_pseudonyms(pseudonym_dict, existing, desired):
196
    """Create a rebase map from pseudonyms and existing/desired ancestry.
197
0.436.189 by Jelmer Vernooij
Fix formatting.
198
    :param pseudonym_dict: Dictionary with pseudonym as returned by
199
        pseudonyms_as_dict()
0.436.172 by Jelmer Vernooij
Split up code for generating rebase map.
200
    :param existing: Existing ancestry, might need to be rebased
201
    :param desired: Desired ancestry
202
    :return: rebase map, as dictionary
203
    """
204
    rebase_map = {}
205
    for revid in existing:
206
        for pn in pseudonym_dict.get(revid, []):
207
            if pn in desired:
208
                rebase_map[revid] = pn
209
    return rebase_map