~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Jelmer Vernooij
  • Date: 2011-01-14 00:58:16 UTC
  • mto: (5582.12.2 weave-plugin)
  • mto: This revision was merged to the branch mainline in revision 5718.
  • Revision ID: jelmer@samba.org-20110114005816-b3g5xigfiy20s29y
Fix imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
209
209
        else:
210
210
            self._branch = self.bzrdir.open_branch()
211
211
        self.basedir = realpath(basedir)
212
 
        # if branch is at our basedir and is a format 6 or less
213
 
        if isinstance(self._format, WorkingTreeFormat2):
214
 
            # share control object
215
 
            self._control_files = self.branch.control_files
216
 
        else:
217
 
            # assume all other formats have their own control files.
218
 
            self._control_files = _control_files
 
212
        self._control_files = _control_files
219
213
        self._transport = self._control_files._transport
220
214
        # update the whole cache up front and write to disk if anything changed;
221
215
        # in the future we might want to do this more selectively
353
347
        return control.open_workingtree(), relpath
354
348
 
355
349
    @staticmethod
356
 
    def open_containing_paths(file_list, default_directory='.',
357
 
        canonicalize=True, apply_view=True):
 
350
    def open_containing_paths(file_list, default_directory=None,
 
351
                              canonicalize=True, apply_view=True):
358
352
        """Open the WorkingTree that contains a set of paths.
359
353
 
360
354
        Fail if the paths given are not all in a single tree.
362
356
        This is used for the many command-line interfaces that take a list of
363
357
        any number of files and that require they all be in the same tree.
364
358
        """
 
359
        if default_directory is None:
 
360
            default_directory = u'.'
365
361
        # recommended replacement for builtins.internal_tree_files
366
362
        if file_list is None or len(file_list) == 0:
367
363
            tree = WorkingTree.open_containing(default_directory)[0]
375
371
                    view_str = views.view_display_str(view_files)
376
372
                    note("Ignoring files outside view. View is %s" % view_str)
377
373
            return tree, file_list
378
 
        tree = WorkingTree.open_containing(file_list[0])[0]
 
374
        if default_directory == u'.':
 
375
            seed = file_list[0]
 
376
        else:
 
377
            seed = default_directory
 
378
            file_list = [osutils.pathjoin(default_directory, f)
 
379
                         for f in file_list]
 
380
        tree = WorkingTree.open_containing(seed)[0]
379
381
        return tree, tree.safe_relpath_files(file_list, canonicalize,
380
 
            apply_view=apply_view)
 
382
                                             apply_view=apply_view)
381
383
 
382
384
    def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
383
385
        """Convert file_list into a list of relpaths in tree.
1663
1665
 
1664
1666
    @needs_write_lock
1665
1667
    def pull(self, source, overwrite=False, stop_revision=None,
1666
 
             change_reporter=None, possible_transports=None, local=False):
 
1668
             change_reporter=None, possible_transports=None, local=False,
 
1669
             show_base=False):
1667
1670
        source.lock_read()
1668
1671
        try:
1669
1672
            old_revision_info = self.branch.last_revision_info()
1683
1686
                                basis_tree,
1684
1687
                                this_tree=self,
1685
1688
                                pb=None,
1686
 
                                change_reporter=change_reporter)
 
1689
                                change_reporter=change_reporter,
 
1690
                                show_base=show_base)
1687
1691
                    basis_root_id = basis_tree.get_root_id()
1688
1692
                    new_root_id = new_basis_tree.get_root_id()
1689
1693
                    if basis_root_id != new_root_id:
2078
2082
                    files_to_backup.append(path[1])
2079
2083
 
2080
2084
        def backup(file_to_backup):
2081
 
            backup_name = self.bzrdir.generate_backup_name(file_to_backup)
 
2085
            backup_name = self.bzrdir._available_backup_name(file_to_backup)
2082
2086
            osutils.rename(abs_path, self.abspath(backup_name))
2083
 
            return "removed %s (but kept a copy: %s)" % (file_to_backup, backup_name)
 
2087
            return "removed %s (but kept a copy: %s)" % (file_to_backup,
 
2088
                                                         backup_name)
2084
2089
 
2085
2090
        # Build inv_delta and delete files where applicable,
2086
2091
        # do this before any modifications to inventory.
2261
2266
    _marker = object()
2262
2267
 
2263
2268
    def update(self, change_reporter=None, possible_transports=None,
2264
 
               revision=None, old_tip=_marker):
 
2269
               revision=None, old_tip=_marker, show_base=False):
2265
2270
        """Update a working tree along its branch.
