3
3
# This program is free software; you can redistribute it and/or modify
4
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
5
# the Free Software Foundation; either version 3 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
18
18
from bzrlib import ui
19
19
from bzrlib.errors import NotBranchError, RevisionNotPresent
20
from bzrlib.knit import KnitVersionedFile
20
from bzrlib.knit import make_file_knit
21
21
from bzrlib.revision import NULL_REVISION
22
22
from bzrlib.trace import mutter
26
from mapping import escape_svn_path
27
from bzrlib.plugins.svn.mapping import escape_svn_path
28
def get_local_changes(paths, mapping, generate_revid, get_children=None):
29
def get_local_changes(paths, branch, mapping, generate_revid,
30
32
for p in sorted(paths.keys()):
33
if not changes.path_is_child(branch, p):
32
36
new_p = mapping.scheme.unprefix(p)[1]
33
37
if data[1] is not None:
100
104
:param renames: List of renames (known file ids for particular paths)
101
105
:param mapping: Mapping
103
changes = get_local_changes(global_changes, mapping,
107
changes = get_local_changes(global_changes, branch, mapping,
104
108
self.repos.generate_revision_id, find_children)
105
109
if find_children is not None:
106
110
def get_children(path, revid):
117
121
idmap.update(renames)
118
122
return (idmap, changes)
120
def get_map(self, uuid, revnum, branch, renames_cb, mapping):
121
raise NotImplementedError(self.get_map)
124
def get_map(self, uuid, revnum, branch, mapping):
125
"""Make sure the map is up to date until revnum."""
126
# First, find the last cached map
129
return {"": (mapping.generate_file_id(uuid, 0, "", u""),
130
self.repos.generate_revision_id(0, "", mapping))}
133
next_parent_revs = []
134
if mapping.is_branch(""):
135
map = {u"": (mapping.generate_file_id(uuid, 0, "", u""), NULL_REVISION)}
139
# No history -> empty map
140
for revmeta in self.repos.iter_reverse_branch_changes(branch, revnum, mapping):
141
revid = revmeta.get_revision_id(mapping)
144
pb = ui.ui_factory.nested_progress_bar()
148
for revmeta in reversed(todo):
149
revid = revmeta.get_revision_id(mapping)
151
def log_find_children(path, revnum):
153
return self.repos._log.find_children(path, revnum)
155
(idmap, changes) = self.apply_changes(self.repos.uuid,
156
revmeta.revnum, revmeta.branch_path, revmeta.paths,
157
mapping.import_fileid_map(revmeta.revprops, revmeta.fileprops),
158
mapping, log_find_children)
159
pb.update('generating file id map', i, len(todo))
161
parent_revs = next_parent_revs
163
self.update_map(map, revid, idmap, changes)
165
next_parent_revs = [revid]
123
171
def update_map(self, map, revid, idmap, changes):
124
172
for p in changes:
138
186
map[parent] = map[parent][0], revid
141
class CachingFileIdMap:
189
class CachingFileIdMap(object):
142
190
"""A file id map that uses a cache."""
143
191
def __init__(self, cache_transport, actual):
144
self.idmap_knit = KnitVersionedFile("fileidmap-v%d" % FILEIDMAP_VERSION, cache_transport, create=True)
192
self.idmap_knit = make_file_knit("fileidmap-v%d" % FILEIDMAP_VERSION, cache_transport, 0644, create=True)
145
193
self.actual = actual
146
194
self.apply_changes = actual.apply_changes
195
self.repos = actual.repos
148
197
def save(self, revid, parent_revids, _map):
149
198
mutter('saving file id map for %r' % revid)
164
def get_map(self, uuid, revnum, branch, renames_cb, mapping):
213
def get_map(self, uuid, revnum, branch, mapping):
165
214
"""Make sure the map is up to date until revnum."""
166
215
# First, find the last cached map
168
next_parent_revs = []
170
217
assert branch == ""
171
218
return {"": (mapping.generate_file_id(uuid, 0, "", u""),
172
219
self.repos.generate_revision_id(0, "", mapping))}
222
next_parent_revs = []
176
224
# No history -> empty map
177
for (bp, paths, rev) in self.repos.follow_branch_history(branch,
179
revid = self.repos.generate_revision_id(rev, bp, mapping)
180
quickrevidmap[revid] = (rev, bp)
225
for revmeta in self.repos.iter_reverse_branch_changes(branch, revnum, mapping):
226
revid = revmeta.get_revision_id(mapping)
182
228
map = self.load(revid)
183
229
# found the nearest cached map
184
230
next_parent_revs = [revid]
186
232
except RevisionNotPresent:
187
todo.append((revid, paths))
189
235
# target revision was present
190
236
if len(todo) == 0:
193
239
if len(next_parent_revs) == 0:
194
if mapping.scheme.is_branch(""):
240
if mapping.is_branch(""):
195
241
map = {u"": (mapping.generate_file_id(uuid, 0, "", u""), NULL_REVISION)}
203
for (revid, global_changes) in reversed(todo):
249
for revmeta in reversed(todo):
250
revid = revmeta.get_revision_id(mapping)
204
251
expensive = False
205
252
def log_find_children(path, revnum):
207
254
return self.repos._log.find_children(path, revnum)
209
(revnum, branch) = quickrevidmap[revid]
210
(idmap, changes) = self.actual.apply_changes(self.repos.uuid, revnum, branch,
211
global_changes, renames_cb(branch, revnum, mapping), mapping,
256
(idmap, changes) = self.actual.apply_changes(self.repos.uuid,
257
revmeta.revnum, revmeta.branch_path, revmeta.paths,
258
mapping.import_fileid_map(revmeta.revprops, revmeta.fileprops),
259
mapping, log_find_children)
213
260
pb.update('generating file id map', i, len(todo))
215
262
parent_revs = next_parent_revs
228
275
self.save(revid, parent_revs, map)
232
class SimpleFileIdMap(CachingFileIdMap):
233
def __init__(self, repos, cache_transport):
234
CachingFileIdMap.__init__(self, cache_transport, FileIdMap(simple_apply_changes, repos))