~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: Vincent Ladeuil
  • Date: 2012-02-14 17:22:37 UTC
  • mfrom: (6466 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120214172237-7dv7er3n4uy8d5m4
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
WorkingTree.open(dir).
23
23
"""
24
24
 
 
25
from __future__ import absolute_import
 
26
 
25
27
from cStringIO import StringIO
26
28
import os
27
29
import sys
31
33
import errno
32
34
import stat
33
35
 
34
 
import bzrlib
35
36
from bzrlib import (
36
37
    bzrdir,
37
38
    cache_utf8,
 
39
    config,
 
40
    conflicts as _mod_conflicts,
38
41
    debug,
39
42
    dirstate,
40
43
    errors,
 
44
    filters as _mod_filters,
41
45
    generate_ids,
42
46
    osutils,
43
47
    revision as _mod_revision,
46
50
    transform,
47
51
    views,
48
52
    )
49
 
import bzrlib.branch
50
 
import bzrlib.ui
51
53
""")
52
54
 
53
55
from bzrlib.decorators import needs_read_lock, needs_write_lock
54
 
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
55
56
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
56
57
from bzrlib.lock import LogicalLockResult
57
 
from bzrlib.mutabletree import needs_tree_write_lock
 
58
from bzrlib.lockable_files import LockableFiles
 
59
from bzrlib.lockdir import LockDir
 
60
from bzrlib.mutabletree import (
 
61
    MutableTree,
 
62
    needs_tree_write_lock,
 
63
    )
58
64
from bzrlib.osutils import (
59
65
    file_kind,
60
66
    isdir,
62
68
    realpath,
63
69
    safe_unicode,
64
70
    )
65
 
from bzrlib.trace import mutter
 
71
from bzrlib.symbol_versioning import (
 
72
    deprecated_in,
 
73
    deprecated_method,
 
74
    )
66
75
from bzrlib.transport.local import LocalTransport
67
 
from bzrlib.tree import InterTree
68
 
from bzrlib.tree import Tree
69
 
from bzrlib.workingtree import WorkingTree, WorkingTree3, WorkingTreeFormat3
70
 
 
71
 
 
72
 
class DirStateWorkingTree(WorkingTree3):
 
76
from bzrlib.tree import (
 
77
    InterTree,
 
78
    InventoryTree,
 
79
    )
 
80
from bzrlib.workingtree import (
 
81
    InventoryWorkingTree,
 
82
    WorkingTree,
 
83
    WorkingTreeFormatMetaDir,
 
84
    )
 
85
 
 
86
 
 
87
class DirStateWorkingTree(InventoryWorkingTree):
 
88
 
