/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Ā up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
import warnings
53
53
 
54
54
import bzrlib
55
 
from bzrlib import bzrdir, errors, ignores, osutils, urlutils
 
55
from bzrlib import (
 
56
    bzrdir,
 
57
    errors,
 
58
    ignores,
 
59
    osutils,
 
60
    symbol_versioning,
 
61
    urlutils,
 
62
    )
56
63
from bzrlib.atomicfile import AtomicFile
57
64
import bzrlib.branch
58
65
from bzrlib.conflicts import Conflict, ConflictList, CONFLICT_SUFFIXES
67
74
                           MergeModifiedFormatError,
68
75
                           UnsupportedOperation,
69
76
                           )
70
 
from bzrlib.inventory import InventoryEntry, Inventory
 
77
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID
71
78
from bzrlib.lockable_files import LockableFiles, TransportLock
72
79
from bzrlib.lockdir import LockDir
73
80
from bzrlib.merge import merge_inner, transform_tree
253
260
            self.basedir = wt.basedir
254
261
            self._control_files = wt._control_files
255
262
            self._hashcache = wt._hashcache
256
 
            self._set_inventory(wt._inventory)
 
263
            self._set_inventory(wt._inventory, dirty=False)
257
264
            self._format = wt._format
258
265
            self.bzrdir = wt.bzrdir
259
266
        from bzrlib.hashcache import HashCache
301
308
            hc.write()
302
309
 
303
310
        if _inventory is None:
304
 
            self._set_inventory(self.read_working_inventory())
 
311
            self._inventory_is_modified = False
 
312
            self.read_working_inventory()
305
313
        else:
306
 
            self._set_inventory(_inventory)
 
314
            # the caller of __init__ has provided an inventory,
 
315
            # we assume they know what they are doing - as its only
 
316
            # the Format factory and creation methods that are
 
317
            # permitted to do this.
 
318
            self._set_inventory(_inventory, dirty=False)
307
319
 