2266
2271
 
2267
2272
        This will update the branch if its bound too, which means we have
2304
2309
            else:
2305
2310
                if old_tip is self._marker:
2306
2311
                    old_tip = None
2307
 
            return self._update_tree(old_tip, change_reporter, revision)
 
2312
            return self._update_tree(old_tip, change_reporter, revision, show_base)
2308
2313
        finally:
2309
2314
            self.unlock()
2310
2315
 
2311
2316
    @needs_tree_write_lock
2312
 
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
 
2317
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None,
 
2318
                     show_base=False):
2313
2319
        """Update a tree to the master branch.
2314
2320
 
2315
2321
        :param old_tip: if supplied, the previous tip revision the branch,
2342
2348
            other_tree = self.branch.repository.revision_tree(old_tip)
2343
2349
            nb_conflicts = merge.merge_inner(self.branch, other_tree,
2344
2350
                                             base_tree, this_tree=self,
2345
 
                                             change_reporter=change_reporter)
 
2351
                                             change_reporter=change_reporter,
 
2352
                                             show_base=show_base)
2346
2353
            if nb_conflicts:
2347
2354
                self.add_parent_tree((old_tip, other_tree))
2348
2355
                trace.note('Rerun update after fixing the conflicts.')
2372
2379
 
2373
2380
            nb_conflicts = merge.merge_inner(self.branch, to_tree, base_tree,
2374
2381
                                             this_tree=self,
2375
 
                                             change_reporter=change_reporter)
 
2382
                                             change_reporter=change_reporter,
 
2383
                                             show_base=show_base)
2376
2384
            self.set_last_revision(revision)
2377
2385
            # TODO - dedup parents list with things merged by pull ?
2378
2386
            # reuse the tree we've updated to to set the basis:
2680
2688
        return ShelfManager(self, self._transport)
2681
2689
 
2682
2690
 
2683
 
class WorkingTree2(WorkingTree):
2684
 
    """This is the Format 2 working tree.
2685
 
 
2686
 
    This was the first weave based working tree.
2687
 
     - uses os locks for locking.
2688
 
     - uses the branch last-revision.
2689
 
    """
2690
 
 
2691
 
    def __init__(self, *args, **kwargs):
2692
 
        super(WorkingTree2, self).__init__(*args, **kwargs)
2693
 
        # WorkingTree2 has more of a constraint that self._inventory must
2694
 
        # exist. Because this is an older format, we don't mind the overhead
2695
 
        # caused by the extra computation here.
2696
 
 
2697
 
        # Newer WorkingTree's should only have self._inventory set when they
2698
 
        # have a read lock.
2699
 
        if self._inventory is None:
2700
 
            self.read_working_inventory()
2701
 
 
2702
 
    def _get_check_refs(self):
2703
 
        """Return the references needed to perform a check of this tree."""
2704
 
        return [('trees', self.last_revision())]
2705
 
 
2706
 
    def lock_tree_write(self):
2707
 
        """See WorkingTree.lock_tree_write().
2708
 
 
2709
 
        In Format2 WorkingTrees we have a single lock for the branch and tree
2710
 
        so lock_tree_write() degrades to lock_write().
2711
 
 
2712
 
        :return: An object with an unlock method which will release the lock
2713
 
            obtained.
2714
 
        """
2715
 
        self.branch.lock_write()
2716
 
        try:
2717
 
            self._control_files.lock_write()
2718
 
            return self
2719
 
        except:
2720
 
            self.branch.unlock()
2721
 
            raise
2722
 
 
2723
 
    def unlock(self):
2724
 
        # do non-implementation specific cleanup
2725
 
        self._cleanup()
2726
 
 
2727
 
        # we share control files:
2728
 
        if self._control_files._lock_count == 3:
2729
 
            # _inventory_is_modified is always False during a read lock.
2730
 
            if self._inventory_is_modified:
2731
 
                self.flush()
2732
 
            self._write_hashcache_if_dirty()
2733
 
 
2734
 
        # reverse order of locking.
2735
 
        try:
2736
 
            return self._control_files.unlock()
2737
 
        finally:
2738
 
            self.branch.unlock()
2739
 
 
2740
 
 
2741
2691
class WorkingTree3(WorkingTree):
2742
2692
    """This is the Format 3 working tree.
