~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/mutabletree.py

  • Committer: Parth Malwankar
  • Date: 2010-06-12 02:58:42 UTC
  • mto: This revision was merged to the branch mainline in revision 5291.
  • Revision ID: parth.malwankar@gmail.com-20100612025842-amc5em04efepm069
reduced STEP in recordcounter to allow more frequent updates
on progress bar for slower connections.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
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
30
30
    bzrdir,
31
31
    errors,
32
32
    hooks,
33
 
    inventory as _mod_inventory,
34
33
    osutils,
35
34
    revisiontree,
 
35
    symbol_versioning,
36
36
    trace,
37
37
    tree,
38
38
    )
79
79
        # used on media which doesn't differentiate the case of names.
80
80
        self.case_sensitive = True
81
81
 
82
 
    def is_control_filename(self, filename):
83
 
        """True if filename is the name of a control file in this tree.
84
 
 
85
 
        :param filename: A filename within the tree. This is a relative path
86
 
        from the root of this tree.
87
 
 
88
 
        This is true IF and ONLY IF the filename is part of the meta data
89
 
        that bzr controls in this tree. I.E. a random .bzr directory placed
90
 
        on disk will not be a control file for this tree.
91
 
        """
92
 
        raise NotImplementedError(self.is_control_filename)
93
 
 
94
82
    @needs_tree_write_lock
95
83
    def add(self, files, ids=None, kinds=None):
96
84
        """Add paths to the set of versioned paths.
160
148
        if sub_tree_id == self.get_root_id():
161
149
            raise errors.BadReferenceTarget(self, sub_tree,
162
150
                                     'Trees have the same root id.')
163
 
        if sub_tree_id in self:
 
151
        if sub_tree_id in self.inventory:
164
152
            raise errors.BadReferenceTarget(self, sub_tree,
165
153
                                            'Root id already present in tree')
166
154
        self._add([sub_tree_path], [sub_tree_id], ['tree-reference'])
175
163
        """
176
164
        raise NotImplementedError(self._add)
177
165
 
 
166
    @needs_tree_write_lock
178
167
    def apply_inventory_delta(self, changes):
179
168
        """Apply changes to the inventory as an atomic operation.
180
169
 
183
172
        :return None:
184
173
        :seealso Inventory.apply_delta: For details on the changes parameter.
185
174
        """
186
 
        raise NotImplementedError(self.apply_inventory_delta)
 
175
        self.flush()
 
176
        inv = self.inventory
 
177
        inv.apply_delta(changes)
 
178
        self._write_inventory(inv)
187
179
 
188
180
    @needs_write_lock
