/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
1
# Copyright (C) 2008 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
"""CommitHandlers that build and save revisions & their inventories."""
18
19
20
from bzrlib import (
21
    errors,
22
    generate_ids,
23
    inventory,
24
    osutils,
25
    revision,
26
    )
27
from bzrlib.plugins.fastimport import helpers, processor
28
29
0.84.3 by Ian Clatworthy
fix inventory copying when using deltas
30
def copy_inventory(inv):
31
    if hasattr(inv, "_get_mutable_inventory"):
32
        # TODO: Make this a public API on inventory
33
        return inv._get_mutable_inventory()
34
    else:
35
        # TODO: Shallow copy - deep inventory copying is expensive
36
        return inv.copy()
37
38
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
39
class GenericCommitHandler(processor.CommitHandler):
40
    """Base class for Bazaar CommitHandlers."""
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
41
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
42
    def __init__(self, command, cache_mgr, rev_store, verbose=False):
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
43
        super(GenericCommitHandler, self).__init__(command)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
44
        self.cache_mgr = cache_mgr
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
45
        self.rev_store = rev_store
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
46
        self.verbose = verbose
47
48
    def pre_process_files(self):
49
        """Prepare for committing."""
50
        self.revision_id = self.gen_revision_id()
51
        # cache of texts for this commit, indexed by file-id
52
        self.lines_for_commit = {}
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
53
        if self.rev_store.expects_rich_root():
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
54
            self.lines_for_commit[inventory.ROOT_ID] = []
55
56
        # Track the heads and get the real parent list
57
        parents = self.cache_mgr.track_heads(self.command)
58
59
        # Convert the parent commit-ids to bzr revision-ids
60
        if parents:
61
            self.parents = [self.cache_mgr.revision_ids[p]
62
                for p in parents]
63
        else:
64
            self.parents = []
65
        self.debug("%s id: %s, parents: %s", self.command.id,
66
            self.revision_id, str(self.parents))
67
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
68
        # Keep the basis inventory. This needs to be treated as read-only.
69
        if len(self.parents) == 0:
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
70
            self.basis_inventory = self.init_inventory()
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
71
        else:
72
            self.basis_inventory = self.get_inventory(self.parents[0])
73
        self.inventory_root = self.basis_inventory.root
74
75
        # directory-path -> inventory-entry for current inventory
76
        self.directory_entries = dict(self.basis_inventory.directories())
77
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
78
    def init_inventory(self):
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
79
        """Generate an inventory for a parentless revision."""
80
        inv = inventory.Inventory(revision_id=self.revision_id)
81
        if self.rev_store.expects_rich_root():
82
            # The very first root needs to have the right revision
83
            inv.root.revision = self.revision_id
84
        return inv
85
86
    def get_inventory(self, revision_id):
87
        """Get the inventory for a revision id."""
88
        try:
89
            inv = self.cache_mgr.inventories[revision_id]
90
        except KeyError:
91
            if self.verbose:
92
                self.note("get_inventory cache miss for %s", revision_id)
93
            # Not cached so reconstruct from the RevisionStore
94
            inv = self.rev_store.get_inventory(revision_id)
95
            self.cache_mgr.inventories[revision_id] = inv
96
        return inv
97
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
98
    def _get_lines(self, file_id):
99
        """Get the lines for a file-id."""
100
        return self.lines_for_commit[file_id]
101
102
    def _get_inventories(self, revision_ids):
103
        """Get the inventories for revision-ids.
104
        
105
        This is a callback used by the RepositoryStore to
106
        speed up inventory reconstruction.
107
        """
108
        present = []
109
        inventories = []
110
        # If an inventory is in the cache, we assume it was
111
        # successfully loaded into the revision store
112
        for revision_id in revision_ids:
113
            try:
114
                inv = self.cache_mgr.inventories[revision_id]
115
                present.append(revision_id)
116
            except KeyError:
117
                if self.verbose:
118
                    self.note("get_inventories cache miss for %s", revision_id)
119
                # Not cached so reconstruct from the revision store
120
                try:
121
                    inv = self.get_inventory(revision_id)
122
                    present.append(revision_id)
123
                except:
124
                    inv = self.init_inventory()
125
                self.cache_mgr.inventories[revision_id] = inv
126
            inventories.append(inv)
127
        return present, inventories
128
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
129
    def bzr_file_id_and_new(self, path):
