/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""WorkingTree object and friends.
18
18
 
19
19
A WorkingTree represents the editable working copy of a branch.
20
 
Operations which represent the WorkingTree are also done here, 
21
 
such as renaming or adding files.  The WorkingTree has an inventory 
22
 
which is updated by these operations.  A commit produces a 
 
20
Operations which represent the WorkingTree are also done here,
 
21
such as renaming or adding files.  The WorkingTree has an inventory
 
22
which is updated by these operations.  A commit produces a
23
23
new revision based on the workingtree and its inventory.
24
24
 
25
25
At the moment every WorkingTree has its own branch.  Remote
64
64
    hashcache,
65
65
    ignores,
66
66
    merge,
67
 
    osutils,
68
67
    revision as _mod_revision,
69
68
    revisiontree,
70
69
    repository,
73
72
    transform,
74
73
    ui,
75
74
    urlutils,
 
75
    views,
76
76
    xml5,
77
77
    xml6,
78
78
    xml7,
80
80
import bzrlib.branch
81
81
from bzrlib.transport import get_transport
82
82
import bzrlib.ui
83
 
from bzrlib.workingtree_4 import WorkingTreeFormat4
 
83
from bzrlib.workingtree_4 import (
 
84
    WorkingTreeFormat4,
 
85
    WorkingTreeFormat5,
 
86
    WorkingTreeFormat6,
 
87
    )
84
88
""")
85
89
 
86
90
from bzrlib import symbol_versioning
87
91
from bzrlib.decorators import needs_read_lock, needs_write_lock
88
92
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
89
 
from bzrlib.lockable_files import LockableFiles, TransportLock
 
93
from bzrlib.lockable_files import LockableFiles
90
94
from bzrlib.lockdir import LockDir
91
95
import bzrlib.mutabletree
92
96
from bzrlib.mutabletree import needs_tree_write_lock
 
97
from bzrlib import osutils
93
98
from bzrlib.osutils import (
94
99
    compact_date,
95
100
    file_kind,
102
107
    splitpath,
103
108
    supports_executable,
104
109
    )
 
110
from bzrlib.filters import filtered_input_file
105
111
from bzrlib.trace import mutter, note
106
112
from bzrlib.transport.local import LocalTransport
107
113
from bzrlib.progress import DummyProgress, ProgressPhase
111
117
        deprecated_method,
112
118
        deprecated_function,
113
119
        DEPRECATED_PARAMETER,
114
 
        zero_eight,
115
 
        zero_eleven,
116
 
        zero_thirteen,
117
120
        )
118
121
 
119
122
 
123
126
ERROR_PATH_NOT_FOUND = 3    # WindowsError errno code, equivalent to ENOENT
124
127
 
125
128
 
126
 
@deprecated_function(zero_thirteen)
127
 
def gen_file_id(name):
128
 
    """Return new file id for the basename 'name'.
129
 
 
130
 
    Use bzrlib.generate_ids.gen_file_id() instead
131
 
    """
132
 
    return generate_ids.gen_file_id(name)
133
 
 
134
 
 
135
 
@deprecated_function(zero_thirteen)
136
 
def gen_root_id():
137
 
    """Return a new tree-root file id.
138
 
 
139
 
    This has been deprecated in favor of bzrlib.generate_ids.gen_root_id()
140
 
    """
141
 
    return generate_ids.gen_root_id()
142
 
 
143
 
 
144
129
class TreeEntry(object):
145
130
    """An entry that implements the minimum interface used by commands.
146
131
 
147
 
    This needs further inspection, it may be better to have 
 
132
    This needs further inspection, it may be better to have
148
133
    InventoryEntries without ids - though that seems wrong. For now,
149
134
    this is a parallel hierarchy to InventoryEntry, and needs to become
150
135
    one of several things: decorates to that hierarchy, children of, or
153
138
    no InventoryEntry available - i.e. for unversioned objects.
154
139
    Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
155
140
    """
156
 
 
 
141
 
157
142
    def __eq__(self, other):
158
143
        # yes, this us ugly, TODO: best practice __eq__ style.
159
144
        return (isinstance(other, TreeEntry)
160
145
                and other.__class__ == self.__class__)
161
 
 
 
146
 
162
147
    def kind_character(self):
163
148
        return "???"
164
149
 
206
191
    not listed in the Inventory and vice versa.
207
192
    """
208
193
 
 
194
    # override this to set the strategy for storing views
 
195
    def _make_views(self):
 
196
        return views.DisabledViews(self)
 
197
 
209
198
    def __init__(self, basedir='.',
210
199
                 branch=DEPRECATED_PARAMETER,
211
200
                 _inventory=None,
222
211
        if not _internal:
223
212
            raise errors.BzrError("Please use bzrdir.open_workingtree or "
224
213
                "WorkingTree.open() to obtain a WorkingTree.")
225
 
        assert isinstance(basedir, basestring), \
226
 
            "base directory %r is not a string" % basedir
227
214
        basedir = safe_unicode(basedir)
228
215
        mutter("opening working tree %r", basedir)
229
216
        if deprecated_passed(branch):
237
224
            self._control_files = self.branch.control_files
238
225
        else:
239
226
            # assume all other formats have their own control files.
240
 
            assert isinstance(_control_files, LockableFiles), \
241
 
                    "_control_files must be a LockableFiles, not %r" \
242
 
                    % _control_files
243
227
            self._control_files = _control_files
 
228
        self._transport = self._control_files._transport
244
229
        # update the whole cache up front and write to disk if anything changed;
245
230
        # in the future we might want to do this more selectively
246
231
        # two possible ways offer themselves : in self._unlock, write the cache
250
235
        wt_trans = self.bzrdir.get_workingtree_transport(None)
251
236
        cache_filename = wt_trans.local_abspath('stat-cache')
252
237
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
253
 
                                              self._control_files._file_mode)
 
238
            self.bzrdir._get_file_mode(),
 
239
            self._content_filter_stack_provider())
254
240
        hc = self._hashcache
255
241
        hc.read()
256
242
        # is this scan needed ? it makes things kinda slow.
270
256
            # the Format factory and creation methods that are
271
257
            # permitted to do this.
272
258
            self._set_inventory(_inventory, dirty=False)
 
259
        self._detect_case_handling()
 
260
        self._rules_searcher = None
 
261
        self.views = self._make_views()
 
262
 
 
263
    def _detect_case_handling(self):
 
264
        wt_trans = self.bzrdir.get_workingtree_transport(None)
 
265
        try:
 
266
            wt_trans.stat("FoRMaT")
 
267
        except errors.NoSuchFile:
 
268
            self.case_sensitive = True
 
269
        else:
 
270
            self.case_sensitive = False
 
271
 
 
272
        self._setup_directory_is_tree_reference()
273
273
 