73
89
    def __init__(self, basedir,
74
90
                 branch,
75
91
                 _control_files=None,
85
101
        self._format = _format
86
102
        self.bzrdir = _bzrdir
87
103
        basedir = safe_unicode(basedir)
88
 
        mutter("opening working tree %r", basedir)
 
104
        trace.mutter("opening working tree %r", basedir)
89
105
        self._branch = branch
90
106
        self.basedir = realpath(basedir)
91
107
        # if branch is at our basedir and is a format 6 or less
125
141
            state.add(f, file_id, kind, None, '')
126
142
        self._make_dirty(reset_inventory=True)
127
143
 
 
144
    def _get_check_refs(self):
 
145
        """Return the references needed to perform a check of this tree."""
 
146
        return [('trees', self.last_revision())]
 
147
 
128
148
    def _make_dirty(self, reset_inventory):
129
149
        """Make the tree state dirty.
130
150
 
182
202
 
183
203
    def _comparison_data(self, entry, path):
184
204
        kind, executable, stat_value = \
185
 
            WorkingTree3._comparison_data(self, entry, path)
 
205
            WorkingTree._comparison_data(self, entry, path)
186
206
        # it looks like a plain directory, but it's really a reference -- see
187
207
        # also kind()
188
208
        if (self._repo_supports_tree_reference and kind == 'directory'
194
214
    def commit(self, message=None, revprops=None, *args, **kwargs):
195
215
        # mark the tree as dirty post commit - commit
196
216
        # can change the current versioned list by doing deletes.
197
 
        result = WorkingTree3.commit(self, message, revprops, *args, **kwargs)
 
217
        result = WorkingTree.commit(self, message, revprops, *args, **kwargs)
198
218
        self._make_dirty(reset_inventory=True)
199
219
        return result
200
220
 
219
239
        local_path = self.bzrdir.get_workingtree_transport(None
220
240
            ).local_abspath('dirstate')
221
241
        self._dirstate = dirstate.DirState.on_file(local_path,
222
 
            self._sha1_provider())
 
242
            self._sha1_provider(), self._worth_saving_limit())
223
243
        return self._dirstate
224
244
 
225
245
    def _sha1_provider(self):
234
254
        else:
235
255
            return None
236
256
 
 
257
    def _worth_saving_limit(self):
 
258
        """How many hash changes are ok before we must save the dirstate.
 
259
 
 
260
        :return: an integer. -1 means never save.
 
261
        """
 
262
        conf = self.get_config_stack()
 
263
        return conf.get('bzr.workingtree.worth_saving_limit')
 
264
 
237
265
    def filter_unversioned_files(self, paths):
238
266
        """Filter out paths that are versioned.
239
267
 
369
397
        state = self.current_dirstate()
370
398
        if stat_value is None:
371
399
            try:
372
 
                stat_value = os.lstat(file_abspath)
 
400
                stat_value = osutils.lstat(file_abspath)
373
401
            except OSError, e:
374
402
                if e.errno == errno.ENOENT:
375
403
                    return None
390
418
                return link_or_sha1
391
419
        return None
392
420
 
393
 
    def _get_inventory(self):
 
421
    def _get_root_inventory(self):
394
422
        """Get the inventory for the tree. This is only valid within a lock."""
395
423
        if 'evil' in debug.debug_flags:
396
424
            trace.mutter_callsite(2,
401
429
        self._generate_inventory()
402
430
        return self._inventory
403
431
 
 
432
    @deprecated_method(deprecated_in((2, 5, 0)))
 
433
    def _get_inventory(self):
 
434
        return self.root_inventory
 
435
 
404
436
    inventory = property(_get_inventory,
405
437
                         doc="Inventory of this Tree")
406
438
 
 
439
    root_inventory = property(_get_root_inventory,
 
440
        "Root inventory of this tree")
 
441
 
407
442
    @needs_read_lock
408
443
    def get_parent_ids(self):
409
444
        """See Tree.get_parent_ids.
456
491
            return False # Missing entries are not executable
457
492
        return entry[1][0][3] # Executable?
458
493
 
459
 
    if not osutils.supports_executable():
460
 
        def is_executable(self, file_id, path=None):
461
 
            """Test if a file is executable or not.
 
494
    def is_executable(self, file_id, path=None):
 
495
        """Test if a file is executable or not.
462
496
 
463
 
            Note: The caller is expected to take a read-lock before calling this.
464
 
            """
 
497
        Note: The caller is expected to take a read-lock before calling this.
 
498
        """
 
499
        if not self._supports_executable():
465
500
            entry = self._get_entry(file_id=file_id, path=path)
466
501
            if entry == (None, None):
467
502
                return False
468
503
            return entry[1][0][3]
469
 
 
470
 
        _is_executable_from_path_and_stat = \
471
 
            _is_executable_from_path_and_stat_from_basis
472
 
    else:
473
 
        def is_executable(self, file_id, path=None):
474
 
            """Test if a file is executable or not.
475
 
 
476
 
            Note: The caller is expected to take a read-lock before calling this.
477
 
            """
 
504
        else:
478
505
            self._must_be_locked()
479
506
            if not path:
480
507
                path = self.id2path(file_id)
481
 
            mode = os.lstat(self.abspath(path)).st_mode
 
508
            mode = osutils.lstat(self.abspath(path)).st_mode
482
509
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
483
510
 
484
511
    def all_file_ids(self):
664
691
 
665
692
        if self._inventory is not None:
666
693
            update_inventory = True
667
 
            inv = self.inventory
 
694
            inv = self.root_inventory
668
695
            to_dir_id = to_entry[0][2]
669
696
            to_dir_ie = inv[to_dir_id]
670
697
        else:
850
877
                rollback_rename()
851
878
                raise
852
879
            result.append((from_rel, to_rel))
853
 
            state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
 
880
            state._mark_modified()
854
881
            self._make_dirty(reset_inventory=False)
855
882
 
856
883
        return result
949
976
                    all_versioned = False
950
977
                    break
951
978
            if not all_versioned:
952
 
                raise errors.PathsNotVersionedError(paths)
 
979
                raise errors.PathsNotVersionedError(
 
980
                    [p.decode('utf-8') for p in paths])
953
981
        # -- remove redundancy in supplied paths to prevent over-scanning --
954
982
        search_paths = osutils.minimum_path_selection(paths)
955
983
        # sketch:
1004
1032
            found_dir_names = set(dir_name_id[:2] for dir_name_id in found)
1005
1033
            for dir_name in split_paths:
1006
1034
                if dir_name not in found_dir_names:
1007
 
                    raise errors.PathsNotVersionedError(paths)
 
1035
                    raise errors.PathsNotVersionedError(
 
1036
                        [p.decode('utf-8') for p in paths])
1008
1037
 
1009
1038
        for dir_name_id, trees_info in found.iteritems():
1010
1039
            for index in search_indexes:
1017
1046
 
1018
1047
        This is a meaningless operation for dirstate, but we obey it anyhow.
1019
1048
        """
1020
 
        return self.inventory
 
1049
        return self.root_inventory
1021
1050
 
1022
1051
    @needs_read_lock
1023
1052
    def revision_tree(self, revision_id):
1113
1142
                        _mod_revision.NULL_REVISION)))