130
        """Get a Bazaar file identifier and new flag for a path.
131
        
132
        :return: file_id, is_new where
133
          is_new = True if the file_id is newly created
134
        """
135
        try:
136
            id = self.cache_mgr.file_ids[path]
137
            return id, False
138
        except KeyError:
139
            id = generate_ids.gen_file_id(path)
140
            self.cache_mgr.file_ids[path] = id
141
            self.debug("Generated new file id %s for '%s'", id, path)
142
            return id, True
143
144
    def bzr_file_id(self, path):
145
        """Get a Bazaar file identifier for a path."""
146
        return self.bzr_file_id_and_new(path)[0]
147
148
    def gen_revision_id(self):
149
        """Generate a revision id.
150
151
        Subclasses may override this to produce deterministic ids say.
152
        """
153
        committer = self.command.committer
154
        # Perhaps 'who' being the person running the import is ok? If so,
155
        # it might be a bit quicker and give slightly better compression?
156
        who = "%s <%s>" % (committer[0],committer[1])
157
        timestamp = committer[2]
158
        return generate_ids.gen_revision_id(who, timestamp)
159
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
160
    def build_revision(self):
161
        rev_props = {}
162
        committer = self.command.committer
163
        who = "%s <%s>" % (committer[0],committer[1])
164
        author = self.command.author
165
        if author is not None:
166
            author_id = "%s <%s>" % (author[0],author[1])
167
            if author_id != who:
168
                rev_props['author'] = author_id
169
        return revision.Revision(
170
           timestamp=committer[2],
171
           timezone=committer[3],
172
           committer=who,
173
           message=helpers.escape_commit_message(self.command.message),
174
           revision_id=self.revision_id,
175
           properties=rev_props,
176
           parent_ids=self.parents)
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
177
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
178
    def _modify_item(self, path, kind, is_executable, data, inv):
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
179
        """Add to or change an item in the inventory."""
180
        # Create the new InventoryEntry
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
181
        basename, parent_ie = self._ensure_directory(path, inv)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
182
        file_id = self.bzr_file_id(path)
183
        ie = inventory.make_entry(kind, basename, parent_ie.file_id, file_id)
184
        ie.revision = self.revision_id
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
185
        if kind == 'file':
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
186
            ie.executable = is_executable
187
            lines = osutils.split_lines(data)
188
            ie.text_sha1 = osutils.sha_strings(lines)
189
            ie.text_size = sum(map(len, lines))
190
            self.lines_for_commit[file_id] = lines
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
191
        elif kind == 'symlink':
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
192
            ie.symlink_target = data.encode('utf8')
193
            # There are no lines stored for a symlink so
194
            # make sure the cache used by get_lines knows that
195
            self.lines_for_commit[file_id] = []
196
        else:
197
            raise errors.BzrError("Cannot import items of kind '%s' yet" %
198
                (kind,))
199
        # Record it
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
200
        if file_id in inv:
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
201
            old_ie = inv[file_id]
202
            if old_ie.kind == 'directory':
203
                self.record_delete(path, old_ie)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
204
            self.record_changed(path, ie, parent_ie)
205
        else:
206
            self.record_new(path, ie)
207
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
208
    def _ensure_directory(self, path, inv):
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
209
        """Ensure that the containing directory exists for 'path'"""
210
        dirname, basename = osutils.split(path)
211
        if dirname == '':
212
            # the root node doesn't get updated
213
            return basename, self.inventory_root
214
        try:
215
            ie = self.directory_entries[dirname]
216
        except KeyError:
217
            # We will create this entry, since it doesn't exist
218
            pass
219
        else:
220
            return basename, ie
221
222
        # No directory existed, we will just create one, first, make sure
223
        # the parent exists
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
224
        dir_basename, parent_ie = self._ensure_directory(dirname, inv)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
225
        dir_file_id = self.bzr_file_id(dirname)
226
        ie = inventory.entry_factory['directory'](dir_file_id,
227
            dir_basename, parent_ie.file_id)
228
        ie.revision = self.revision_id
229
        self.directory_entries[dirname] = ie
230
        # There are no lines stored for a directory so
231
        # make sure the cache used by get_lines knows that
232
        self.lines_for_commit[dir_file_id] = []
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
233
234
        # It's possible that a file or symlink with that file-id