274
274
    branch = property(
275
275
        fget=lambda self: self._branch,
296
296
    def supports_tree_reference(self):
297
297
        return False
298
298
 
 
299
    def supports_content_filtering(self):
 
300
        return self._format.supports_content_filtering()
 
301
 
 
302
    def supports_views(self):
 
303
        return self.views.supports_views()
 
304
 
299
305
    def _set_inventory(self, inv, dirty):
300
306
        """Set the internal cached inventory.
301
307
 
306
312
            False then the inventory is the same as that on disk and any
307
313
            serialisation would be unneeded overhead.
308
314
        """
309
 
        assert inv.root is not None
310
315
        self._inventory = inv
311
316
        self._inventory_is_modified = dirty
312
317
 
316
321
 
317
322
        """
318
323
        if path is None:
319
 
            path = os.path.getcwdu()
 
324
            path = osutils.getcwd()
320
325
        control = bzrdir.BzrDir.open(path, _unsupported)
321
326
        return control.open_workingtree(_unsupported)
322
 
        
 
327
 
323
328
    @staticmethod
324
329
    def open_containing(path=None):
325
330
        """Open an existing working tree which has its root about path.
326
 
        
 
331
 
327
332
        This probes for a working tree at path and searches upwards from there.
328
333
 
329
334
        Basically we keep looking up until we find the control directory or
347
352
        """
348
353
        return WorkingTree.open(path, _unsupported=True)
349
354
 
 
355
    @staticmethod
 
356
    def find_trees(location):
 
357
        def list_current(transport):
 
358
            return [d for d in transport.list_dir('') if d != '.bzr']
 
359
        def evaluate(bzrdir):
 
360
            try:
 
361
                tree = bzrdir.open_workingtree()
 
362
            except errors.NoWorkingTree:
 
363
                return True, None
 
364
            else:
 
365
                return True, tree
 
366
        transport = get_transport(location)
 
367
        iterator = bzrdir.BzrDir.find_bzrdirs(transport, evaluate=evaluate,
 
368
                                              list_current=list_current)
 
369
        return [t for t in iterator if t is not None]
 
370
 
350
371
    # should be deprecated - this is slow and in any case treating them as a
351
372
    # container is (we now know) bad style -- mbp 20070302
352
373
    ## @deprecated_method(zero_fifteen)
361
382
            if osutils.lexists(self.abspath(path)):
362
383
                yield ie.file_id
363
384
 
 
385
    def all_file_ids(self):
 
386
        """See Tree.iter_all_file_ids"""
 
387
        return set(self.inventory)
 
388
 
364
389
    def __repr__(self):
365
390
        return "<%s of %s>" % (self.__class__.__name__,
366
391
                               getattr(self, 'basedir', None))
370
395
 
371
396
    def basis_tree(self):
372
397
        """Return RevisionTree for the current last revision.
373
 
        
 
398
 
374
399
        If the left most parent is a ghost then the returned tree will be an
375
 
        empty tree - one obtained by calling repository.revision_tree(None).
 
400
        empty tree - one obtained by calling
 
401
        repository.revision_tree(NULL_REVISION).
376
402
        """
377
403
        try:
378
404
            revision_id = self.get_parent_ids()[0]
380
406
            # no parents, return an empty revision tree.
381
407
            # in the future this should return the tree for
382
408
            # 'empty:' - the implicit root empty tree.
383
 
            return self.branch.repository.revision_tree(None)
 
409
            return self.branch.repository.revision_tree(
 
410
                       _mod_revision.NULL_REVISION)
384
411
        try:
385
412
            return self.revision_tree(revision_id)
386
413
        except errors.NoSuchRevision:
390
417
        # at this point ?
391
418
        try:
392
419
            return self.branch.repository.revision_tree(revision_id)
393
 
        except errors.RevisionNotPresent:
 
420
        except (errors.RevisionNotPresent, errors.NoSuchRevision):
394
421
            # the basis tree *may* be a ghost or a low level error may have
395
 
            # occured. If the revision is present, its a problem, if its not
 
422
            # occurred. If the revision is present, its a problem, if its not
396
423
            # its a ghost.
397
424
            if self.branch.repository.has_revision(revision_id):
398
425
                raise
399
426
            # the basis tree is a ghost so return an empty tree.
400
 
            return self.branch.repository.revision_tree(None)
 
427
            return self.branch.repository.revision_tree(
 
428
                       _mod_revision.NULL_REVISION)
401
429
 
402
430
    def _cleanup(self):
403
431
        self._flush_ignore_list_cache()
404
432
 
405
 
    @staticmethod
406
 
    @deprecated_method(zero_eight)
407
 
    def create(branch, directory):
408
 
        """Create a workingtree for branch at directory.
409
 
 
410
 
        If existing_directory already exists it must have a .bzr directory.
411
 
        If it does not exist, it will be created.
412
 
 
413
 
        This returns a new WorkingTree object for the new checkout.
414
 
 
415
 
        TODO FIXME RBC 20060124 when we have checkout formats in place this
416
 
        should accept an optional revisionid to checkout [and reject this if
417
 
        checking out into the same dir as a pre-checkout-aware branch format.]
418
 
 
419
 
        XXX: When BzrDir is present, these should be created through that 
420
 
        interface instead.
421
 
        """
422
 
        warnings.warn('delete WorkingTree.create', stacklevel=3)
423
 
        transport = get_transport(directory)
424
 
        if branch.bzrdir.root_transport.base == transport.base:
425
 
            # same dir 
426
 
            return branch.bzrdir.create_workingtree()
427
 
        # different directory, 
428
 
        # create a branch reference
429
 
        # and now a working tree.
430
 
        raise NotImplementedError
431
 
 
432
 
    @staticmethod
433
 
    @deprecated_method(zero_eight)
434
 
    def create_standalone(directory):
435
 
        """Create a checkout and a branch and a repo at directory.
436
 
 
437
 
        Directory must exist and be empty.
438
 
 
439
 
        please use BzrDir.create_standalone_workingtree
440
 
        """
441
 
        return bzrdir.BzrDir.create_standalone_workingtree(directory)
442
 
 
443
433
    def relpath(self, path):
444
434
        """Return the local path portion from a given path.
445
 
        
446
 
        The path may be absolute or relative. If its a relative path it is 
 
435
 
 
436
        The path may be absolute or relative. If its a relative path it is
447
437
        interpreted relative to the python current working directory.
448
438
        """
449
439
        return osutils.relpath(self.basedir, path)
451
441
    def has_filename(self, filename):
452
442
        return osutils.lexists(self.abspath(filename))
453
443
 
454
 
    def get_file(self, file_id):
455
 
        file_id = osutils.safe_file_id(file_id)
456
 
        return self.get_file_byname(self.id2path(file_id))
457
 
 
458
 
    def get_file_text(self, file_id):
459
 
        file_id = osutils.safe_file_id(file_id)
460
 
        return self.get_file(file_id).read()
461
 
 
462
 
    def get_file_byname(self, filename):
463
 
        return file(self.abspath(filename), 'rb')
 
444
    def get_file(self, file_id, path=None, filtered=True):
 
445
        return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
 
446
 
 
447
    def get_file_with_stat(self, file_id, path=None, filtered=True,
 
448
        _fstat=os.fstat):
 
449
        """See MutableTree.get_file_with_stat."""
 
450
        if path is None:
 
451
            path = self.id2path(file_id)
 
452
        file_obj = self.get_file_byname(path, filtered=False)
 
453
        stat_value = _fstat(file_obj.fileno())
 
454
        if self.supports_content_filtering() and filtered:
 
455
            filters = self._content_filter_stack(path)
 
456
            file_obj = filtered_input_file(file_obj, filters)
 
457
        return (file_obj, stat_value)
 
458
 
 
459
    def get_file_text(self, file_id, path=None, filtered=True):
 
460
        return self.get_file(file_id, path=path, filtered=filtered).read()
 
461
 
 
462
    def get_file_byname(self, filename, filtered=True):
 
463
        path = self.abspath(filename)
 
464
        f = file(path, 'rb')
 
465
        if self.supports_content_filtering() and filtered:
 
466
            filters = self._content_filter_stack(filename)
 
467
            return filtered_input_file(f, filters)
 
468
        else:
 
469
            return f
 
470
 
 
471
    def get_file_lines(self, file_id, path=None, filtered=True):
 
472
        """See Tree.get_file_lines()"""
 
473
        file = self.get_file(file_id, path, filtered=filtered)
 
474
        try:
 
475
            return file.readlines()
 
476
        finally:
 
477
            file.close()
464
478
 
465
479
    @needs_read_lock
466
480
    def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
473
487
        incorrectly attributed to CURRENT_REVISION (but after committing, the
474
488
        attribution will be correct).
475
489
        """
476
 
        file_id = osutils.safe_file_id(file_id)
477
490
        basis = self.basis_tree()
478
491
        basis.lock_read()
479
492
        try:
480
 
            changes = self._iter_changes(basis, True, [self.id2path(file_id)],
 
493
            changes = self.iter_changes(basis, True, [self.id2path(file_id)],
481
494
                require_versioned=True).next()
482
495
            changed_content, kind = changes[2], changes[6]
483
496
            if not changed_content:
509
522
 
510
523
    def get_parent_ids(self):
511
524
        """See Tree.get_parent_ids.
512
 
        
 
525
 
513
526
        This implementation reads the pending merges list and last_revision
514
527
        value and uses that to decide what the parents list should be.
515
528
        """
519
532
        else:
520
533
            parents = [last_rev]
521
534
        try:
522
 
            merges_file = self._control_files.get('pending-merges')
 
535
            merges_file = self._transport.get('pending-merges')
523
536
        except errors.NoSuchFile:
524
537
            pass
525
538
        else:
526
539
            for l in merges_file.readlines():
527
 
                revision_id = osutils.safe_revision_id(l.rstrip('\n'))
 
540
                revision_id = l.rstrip('\n')
528
541
                parents.append(revision_id)
529
542
        return parents
530
543
 
532
545
    def get_root_id(self):
533
546
        """Return the id of this trees root"""
534
547
        return self._inventory.root.file_id
535
 
        
 
548
 
536
549
    def _get_store_filename(self, file_id):
537
550
        ## XXX: badly named; this is not in the store at all
538
 
        file_id = osutils.safe_file_id(file_id)
539
551
        return self.abspath(self.id2path(file_id))
540
552
 
541
553
    @needs_read_lock
542
554
    def clone(self, to_bzrdir, revision_id=None):
543
555
        """Duplicate this working tree into to_bzr, including all state.
544
 
        
 
556
 
545
557
        Specifically modified files are kept as modified, but
546
558
        ignored and unknown files are discarded.
547
559
 
548
560
        If you want to make a new line of development, see bzrdir.sprout()
549
561
 
550
562
        revision
551
 
            If not None, the cloned tree will have its last revision set to 
552
 
            revision, and and difference between the source trees last revision
 
563
            If not None, the cloned tree will have its last revision set to
 
564
            revision, and difference between the source trees last revision
553
565
            and this one merged in.
554
566
        """
555
567
        # assumes the target bzr dir format is compatible.
556
 
        result = self._format.initialize(to_bzrdir)
 
568
        result = to_bzrdir.create_workingtree()
557
569
        self.copy_content_into(result, revision_id)
558
570
        return result
559
571
 
570
582
            tree.set_parent_ids([revision_id])
571
583
 
572
584
    def id2abspath(self, file_id):
573
 
        file_id = osutils.safe_file_id(file_id)
574
585
        return self.abspath(self.id2path(file_id))
575
586
 
576
587
    def has_id(self, file_id):
577
588
        # files that have been deleted are excluded
578
 
        file_id = osutils.safe_file_id(file_id)
579
589
        inv = self.inventory
580
590
        if not inv.has_id(file_id):
581
591
            return False
583
593
        return osutils.lexists(self.abspath(path))
584
594
 
585
595
    def has_or_had_id(self, file_id):
586
 
        file_id = osutils.safe_file_id(file_id)
587
596
        if file_id == self.inventory.root.file_id:
588
597
            return True
589
598
        return self.inventory.has_id(file_id)
591
600
    __contains__ = has_id
592
601
 
593
602
    def get_file_size(self, file_id):
594
 
        file_id = osutils.safe_file_id(file_id)
595
 
        return os.path.getsize(self.id2abspath(file_id))
 
603
        """See Tree.get_file_size"""
 
604
        try:
 
605
            return os.path.getsize(self.id2abspath(file_id))
 
606
        except OSError, e:
 
607
            if e.errno != errno.ENOENT:
 
608
                raise
 
609
            else:
 
610
                return None
596
611
 
597
612
    @needs_read_lock
598
613
    def get_file_sha1(self, file_id, path=None, stat_value=None):
599
 
        file_id = osutils.safe_file_id(file_id)
600
614
        if not path:
601
615
            path = self._inventory.id2path(file_id)
602
616
        return self._hashcache.get_sha1(path, stat_value)
603
617
 
604
618
    def get_file_mtime(self, file_id, path=None):
605
 
        file_id = osutils.safe_file_id(file_id)
606
619
        if not path:
607
620
            path = self.inventory.id2path(file_id)
608
621
        return os.lstat(self.abspath(path)).st_mtime
609
622
 
 
623
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
 
624
        file_id = self.path2id(path)
 
625
        return self._inventory[file_id].executable
 
626
 
 
627
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
 
628
        mode = stat_result.st_mode
 
629
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
 
630
 
610
631
    if not supports_executable():
611
632
        def is_executable(self, file_id, path=None):
612
 
            file_id = osutils.safe_file_id(file_id)
613
633
            return self._inventory[file_id].executable
 
634
 
 
635
        _is_executable_from_path_and_stat = \
 
636
            _is_executable_from_path_and_stat_from_basis
614
637
    else:
615
638
        def is_executable(self, file_id, path=None):
616
639
            if not path:
617
 
                file_id = osutils.safe_file_id(file_id)
618
640
                path = self.id2path(file_id)
619
641
            mode = os.lstat(self.abspath(path)).st_mode
620
642
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
621
643
 
 
644
        _is_executable_from_path_and_stat = \
 
645
            _is_executable_from_path_and_stat_from_stat
 
646
 
622
647
    @needs_tree_write_lock
623
648
    def _add(self, files, ids, kinds):
624
649
        """See MutableTree._add."""
625
650
        # TODO: Re-adding a file that is removed in the working copy
626
651
        # should probably put it back with the previous ID.
627
 
        # the read and write working inventory should not occur in this 
 
652
        # the read and write working inventory should not occur in this
628
653
        # function - they should be part of lock_write and unlock.
629
654
        inv = self.inventory
630
655
        for f, file_id, kind in zip(files, ids, kinds):
631
 
            assert kind is not None
632
656
            if file_id is None:
633
657
                inv.add_path(f, kind=kind)
634
658
            else:
635
 
                file_id = osutils.safe_file_id(file_id)
636
659
                inv.add_path(f, kind=kind, file_id=file_id)
637
660
            self._inventory_is_modified = True
638
661
 
700
723
        if updated:
701
724
            self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
702
725
 
703
 
    @deprecated_method(zero_eleven)
704
 
    @needs_read_lock
705
 
    def pending_merges(self):
706
 
        """Return a list of pending merges.
707
 
 
708
 
        These are revisions that have been merged into the working
709
 
        directory but not yet committed.
710
 
 
711
 
        As of 0.11 this is deprecated. Please see WorkingTree.get_parent_ids()
712
 
        instead - which is available on all tree objects.
713
 
        """
714
 
        return self.get_parent_ids()[1:]
 
726
    def path_content_summary(self, path, _lstat=os.lstat,
 
727
        _mapper=osutils.file_kind_from_stat_mode):
 
728
        """See Tree.path_content_summary."""
 
729
        abspath = self.abspath(path)
 
730
        try:
 
731
            stat_result = _lstat(abspath)
 
732
        except OSError, e:
 
733
            if getattr(e, 'errno', None) == errno.ENOENT:
 
734
                # no file.
 
735
                return ('missing', None, None, None)
 
736
            # propagate other errors
 
737
            raise
 
738
        kind = _mapper(stat_result.st_mode)
 
739
        if kind == 'file':
 
740
            size = stat_result.st_size
 
741
            # try for a stat cache lookup
 
742
            executable = self._is_executable_from_path_and_stat(path, stat_result)
 
743
            return (kind, size, executable, self._sha_from_stat(
 
744
                path, stat_result))
 
745
        elif kind == 'directory':
 
746
            # perhaps it looks like a plain directory, but it's really a
 
747
            # reference.
 
748
            if self._directory_is_tree_reference(path):
 
749
                kind = 'tree-reference'
 
750
            return kind, None, None, None
 
751
        elif kind == 'symlink':
 
752
            target = osutils.readlink(abspath)
 
753
            return ('symlink', None, None, target)
 
754
        else:
 
755
            return (kind, None, None, None)
715
756
 
716
757
    def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
717
758
        """Common ghost checking functionality from set_parent_*.
727
768
 
728
769
    def _set_merges_from_parent_ids(self, parent_ids):
729
770
        merges = parent_ids[1:]
730
 
        self._control_files.put_bytes('pending-merges', '\n'.join(merges))
 
771
        self._transport.put_bytes('pending-merges', '\n'.join(merges),
 
772
            mode=self.bzrdir._get_file_mode())
 
773
 
 
774
    def _filter_parent_ids_by_ancestry(self, revision_ids):
 
775
        """Check that all merged revisions are proper 'heads'.
 
776
 
 
777
        This will always return the first revision_id, and any merged revisions
 
778
        which are
 
779
        """
 
780
        if len(revision_ids) == 0:
 
781
            return revision_ids
 
782
        graph = self.branch.repository.get_graph()
 
783
        heads = graph.heads(revision_ids)
 
784
        new_revision_ids = revision_ids[:1]
 
785
        for revision_id in revision_ids[1:]:
 
786
            if revision_id in heads and revision_id not in new_revision_ids:
 
787
                new_revision_ids.append(revision_id)
 
788
        if new_revision_ids != revision_ids:
 
789
            trace.mutter('requested to set revision_ids = %s,'
 
790
                         ' but filtered to %s', revision_ids, new_revision_ids)
 
791
        return new_revision_ids
731
792
 
732
793
    @needs_tree_write_lock
733
794
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
734
795
        """Set the parent ids to revision_ids.
735
 
        
 
796
 
736
797
        See also set_parent_trees. This api will try to retrieve the tree data
737
798
        for each element of revision_ids from the trees repository. If you have
738
799
        tree data already available, it is more efficient to use
742
803
        :param revision_ids: The revision_ids to set as the parent ids of this
743
804
            working tree. Any of these may be ghosts.
744
805
        """
745
 
        revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
746
806
        self._check_parents_for_ghosts(revision_ids,
747
807
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
748
808
        for revision_id in revision_ids:
749
809
            _mod_revision.check_not_reserved_id(revision_id)
750
810
 
 
811
        revision_ids = self._filter_parent_ids_by_ancestry(revision_ids)
 
812
 
751
813
        if len(revision_ids) > 0:
752
814
            self.set_last_revision(revision_ids[0])
753
815
        else:
758
820
    @needs_tree_write_lock
759
821
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
760
822
        """See MutableTree.set_parent_trees."""
761
 
        parent_ids = [osutils.safe_revision_id(rev) for (rev, tree) in parents_list]
 
823
        parent_ids = [rev for (rev, tree) in parents_list]
762
824
        for revision_id in parent_ids:
763
825
            _mod_revision.check_not_reserved_id(revision_id)
764
826
 
765
827
        self._check_parents_for_ghosts(parent_ids,
766
828
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
767
829
 
 
830
        parent_ids = self._filter_parent_ids_by_ancestry(parent_ids)
 
831
 
768
832
        if len(parent_ids) == 0:
769
833
            leftmost_parent_id = _mod_revision.NULL_REVISION
770
834
            leftmost_parent_tree = None
797
861
                yield Stanza(file_id=file_id.decode('utf8'), hash=hash)
798
862
        self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
799
863
 
 
864
    def _sha_from_stat(self, path, stat_result):
 
865
        """Get a sha digest from the tree's stat cache.
 
866
 
 
867
        The default implementation assumes no stat cache is present.
 
868
 
 
869
        :param path: The path.
 
870
        :param stat_result: The stat result being looked up.
 
871
        """
 
872
        return None
 
873
 
800
874
    def _put_rio(self, filename, stanzas, header):
801
875
        self._must_be_locked()
802
876
        my_file = rio_file(stanzas, header)
803
 
        self._control_files.put(filename, my_file)
 
877
        self._transport.put_file(filename, my_file,
 
878
            mode=self.bzrdir._get_file_mode())
804
879
 
805
880
    @needs_write_lock # because merge pulls data into the branch.
806
881
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
824
899
            merger.check_basis(check_clean=True, require_commits=False)
825
900
            if to_revision is None:
826
901
                to_revision = _mod_revision.ensure_null(branch.last_revision())
827
 
            else:
828
 
                to_revision = osutils.safe_revision_id(to_revision)
829
902
            merger.other_rev_id = to_revision
830
903
            if _mod_revision.is_null(merger.other_rev_id):
831
904
                raise errors.NoCommits(branch)
859
932
    def merge_modified(self):
860
933
        """Return a dictionary of files modified by a merge.
861
934
 
862
 
        The list is initialized by WorkingTree.set_merge_modified, which is 
 
935
        The list is initialized by WorkingTree.set_merge_modified, which is
863
936
        typically called after we make some automatic updates to the tree
864
937
        because of a merge.
865
938
 
867
940
        still in the working inventory and have that text hash.
868
941
        """
869
942
        try:
870
 
            hashfile = self._control_files.get('merge-hashes')
 
943
            hashfile = self._transport.get('merge-hashes')
871
944
        except errors.NoSuchFile:
872
945
            return {}
873
 
        merge_hashes = {}
874
946
        try:
875
 
            if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
 
947
            merge_hashes = {}
 
948
            try:
 
949
                if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
 
950
                    raise errors.MergeModifiedFormatError()
 
951
            except StopIteration:
876
952
                raise errors.MergeModifiedFormatError()
877
 
        except StopIteration:
878
 
            raise errors.MergeModifiedFormatError()
879
 
        for s in RioReader(hashfile):
880
 
            # RioReader reads in Unicode, so convert file_ids back to utf8
881
 
            file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
882
 
            if file_id not in self.inventory:
883
 
                continue
884
 
            text_hash = s.get("hash")
885
 
            if text_hash == self.get_file_sha1(file_id):
886
 
                merge_hashes[file_id] = text_hash
887
 
        return merge_hashes
 
953
            for s in RioReader(hashfile):
 
954
                # RioReader reads in Unicode, so convert file_ids back to utf8
 
955
                file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
 
956
                if file_id not in self.inventory:
 
957
                    continue
 
958
                text_hash = s.get("hash")
 
959
                if text_hash == self.get_file_sha1(file_id):
 
960
                    merge_hashes[file_id] = text_hash
 
961
            return merge_hashes
 
962
        finally:
 
963
            hashfile.close()
888
964
 
889
965
    @needs_write_lock
890
966
    def mkdir(self, path, file_id=None):
896
972
        return file_id
897
973
 
898
974
    def get_symlink_target(self, file_id):
899
 
        file_id = osutils.safe_file_id(file_id)
900
 
        return os.readlink(self.id2abspath(file_id))
 
975
        abspath = self.id2abspath(file_id)
 
976
        target = osutils.readlink(abspath)
 
977
        return target
901
978
 
902
979
    @needs_write_lock
903
980
    def subsume(self, other_tree):
941
1018
            other_tree.unlock()
942
1019
        other_tree.bzrdir.retire_bzrdir()
943
1020
 
 
1021
    def _setup_directory_is_tree_reference(self):
 
1022
        if self._branch.repository._format.supports_tree_reference:
 
1023
            self._directory_is_tree_reference = \
 
1024
                self._directory_may_be_tree_reference
 
1025
        else:
 
1026
            self._directory_is_tree_reference = \
 
1027
                self._directory_is_never_tree_reference
 
1028
 
 
1029
    def _directory_is_never_tree_reference(self, relpath):
 
1030
        return False
 
1031
 
 
1032
    def _directory_may_be_tree_reference(self, relpath):
 
1033
        # as a special case, if a directory contains control files then
 
1034
        # it's a tree reference, except that the root of the tree is not
 
1035
        return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
 
1036
        # TODO: We could ask all the control formats whether they
 
1037
        # recognize this directory, but at the moment there's no cheap api
 
1038
        # to do that.  Since we probably can only nest bzr checkouts and
 
1039
        # they always use this name it's ok for now.  -- mbp 20060306
 
1040
        #
 
1041
        # FIXME: There is an unhandled case here of a subdirectory
 
1042
        # containing .bzr but not a branch; that will probably blow up
 
1043
        # when you try to commit it.  It might happen if there is a
 
1044
        # checkout in a subdirectory.  This can be avoided by not adding
 
1045
        # it.  mbp 20070306
 
1046
 
944
1047
    @needs_tree_write_lock
945
1048
    def extract(self, file_id, format=None):
946
1049
        """Extract a subtree from this tree.
947
 
        
 
1050
 
948
1051
        A new branch will be created, relative to the path for this tree.
949
1052
        """
950
1053
        self.flush()
955
1058
                transport = transport.clone(name)
956
1059
                transport.ensure_base()
957
1060
            return transport
958
 
            
 
1061
 
959
1062
        sub_path = self.id2path(file_id)
960
1063
        branch_transport = mkdirs(sub_path)
961
1064
        if format is None:
962
 
            format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
 
1065
            format = self.bzrdir.cloning_metadir()
963
1066
        branch_transport.ensure_base()
964
1067
        branch_bzrdir = format.initialize_on_transport(branch_transport)
965
1068
        try:
966
1069
            repo = branch_bzrdir.find_repository()
967
1070
        except errors.NoRepositoryPresent:
968
1071
            repo = branch_bzrdir.create_repository()
969
 
            assert repo.supports_rich_root()
970
 
        else:
971
 
            if not repo.supports_rich_root():
972
 
                raise errors.RootNotRich()
 
1072
        if not repo.supports_rich_root():
 
1073
            raise errors.RootNotRich()
973
1074
        new_branch = branch_bzrdir.create_branch()
974
1075
        new_branch.pull(self.branch)
975
1076
        for parent_id in self.get_parent_ids():
993
1094
        return wt
994
1095
 
995
1096
    def _serialize(self, inventory, out_file):
996
 
        xml5.serializer_v5.write_inventory(self._inventory, out_file)
 
1097
        xml5.serializer_v5.write_inventory(self._inventory, out_file,
 
1098
            working=True)
997
1099
 
998
1100
    def _deserialize(selt, in_file):
999
1101
        return xml5.serializer_v5.read_inventory(in_file)
1006
1108
        sio = StringIO()
1007
1109
        self._serialize(self._inventory, sio)
1008
1110
        sio.seek(0)
1009
 
        self._control_files.put('inventory', sio)
 
1111
        self._transport.put_file('inventory', sio,
 
1112
            mode=self.bzrdir._get_file_mode())
1010
1113
        self._inventory_is_modified = False
1011
1114
 
1012
1115
    def _kind(self, relpath):
1043
1146
        # directory file_id, relative path, absolute path, reverse sorted children
1044
1147
        children = os.listdir(self.basedir)
1045
1148
        children.sort()
1046
 
        # jam 20060527 The kernel sized tree seems equivalent whether we 
 
1149
        # jam 20060527 The kernel sized tree seems equivalent whether we
1047
1150
        # use a deque and popleft to keep them sorted, or if we use a plain
1048
1151
        # list and just reverse() them.
1049
1152
        children = collections.deque(children)
1069
1172
 
1070
1173
                # absolute path
1071
1174
                fap = from_dir_abspath + '/' + f
1072
 
                
 
1175
 
1073
1176
                f_ie = inv.get_child(from_dir_id, f)
1074
1177
                if f_ie:
1075
1178
                    c = 'V'
1107
1210
                    except KeyError:
1108
1211
                        yield fp[1:], c, fk, None, TreeEntry()
1109
1212
                    continue
1110
 
                
 
1213
 
1111
1214
                if fk != 'directory':
1112
1215
                    continue
1113
1216
 
1130
1233
        to_dir must exist in the inventory.
1131
1234
 
1132
1235
        If to_dir exists and is a directory, the files are moved into
1133
 
        it, keeping their old names.  
 
1236
        it, keeping their old names.
1134
1237
 
1135
1238
        Note that to_dir is only the last component of the new name;
1136
1239
        this doesn't change the directory.
1173
1276
                                       DeprecationWarning)
1174
1277
 
1175
1278
        # check destination directory
1176
 
        assert not isinstance(from_paths, basestring)
 
1279
        if isinstance(from_paths, basestring):
 
1280
            raise ValueError()
1177
1281
        inv = self.inventory
1178
1282
        to_abs = self.abspath(to_dir)
1179
1283
        if not isdir(to_abs):
1263
1367
                only_change_inv = True
1264
1368
            elif self.has_filename(from_rel) and not self.has_filename(to_rel):
1265
1369
                only_change_inv = False
 
1370
            elif (not self.case_sensitive
 
1371
                  and from_rel.lower() == to_rel.lower()
 
1372
                  and self.has_filename(from_rel)):
 
1373
                only_change_inv = False
1266
1374
            else:
1267
1375
                # something is wrong, so lets determine what exactly
1268
1376
                if not self.has_filename(from_rel) and \
1271
1379
                        errors.PathsDoNotExist(paths=(str(from_rel),
1272
1380
                        str(to_rel))))
1273
1381
                else:
1274
 
                    raise errors.RenameFailedFilesExist(from_rel, to_rel,
1275
 
                        extra="(Use --after to update the Bazaar id)")
 
1382
                    raise errors.RenameFailedFilesExist(from_rel, to_rel)
1276
1383
            rename_entry.only_change_inv = only_change_inv
1277
1384
        return rename_entries
1278
1385
 
1409
1516
        These are files in the working directory that are not versioned or
1410
1517
        control files or ignored.
1411
1518
        """
1412
 
        # force the extras method to be fully executed before returning, to 
 
1519
        # force the extras method to be fully executed before returning, to
1413
1520
        # prevent race conditions with the lock
1414
1521
        return iter(
1415
1522
            [subp for subp in self.extras() if not self.is_ignored(subp)])
1425
1532
        :raises: NoSuchId if any fileid is not currently versioned.
1426
1533
        """
1427
1534
        for file_id in file_ids:
1428
 
            file_id = osutils.safe_file_id(file_id)
 
1535
            if file_id not in self._inventory:
 
1536
                raise errors.NoSuchId(self, file_id)
 
1537
        for file_id in file_ids:
1429
1538
            if self._inventory.has_id(file_id):
1430
1539
                self._inventory.remove_recursive_id(file_id)
1431
 
            else:
1432
 
                raise errors.NoSuchId(self, file_id)
1433
1540
        if len(file_ids):
1434
 
            # in the future this should just set a dirty bit to wait for the 
 
1541
            # in the future this should just set a dirty bit to wait for the
1435
1542
            # final unlock. However, until all methods of workingtree start
1436
 
            # with the current in -memory inventory rather than triggering 
 
1543
            # with the current in -memory inventory rather than triggering
1437
1544
            # a read, it is more complex - we need to teach read_inventory
1438
1545
            # to know when to read, and when to not read first... and possibly
1439
1546
            # to save first when the in memory one may be corrupted.
1440
1547
            # so for now, we just only write it if it is indeed dirty.
1441
1548
            # - RBC 20060907
1442
1549
            self._write_inventory(self._inventory)
1443
 
    
1444
 
    @deprecated_method(zero_eight)
1445
 
    def iter_conflicts(self):
1446
 
        """List all files in the tree that have text or content conflicts.
1447
 
        DEPRECATED.  Use conflicts instead."""
1448
 
        return self._iter_conflicts()
1449
1550
 
1450
1551
    def _iter_conflicts(self):
1451
1552
        conflicted = set()
1460
1561
 
1461
1562
    @needs_write_lock
1462
1563
    def pull(self, source, overwrite=False, stop_revision=None,
1463
 
             change_reporter=None):
 
1564
             change_reporter=None, possible_transports=None, local=False):
1464
1565
        top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1465
1566
        source.lock_read()
1466
1567
        try:
1468
1569
            pp.next_phase()
1469
1570
            old_revision_info = self.branch.last_revision_info()
1470
1571
            basis_tree = self.basis_tree()
1471
 
            count = self.branch.pull(source, overwrite, stop_revision)
 
1572
            count = self.branch.pull(source, overwrite, stop_revision,
 
1573
                                     possible_transports=possible_transports,
 
1574
                                     local=local)
1472
1575
            new_revision_info = self.branch.last_revision_info()
1473
1576
            if new_revision_info != old_revision_info:
1474
1577
                pp.next_phase()
1486
1589
                                change_reporter=change_reporter)
1487
1590
                    if (basis_tree.inventory.root is None and
1488
1591
                        new_basis_tree.inventory.root is not None):
1489
 
                        self.set_root_id(new_basis_tree.inventory.root.file_id)
 
1592
                        self.set_root_id(new_basis_tree.get_root_id())
1490
1593
                finally:
1491
1594
                    pb.finished()
1492
1595
                    basis_tree.unlock()
1494
1597
                # reuse the revisiontree we merged against to set the new
1495
1598
                # tree data.
1496
1599
                parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1497
 
                # we have to pull the merge trees out again, because 
1498
 
                # merge_inner has set the ids. - this corner is not yet 
 
1600
                # we have to pull the merge trees out again, because
 
1601
                # merge_inner has set the ids. - this corner is not yet
1499
1602
                # layered well enough to prevent double handling.
1500
1603
                # XXX TODO: Fix the double handling: telling the tree about
1501
1604
                # the already known parent data is wasteful.
1512
1615
    @needs_write_lock
1513
1616
    def put_file_bytes_non_atomic(self, file_id, bytes):
1514
1617
        """See MutableTree.put_file_bytes_non_atomic."""
1515
 
        file_id = osutils.safe_file_id(file_id)
1516
1618
        stream = file(self.id2abspath(file_id), 'wb')
1517
1619
        try:
1518
1620
            stream.write(bytes)
1540
1642
 
1541
1643
            fl = []
1542
1644
            for subf in os.listdir(dirabs):
1543
 
                if subf == '.bzr':
 
1645
                if self.bzrdir.is_control_filename(subf):
1544
1646
                    continue
1545
1647
                if subf not in dir_entry.children:
1546
 
                    subf_norm, can_access = osutils.normalized_filename(subf)
 
1648
                    try:
 
1649
                        (subf_norm,
 
1650
                         can_access) = osutils.normalized_filename(subf)
 
1651
                    except UnicodeDecodeError:
 
1652
                        path_os_enc = path.encode(osutils._fs_enc)
 
1653
                        relpath = path_os_enc + '/' + subf
 
1654
                        raise errors.BadFilenameEncoding(relpath,
 
1655
                                                         osutils._fs_enc)
1547
1656
                    if subf_norm != subf and can_access:
1548
1657
                        if subf_norm not in dir_entry.children:
1549
1658
                            fl.append(subf_norm)
1550
1659
                    else:
1551
1660
                        fl.append(subf)
1552
 
            
 
1661
 
1553
1662
            fl.sort()
1554
1663
            for subf in fl:
1555
1664
                subp = pathjoin(path, subf)
1571
1680
        if ignoreset is not None:
1572
1681
            return ignoreset
1573
1682
 
1574
 
        ignore_globs = set(bzrlib.DEFAULT_IGNORE)
 
1683
        ignore_globs = set()
1575
1684
        ignore_globs.update(ignores.get_runtime_ignores())
1576
1685
        ignore_globs.update(ignores.get_user_ignores())
1577
1686
        if self.has_filename(bzrlib.IGNORE_FILENAME):
1604
1713
    def kind(self, file_id):
1605
1714
        return file_kind(self.id2abspath(file_id))
1606
1715
 
 
1716
    def stored_kind(self, file_id):
 
1717
        """See Tree.stored_kind"""
 
1718
        return self.inventory[file_id].kind
 
1719
 
1607
1720
    def _comparison_data(self, entry, path):
1608
1721
        abspath = self.abspath(path)
1609
1722
        try:
1640
1753
    @needs_read_lock
1641
1754
    def _last_revision(self):
1642
1755
        """helper for get_parent_ids."""
1643
 
        return self.branch.last_revision()
 
1756
        return _mod_revision.ensure_null(self.branch.last_revision())
1644
1757
 
1645
1758
    def is_locked(self):
1646
1759
        return self._control_files.is_locked()
1691
1804
    def _reset_data(self):
1692
1805
        """Reset transient data that cannot be revalidated."""
1693
1806
        self._inventory_is_modified = False
1694
 
        result = self._deserialize(self._control_files.get('inventory'))
 
1807
        result = self._deserialize(self._transport.get('inventory'))
1695
1808
        self._set_inventory(result, dirty=False)
1696
1809
 
1697
1810
    @needs_tree_write_lock
1698
1811
    def set_last_revision(self, new_revision):
1699
1812
        """Change the last revision in the working tree."""
1700
 
        new_revision = osutils.safe_revision_id(new_revision)
1701
1813
        if self._change_last_revision(new_revision):
1702
1814
            self._cache_basis_inventory(new_revision)
1703
1815
 
1704
1816
    def _change_last_revision(self, new_revision):
1705
1817
        """Template method part of set_last_revision to perform the change.
1706
 
        
 
1818
 
1707
1819
        This is used to allow WorkingTree3 instances to not affect branch
1708
1820
        when their last revision is set.
1709
1821
        """
1719
1831
 
1720
1832
    def _write_basis_inventory(self, xml):
1721
1833
        """Write the basis inventory XML to the basis-inventory file"""
1722
 
        assert isinstance(xml, str), 'serialised xml must be bytestring.'
1723
1834
        path = self._basis_inventory_name()
1724
1835
        sio = StringIO(xml)
1725
 
        self._control_files.put(path, sio)
 
1836
        self._transport.put_file(path, sio,
 
1837
            mode=self.bzrdir._get_file_mode())
1726
1838
 
1727
1839
    def _create_basis_xml_from_inventory(self, revision_id, inventory):
1728
1840
        """Create the text that will be saved in basis-inventory"""
1729
 
        # TODO: jam 20070209 This should be redundant, as the revision_id
1730
 
        #       as all callers should have already converted the revision_id to
1731
 
        #       utf8
1732
 
        inventory.revision_id = osutils.safe_revision_id(revision_id)
 
1841
        inventory.revision_id = revision_id
1733
1842
        return xml7.serializer_v7.write_inventory_to_string(inventory)
1734
1843
 
1735
1844
    def _cache_basis_inventory(self, new_revision):
1738
1847
        # as commit already has that ready-to-use [while the format is the
1739
1848
        # same, that is].
1740
1849
        try:
1741
 
            # this double handles the inventory - unpack and repack - 
 
1850
            # this double handles the inventory - unpack and repack -
1742
1851
            # but is easier to understand. We can/should put a conditional
1743
1852
            # in here based on whether the inventory is in the latest format
1744
1853
            # - perhaps we should repack all inventories on a repository
1745
1854
            # upgrade ?
1746
1855
            # the fast path is to copy the raw xml from the repository. If the
1747
 
            # xml contains 'revision_id="', then we assume the right 
 
1856
            # xml contains 'revision_id="', then we assume the right
1748
1857
            # revision_id is set. We must check for this full string, because a
1749
1858
            # root node id can legitimately look like 'revision_id' but cannot
1750
1859
            # contain a '"'.
1751
1860
            xml = self.branch.repository.get_inventory_xml(new_revision)
1752
1861
            firstline = xml.split('\n', 1)[0]
1753
 
            if (not 'revision_id="' in firstline or 
 
1862
            if (not 'revision_id="' in firstline or
1754
1863
                'format="7"' not in firstline):
1755
1864
                inv = self.branch.repository.deserialise_inventory(
1756
1865
                    new_revision, xml)
1762
1871
    def read_basis_inventory(self):
1763
1872
        """Read the cached basis inventory."""
1764
1873
        path = self._basis_inventory_name()
1765
 
        return self._control_files.get(path).read()
1766
 
        
 
1874
        return self._transport.get_bytes(path)
 
1875
 
1767
1876
    @needs_read_lock
1768
1877
    def read_working_inventory(self):
1769
1878
        """Read the working inventory.
1770
 
        
 
1879
 
1771
1880
        :raises errors.InventoryModified: read_working_inventory will fail
1772
1881
            when the current in memory inventory has been modified.
1773
1882
        """
1774
 
        # conceptually this should be an implementation detail of the tree. 
 
1883
        # conceptually this should be an implementation detail of the tree.
1775
1884
        # XXX: Deprecate this.
1776
1885
        # ElementTree does its own conversion from UTF-8, so open in
1777
1886
        # binary.
1778
1887
        if self._inventory_is_modified:
1779
1888
            raise errors.InventoryModified(self)
1780
 
        result = self._deserialize(self._control_files.get('inventory'))
 
1889
        result = self._deserialize(self._transport.get('inventory'))
1781
1890
        self._set_inventory(result, dirty=False)
1782
1891
        return result
1783
1892
 
1791
1900
        :force: Delete files and directories, even if they are changed and
1792
1901
            even if the directories are not empty.
1793
1902
        """
1794
 
        ## TODO: Normalize names
1795
 
 
1796
1903
        if isinstance(files, basestring):
1797
1904
            files = [files]
1798
1905
 
1799
1906
        inv_delta = []
1800
1907
 
1801
1908
        new_files=set()
1802
 
        unknown_files_in_directory=set()
 
1909
        unknown_nested_files=set()
1803
1910
 
1804
1911
        def recurse_directory_to_add_files(directory):
1805
 
            # recurse directory and add all files
 
1912
            # Recurse directory and add all files
1806
1913
            # so we can check if they have changed.
1807
1914
            for parent_info, file_infos in\
1808
 
                osutils.walkdirs(self.abspath(directory),
1809
 
                    directory):
1810
 
                for relpath, basename, kind, lstat, abspath in file_infos:
1811
 
                    if kind == 'file':
1812
 
                        if self.path2id(relpath): #is it versioned?
1813
 
                            new_files.add(relpath)
1814
 
                        else:
1815
 
                            unknown_files_in_directory.add(
1816
 
                                (relpath, None, kind))
 
1915
                self.walkdirs(directory):
 
1916
                for relpath, basename, kind, lstat, fileid, kind in file_infos:
 
1917
                    # Is it versioned or ignored?
 
1918
                    if self.path2id(relpath) or self.is_ignored(relpath):
 
1919
                        # Add nested content for deletion.
 
1920
                        new_files.add(relpath)
 
1921
                    else:
 
1922
                        # Files which are not versioned and not ignored
 
1923
                        # should be treated as unknown.
 
1924
                        unknown_nested_files.add((relpath, None, kind))
1817
1925
 
1818
1926
        for filename in files:
1819
1927
            # Get file name into canonical form.
1821
1929
            filename = self.relpath(abspath)
1822
1930
            if len(filename) > 0:
1823
1931
                new_files.add(filename)
1824
 
                if osutils.isdir(abspath):
1825
 
                    recurse_directory_to_add_files(filename)
1826
 
        files = [f for f in new_files]
 
1932
                recurse_directory_to_add_files(filename)
 
1933
 
 
1934
        files = list(new_files)
1827
1935
 
1828
1936
        if len(files) == 0:
1829
1937
            return # nothing to do
1830
1938
 
1831
1939
        # Sort needed to first handle directory content before the directory
1832
1940
        files.sort(reverse=True)
 
1941
 
 
1942
        # Bail out if we are going to delete files we shouldn't
1833
1943
        if not keep_files and not force:
1834
 
            has_changed_files = len(unknown_files_in_directory) > 0
 
1944
            has_changed_files = len(unknown_nested_files) > 0
1835
1945
            if not has_changed_files:
1836
1946
                for (file_id, path, content_change, versioned, parent_id, name,
1837
 
                     kind, executable) in self._iter_changes(self.basis_tree(),
 
1947
                     kind, executable) in self.iter_changes(self.basis_tree(),
1838
1948
                         include_unchanged=True, require_versioned=False,
1839
1949
                         want_unversioned=True, specific_files=files):
1840
 
                    # check if it's unknown OR changed but not deleted:
1841
 
                    if (versioned == (False, False)
1842
 
                        or (content_change and kind[1] != None)):
 
1950
                    if versioned == (False, False):
 
1951
                        # The record is unknown ...
 
1952
                        if not self.is_ignored(path[1]):
 
1953
                            # ... but not ignored
 
1954
                            has_changed_files = True
 
1955
                            break
 
1956
                    elif content_change and (kind[1] is not None):
 
1957
                        # Versioned and changed, but not deleted
1843
1958
                        has_changed_files = True
1844
1959
                        break
1845
1960
 
1846
1961
            if has_changed_files:
1847
 
                # make delta to show ALL applicable changes in error message.
 
1962
                # Make delta show ALL applicable changes in error message.
1848
1963
                tree_delta = self.changes_from(self.basis_tree(),
 
1964
                    require_versioned=False, want_unversioned=True,
1849
1965
                    specific_files=files)
1850
 
                for unknown_file in unknown_files_in_directory:
1851
 
                    tree_delta.unversioned.extend((unknown_file,))
 
1966
                for unknown_file in unknown_nested_files:
 
1967
                    if unknown_file not in tree_delta.unversioned:
 
1968
                        tree_delta.unversioned.extend((unknown_file,))
1852
1969
                raise errors.BzrRemoveChangedFilesError(tree_delta)
1853
1970
 
1854
 
        # do this before any modifications
 
1971
        # Build inv_delta and delete files where applicable,
 
1972
        # do this before any modifications to inventory.
1855
1973
        for f in files:
1856
1974
            fid = self.path2id(f)
1857
 
            message=None
 
1975
            message = None
1858
1976
            if not fid:
1859
 
                message="%s is not versioned." % (f,)
 
1977
                message = "%s is not versioned." % (f,)
1860
1978
            else:
1861
1979
                if verbose:
1862
1980
                    # having removed it, it must be either ignored or unknown
1866
1984
                        new_status = '?'
1867
1985
                    textui.show_status(new_status, self.kind(fid), f,
1868
1986
                                       to_file=to_file)
1869
 
                # unversion file
 
1987
                # Unversion file
1870
1988
                inv_delta.append((f, None, fid, None))
1871
 
                message="removed %s" % (f,)
 
1989
                message = "removed %s" % (f,)
1872
1990
 
1873
1991
            if not keep_files:
1874
1992
                abs_path = self.abspath(f)
1875
1993
                if osutils.lexists(abs_path):
1876
1994
                    if (osutils.isdir(abs_path) and
1877
1995
                        len(os.listdir(abs_path)) > 0):
1878
 
                        message="%s is not empty directory "\
1879
 
                            "and won't be deleted." % (f,)
 
1996
                        if force:
 
1997
                            osutils.rmtree(abs_path)
 
1998
                        else:
 
1999
                            message = "%s is not an empty directory "\
 
2000
                                "and won't be deleted." % (f,)
1880
2001
                    else:
1881
2002
                        osutils.delete_any(abs_path)
1882
 
                        message="deleted %s" % (f,)
 
2003
                        message = "deleted %s" % (f,)
1883
2004
                elif message is not None:
1884
 
                    # only care if we haven't done anything yet.
1885
 
                    message="%s does not exist." % (f,)
 
2005
                    # Only care if we haven't done anything yet.
 
2006
                    message = "%s does not exist." % (f,)
1886
2007
 
1887
 
            # print only one message (if any) per file.
 
2008
            # Print only one message (if any) per file.
1888
2009
            if message is not None:
1889
2010
                note(message)
1890
2011
        self.apply_inventory_delta(inv_delta)
1891
2012
 
1892
2013
    @needs_tree_write_lock
1893
 
    def revert(self, filenames, old_tree=None, backups=True, 
 
2014
    def revert(self, filenames=None, old_tree=None, backups=True,
1894
2015
               pb=DummyProgress(), report_changes=False):
1895
2016
        from bzrlib.conflicts import resolve
 
2017
        if filenames == []:
 
2018
            filenames = None
 
2019
            symbol_versioning.warn('Using [] to revert all files is deprecated'
 
2020
                ' as of bzr 0.91.  Please use None (the default) instead.',
 
2021
                DeprecationWarning, stacklevel=2)
1896
2022
        if old_tree is None:
1897
 
            old_tree = self.basis_tree()
1898
 
        conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1899
 
                                     report_changes)
1900
 
        if not len(filenames):
1901
 
            self.set_parent_ids(self.get_parent_ids()[:1])
1902
 
            resolve(self)
 
2023
            basis_tree = self.basis_tree()
 
2024
            basis_tree.lock_read()
 
2025
            old_tree = basis_tree
1903
2026
        else:
1904
 
            resolve(self, filenames, ignore_misses=True)
 
2027
            basis_tree = None
 
2028
        try:
 
2029
            conflicts = transform.revert(self, old_tree, filenames, backups, pb,
 
2030
                                         report_changes)
 
2031
            if filenames is None and len(self.get_parent_ids()) > 1:
 
2032
                parent_trees = []
 
2033
                last_revision = self.last_revision()
 
2034
                if last_revision != NULL_REVISION:
 
2035
                    if basis_tree is None:
 
2036
                        basis_tree = self.basis_tree()
 
2037
                        basis_tree.lock_read()
 
2038
                    parent_trees.append((last_revision, basis_tree))
 
2039
                self.set_parent_trees(parent_trees)
 
2040
                resolve(self)
 
2041
            else:
 
2042
                resolve(self, filenames, ignore_misses=True, recursive=True)
 
2043
        finally:
 
2044
            if basis_tree is not None:
 
2045
                basis_tree.unlock()
1905
2046
        return conflicts
1906
2047
 
1907
2048
    def revision_tree(self, revision_id):
1942
2083
            name = os.path.basename(path)
1943
2084
            if name == "":
1944
2085
                continue
1945
 
            # fixme, there should be a factory function inv,add_?? 
 
2086
            # fixme, there should be a factory function inv,add_??
1946
2087
            if kind == 'directory':
1947
2088
                inv.add(InventoryDirectory(file_id, name, parent))
1948
2089
            elif kind == 'file':
1956
2097
    @needs_tree_write_lock
1957
2098
    def set_root_id(self, file_id):
1958
2099
        """Set the root id for this tree."""
1959
 
        # for compatability 
 
2100
        # for compatability
1960
2101
        if file_id is None:
1961
 
            symbol_versioning.warn(symbol_versioning.zero_twelve
1962
 
                % 'WorkingTree.set_root_id with fileid=None',
1963
 
                DeprecationWarning,
1964
 
                stacklevel=3)
1965
 
            file_id = ROOT_ID
1966
 
        else:
1967
 
            file_id = osutils.safe_file_id(file_id)
 
2102
            raise ValueError(
 
2103
                'WorkingTree.set_root_id with fileid=None')
 
2104
        file_id = osutils.safe_file_id(file_id)
1968
2105
        self._set_root_id(file_id)
1969
2106
 
1970
2107
    def _set_root_id(self, file_id):
1971
2108
        """Set the root id for this tree, in a format specific manner.
1972
2109
 
1973
 
        :param file_id: The file id to assign to the root. It must not be 
 
2110
        :param file_id: The file id to assign to the root. It must not be
1974
2111
            present in the current inventory or an error will occur. It must
1975
2112
            not be None, but rather a valid file id.
1976
2113
        """
1995
2132
 
1996
2133
    def unlock(self):
1997
2134
        """See Branch.unlock.
1998
 
        
 
2135
 
1999
2136
        WorkingTree locking just uses the Branch locking facilities.
2000
2137
        This is current because all working trees have an embedded branch
2001
2138
        within them. IF in the future, we were to make branch data shareable
2002
 
        between multiple working trees, i.e. via shared storage, then we 
 
2139
        between multiple working trees, i.e. via shared storage, then we
2003
2140
        would probably want to lock both the local tree, and the branch.
2004
2141
        """
2005
2142
        raise NotImplementedError(self.unlock)
2006
2143
 
2007
 
    def update(self, change_reporter=None):
 
2144
    def update(self, change_reporter=None, possible_transports=None):
2008
2145
        """Update a working tree along its branch.
2009
2146
 
2010
2147
        This will update the branch if its bound too, which means we have
2029
2166
          basis.
2030
2167
        - Do a 'normal' merge of the old branch basis if it is relevant.
2031
2168
        """
2032
 
        if self.branch.get_master_branch() is not None:
 
2169
        if self.branch.get_bound_location() is not None:
2033
2170
            self.lock_write()
2034
2171
            update_branch = True
2035
2172
        else:
2037
2174
            update_branch = False
2038
2175
        try:
2039
2176
            if update_branch:
2040
 
                old_tip = self.branch.update()
 
2177
                old_tip = self.branch.update(possible_transports)
2041
2178
            else:
2042
2179
                old_tip = None
2043
2180
            return self._update_tree(old_tip, change_reporter)
2057
2194
        # cant set that until we update the working trees last revision to be
2058
2195
        # one from the new branch, because it will just get absorbed by the
2059
2196
        # parent de-duplication logic.
2060
 
        # 
 
2197
        #
2061
2198
        # We MUST save it even if an error occurs, because otherwise the users
2062
2199
        # local work is unreferenced and will appear to have been lost.
2063
 
        # 
 
2200
        #
2064
2201
        result = 0
2065
2202
        try:
2066
2203
            last_rev = self.get_parent_ids()[0]
2073
2210
            try:
2074
2211
                to_tree = self.branch.basis_tree()
2075
2212
                if basis.inventory.root is None:
2076
 
                    self.set_root_id(to_tree.inventory.root.file_id)
 
2213
                    self.set_root_id(to_tree.get_root_id())
2077
2214
                    self.flush()
2078
2215
                result += merge.merge_inner(
2079
2216
                                      self.branch,
2088
2225
            parent_trees = [(self.branch.last_revision(), to_tree)]
2089
2226
            merges = self.get_parent_ids()[1:]
2090
2227
            # Ideally we ask the tree for the trees here, that way the working
2091
 
            # tree can decide whether to give us teh entire tree or give us a
 
2228
            # tree can decide whether to give us the entire tree or give us a
2092
2229
            # lazy initialised tree. dirstate for instance will have the trees
2093
2230
            # in ram already, whereas a last-revision + basis-inventory tree
2094
2231
            # will not, but also does not need them when setting parents.
2221
2358
            current_inv = None
2222
2359
            inv_finished = True
2223
2360
        while not inv_finished or not disk_finished:
 
2361
            if current_disk:
 
2362
                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
 
2363
                    cur_disk_dir_content) = current_disk
 
2364
            else:
 
2365
                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
 
2366
                    cur_disk_dir_content) = ((None, None), None)
2224
2367
            if not disk_finished:
2225
2368
                # strip out .bzr dirs
2226
 
                if current_disk[0][1][top_strip_len:] == '':
2227
 
                    # osutils.walkdirs can be made nicer - 
 
2369
                if (cur_disk_dir_path_from_top[top_strip_len:] == '' and
 
2370
                    len(cur_disk_dir_content) > 0):
 
2371
                    # osutils.walkdirs can be made nicer -
2228
2372
                    # yield the path-from-prefix rather than the pathjoined
2229
2373
                    # value.
2230
 
                    bzrdir_loc = bisect_left(current_disk[1], ('.bzr', '.bzr'))
2231
 
                    if current_disk[1][bzrdir_loc][0] == '.bzr':
 
2374
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
 
2375
                        ('.bzr', '.bzr'))
 