1114
1143
                ghosts.append(rev_id)
1115
1144
            accepted_revisions.add(rev_id)
1116
 
        dirstate.set_parent_trees(real_trees, ghosts=ghosts)
 
1145
        updated = False
 
1146
        if (len(real_trees) == 1
 
1147
            and not ghosts
 
1148
            and self.branch.repository._format.fast_deltas
 
1149
            and isinstance(real_trees[0][1],
 
1150
                revisiontree.InventoryRevisionTree)
 
1151
            and self.get_parent_ids()):
 
1152
            rev_id, rev_tree = real_trees[0]
 
1153
            basis_id = self.get_parent_ids()[0]
 
1154
            # There are times when basis_tree won't be in
 
1155
            # self.branch.repository, (switch, for example)
 
1156
            try:
 
1157
                basis_tree = self.branch.repository.revision_tree(basis_id)
 
1158
            except errors.NoSuchRevision:
 
1159
                # Fall back to the set_parent_trees(), since we can't use
 
1160
                # _make_delta if we can't get the RevisionTree
 
1161
                pass
 
1162
            else:
 
1163
                delta = rev_tree.root_inventory._make_delta(
 
1164
                    basis_tree.root_inventory)
 
1165
                dirstate.update_basis_by_delta(delta, rev_id)
 
1166
                updated = True
 
1167
        if not updated:
 
1168
            dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1117
1169
        self._make_dirty(reset_inventory=False)
1118
1170
 
1119
1171
    def _set_root_id(self, file_id):
1139
1191
 
1140
1192
    def unlock(self):
1141
1193
        """Unlock in format 4 trees needs to write the entire dirstate."""
1142
 
        # do non-implementation specific cleanup
1143
 
        self._cleanup()
1144
 
 
1145
1194
        if self._control_files._lock_count == 1:
 
1195
            # do non-implementation specific cleanup
 
1196
            self._cleanup()
 
1197
 
1146
1198
            # eventually we should do signature checking during read locks for
1147
1199
            # dirstate updates.
