~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 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
58
58
    ignores,
59
59
    inventory,
60
60
    merge,
 
61
    registry,
61
62
    revision as _mod_revision,
62
63
    revisiontree,
63
64
    trace,
209
210
        else:
210
211
            self._branch = self.bzrdir.open_branch()
211
212
        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
 
213
        self._control_files = _control_files
219
214
        self._transport = self._control_files._transport
220
215
        # update the whole cache up front and write to disk if anything changed;
221
216
        # in the future we might want to do this more selectively
259
254
    def control_transport(self):
260
255
        return self._transport
261
256
 
 
257
    def is_control_filename(self, filename):
 
258
        """True if filename is the name of a control file in this tree.
 
259
 
 
260
        :param filename: A filename within the tree. This is a relative path
 
261
        from the root of this tree.
 
262
 
 
263
        This is true IF and ONLY IF the filename is part of the meta data
 
264
        that bzr controls in this tree. I.E. a random .bzr directory placed
 
265
        on disk will not be a control file for this tree.
 
266
        """
 
267
        return self.bzrdir.is_control_filename(filename)
 
268
 
262
269
    def _detect_case_handling(self):
263
270
        wt_trans = self.bzrdir.get_workingtree_transport(None)
264
271
        try:
265
 
            wt_trans.stat("FoRMaT")
 
272
            wt_trans.stat(self._format.case_sensitive_filename)
266
273
        except errors.NoSuchFile:
267
274
            self.case_sensitive = True
268
275
        else:
353
360
        return control.open_workingtree(), relpath
354
361
 
355
362
    @staticmethod
356
 
    def open_containing_paths(file_list, default_directory='.',
357
 
        canonicalize=True, apply_view=True):
 
363
    def open_containing_paths(file_list, default_directory=None,
 
364
                              canonicalize=True, apply_view=True):
358
365
        """Open the WorkingTree that contains a set of paths.
359
366
 
360
367
        Fail if the paths given are not all in a single tree.
362
369
        This is used for the many command-line interfaces that take a list of
363
370
        any number of files and that require they all be in the same tree.
364
371
        """
 
372
        if default_directory is None:
 
373
            default_directory = u'.'
365
374
        # recommended replacement for builtins.internal_tree_files
366
375
        if file_list is None or len(file_list) == 0:
367
376
            tree = WorkingTree.open_containing(default_directory)[0]
375
384
                    view_str = views.view_display_str(view_files)
376
385
                    note("Ignoring files outside view. View is %s" % view_str)
377
386
            return tree, file_list
378
 
        tree = WorkingTree.open_containing(file_list[0])[0]
 
387
        if default_directory == u'.':
 
388
            seed = file_list[0]
 
389
        else:
 
390
            seed = default_directory
 
391
            file_list = [osutils.pathjoin(default_directory, f)
 
392
                         for f in file_list]
 
393
        tree = WorkingTree.open_containing(seed)[0]
379
394
        return tree, tree.safe_relpath_files(file_list, canonicalize,
380
 
            apply_view=apply_view)
 
395
                                             apply_view=apply_view)
381
396
 
382
397
    def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
