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