235
        # already exists. If it does, we need to delete it.
236
        if dir_file_id in inv:
237
            self.record_delete(dirname, ie)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
238
        self.record_new(dirname, ie)
239
        return basename, ie
240
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
241
    def _delete_item(self, path, inv):
242
        file_id = inv.path2id(path)
243
        ie = inv[file_id]
0.81.9 by Ian Clatworthy
refactor delete_item
244
        self.record_delete(path, ie)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
245
246
    def _copy_item(self, src_path, dest_path, inv):
247
        if not self.parents:
248
            self.warning("ignoring copy of %s to %s - no parent revisions",
249
                src_path, dest_path)
250
            return
251
        file_id = inv.path2id(src_path)
252
        if file_id is None:
253
            self.warning("ignoring copy of %s to %s - source does not exist",
254
                src_path, dest_path)
255
            return
256
        ie = inv[file_id]
257
        kind = ie.kind
258
        if kind == 'file':
259
            content = self.rev_store.get_file_text(self.parents[0], file_id)
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
260
            self._modify_item(dest_path, kind, ie.executable, content, inv)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
261
        elif kind == 'symlink':
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
262
            self._modify_item(dest_path, kind, False, ie.symlink_target, inv)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
263
        else:
264
            self.warning("ignoring copy of %s %s - feature not yet supported",
265
                kind, path)
266
267
    def _rename_item(self, old_path, new_path, inv):
0.81.8 by Ian Clatworthy
refactor rename_item
268
        file_id = inv.path2id(old_path)
269
        ie = inv[file_id]
270
        rev_id = ie.revision
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
271
        new_file_id = inv.path2id(new_path)
272
        if new_file_id is not None:
0.81.9 by Ian Clatworthy
refactor delete_item
273
            self.record_delete(new_path, inv[new_file_id])
0.81.8 by Ian Clatworthy
refactor rename_item
274
        self.record_rename(old_path, new_path, file_id, ie)
275
        self.cache_mgr.rename_path(old_path, new_path)
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
276
0.81.8 by Ian Clatworthy
refactor rename_item
277
        # The revision-id for this entry will be/has been updated and
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
278
        # that means the loader then needs to know what the "new" text is.
279
        # We therefore must go back to the revision store to get it.
0.81.8 by Ian Clatworthy
refactor rename_item
280
        lines = self.rev_store.get_file_lines(rev_id, file_id)
281
        self.lines_for_commit[file_id] = lines
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
282
283
    def _delete_all_items(self, inv):
284
        for name, root_item in inv.root.children.iteritems():
285
            inv.remove_recursive_id(root_item.file_id)
286
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
287
288
class InventoryCommitHandler(GenericCommitHandler):
0.81.3 by Ian Clatworthy
enhance RevisionLoader to try inventory deltas & decide on rich-roots
289
    """A CommitHandler that builds and saves full inventories."""
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
290
291
    def pre_process_files(self):
292
        super(InventoryCommitHandler, self).pre_process_files()
293
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
294
        # Seed the inventory from the previous one
295
        if len(self.parents) == 0:
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
296
            self.inventory = self.basis_inventory
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
297
        else:
0.84.3 by Ian Clatworthy
fix inventory copying when using deltas
298
            self.inventory = copy_inventory(self.basis_inventory)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
299
        self.inventory_root = self.inventory.root
300
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
301
        # directory-path -> inventory-entry for current inventory
302
        self.directory_entries = dict(self.inventory.directories())
303
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
304
        # Initialise the inventory revision info as required
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
305
        if self.rev_store.expects_rich_root():
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
306
            self.inventory.revision_id = self.revision_id
307
        else:
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
308
            # In this revision store, root entries have no knit or weave.
309
            # When serializing out to disk and back in, root.revision is
310
            # always the new revision_id.
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
311
            self.inventory.root.revision = self.revision_id
312
313
    def post_process_files(self):
314
        """Save the revision."""
315
        self.cache_mgr.inventories[self.revision_id] = self.inventory
0.81.2 by Ian Clatworthy
refactor InventoryCommitHandler general stuff into parent class
316
        rev = self.build_revision()
0.81.4 by Ian Clatworthy
generalise RevisionLoader to RevisionStore as a repo abstraction
317
        self.rev_store.load(rev, self.inventory, None,
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
318
            lambda file_id: self._get_lines(file_id),
319
            lambda revision_ids: self._get_inventories(revision_ids))