189
181
    def commit(self, message=None, revprops=None, *args,
341
333
        :return: None
342
334
        """
343
335
 
 
336
    def _fix_case_of_inventory_path(self, path):
 
337
        """If our tree isn't case sensitive, return the canonical path"""
 
338
        if not self.case_sensitive:
 
339
            path = self.get_canonical_inventory_path(path)
 
340
        return path
 
341
 
344
342
    @needs_write_lock
345
343
    def put_file_bytes_non_atomic(self, file_id, bytes):
346
344
        """Update the content of a file in the tree.
370
368
        """
371
369
        raise NotImplementedError(self.set_parent_trees)
372
370
 
373
 
    def smart_add(self, file_list, recurse=True, action=None, save=True):
374
 
        """Version file_list, optionally recursing into directories.
375
 
 
376
 
        This is designed more towards DWIM for humans than API clarity.
377
 
        For the specific behaviour see the help for cmd_add().
378
 
 
379
 
        :param file_list: List of zero or more paths.  *NB: these are 
380
 
            interpreted relative to the process cwd, not relative to the 
381
 
            tree.*  (Add and most other tree methods use tree-relative
382
 
            paths.)
383
 
        :param action: A reporter to be called with the inventory, parent_ie,
384
 
            path and kind of the path being added. It may return a file_id if
385
 
            a specific one should be used.
386
 
        :param save: Save the inventory after completing the adds. If False
387
 
            this provides dry-run functionality by doing the add and not saving
388
 
            the inventory.
389
 
        :return: A tuple - files_added, ignored_files. files_added is the count
390
 
            of added files, and ignored_files is a dict mapping files that were
391
 
            ignored to the rule that caused them to be ignored.
392
 
        """
393
 
        raise NotImplementedError(self.smart_add)
394
 
 
395
 
    def update_basis_by_delta(self, new_revid, delta):
396
 
        """Update the parents of this tree after a commit.
397
 
 
398
 
        This gives the tree one parent, with revision id new_revid. The
399
 
        inventory delta is applied to the current basis tree to generate the
400
 
        inventory for the parent new_revid, and all other parent trees are
401
 
        discarded.
402
 
 
403
 
        All the changes in the delta should be changes synchronising the basis
404
 
        tree with some or all of the working tree, with a change to a directory
405
 
        requiring that its contents have been recursively included. That is,
406
 
        this is not a general purpose tree modification routine, but a helper
407
 
        for commit which is not required to handle situations that do not arise
408
 
        outside of commit.
409
 
 
410
 
        See the inventory developers documentation for the theory behind
411
 
        inventory deltas.
412
 
 
413
 
        :param new_revid: The new revision id for the trees parent.
414
 
        :param delta: An inventory delta (see apply_inventory_delta) describing
415
 
            the changes from the current left most parent revision to new_revid.
416
 
        """
417
 
        raise NotImplementedError(self.update_basis_by_delta)
418
 
 
419
 
 
420
 
class MutableInventoryTree(MutableTree,tree.InventoryTree):
421
 
 
422
 
    @needs_tree_write_lock
423
 
    def apply_inventory_delta(self, changes):
424
 
        """Apply changes to the inventory as an atomic operation.
425
 
 
426
 
        :param changes: An inventory delta to apply to the working tree's
427
 
            inventory.
428
 
        :return None:
429
 
        :seealso Inventory.apply_delta: For details on the changes parameter.
430
 
        """
431
 
        self.flush()
432
 
        inv = self.inventory
433
 
        inv.apply_delta(changes)
434
 
        self._write_inventory(inv)
435
 
 
436
 
    def _fix_case_of_inventory_path(self, path):
437
 
        """If our tree isn't case sensitive, return the canonical path"""
438
 
        if not self.case_sensitive:
439
 
            path = self.get_canonical_inventory_path(path)
440
 
        return path
441
 
 
442
 
    @needs_tree_write_lock
443
 
    def smart_add(self, file_list, recurse=True, action=None, save=True):
444
 
        """Version file_list, optionally recursing into directories.
445
 
 
446
 
        This is designed more towards DWIM for humans than API clarity.
447
 
        For the specific behaviour see the help for cmd_add().
448
 
 
449
 
        :param file_list: List of zero or more paths.  *NB: these are 
450
 
            interpreted relative to the process cwd, not relative to the 
451
 
            tree.*  (Add and most other tree methods use tree-relative
452
 
            paths.)
 
371
    @needs_tree_write_lock
 
372
    def smart_add(self, file_list, recurse=True, action=None, save=True):
 
373
        """Version file_list, optionally recursing into directories.
 
374
 
 
375
        This is designed more towards DWIM for humans than API clarity.
 
376
        For the specific behaviour see the help for cmd_add().
 
377
 
453
378
        :param action: A reporter to be called with the inventory, parent_ie,
454
379
            path and kind of the path being added. It may return a file_id if
455
380
            a specific one should be used.
486
411
            for c in self.conflicts():
487
412
                conflicts_related.update(c.associated_filenames())
488
413
 
489
 
        # expand any symlinks in the directory part, while leaving the
490
 
        # filename alone
491
 
        # only expanding if symlinks are supported avoids windows path bugs
492
 
        if osutils.has_symlinks():
493
 
            file_list = map(osutils.normalizepath, file_list)
494
 
 
495
414
        # validate user file paths and convert all paths to tree
496
415
        # relative : it's cheaper to make a tree relative path an abspath
497
416
        # than to convert an abspath to tree relative, and it's cheaper to
617
536
                        this_ie = None
618
537
                    else:
619
538
                        this_ie = inv[this_id]
620
 
                        # Same as in _add_one below, if the inventory doesn't
621
 
                        # think this is a directory, update the inventory
622
 
                        if this_ie.kind != 'directory':
623
 
                            this_ie = _mod_inventory.make_entry('directory',
624
 
                                this_ie.name, this_ie.parent_id, this_id)
625
 
                            del inv[this_id]
626
 
                            inv.add(this_ie)
627
539
 
628
540
                for subf in sorted(os.listdir(abspath)):
629
541
                    # here we could use TreeDirectory rather than
693
605
        # TODO: Consider re-evaluating the need for this with CHKInventory
694
606
        # we don't strictly need to mutate an inventory for this
695
607
        # it only makes sense when apply_delta is cheaper than get_inventory()
696
 
        inventory = _mod_inventory.mutable_inventory_from_tree(basis)
 
608
        inventory = basis.inventory._get_mutable_inventory()
697
609
        basis.unlock()
698
610
        inventory.apply_delta(delta)
699
 
        rev_tree = revisiontree.InventoryRevisionTree(self.branch.repository,
 
611
        rev_tree = revisiontree.RevisionTree(self.branch.repository,
700
612
                                             inventory, new_revid)
701
613
        self.set_parent_trees([(new_revid, rev_tree)])
702
614
 
710
622
        """Create the default hooks.
711
623
 
712
624
        """
713
 
        hooks.Hooks.__init__(self, "bzrlib.mutabletree", "MutableTree.hooks")
714
 
        self.add_hook('start_commit',
 
625
        hooks.Hooks.__init__(self)
 
626
        self.create_hook(hooks.HookPoint('start_commit',
715
627
            "Called before a commit is performed on a tree. The start commit "
716
628
            "hook is able to change the tree before the commit takes place. "
717
629
            "start_commit is called with the bzrlib.mutabletree.MutableTree "
718
 
            "that the commit is being performed on.", (1, 4))
719
 
        self.add_hook('post_commit',
 
630
            "that the commit is being performed on.", (1, 4), None))
 
631
        self.create_hook(hooks.HookPoint('post_commit',
720
632
            "Called after a commit is performed on a tree. The hook is "
721
633
            "called with a bzrlib.mutabletree.PostCommitHookParams object. "
722
634
            "The mutable tree the commit was performed on is available via "
723
 
            "the mutable_tree attribute of that object.", (2, 0))
 
635
            "the mutable_tree attribute of that object.", (2, 0), None))
724
636
 
725
637
 
726
638
# install the default hooks into the MutableTree class.
803
715
        file_id or None to generate a new file id
804
716
    :returns: None
805
717
    """
806
 
    # if the parent exists, but isn't a directory, we have to do the
807
 
    # kind change now -- really the inventory shouldn't pretend to know
808
 
    # the kind of wt files, but it does.
809
 
    if parent_ie.kind != 'directory':
810
 
        # nb: this relies on someone else checking that the path we're using
811
 
        # doesn't contain symlinks.
812
 
        new_parent_ie = _mod_inventory.make_entry('directory', parent_ie.name,
813
 
            parent_ie.parent_id, parent_ie.file_id)
814
 
        del inv[parent_ie.file_id]
815
 
        inv.add(new_parent_ie)
816
 
        parent_ie = new_parent_ie
817
718
    file_id = file_id_callback(inv, parent_ie, path, kind)
818
719
    entry = inv.make_entry(kind, path.base_path, parent_ie.file_id,
819
720
        file_id=file_id)