383
398
        """Convert file_list into a list of relpaths in tree.
1382
1397
        to_dir_id = inv.path2id(to_dir)
1383
1398
        if to_dir_id is None:
1384
1399
            raise errors.BzrMoveFailedError('',to_dir,
1385
 
                errors.NotVersionedError(path=str(to_dir)))
 
1400
                errors.NotVersionedError(path=to_dir))
1386
1401
 
1387
1402
        to_dir_ie = inv[to_dir_id]
1388
1403
        if to_dir_ie.kind != 'directory':
1395
1410
            from_id = inv.path2id(from_rel)
1396
1411
            if from_id is None:
1397
1412
                raise errors.BzrMoveFailedError(from_rel,to_dir,
1398
 
                    errors.NotVersionedError(path=str(from_rel)))
 
1413
                    errors.NotVersionedError(path=from_rel))
1399
1414
 
1400
1415
            from_entry = inv[from_id]
1401
1416
            from_parent_id = from_entry.parent_id
1443
1458
            # check the inventory for source and destination
1444
1459
            if from_id is None:
1445
1460
                raise errors.BzrMoveFailedError(from_rel,to_rel,
1446
 
                    errors.NotVersionedError(path=str(from_rel)))
 
1461
                    errors.NotVersionedError(path=from_rel))
1447
1462
            if to_id is not None:
1448
1463
                raise errors.BzrMoveFailedError(from_rel,to_rel,
1449
 
                    errors.AlreadyVersionedError(path=str(to_rel)))
 
1464
                    errors.AlreadyVersionedError(path=to_rel))
1450
1465
 
1451
1466
            # try to determine the mode for rename (only change inv or change
1452
1467
            # inv and file system)
1453
1468
            if after:
1454
1469
                if not self.has_filename(to_rel):
1455
1470
                    raise errors.BzrMoveFailedError(from_id,to_rel,
1456
 
                        errors.NoSuchFile(path=str(to_rel),
 
1471
                        errors.NoSuchFile(path=to_rel,
1457
1472
                        extra="New file has not been created yet"))
1458
1473
                only_change_inv = True
1459
1474
            elif not self.has_filename(from_rel) and self.has_filename(to_rel):
1561
1576
            from_id = basis_tree.path2id(from_rel)
1562
1577
            if from_id is None:
1563
1578
                raise errors.BzrRenameFailedError(from_rel,to_rel,
1564
 
                    errors.NotVersionedError(path=str(from_rel)))
 
1579
                    errors.NotVersionedError(path=from_rel))
1565
1580
            # put entry back in the inventory so we can rename it
1566
1581
            from_entry = basis_tree.inventory[from_id].copy()
1567
1582
            inv.add(from_entry)
1585
1600
        # versioned
1586
1601
        if to_dir_id is None:
1587
1602
            raise errors.BzrMoveFailedError(from_rel,to_rel,
1588
 
                errors.NotVersionedError(path=str(to_dir)))
 
1603
                errors.NotVersionedError(path=to_dir))
1589
1604
 
1590
1605
        # all checks done. now we can continue with our actual work
1591
1606
        mutter('rename_one:\n'
1650
1665
            # - RBC 20060907
1651
1666
            self._write_inventory(self._inventory)
1652
1667
 
1653
 
    def _iter_conflicts(self):
1654
 
        conflicted = set()
1655
 
        for info in self.list_files():
1656
 
            path = info[0]
1657
 
            stem = get_conflicted_stem(path)
1658
 
            if stem is None:
1659
 
                continue
1660
 
            if stem not in conflicted:
1661
 
                conflicted.add(stem)
1662
 
                yield stem
1663
 
 
1664
1668
    @needs_write_lock
1665
1669
    def pull(self, source, overwrite=False, stop_revision=None,
1666
 
             change_reporter=None, possible_transports=None, local=False):
 
1670
             change_reporter=None, possible_transports=None, local=False,
 
1671
             show_base=False):
1667
1672
        source.lock_read()
1668
1673
        try:
1669
1674
            old_revision_info = self.branch.last_revision_info()
1683
1688
                                basis_tree,
1684
1689
                                this_tree=self,
1685
1690
                                pb=None,
1686
 
                                change_reporter=change_reporter)
 
1691
                                change_reporter=change_reporter,
 
1692
                                show_base=show_base)
1687
1693
                    basis_root_id = basis_tree.get_root_id()
1688
1694
                    new_root_id = new_basis_tree.get_root_id()
1689
1695
                    if basis_root_id != new_root_id:
2078
2084
                    files_to_backup.append(path[1])
2079
2085
 
2080
2086
        def backup(file_to_backup):
2081
 
            backup_name = self.bzrdir.generate_backup_name(file_to_backup)
 
2087
            backup_name = self.bzrdir._available_backup_name(file_to_backup)
2082
2088
            osutils.rename(abs_path, self.abspath(backup_name))
2083
 
            return "removed %s (but kept a copy: %s)" % (file_to_backup, backup_name)
 
2089
            return "removed %s (but kept a copy: %s)" % (file_to_backup,
 
2090
                                                         backup_name)
2084
2091
 
2085
2092
        # Build inv_delta and delete files where applicable,
2086
2093
        # do this before any modifications to inventory.
2261
2268
    _marker = object()
2262
2269
 
2263
2270
    def update(self, change_reporter=None, possible_transports=None,
2264
 
               revision=None, old_tip=_marker):
 
2271
               revision=None, old_tip=_marker, show_base=False):
2265
2272
        """Update a working tree along its branch.