2376
                    if (bzrdir_loc < len(cur_disk_dir_content)
 
2377
                        and self.bzrdir.is_control_filename(
 
2378
                            cur_disk_dir_content[bzrdir_loc][0])):
2232
2379
                        # we dont yield the contents of, or, .bzr itself.
2233
 
                        del current_disk[1][bzrdir_loc]
 
2380
                        del cur_disk_dir_content[bzrdir_loc]
2234
2381
            if inv_finished:
2235
2382
                # everything is unknown
2236
2383
                direction = 1
2238
2385
                # everything is missing
2239
2386
                direction = -1
2240
2387
            else:
2241
 
                direction = cmp(current_inv[0][0], current_disk[0][0])
 
2388
                direction = cmp(current_inv[0][0], cur_disk_dir_relpath)
2242
2389
            if direction > 0:
2243
2390
                # disk is before inventory - unknown
2244
2391
                dirblock = [(relpath, basename, kind, stat, None, None) for
2245
 
                    relpath, basename, kind, stat, top_path in current_disk[1]]
2246
 
                yield (current_disk[0][0], None), dirblock
 
2392
                    relpath, basename, kind, stat, top_path in
 
2393
                    cur_disk_dir_content]
 
2394
                yield (cur_disk_dir_relpath, None), dirblock