320
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
321
    def record_new(self, path, ie):
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
322
        try:
323
            self.inventory.add(ie)
324
        except errors.DuplicateFileId:
325
            # Directory already exists as a file or symlink
326
            del self.inventory[ie.file_id]
327
            # Try again
328
            self.inventory.add(ie)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
329
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
330
    def record_changed(self, path, ie, parent_ie):
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
331
        # HACK: no API for this (del+add does more than it needs to)
332
        self.inventory._byid[ie.file_id] = ie
333
        parent_ie.children[ie.name] = ie
334
0.81.9 by Ian Clatworthy
refactor delete_item
335
    def record_delete(self, path, ie):
336
        self.inventory.remove_recursive_id(ie.file_id)
0.81.8 by Ian Clatworthy
refactor rename_item
337
338
    def record_rename(self, old_path, new_path, file_id, ie):
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
339
        new_basename, new_parent_ie = self._ensure_directory(new_path,
340
            self.inventory)
0.81.8 by Ian Clatworthy
refactor rename_item
341
        new_parent_id = new_parent_ie.file_id
342
        self.inventory.rename(file_id, new_parent_id, new_basename)
343
        self.inventory[file_id].revision = self.revision_id
344
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
345
    def _delete_item(self, path):
346
        # NOTE: I'm retaining this method for now, instead of using the
347
        # one in the superclass, because it's taken quite a lot of tweaking
348
        # to cover all the edge cases seen in the wild. Long term, it can
349
        # probably go once the higher level method does "warn_unless_in_merges"
350
        # and handles all the various special cases ...
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
351
        fileid = self.bzr_file_id(path)
352
        dirname, basename = osutils.split(path)
353
        if (fileid in self.inventory and
354
            isinstance(self.inventory[fileid], inventory.InventoryDirectory)):
355
            for child_path in self.inventory[fileid].children.keys():
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
356
                self._delete_item(osutils.pathjoin(path, child_path))
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
357
        try:
358
            if self.inventory.id2path(fileid) == path:
359
                del self.inventory[fileid]
360
            else:
361
                # already added by some other name?
362
                if dirname in self.cache_mgr.file_ids:
363
                    parent_id = self.cache_mgr.file_ids[dirname]
364
                    del self.inventory[parent_id].children[basename]
365
        except KeyError:
366
            self._warn_unless_in_merges(fileid, path)
367
        except errors.NoSuchId:
368
            self._warn_unless_in_merges(fileid, path)
369
        except AttributeError, ex:
370
            if ex.args[0] == 'children':
371
                # A directory has changed into a file and then one
372
                # of it's children is being deleted!
373
                self._warn_unless_in_merges(fileid, path)
374
            else:
375
                raise
376
        try:
377
            self.cache_mgr.delete_path(path)
378
        except KeyError:
379
            pass
380
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
381
    def _warn_unless_in_merges(self, fileid, path):
382
        if len(self.parents) <= 1:
383
            return
384
        for parent in self.parents[1:]:
385
            if fileid in self.get_inventory(parent):
386
                return
387
        self.warning("ignoring delete of %s as not in parent inventories", path)
388
389
    def modify_handler(self, filecmd):
390
        if filecmd.dataref is not None:
391
            data = self.cache_mgr.fetch_blob(filecmd.dataref)
392
        else:
393
            data = filecmd.data
394
        self.debug("modifying %s", filecmd.path)
395
        self._modify_item(filecmd.path, filecmd.kind,
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
396
            filecmd.is_executable, data, self.inventory)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
397
398
    def delete_handler(self, filecmd):
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
399
        self.debug("deleting %s", filecmd.path)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
400
        self._delete_item(filecmd.path)
401
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
402
    def copy_handler(self, filecmd):
403
        src_path = filecmd.src_path
404
        dest_path = filecmd.dest_path
405
        self.debug("copying %s to %s", src_path, dest_path)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
406
        self._copy_item(src_path, dest_path, self.inventory)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
407
408
    def rename_handler(self, filecmd):
409
        old_path = filecmd.old_path
410
        new_path = filecmd.new_path
411
        self.debug("renaming %s to %s", old_path, new_path)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
412
        self._rename_item(old_path, new_path, self.inventory)