1148
1200
            if self._control_files._lock_mode == 'w':
1254
1306
    def rename_one(self, from_rel, to_rel, after=False):
1255
1307
        """See WorkingTree.rename_one"""
1256
1308
        self.flush()
1257
 
        WorkingTree.rename_one(self, from_rel, to_rel, after)
 
1309
        super(DirStateWorkingTree, self).rename_one(from_rel, to_rel, after)
1258
1310
 
1259
1311
    @needs_tree_write_lock
1260
1312
    def apply_inventory_delta(self, changes):
1286
1338
        # being created.
1287
1339
        self._inventory = None
1288
1340
        # generate a delta,
1289
 
        delta = inv._make_delta(self.inventory)
 
1341
        delta = inv._make_delta(self.root_inventory)
1290
1342
        # and apply it.
1291
1343
        self.apply_inventory_delta(delta)
1292
1344
        if had_inventory:
1312
1364
            base_tree = trees[0][1]
1313
1365
        state = self.current_dirstate()
1314
1366
        # We don't support ghosts yet
1315
 
        state.set_state_from_scratch(base_tree.inventory, trees, [])
 
1367
        state.set_state_from_scratch(base_tree.root_inventory, trees, [])
1316
1368
 
1317
1369
 
1318
1370
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1324
1376
        """See dirstate.SHA1Provider.sha1()."""
1325
1377
        filters = self.tree._content_filter_stack(
1326
1378
            self.tree.relpath(osutils.safe_unicode(abspath)))
1327
 
        return internal_size_sha_file_byname(abspath, filters)[1]
 
1379
        return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
1328
1380
 
1329
1381
    def stat_and_sha1(self, abspath):
1330
1382
        """See dirstate.SHA1Provider.stat_and_sha1()."""
1334
1386
        try:
1335
1387
            statvalue = os.fstat(file_obj.fileno())
1336
1388
            if filters:
1337
 
                file_obj = filtered_input_file(file_obj, filters)
 
1389
                file_obj = _mod_filters.filtered_input_file(file_obj, filters)
1338
1390
            sha1 = osutils.size_sha_file(file_obj)[1]
1339
1391
        finally:
1340
1392
            file_obj.close()
1370
1422
class WorkingTree4(DirStateWorkingTree):
1371
1423
    """This is the Format 4 working tree.
1372
1424
 
1373
 
    This differs from WorkingTree3 by:
 
1425
    This differs from WorkingTree by:
1374
1426
     - Having a consolidated internal dirstate, stored in a
1375
1427
       randomly-accessible sorted file on disk.
1376
1428
     - Not having a regular inventory attribute.  One can be synthesized
1404
1456
        return views.PathBasedViews(self)
1405
1457
 
1406
1458
 
1407
 
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
 
1459
class DirStateWorkingTreeFormat(WorkingTreeFormatMetaDir):
1408
1460
 
1409
1461
    missing_parent_conflicts = True
1410
1462
 
 
1463
    supports_versioned_directories = True
 
1464
 
 
1465
    _lock_class = LockDir
 
1466
    _lock_file_name = 'lock'
 
1467
 
 
1468
    def _open_control_files(self, a_bzrdir):
 
1469
        transport = a_bzrdir.get_workingtree_transport(None)
 
1470
        return LockableFiles(transport, self._lock_file_name,
 
1471
                             self._lock_class)
 
1472
 
1411
1473
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1412
1474
                   accelerator_tree=None, hardlink=False):
1413
1475
        """See WorkingTreeFormat.initialize().
1414
1476
 
1415
1477
        :param revision_id: allows creating a working tree at a different
1416
 
        revision than the branch is at.
 
1478
            revision than the branch is at.
1417
1479
        :param accelerator_tree: A tree which can be used for retrieving file
1418
1480
            contents more quickly than the revision tree, i.e. a workingtree.
1419
1481
            The revision tree will be used for cases where accelerator_tree's
1430
1492
        control_files = self._open_control_files(a_bzrdir)
1431
1493
        control_files.create_lock()