308
320
    branch = property(
309
321
        fget=lambda self: self._branch,
324
336
        self._control_files.break_lock()
325
337
        self.branch.break_lock()
326
338
 
327
 
    def _set_inventory(self, inv):
 
339
    def _set_inventory(self, inv, dirty):
 
340
        """Set the internal cached inventory.
 
341
 
 
342
        :param inv: The inventory to set.
 
343
        :param dirty: A boolean indicating whether the inventory is the same
 
344
            logical inventory as whats on disk. If True the inventory is not
 
345
            the same and should be written to disk or data will be lost, if
 
346
            False then the inventory is the same as that on disk and any
 
347
            serialisation would be unneeded overhead.
 
348
        """
328
349
        assert inv.root is not None
329
350
        self._inventory = inv
 
351
        self._inventory_is_modified = dirty
330
352
 
331
353
    @staticmethod
332
354
    def open(path=None, _unsupported=False):
491
513
                parents.append(l.rstrip('\n'))
492
514
        return parents
493
515
 
 
516
    @needs_read_lock
494
517
    def get_root_id(self):
495
518
        """Return the id of this trees root"""
496
 
        inv = self.read_working_inventory()
497
 
        return inv.root.file_id
 
519
        return self._inventory.root.file_id
498
520
        
499
521
    def _get_store_filename(self, file_id):
500
522
        ## XXX: badly named; this is not in the store at all
837
859
        else:
838
860
            return '?'
839
861
 
 
862
    def flush(self):
 
863
        """Write the in memory inventory to disk."""
 
864
        # TODO: Maybe this should only write on dirty ?
 
865
        if self._control_files._lock_mode != 'w':
 
866
            raise errors.NotWriteLocked(self)
 
867
        sio = StringIO()
 
868
        bzrlib.xml5.serializer_v5.write_inventory(self._inventory, sio)
 
869
        sio.seek(0)
 
870
        self._control_files.put('inventory', sio)
 
871
        self._inventory_is_modified = False
 
872
 
840
873
    def list_files(self, include_root=False):
841
874
        """Recursively list all files as (path, class, kind, id, entry).
842
875
 
998
1031
        # create a file in this interval and then the rename might be
999
1032
        # left half-done.  But we should have caught most problems.
1000
1033
        orig_inv = deepcopy(self.inventory)
 
1034
        original_modified = self._inventory_is_modified
1001
1035
        try:
 
1036
            if len(from_paths):
 
1037
                self._inventory_is_modified = True
1002
1038
            for f in from_paths:
1003
1039
                name_tail = splitpath(f)[-1]
1004
1040
                dest_path = pathjoin(to_name, name_tail)
1012
1048
                            ["rename rolled back"])
1013
1049
        except:
1014
1050
            # restore the inventory on error
1015
 
            self._set_inventory(orig_inv)
 
1051
            self._set_inventory(orig_inv, dirty=original_modified)
1016
1052
            raise
1017
1053
        self._write_inventory(inv)
1018
1054
        return result
1458
1494
        
1459
1495
    @needs_read_lock
1460
1496
    def read_working_inventory(self):
1461
 
        """Read the working inventory."""
 
1497
        """Read the working inventory.
 
1498
        
 
1499
        :raises errors.InventoryModified: When the current in memory
 
1500
            inventory has been modified, read_working_inventory will
 
1501
            fail.
 
1502
        """
 
1503
        # conceptually this should be an implementation detail of the tree. 
 
1504
        # XXX: Deprecate this.
1462
1505
        # ElementTree does its own conversion from UTF-8, so open in
1463
1506
        # binary.
 
1507
        if self._inventory_is_modified:
 
1508
            raise errors.InventoryModified(self)
1464
1509
        result = bzrlib.xml5.serializer_v5.read_inventory(
1465
1510
            self._control_files.get('inventory'))
1466
 
        self._set_inventory(result)
 
1511
        self._set_inventory(result, dirty=False)
1467
1512
        return result
1468
1513
 
1469
1514
    @needs_tree_write_lock
1573
1618
    @needs_tree_write_lock
1574
1619
    def set_root_id(self, file_id):
1575
1620
        """Set the root id for this tree."""
1576
 
        inv = self.read_working_inventory()
 
1621
        # for compatability 
 
1622
        if file_id is None:
 
1623
            symbol_versioning.warn(symbol_versioning.zero_twelve
 
1624
                % 'WorkingTree.set_root_id with fileid=None',
 
1625
                DeprecationWarning,
 
1626
                stacklevel=3)
 
1627
            file_id = ROOT_ID
 
1628
        inv = self._inventory
1577
1629
        orig_root_id = inv.root.file_id
 
1630
        # TODO: it might be nice to exit early if there was nothing
 
1631
        # to do, saving us from trigger a sync on unlock.
 
1632
        self._inventory_is_modified = True
 
1633
        # we preserve the root inventory entry object, but
 
1634
        # unlinkit from the byid index
1578
1635
        del inv._byid[inv.root.file_id]
1579
1636
        inv.root.file_id = file_id
 
1637
        # and link it into the index with the new changed id.
1580
1638
        inv._byid[inv.root.file_id] = inv.root
 
1639
        # and finally update all children to reference the new id.
 
1640
        # XXX: this should be safe to just look at the root.children
 
1641
        # list, not the WHOLE INVENTORY.
1581
1642
        for fid in inv:
1582
1643
            entry = inv[fid]
1583
1644
            if entry.parent_id == orig_root_id:
1584
1645
                entry.parent_id = inv.root.file_id
1585
 
        self._write_inventory(inv)
1586
1646
 
1587
1647
    def unlock(self):
1588
1648
        """See Branch.unlock.
1685
1745
    @needs_tree_write_lock
1686
1746
    def _write_inventory(self, inv):
1687
1747
        """Write inventory as the current inventory."""
1688
 
        sio = StringIO()
1689
 
        bzrlib.xml5.serializer_v5.write_inventory(inv, sio)
1690
 
        sio.seek(0)
1691
 
        self._control_files.put('inventory', sio)
1692
 
        self._set_inventory(inv)
1693
 
        mutter('wrote working inventory')
 
1748
        self._set_inventory(inv, dirty=True)
 
1749
        self.flush()
1694
1750
 
1695
1751
    def set_conflicts(self, arg):
1696
1752
        raise UnsupportedOperation(self.set_conflicts, self)
1747
1803
 
1748
1804
    def unlock(self):
1749
1805
        # we share control files:
1750
 
        if self._hashcache.needs_write and self._control_files._lock_count==3:
1751
 
            self._hashcache.write()
 
1806
        if self._control_files._lock_count == 3:
 
1807
            # _inventory_is_modified is always False during a read lock.
 
1808
            if self._inventory_is_modified:
 
1809
                self.flush()
 
1810
            if self._hashcache.needs_write:
 
1811
                self._hashcache.write()
1752
1812
        # reverse order of locking.
1753
1813
        try:
1754
1814
            return self._control_files.unlock()
1812
1872
        return ConflictList.from_stanzas(RioReader(confile))
1813
1873
 
1814
1874
    def unlock(self):
1815
 
        if self._hashcache.needs_write and self._control_files._lock_count==1:
1816
 
            self._hashcache.write()
 
1875
        if self._control_files._lock_count == 1:
 
1876
            # _inventory_is_modified is always False during a read lock.
 
1877
            if self._inventory_is_modified:
 
1878
                self.flush()
 
1879
            if self._hashcache.needs_write:
 
1880
                self._hashcache.write()
1817
1881
        # reverse order of locking.
1818
1882
        try:
1819
1883
            return self._control_files.unlock()
1965
2029
                         _internal=True,
1966
2030
                         _format=self,
1967
2031
                         _bzrdir=a_bzrdir)
1968
 
        wt._write_inventory(inv)
1969
2032
        wt.set_root_id(inv.root.file_id)
1970
2033
        basis_tree = branch.repository.revision_tree(revision)
1971
2034
        wt.set_parent_trees([(revision, basis_tree)])
2037
2100
        branch = a_bzrdir.open_branch()
2038
2101
        if revision_id is None:
2039
2102
            revision_id = branch.last_revision()
2040
 
        inv = Inventory() 
 
2103
        inv = Inventory()
2041
2104
        wt = WorkingTree3(a_bzrdir.root_transport.local_abspath('.'),
2042
2105
                         branch,
2043
2106
                         inv,
2047
2110
                         _control_files=control_files)
2048
2111
        wt.lock_tree_write()
2049
2112
        try:
2050
 
            wt._write_inventory(inv)
2051
2113
            wt.set_root_id(inv.root.file_id)
2052
2114
            basis_tree = branch.repository.revision_tree(revision_id)
2053
2115
            if revision_id == bzrlib.revision.NULL_REVISION:
2056
2118
                wt.set_parent_trees([(revision_id, basis_tree)])
2057
2119
            build_tree(basis_tree, wt)
2058
2120
        finally:
 
2121
            # unlock in this order so that the unlock-triggers-flush in
 
2122
            # WorkingTree is given a chance to fire.
 
2123
            control_files.unlock()
2059
2124
            wt.unlock()
2060
 
            control_files.unlock()
2061
2125
        return wt
2062
2126
 
2063
2127
    def __init__(self):