2247
2395
                try:
2248
2396
                    current_disk = disk_iterator.next()
2249
2397
                except StopIteration:
2251
2399
            elif direction < 0:
2252
2400
                # inventory is before disk - missing.
2253
2401
                dirblock = [(relpath, basename, 'unknown', None, fileid, kind)
2254
 
                    for relpath, basename, dkind, stat, fileid, kind in 
 
2402
                    for relpath, basename, dkind, stat, fileid, kind in
2255
2403
                    current_inv[1]]
2256
2404
                yield (current_inv[0][0], current_inv[0][1]), dirblock
2257
2405
                try:
2263
2411
                # merge the inventory and disk data together
2264
2412
                dirblock = []
2265
2413
                for relpath, subiterator in itertools.groupby(sorted(
2266
 
                    current_inv[1] + current_disk[1], key=operator.itemgetter(0)), operator.itemgetter(1)):
 
2414
                    current_inv[1] + cur_disk_dir_content,
 
2415
                    key=operator.itemgetter(0)), operator.itemgetter(1)):
2267
2416
                    path_elements = list(subiterator)
2268
2417
                    if len(path_elements) == 2:
2269
2418
                        inv_row, disk_row = path_elements
2322
2471
                relroot = ""
2323
2472
            # FIXME: stash the node in pending