1432
1494
        control_files.lock_write()
1433
 
        transport.put_bytes('format', self.get_format_string(),
 
1495
        transport.put_bytes('format', self.as_string(),
1434
1496
            mode=a_bzrdir._get_file_mode())
1435
1497
        if from_branch is not None:
1436
1498
            branch = from_branch
1496
1558
                transform.build_tree(basis, wt, accelerator_tree,
1497
1559
                                     hardlink=hardlink,
1498
1560
                                     delta_from_tree=delta_from_tree)
 
1561
                for hook in MutableTree.hooks['post_build_tree']:
 
1562
                    hook(wt)
1499
1563
            finally:
1500
1564
                basis.unlock()
1501
1565
        finally:
1512
1576
        :param wt: the WorkingTree object
1513
1577
        """
1514
1578
 
 
1579
    def open(self, a_bzrdir, _found=False):
 
1580
        """Return the WorkingTree object for a_bzrdir
 
1581
 
 
1582
        _found is a private parameter, do not use it. It is used to indicate
 
1583
               if format probing has already been done.
 
1584
        """
 
1585
        if not _found:
 
1586
            # we are being called directly and must probe.
 
1587
            raise NotImplementedError
 
1588
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
1589
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
1590
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
1591
        return wt
 
1592
 
1515
1593
    def _open(self, a_bzrdir, control_files):
1516
1594
        """Open the tree itself.
1517
1595
 
1531
1609
        """Overrideable method to get a bzrdir for testing."""
1532
1610
        # please test against something that will let us do tree references
1533
1611
        return bzrdir.format_registry.make_bzrdir(
1534
 
            'dirstate-with-subtree')
 
1612
            'development-subtree')
1535
1613
 
1536
1614
    _matchingbzrdir = property(__get_matchingbzrdir)
1537
1615
 
1542
1620
    This format:
1543
1621
        - exists within a metadir controlling .bzr
1544
1622
        - includes an explicit version marker for the workingtree control
1545
 
          files, separate from the BzrDir format
 
1623
          files, separate from the ControlDir format
1546
1624
        - modifies the hash cache format
1547
1625
        - is new in bzr 0.15
1548
1626
        - uses a LockDir to guard access to it.
1552
1630
 
1553
1631
    _tree_class = WorkingTree4
1554
1632
 
1555
 
    def get_format_string(self):
 
1633
    @classmethod
 
1634
    def get_format_string(cls):
1556
1635
        """See WorkingTreeFormat.get_format_string()."""
1557
1636
        return "Bazaar Working Tree Format 4 (bzr 0.15)\n"
1558
1637
 
1569
1648
 
1570
1649
    _tree_class = WorkingTree5
1571
1650
 
1572
 
    def get_format_string(self):
 
1651
    @classmethod
 
1652
    def get_format_string(cls):
1573
1653
        """See WorkingTreeFormat.get_format_string()."""
1574
1654
        return "Bazaar Working Tree Format 5 (bzr 1.11)\n"
1575
1655
 
1589
1669
 
1590
1670
    _tree_class = WorkingTree6
1591
1671
 
1592
 
    def get_format_string(self):
 
1672
    @classmethod
 
1673
    def get_format_string(cls):
1593
1674
        """See WorkingTreeFormat.get_format_string()."""
1594
1675
        return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1595
1676
 
1608
1689
        return True
1609
1690
 
1610
1691
 
1611
 
class DirStateRevisionTree(Tree):
 
