~bzr/ubuntu/maverick/bzr-svn/bzr-ppa

« back to all changes in this revision

Viewing changes to fileids.py

  • Committer: Jelmer Vernooij
  • Date: 2008-05-11 19:29:26 UTC
  • mfrom: (220.36.144 0.4)
  • Revision ID: jelmer@samba.org-20080511192926-7mh02j45r25qmzkz
Merge 0.4 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
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.
7
7
 
8
8
# This program is distributed in the hope that it will be useful,
17
17
 
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
23
23
 
24
24
import urllib
25
25
 
26
 
from mapping import escape_svn_path
 
26
import changes
 
27
from bzrlib.plugins.svn.mapping import escape_svn_path
27
28
 
28
 
def get_local_changes(paths, mapping, generate_revid, get_children=None):
 
29
def get_local_changes(paths, branch, mapping, generate_revid, 
 
30
                      get_children=None):
29
31
    new_paths = {}
30
32
    for p in sorted(paths.keys()):
 
33
        if not changes.path_is_child(branch, p):
 
34
            continue
31
35
        data = paths[p]
32
36
        new_p = mapping.scheme.unprefix(p)[1]
33
37
        if data[1] is not None:
78
82
 
79
83
    return map
80
84
 
81
 
class FileIdMap:
 
85
class FileIdMap(object):
82
86
    """File id store. 
83
87
 
84
88
    Keeps a map
100
104
        :param renames: List of renames (known file ids for particular paths)
101
105
        :param mapping: Mapping
102
106
        """
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)
119
123
 
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
 
127
        if revnum == 0:
 
128
            assert branch == ""
 
129
            return {"": (mapping.generate_file_id(uuid, 0, "", u""), 
 
130
              self.repos.generate_revision_id(0, "", mapping))}
 
131
 
 
132
        todo = []
 
133
        next_parent_revs = []
 
134
        if mapping.is_branch(""):
 
135
            map = {u"": (mapping.generate_file_id(uuid, 0, "", u""), NULL_REVISION)}
 
136
        else:
 
137
            map = {}
 
138
 
 
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)
 
142
            todo.append(revmeta)
 
143
   
 
144
        pb = ui.ui_factory.nested_progress_bar()
 
145
 
 
146
        try:
 
147
            i = 1
 
148
            for revmeta in reversed(todo):
 
149
                revid = revmeta.get_revision_id(mapping)
 
150
                expensive = False
 
151
                def log_find_children(path, revnum):
 
152
                    expensive = True
 
153
                    return self.repos._log.find_children(path, revnum)
 
154
 
 
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))
 
160
 
 
161
                parent_revs = next_parent_revs
 
162
 
 
163
                self.update_map(map, revid, idmap, changes)
 
164
                       
 
165
                next_parent_revs = [revid]
 
166
                i += 1
 
167
        finally:
 
168
            pb.finished()
 
169
        return map
122
170
 
123
171
    def update_map(self, map, revid, idmap, changes):
124
172
        for p in changes:
138
186
                map[parent] = map[parent][0], revid
139
187
 
140
188
 
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
147
196
 
148
197
    def save(self, revid, parent_revids, _map):
149
198
        mutter('saving file id map for %r' % revid)
161
210
 
162
211
        return map
163
212
 
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
167
 
        todo = []
168
 
        next_parent_revs = []
169
216
        if revnum == 0:
170
217
            assert branch == ""
171
218
            return {"": (mapping.generate_file_id(uuid, 0, "", u""), 
172
219
              self.repos.generate_revision_id(0, "", mapping))}
173
220
 
174
 
        quickrevidmap = {}
 
221
        todo = []
 
222
        next_parent_revs = []
175
223
 
176
224
        # No history -> empty map
177
 
        for (bp, paths, rev) in self.repos.follow_branch_history(branch, 
178
 
                                             revnum, mapping):
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)
181
227
            try:
182
228
                map = self.load(revid)
183
229
                # found the nearest cached map
184
230
                next_parent_revs = [revid]
185
231
                break
186
232
            except RevisionNotPresent:
187
 
                todo.append((revid, paths))
 
233
                todo.append(revmeta)
188
234
   
189
235
        # target revision was present
190
236
        if len(todo) == 0:
191
237
            return map
192
238
 
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)}
196
242
            else:
197
243
                map = {}
200
246
 
201
247
        try:
202
248
            i = 1
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):
206
253
                    expensive = True
207
254
                    return self.repos._log.find_children(path, revnum)
208
255
 
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,
212
 
                                          log_find_children)
 
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))
214
261
 
215
262
                parent_revs = next_parent_revs
228
275
            self.save(revid, parent_revs, map)
229
276
        return map
230
277
 
231
 
 
232
 
class SimpleFileIdMap(CachingFileIdMap):
233
 
    def __init__(self, repos, cache_transport):
234
 
        CachingFileIdMap.__init__(self, cache_transport, FileIdMap(simple_apply_changes, repos))
235
 
        self.repos = repos
236
 
 
237
 
 
238