2324
2473
            entry = inv[top_id]
2325
 
            for name, child in entry.sorted_children():
2326
 
                dirblock.append((relroot + name, name, child.kind, None,
2327
 
                    child.file_id, child.kind
2328
 
                    ))
 
2474
            if entry.kind == 'directory':
 
2475
                for name, child in entry.sorted_children():
 
2476
                    dirblock.append((relroot + name, name, child.kind, None,
 
2477
                        child.file_id, child.kind
 
2478
                        ))
2329
2479
            yield (currentdir[0], entry.file_id), dirblock
2330
2480
            # push the user specified dirs from dirblock
2331
2481
            for dir in reversed(dirblock):
2364
2514
        self.set_conflicts(un_resolved)
2365
2515
        return un_resolved, resolved
2366
2516
 
 
2517
    @needs_read_lock
 
2518
    def _check(self):
 
2519
        tree_basis = self.basis_tree()
 
2520
        tree_basis.lock_read()
 
2521
        try:
 
2522
            repo_basis = self.branch.repository.revision_tree(
 
2523
                self.last_revision())
 
2524
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
 
2525
                raise errors.BzrCheckError(
 
2526
                    "Mismatched basis inventory content.")
 
2527
            self._validate()
 
2528
        finally:
 
2529
            tree_basis.unlock()
 