1692
class DirStateRevisionTree(InventoryTree):
1612
1693
    """A revision tree pulling the inventory from a dirstate.
1613
1694
    
1614
1695
    Note that this is one of the historical (ie revision) trees cached in the
1633
1714
    def annotate_iter(self, file_id,
1634
1715
                      default_revision=_mod_revision.CURRENT_REVISION):
1635
1716
        """See Tree.annotate_iter"""
1636
 
        text_key = (file_id, self.inventory[file_id].revision)
 
1717
        text_key = (file_id, self.get_file_revision(file_id))
1637
1718
        annotations = self._repository.texts.annotate(text_key)
1638
1719
        return [(key[-1], line) for (key, line) in annotations]
1639
1720
 
1640
 
    def _get_ancestors(self, default_revision):
1641
 
        return set(self._repository.get_ancestry(self._revision_id,
1642
 
                                                 topo_sorted=False))
1643
1721
    def _comparison_data(self, entry, path):
1644
1722
        """See Tree._comparison_data."""
1645
1723
        if entry is None:
1786
1864
        # Make sure the file exists
1787
1865
        entry = self._get_entry(file_id, path=path)
1788
1866
        if entry == (None, None): # do we raise?
1789
 
            return None
 
1867
            raise errors.NoSuchId(self, file_id)
1790
1868
        parent_index = self._get_parent_index()
1791
1869
        last_changed_revision = entry[1][parent_index][4]
1792
1870
        try:
1803
1881
            return parent_details[1]
1804
1882
        return None
1805
1883
 
 
1884
    @needs_read_lock
 
1885
    def get_file_revision(self, file_id):
 
1886
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1887
        return inv[inv_file_id].revision
 
1888
 
1806
1889
    def get_file(self, file_id, path=None):
1807
1890
        return StringIO(self.get_file_text(file_id))
1808
1891
 
1809
1892
    def get_file_size(self, file_id):
1810
1893
        """See Tree.get_file_size"""
1811
 
        return self.inventory[file_id].text_size
 
1894
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1895
        return inv[inv_file_id].text_size
1812
1896
 
1813
1897
    def get_file_text(self, file_id, path=None):
1814
1898
        _, content = list(self.iter_files_bytes([(file_id, None)]))[0]
1815
1899
        return ''.join(content)
1816
1900
 
1817
1901
    def get_reference_revision(self, file_id, path=None):
1818
 
        return self.inventory[file_id].reference_revision
 
1902
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1903
        return inv[inv_file_id].reference_revision
1819
1904
 
1820
1905
    def iter_files_bytes(self, desired_files):
1821
1906
        """See Tree.iter_files_bytes.
1831
1916
                                       identifier))
1832
1917
        return self._repository.iter_files_bytes(repo_desired_files)
1833
1918
 
1834
 
    def get_symlink_target(self, file_id):
 
1919
    def get_symlink_target(self, file_id, path=None):
1835
1920
        entry = self._get_entry(file_id=file_id)
1836
1921
        parent_index = self._get_parent_index()
1837
1922
        if entry[1][parent_index][0] != 'l':
1845
1930
        """Return the revision id for this tree."""
1846
1931
        return self._revision_id
1847
1932
 
1848
 
    def _get_inventory(self):
 
1933
    def _get_root_inventory(self):
1849
1934
        if self._inventory is not None:
1850
1935
            return self._inventory
1851
1936
        self._must_be_locked()
1852
1937
        self._generate_inventory()
1853
1938
        return self._inventory
1854
1939
 
 
1940
    root_inventory = property(_get_root_inventory,
 
1941
                         doc="Inventory of this Tree")
 
1942
 
 
1943
    @deprecated_method(deprecated_in((2, 5, 0)))
 
1944
    def _get_inventory(self):
 
1945
        return self.root_inventory
 
1946
 
1855
1947
    inventory = property(_get_inventory,
1856
1948
                         doc="Inventory of this Tree")
1857
1949
 
1875
1967
 
1876
1968
    def path_content_summary(self, path):
1877
1969
        """See Tree.path_content_summary."""
1878
 
        id = self.inventory.path2id(path)
1879
 
        if id is None:
 
1970
        inv, inv_file_id = self._path2inv_file_id(path)
 
1971
        if inv_file_id is None:
1880
1972
            return ('missing', None, None, None)
1881
 
        entry = self._inventory[id]
 
1973
        entry = inv[inv_file_id]
1882
1974
        kind = entry.kind
1883
1975
        if kind == 'file':