2743
2693
 
2912
2862
        del klass._formats[format.get_format_string()]
2913
2863
 
2914
2864
 
2915
 
class WorkingTreeFormat2(WorkingTreeFormat):
2916
 
    """The second working tree format.
2917
 
 
2918
 
    This format modified the hash cache from the format 1 hash cache.
2919
 
    """
2920
 
 
2921
 
    upgrade_recommended = True
2922
 
 
2923
 
    def get_format_description(self):
2924
 
        """See WorkingTreeFormat.get_format_description()."""
2925
 
        return "Working tree format 2"
2926
 
 
2927
 
    def _stub_initialize_on_transport(self, transport, file_mode):
2928
 
        """Workaround: create control files for a remote working tree.
2929
 
 
2930
 
        This ensures that it can later be updated and dealt with locally,
2931
 
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2932
 
        no working tree.  (See bug #43064).
2933
 
        """
2934
 
        sio = StringIO()
2935
 
        inv = inventory.Inventory()
2936
 
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2937
 
        sio.seek(0)
2938
 
        transport.put_file('inventory', sio, file_mode)
2939
 
        transport.put_bytes('pending-merges', '', file_mode)
2940
 
 
2941
 
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2942
 
                   accelerator_tree=None, hardlink=False):
2943
 
        """See WorkingTreeFormat.initialize()."""
2944
 
        if not isinstance(a_bzrdir.transport, LocalTransport):
2945
 
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
2946
 
        if from_branch is not None:
2947
 
            branch = from_branch
2948
 
        else:
2949
 
            branch = a_bzrdir.open_branch()
2950
 
        if revision_id is None:
2951
 
            revision_id = _mod_revision.ensure_null(branch.last_revision())
2952
 
        branch.lock_write()
2953
 
        try:
2954
 
            branch.generate_revision_history(revision_id)
2955
 
        finally:
2956
 
            branch.unlock()
2957
 
        inv = inventory.Inventory()
2958
 
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2959
 
                         branch,
2960
 
                         inv,
2961
 
                         _internal=True,
2962
 
                         _format=self,
2963
 
                         _bzrdir=a_bzrdir)
2964
 
        basis_tree = branch.repository.revision_tree(revision_id)
2965
 
        if basis_tree.inventory.root is not None:
2966
 
            wt.set_root_id(basis_tree.get_root_id())
2967
 
        # set the parent list and cache the basis tree.
2968
 
        if _mod_revision.is_null(revision_id):
2969
 
            parent_trees = []
2970
 
        else:
2971
 
            parent_trees = [(revision_id, basis_tree)]
2972
 
        wt.set_parent_trees(parent_trees)
2973
 
        transform.build_tree(basis_tree, wt)
2974
 
        return wt
2975
 
 
2976
 
    def __init__(self):
2977
 
        super(WorkingTreeFormat2, self).__init__()
2978
 
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
2979
 
 
2980
 
    def open(self, a_bzrdir, _found=False):
2981
 
        """Return the WorkingTree object for a_bzrdir
2982
 
 
2983
 
        _found is a private parameter, do not use it. It is used to indicate
2984
 
               if format probing has already been done.
2985
 
        """
2986
 
        if not _found:
2987
 
            # we are being called directly and must probe.
2988
 
            raise NotImplementedError
2989
 
        if not isinstance(a_bzrdir.transport, LocalTransport):
2990
 
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
2991
 
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2992
 
                           _internal=True,
2993
 
                           _format=self,
2994
 
                           _bzrdir=a_bzrdir)
2995
 
        return wt
2996
 
 
2997
2865
class WorkingTreeFormat3(WorkingTreeFormat):
2998
2866
    """The second working tree format updated to record a format marker.
2999
2867
 
3131
2999
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3132
3000
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3133
3001
WorkingTreeFormat.set_default_format(__default_format)
3134
 
# formats which have no format string are not discoverable
3135
 
# and not independently creatable, so are not registered.
3136
 
_legacy_formats = [WorkingTreeFormat2(),
3137
 
                   ]
 
3002