2530
 
2367
2531
    def _validate(self):
2368
2532
        """Validate internal structures.
2369
2533
 
2375
2539
        """
2376
2540
        return
2377
2541
 
 
2542
    @needs_read_lock
 
2543
    def _get_rules_searcher(self, default_searcher):
 
2544
        """See Tree._get_rules_searcher."""
 
2545
        if self._rules_searcher is None:
 
2546
            self._rules_searcher = super(WorkingTree,
 
2547
                self)._get_rules_searcher(default_searcher)
 
2548
        return self._rules_searcher
 
2549
 
 
2550
    def get_shelf_manager(self):
 
2551
        """Return the ShelfManager for this WorkingTree."""
 
2552
        from bzrlib.shelf import ShelfManager
 
2553
        return ShelfManager(self, self._transport)
 
2554
 
2378
2555
 
2379
2556
class WorkingTree2(WorkingTree):
2380
2557
    """This is the Format 2 working tree.
2381
2558
 
2382
 
    This was the first weave based working tree. 
 
2559
    This was the first weave based working tree.
2383
2560
     - uses os locks for locking.
2384
2561
     - uses the branch last-revision.
2385
2562
    """
2418
2595
            if self._inventory_is_modified:
2419
2596
                self.flush()
2420
2597
            self._write_hashcache_if_dirty()