2266
2273
 
2267
2274
        This will update the branch if its bound too, which means we have
2304
2311
            else:
2305
2312
                if old_tip is self._marker:
2306
2313
                    old_tip = None
2307
 
            return self._update_tree(old_tip, change_reporter, revision)
 
2314
            return self._update_tree(old_tip, change_reporter, revision, show_base)
2308
2315
        finally:
2309
2316
            self.unlock()
2310
2317
 
2311
2318
    @needs_tree_write_lock
2312
 
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
 
2319
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None,
 
2320
                     show_base=False):
2313
2321
        """Update a tree to the master branch.
2314
2322
 
2315
2323
        :param old_tip: if supplied, the previous tip revision the branch,
2342
2350
            other_tree = self.branch.repository.revision_tree(old_tip)
2343
2351
            nb_conflicts = merge.merge_inner(self.branch, other_tree,
2344
2352
                                             base_tree, this_tree=self,
2345
 
                                             change_reporter=change_reporter)
 
2353
                                             change_reporter=change_reporter,
 
2354
                                             show_base=show_base)
2346
2355
            if nb_conflicts:
2347
2356
                self.add_parent_tree((old_tip, other_tree))
2348
2357
                trace.note('Rerun update after fixing the conflicts.')
2372
2381
 
2373
2382
            nb_conflicts = merge.merge_inner(self.branch, to_tree, base_tree,
2374
2383
                                             this_tree=self,
2375
 
                                             change_reporter=change_reporter)
 
2384
                                             change_reporter=change_reporter,
 
2385
                                             show_base=show_base)
2376
2386
            self.set_last_revision(revision)
2377
2387
            # TODO - dedup parents list with things merged by pull ?
2378
2388
            # reuse the tree we've updated to to set the basis:
2419
2429
    def add_conflicts(self, arg):
2420
2430
        raise errors.UnsupportedOperation(self.add_conflicts, self)
2421
2431
 
2422
 
    @needs_read_lock
2423
2432
    def conflicts(self):
2424
 
        conflicts = _mod_conflicts.ConflictList()
2425
 
        for conflicted in self._iter_conflicts():
2426
 
            text = True
2427
 
            try:
2428
 
                if file_kind(self.abspath(conflicted)) != "file":
2429
 
                    text = False
2430
 
            except errors.NoSuchFile:
2431
 
                text = False
2432
 
            if text is True:
2433
 
                for suffix in ('.THIS', '.OTHER'):
2434
 
                    try:
2435
 
                        kind = file_kind(self.abspath(conflicted+suffix))
2436
 
                        if kind != "file":
2437
 
                            text = False
2438
 
                    except errors.NoSuchFile:
2439
 
                        text = False
2440
 
                    if text == False:
2441
 
                        break
2442
 
            ctype = {True: 'text conflict', False: 'contents conflict'}[text]
2443
 
            conflicts.append(_mod_conflicts.Conflict.factory(ctype,
2444
 
                             path=conflicted,
2445
 
                             file_id=self.path2id(conflicted)))
2446
 
        return conflicts
 
2433
        raise NotImplementedError(self.conflicts)
2447
2434
 
2448
2435
    def walkdirs(self, prefix=""):
2449
2436
        """Walk the directories of this tree.
2667
2654
        """
2668
2655
        return
2669
2656
 
 
2657
    @needs_read_lock
 
2658
    def check_state(self):
 
2659
        """Check that the working state is/isn't valid."""
 
2660
        check_refs = self._get_check_refs()
 
2661
        refs = {}
 
2662
        for ref in check_refs:
 
2663
            kind, value = ref
 
2664
            if kind == 'trees':
 
2665
                refs[ref] = self.branch.repository.revision_tree(value)
 
2666
        self._check(refs)
 
2667
 
 
2668
    @needs_tree_write_lock
 
2669
    def reset_state(self, revision_ids=None):
 
