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