2421
 
                    
 
2598
 
2422
2599
        # reverse order of locking.
2423
2600
        try:
2424
2601
            return self._control_files.unlock()
2440
2617
    def _last_revision(self):
2441
2618
        """See Mutable.last_revision."""
2442
2619
        try:
2443
 
            return osutils.safe_revision_id(
2444
 
                        self._control_files.get('last-revision').read())
 
2620
            return self._transport.get_bytes('last-revision')
2445
2621
        except errors.NoSuchFile:
2446
 
            return None
 
2622
            return _mod_revision.NULL_REVISION
2447
2623
 
2448
2624
    def _change_last_revision(self, revision_id):
2449
2625
        """See WorkingTree._change_last_revision."""
2450
2626
        if revision_id is None or revision_id == NULL_REVISION:
2451
2627
            try:
2452
 
                self._control_files._transport.delete('last-revision')
 
2628
                self._transport.delete('last-revision')
2453
2629
            except errors.NoSuchFile:
2454
2630
                pass
2455
2631
            return False
2456
2632
        else:
2457
 
            self._control_files.put_bytes('last-revision', revision_id)
 
2633
            self._transport.put_bytes('last-revision', revision_id,
 
2634
                mode=self.bzrdir._get_file_mode())
2458
2635
            return True
2459
2636
 
2460
2637
    @needs_tree_write_lock
2461
2638
    def set_conflicts(self, conflicts):