2670
        """Reset the state of the working tree.
 
2671
 
 
2672
        This does a hard-reset to a last-known-good state. This is a way to
 
2673
        fix if something got corrupted (like the .bzr/checkout/dirstate file)
 
2674
        """
 
2675
        if revision_ids is None:
 
2676
            revision_ids = self.get_parent_ids()
 
2677
        if not revision_ids:
 
2678
            rt = self.branch.repository.revision_tree(
 
2679
                _mod_revision.NULL_REVISION)
 
2680
        else:
 
2681
            rt = self.branch.repository.revision_tree(revision_ids[0])
 
2682
        self._write_inventory(rt.inventory)
 
2683
        self.set_parent_ids(revision_ids)
 
2684
 
2670
2685
    def _get_rules_searcher(self, default_searcher):
2671
2686
        """See Tree._get_rules_searcher."""
2672
2687
        if self._rules_searcher is None:
2680
2695
        return ShelfManager(self, self._transport)
2681
2696
 
2682
2697
 
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
2698
class WorkingTree3(WorkingTree):
2742
2699
    """This is the Format 3 working tree.
2743
2700
 
2816
2773
            self.branch.unlock()
2817
2774
 
2818
2775
 
2819
 
def get_conflicted_stem(path):
2820
 
    for suffix in _mod_conflicts.CONFLICT_SUFFIXES:
2821
 
        if path.endswith(suffix):
2822
 
            return path[:-len(suffix)]
2823
 
 
2824
 
 
2825
 
class WorkingTreeFormat(object):
 
2776
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
 
2777
    """Registry for working tree formats."""
 
2778
 
 
2779
    def __init__(self, other_registry=None):
 
2780
        super(WorkingTreeFormatRegistry, self).__init__(other_registry)
 
2781
        self._default_format = None
 
2782
 
 
2783
    def get_default(self):
 
2784
        """Return the current default format."""
 
2785
        return self._default_format
 
2786
 
 
2787
    def set_default(self, format):
 
2788
        self._default_format = format
 
2789
 
 
2790
 
 
2791
format_registry = WorkingTreeFormatRegistry()
 
2792
 
 
2793
 
 
2794
class WorkingTreeFormat(controldir.ControlComponentFormat):
2826
2795
    """An encapsulation of the initialization and open routines for a format.
2827
2796
 
2828
2797
    Formats provide three things:
2840
2809
    object will be created every time regardless.
2841
2810
    """
2842
2811
 
2843
 
    _default_format = None
2844
 
    """The default format used for new trees."""
2845
 
 
2846
 
    _formats = {}
2847
 
    """The known formats."""
2848
 
 
2849
2812
    requires_rich_root = False
2850
2813
 
2851
2814
    upgrade_recommended = False
2852
2815
 
 
2816
    requires_normalized_unicode_filenames = False
 
2817
 
 
2818
    case_sensitive_filename = "FoRMaT"
 
2819
 
 
2820
    missing_parent_conflicts = False
 
2821
    """If this format supports missing parent conflicts."""
 
2822
 
2853
2823
    @classmethod
2854
2824
    def find_format(klass, a_bzrdir):
2855
2825
        """Return the format for the working tree object in a_bzrdir."""
2856
2826
        try:
2857
2827
            transport = a_bzrdir.get_workingtree_transport(None)
2858
2828
            format_string = transport.get_bytes("format")
2859
 
            return klass._formats[format_string]
 
2829
            return format_registry.get(format_string)
2860
2830
        except errors.NoSuchFile:
2861
2831
            raise errors.NoWorkingTree(base=transport.base)
2862
2832
        except KeyError:
2863
2833
            raise errors.UnknownFormatError(format=format_string,
2864
2834
                                            kind="working tree")
2865
2835
 
 
2836
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
2837
                   accelerator_tree=None, hardlink=False):
 
2838
        """Initialize a new working tree in a_bzrdir.
 
2839
 
 
2840
        :param a_bzrdir: BzrDir to initialize the working tree in.
 
2841
        :param revision_id: allows creating a working tree at a different
 
2842
            revision than the branch is at.
 
2843
        :param from_branch: Branch to checkout
 