0.81.1 by Ian Clatworthy
move GenericCommitHandler into its own module in prep for a delta-based one
413
414
    def deleteall_handler(self, filecmd):
415
        self.debug("deleting all files (and also all directories)")
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
416
        self._delete_all_items(self.inventory)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
417
418
419
class DeltaCommitHandler(GenericCommitHandler):
420
    """A CommitHandler that builds and saves inventory deltas."""
421
422
    def pre_process_files(self):
423
        super(DeltaCommitHandler, self).pre_process_files()
424
        self.delta = []
425
426
    def post_process_files(self):
427
        """Save the revision."""
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
428
        #for path, entry in self.basis_inventory.iter_entries_by_dir():
429
        #    print "ie for %s:\n%r" % (path, entry)
430
        #print "delta:\n%r" % (self.delta,)
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
431
        rev = self.build_revision()
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
432
        inv = self.rev_store.load_using_delta(rev, self.basis_inventory,
433
            self.delta, None,
434
            lambda file_id: self._get_lines(file_id),
435
            lambda revision_ids: self._get_inventories(revision_ids))
0.81.5 by Ian Clatworthy
basic DeltaCommitHandler generating deltas
436
        self.cache_mgr.inventories[self.revision_id] = inv
437
438
    def record_new(self, path, ie):
439
        self.delta.append((None, path, ie.file_id, ie))
440
441
    def record_changed(self, path, ie, parent_ie=None):
442
        self.delta.append((path, path, ie.file_id, ie))
443
0.81.9 by Ian Clatworthy
refactor delete_item
444
    def record_delete(self, path, ie):
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
445
        self.delta.append((path, None, ie.file_id, None))
446
        if ie.kind == 'directory':
447
            for child_path, entry in \
448
                self.basis_inventory.iter_entries_by_dir(from_dir=ie):
449
                #print "deleting child %s" % child_path
450
                self.delta.append((child_path, None, entry.file_id, None))
0.81.8 by Ian Clatworthy
refactor rename_item
451
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
452
    def record_rename(self, old_path, new_path, file_id, old_ie):
453
        new_ie = old_ie.copy()
454
        new_basename, new_parent_ie = self._ensure_directory(new_path,
455
            self.basis_inventory)
456
        new_ie.name = new_basename
457
        new_ie.parent_id = new_parent_ie.file_id
458
        new_ie.revision = self.revision_id
459
        self.delta.append((old_path, new_path, file_id, new_ie))
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
460
461
    def modify_handler(self, filecmd):
462
        if filecmd.dataref is not None:
463
            data = self.cache_mgr.fetch_blob(filecmd.dataref)
464
        else:
465
            data = filecmd.data
466
        self.debug("modifying %s", filecmd.path)
467
        self._modify_item(filecmd.path, filecmd.kind,
0.81.7 by Ian Clatworthy
merge import tests and tweaks to make them pass
468
            filecmd.is_executable, data, self.basis_inventory)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
469
470
    def delete_handler(self, filecmd):
471
        self.debug("deleting %s", filecmd.path)
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
472
        self._delete_item(filecmd.path, self.basis_inventory)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
473
474
    def copy_handler(self, filecmd):
475
        src_path = filecmd.src_path
476
        dest_path = filecmd.dest_path
477
        self.debug("copying %s to %s", src_path, dest_path)
0.81.10 by Ian Clatworthy
get DeltaCommitHandler passing all tests
478
        self._copy_item(src_path, dest_path, self.basis_inventory)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
479
480
    def rename_handler(self, filecmd):
481
        old_path = filecmd.old_path
482
        new_path = filecmd.new_path
483
        self.debug("renaming %s to %s", old_path, new_path)
484
        self._rename_item(old_path, new_path, self.basis_inventory)
485
486
    def deleteall_handler(self, filecmd):
487
        self.debug("deleting all files (and also all directories)")
488
        # I'm not 100% sure this will work in the delta case.
489
        # But clearing out the basis inventory so that everything
490
        # is added sounds ok in theory ...
491
        # We grab a copy as the basis is likely to be cached and
492
        # we don't want to destroy the cached version
0.84.3 by Ian Clatworthy
fix inventory copying when using deltas
493
        self.basis_inventory = copy_inventory(self.basis_inventory)
0.81.6 by Ian Clatworthy
basic DeltaCommitHandler mostly going bar rename
494
        self._delete_all_items(self.basis_inventory)