2462
 
        self._put_rio('conflicts', conflicts.to_stanzas(), 
 
2639
        self._put_rio('conflicts', conflicts.to_stanzas(),
2463
2640
                      CONFLICT_HEADER_1)
2464
2641
 
2465
2642
    @needs_tree_write_lock
2472
2649
    @needs_read_lock
2473
2650
    def conflicts(self):
2474
2651
        try:
2475
 
            confile = self._control_files.get('conflicts')
 
2652
            confile = self._transport.get('conflicts')
2476
2653
        except errors.NoSuchFile:
2477
2654
            return _mod_conflicts.ConflictList()
2478
2655
        try:
2479
 
            if confile.next() != CONFLICT_HEADER_1 + '\n':
 
2656
            try:
 
2657
                if confile.next() != CONFLICT_HEADER_1 + '\n':
 
2658
                    raise errors.ConflictFormatError()
 
2659
            except StopIteration:
2480
2660
                raise errors.ConflictFormatError()
2481
 
        except StopIteration:
2482
 
            raise errors.ConflictFormatError()
2483
 
        return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
 
2661
            return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
 
2662
        finally:
 
2663
            confile.close()
2484
2664
 
2485
2665
    def unlock(self):
2486
2666
        # do non-implementation specific cleanup
2503
2683
            return path[:-len(suffix)]
2504
2684
 
2505
2685
 
2506
 
@deprecated_function(zero_eight)
2507
 
def is_control_file(filename):
2508
 
    """See WorkingTree.is_control_filename(filename)."""
2509
 
    ## FIXME: better check
2510
 
    filename = normpath(filename)
2511
 
    while filename != '':
2512
 
        head, tail = os.path.split(filename)
2513
 
        ## mutter('check %r for control file' % ((head, tail),))
2514
 
        if tail == '.bzr':
2515
 
            return True
2516
 
        if filename == head:
2517
 
            break
2518
 
        filename = head
2519
 
    return False
2520
 
 
2521
 
 
2522
2686
class WorkingTreeFormat(object):
2523
2687
    """An encapsulation of the initialization and open routines for a format.
2524
2688
 
2527
2691
     * a format string,
2528
2692
     * an open routine.
2529
2693
 
2530
 
    Formats are placed in an dict by their format string for reference 
 
2694
    Formats are placed in an dict by their format string for reference
2531
2695
    during workingtree opening. Its not required that these be instances, they
2532
 
    can be classes themselves with class methods - it simply depends on 
 
2696
    can be classes themselves with class methods - it simply depends on
2533
2697
    whether state is needed for a given format or not.
2534
2698
 
2535
2699
    Once a format is deprecated, just deprecate the initialize and open
2536
 
    methods on the format class. Do not deprecate the object, as the 
 
2700
    methods on the format class. Do not deprecate the object, as the
2537
2701
    object will be created every time regardless.
2538
2702
    """
2539
2703
 
2557
2721
        except errors.NoSuchFile:
2558
2722
            raise errors.NoWorkingTree(base=transport.base)
2559
2723
        except KeyError:
2560
 
            raise errors.UnknownFormatError(format=format_string)
 
2724
            raise errors.UnknownFormatError(format=format_string,
 
2725
                                            kind="working tree")
2561
2726
 
2562
2727
    def __eq__(self, other):
2563
2728
        return self.__class__ is other.__class__
2582
2747
        """Is this format supported?
2583
2748
 
2584
2749
        Supported formats can be initialized and opened.
2585
 
        Unsupported formats may not support initialization or committing or 
 
2750
        Unsupported formats may not support initialization or committing or
2586
2751
        some other features depending on the reason for not being supported.
2587
2752
        """
2588
2753
        return True
2589
2754
 
 
2755
    def supports_content_filtering(self):
 
2756
        """True if this format supports content filtering."""
 
2757
        return False
 
2758
 
 
2759
    def supports_views(self):
 
2760
        """True if this format supports stored views."""
 
2761
        return False
 
2762
 
2590
2763
    @classmethod
2591
2764
    def register_format(klass, format):
2592
2765
        klass._formats[format.get_format_string()] = format
2597
2770
 
2598
2771
    @classmethod
2599
2772
    def unregister_format(klass, format):
2600
 
        assert klass._formats[format.get_format_string()] is format
2601
2773
        del klass._formats[format.get_format_string()]
2602
2774
 
2603
2775
 
2604
2776
class WorkingTreeFormat2(WorkingTreeFormat):
2605
 
    """The second working tree format. 
 
2777
    """The second working tree format.
2606
2778
 
2607
2779
    This format modified the hash cache from the format 1 hash cache.
2608
2780
    """
2613
2785
        """See WorkingTreeFormat.get_format_description()."""
2614
2786
        return "Working tree format 2"
2615
2787
 
2616
 
    def stub_initialize_remote(self, control_files):
2617
 
        """As a special workaround create critical control files for a remote working tree
2618
 
        
 
2788
    def _stub_initialize_on_transport(self, transport, file_mode):
 
2789
        """Workaround: create control files for a remote working tree.
 
2790
 
2619
2791
        This ensures that it can later be updated and dealt with locally,
2620
 
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with 
 
2792
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2621
2793
        no working tree.  (See bug #43064).
2622
2794
        """
2623
2795
        sio = StringIO()
2624
2796
        inv = Inventory()
2625
 
        xml5.serializer_v5.write_inventory(inv, sio)
 
2797
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2626
2798
        sio.seek(0)
2627
 
        control_files.put('inventory', sio)
2628
 
 
2629
 
        control_files.put_bytes('pending-merges', '')
2630
 
        
2631
 
 
2632
 
    def initialize(self, a_bzrdir, revision_id=None):
 
2799
        transport.put_file('inventory', sio, file_mode)
 
2800
        transport.put_bytes('pending-merges', '', file_mode)
 
2801
 
 
2802
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
2803
                   accelerator_tree=None, hardlink=False):
2633
2804
        """See WorkingTreeFormat.initialize()."""
2634
2805
        if not isinstance(a_bzrdir.transport, LocalTransport):
2635
2806
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
2636
 
        branch = a_bzrdir.open_branch()
 
2807
        if from_branch is not None:
 
2808
            branch = from_branch
 
2809
        else:
 
2810
            branch = a_bzrdir.open_branch()
2637
2811
        if revision_id is None:
2638
2812
            revision_id = _mod_revision.ensure_null(branch.last_revision())
2639
 
        else:
2640
 
            revision_id = osutils.safe_revision_id(revision_id)
2641
2813
        branch.lock_write()
2642
2814
        try:
2643
2815
            branch.generate_revision_history(revision_id)
2652
2824
                         _bzrdir=a_bzrdir)
2653
2825
        basis_tree = branch.repository.revision_tree(revision_id)
2654
2826
        if basis_tree.inventory.root is not None:
2655
 
            wt.set_root_id(basis_tree.inventory.root.file_id)
 
2827
            wt.set_root_id(basis_tree.get_root_id())
2656
2828
        # set the parent list and cache the basis tree.
2657
2829
        if _mod_revision.is_null(revision_id):
2658
2830
            parent_trees = []
2694
2866
        - is new in bzr 0.8
2695
2867
        - uses a LockDir to guard access for writes.
2696
2868
    """
2697
 
    
 
2869
 
2698
2870
    upgrade_recommended = True
2699
2871
 
2700
2872
    def get_format_string(self):
2717
2889
 
2718
2890
    def _open_control_files(self, a_bzrdir):
2719
2891
        transport = a_bzrdir.get_workingtree_transport(None)
2720
 
        return LockableFiles(transport, self._lock_file_name, 
 
2892
        return LockableFiles(transport, self._lock_file_name,
2721
2893
                             self._lock_class)
2722
2894
 
2723
 
    def initialize(self, a_bzrdir, revision_id=None):
 
2895
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
2896
                   accelerator_tree=None, hardlink=False):
2724
2897
        """See WorkingTreeFormat.initialize().
2725
 
        
2726
 
        revision_id allows creating a working tree at a different
2727
 
        revision than the branch is at.
 
2898
 
 
2899
        :param revision_id: if supplied, create a working tree at a different
 
2900
            revision than the branch is at.
 
2901
        :param accelerator_tree: A tree which can be used for retrieving file
 
2902
            contents more quickly than the revision tree, i.e. a workingtree.
 
2903
            The revision tree will be used for cases where accelerator_tree's
 
2904
            content is different.
 
2905
        :param hardlink: If true, hard-link files from accelerator_tree,
 
2906
            where possible.
2728
2907
        """
2729
2908
        if not isinstance(a_bzrdir.transport, LocalTransport):
2730
2909
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
2732
2911
        control_files = self._open_control_files(a_bzrdir)
2733
2912
        control_files.create_lock()
2734
2913
        control_files.lock_write()
2735
 
        control_files.put_utf8('format', self.get_format_string())
2736
 
        branch = a_bzrdir.open_branch()
 
2914
        transport.put_bytes('format', self.get_format_string(),
 
2915
            mode=a_bzrdir._get_file_mode())
 
2916
        if from_branch is not None:
 
2917
            branch = from_branch
 
2918
        else:
 
2919
            branch = a_bzrdir.open_branch()
2737
2920
        if revision_id is None:
2738
2921
            revision_id = _mod_revision.ensure_null(branch.last_revision())
2739
 
        else:
2740
 
            revision_id = osutils.safe_revision_id(revision_id)
2741
2922
        # WorkingTree3 can handle an inventory which has a unique root id.
2742
2923
        # as of bzr 0.12. However, bzr 0.11 and earlier fail to handle
2743
2924
        # those trees. And because there isn't a format bump inbetween, we
2756
2937
            basis_tree = branch.repository.revision_tree(revision_id)
2757
2938
            # only set an explicit root id if there is one to set.
2758
2939
            if basis_tree.inventory.root is not None:
2759
 
                wt.set_root_id(basis_tree.inventory.root.file_id)
 
2940
                wt.set_root_id(basis_tree.get_root_id())
2760
2941
            if revision_id == NULL_REVISION:
2761
2942
                wt.set_parent_trees([])
2762
2943
            else:
2791
2972
 
2792
2973
    def _open(self, a_bzrdir, control_files):
2793
2974
        """Open the tree itself.
2794
 
        
 
2975
 
2795
2976
        :param a_bzrdir: the dir for the tree.
2796
2977
        :param control_files: the control files for the tree.
2797
2978
        """
2807
2988
 
2808
2989
__default_format = WorkingTreeFormat4()
2809
2990
WorkingTreeFormat.register_format(__default_format)
 
2991
WorkingTreeFormat.register_format(WorkingTreeFormat6())
 
2992
WorkingTreeFormat.register_format(WorkingTreeFormat5())
2810
2993
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2811
2994
WorkingTreeFormat.set_default_format(__default_format)
2812
2995
# formats which have no format string are not discoverable