2844
        :param accelerator_tree: A tree which can be used for retrieving file
 
2845
            contents more quickly than the revision tree, i.e. a workingtree.
 
2846
            The revision tree will be used for cases where accelerator_tree's
 
2847
            content is different.
 
2848
        :param hardlink: If true, hard-link files from accelerator_tree,
 
2849
            where possible.
 
2850
        """
 
2851
        raise NotImplementedError(self.initialize)
 
2852
 
2866
2853
    def __eq__(self, other):
2867
2854
        return self.__class__ is other.__class__
2868
2855
 
2870
2857
        return not (self == other)
2871
2858
 
2872
2859
    @classmethod
 
2860
    @symbol_versioning.deprecated_method(
 
2861
        symbol_versioning.deprecated_in((2, 4, 0)))
2873
2862
    def get_default_format(klass):
2874
2863
        """Return the current default format."""
2875
 
        return klass._default_format
 
2864
        return format_registry.get_default()
2876
2865
 
2877
2866
    def get_format_string(self):
2878
2867
        """Return the ASCII format string that identifies this format."""
2900
2889
        return False
2901
2890
 
2902
2891
    @classmethod
 
2892
    @symbol_versioning.deprecated_method(
 
2893
        symbol_versioning.deprecated_in((2, 4, 0)))
2903
2894
    def register_format(klass, format):
2904
 
        klass._formats[format.get_format_string()] = format
2905
 
 
2906
 
    @classmethod
 
2895
        format_registry.register(format)
 
2896
 
 
2897
    @classmethod
 
2898
    @symbol_versioning.deprecated_method(
 
2899
        symbol_versioning.deprecated_in((2, 4, 0)))
 
2900
    def register_extra_format(klass, format):
 
2901
        format_registry.register_extra(format)
 
2902
 
 
2903
    @classmethod
 
2904
    @symbol_versioning.deprecated_method(
 
2905
        symbol_versioning.deprecated_in((2, 4, 0)))
 
2906
    def unregister_extra_format(klass, format):
 
2907
        format_registry.unregister_extra(format)
 
2908
 
 
2909
    @classmethod
 
2910
    @symbol_versioning.deprecated_method(
 
2911
        symbol_versioning.deprecated_in((2, 4, 0)))
 
2912
    def get_formats(klass):
 
2913
        return format_registry._get_all()
 
2914
 
 
2915
    @classmethod
 
2916
    @symbol_versioning.deprecated_method(
 
2917
        symbol_versioning.deprecated_in((2, 4, 0)))
2907
2918
    def set_default_format(klass, format):
2908
 
        klass._default_format = format
 
2919
        format_registry.set_default(format)
2909
2920
 
2910
2921
    @classmethod
 
2922
    @symbol_versioning.deprecated_method(
 
2923
        symbol_versioning.deprecated_in((2, 4, 0)))
2911
2924
    def unregister_format(klass, format):
2912
 
        del klass._formats[format.get_format_string()]
2913
 
 
2914
 
 
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
 
2925
        format_registry.remove(format)
 
2926
 
2996
2927
 
2997
2928
class WorkingTreeFormat3(WorkingTreeFormat):
2998
2929
    """The second working tree format updated to record a format marker.
3008
2939
 
3009
2940
    upgrade_recommended = True
3010
2941
 
 
2942
    missing_parent_conflicts = True
 
2943
 
3011
2944
    def get_format_string(self):
3012
2945
        """See WorkingTreeFormat.get_format_string()."""
3013
2946
        return "Bazaar-NG Working Tree format 3"
3126
3059
 
3127
3060
 
3128
3061
__default_format = WorkingTreeFormat6()
3129
 
WorkingTreeFormat.register_format(__default_format)
3130
 
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3131
 
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3132
 
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3133
 
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
 
                   ]
 
3062
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
 
3063
    "bzrlib.workingtree_4", "WorkingTreeFormat4")
 
3064
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
 
3065
    "bzrlib.workingtree_4", "WorkingTreeFormat5")
 
3066
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
 
3067
    "bzrlib.workingtree_4", "WorkingTreeFormat6")
 
3068
format_registry.register(WorkingTreeFormat3())
 
3069
format_registry.set_default(__default_format)