1884
1976
            return (kind, entry.text_size, entry.executable, entry.text_sha1)
1888
1980
            return (kind, None, None, None)
1889
1981
 
1890
1982
    def is_executable(self, file_id, path=None):
1891
 
        ie = self.inventory[file_id]
 
1983
        inv, inv_file_id = self._unpack_file_id(file_id)
 
1984
        ie = inv[inv_file_id]
1892
1985
        if ie.kind != "file":
1893
1986
            return False
1894
1987
        return ie.executable
1899
1992
    def list_files(self, include_root=False, from_dir=None, recursive=True):
1900
1993
        # We use a standard implementation, because DirStateRevisionTree is
1901
1994
        # dealing with one of the parents of the current state
1902
 
        inv = self._get_inventory()
1903
1995
        if from_dir is None:
 
1996
            inv = self.root_inventory
1904
1997
            from_dir_id = None
1905
1998
        else:
1906
 
            from_dir_id = inv.path2id(from_dir)
 
1999
            inv, from_dir_id = self._path2inv_file_id(from_dir)
1907
2000
            if from_dir_id is None:
1908
2001
                # Directory not versioned
1909
2002
                return
 
2003
        # FIXME: Support nested trees
1910
2004
        entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
1911
2005
        if inv.root is not None and not include_root and from_dir is None:
1912
2006
            entries.next()
1962
2056
        # So for now, we just build up the parent inventory, and extract
1963
2057
        # it the same way RevisionTree does.
1964
2058
        _directory = 'directory'
1965
 
        inv = self._get_inventory()
 
2059
        inv = self._get_root_inventory()
1966
2060
        top_id = inv.path2id(prefix)
1967
2061
        if top_id is None:
1968
2062
            pending = []
2009
2103
    def make_source_parent_tree(source, target):
2010
2104
        """Change the source tree into a parent of the target."""
2011
2105
        revid = source.commit('record tree')
2012
 
        target.branch.repository.fetch(source.branch.repository, revid)
 
2106
        target.branch.fetch(source.branch, revid)
2013
2107
        target.set_parent_ids([revid])
2014
2108
        return target.basis_tree(), target
2015
2109
 
2107
2201
                path_entries = state._entries_for_path(path)
2108
2202
                if not path_entries:
2109
2203
                    # this specified path is not present at all: error
2110
 
                    not_versioned.append(path)
 
2204
                    not_versioned.append(path.decode('utf-8'))
2111
2205
                    continue
2112
2206
                found_versioned = False
2113
2207
                # for each id at this path
2121
2215
                if not found_versioned:
2122
2216
                    # none of the indexes was not 'absent' at all ids for this
2123
2217
                    # path.
2124
 
                    not_versioned.append(path)
 
2218
                    not_versioned.append(path.decode('utf-8'))
2125
2219
            if len(not_versioned) > 0:
2126
2220
                raise errors.PathsNotVersionedError(not_versioned)
2127
2221
        # -- remove redundancy in supplied specific_files to prevent over-scanning --
2194
2288
    def update_format(self, tree):
2195
2289
        """Change the format marker."""
2196
2290
        tree._transport.put_bytes('format',
2197
 
            self.target_format.get_format_string(),
 
2291
            self.target_format.as_string(),
2198
2292
            mode=tree.bzrdir._get_file_mode())
2199
2293
 
2200
2294
 
2217
2311
    def update_format(self, tree):
2218
2312
        """Change the format marker."""
2219
2313
        tree._transport.put_bytes('format',
2220
 
            self.target_format.get_format_string(),
 
2314
            self.target_format.as_string(),
2221
2315
            mode=tree.bzrdir._get_file_mode())
2222
2316
 
2223
2317
 
2246
2340
    def update_format(self, tree):
2247
2341
        """Change the format marker."""
2248
2342
        tree._transport.put_bytes('format',
2249
 
            self.target_format.get_format_string(),
 
2343
            self.target_format.as_string(),
2250
2344
            mode=tree.bzrdir._get_file_mode())