~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-30 12:52:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6418.
  • Revision ID: jelmer@samba.org-20111230125254-igy1abnixsvulfqd
Simplify code a bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2007-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
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
 
import bzrlib.mutabletree
 
57
from bzrlib.lock import LogicalLockResult
 
58
from bzrlib.lockable_files import LockableFiles
 
59
from bzrlib.lockdir import LockDir
57
60
from bzrlib.mutabletree import needs_tree_write_lock
58
61
from bzrlib.osutils import (
59
62
    file_kind,
62
65
    realpath,
63
66
    safe_unicode,
64
67
    )
65
 
from bzrlib.trace import mutter
66
68
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):
 
69
from bzrlib.tree import (
 
70
    InterTree,
 
71
    InventoryTree,
 
72
    )
 
73
from bzrlib.workingtree import (
 
74
    InventoryWorkingTree,
 
75
    WorkingTree,
 
76
    WorkingTreeFormatMetaDir,
 
77
    )
 
78
 
 
79
 
 
80
class DirStateWorkingTree(InventoryWorkingTree):
 
81
 
73
82
    def __init__(self, basedir,
74
83
                 branch,
75
84
                 _control_files=None,
85
94
        self._format = _format
86
95
        self.bzrdir = _bzrdir
87
96
        basedir = safe_unicode(basedir)
88
 
        mutter("opening working tree %r", basedir)
 
97
        trace.mutter("opening working tree %r", basedir)
89
98
        self._branch = branch
90
99
        self.basedir = realpath(basedir)
91
100
        # if branch is at our basedir and is a format 6 or less
125
134
            state.add(f, file_id, kind, None, '')
126
135
        self._make_dirty(reset_inventory=True)
127
136
 
 
137
    def _get_check_refs(self):
 
138
        """Return the references needed to perform a check of this tree."""
 
139
        return [('trees', self.last_revision())]
 
140
 
128
141
    def _make_dirty(self, reset_inventory):
129
142
        """Make the tree state dirty.
130
143
 
182
195
 
183
196
    def _comparison_data(self, entry, path):
184
197
        kind, executable, stat_value = \
185
 
            WorkingTree3._comparison_data(self, entry, path)
 
198
            WorkingTree._comparison_data(self, entry, path)
186
199
        # it looks like a plain directory, but it's really a reference -- see
187
200
        # also kind()
188
201
        if (self._repo_supports_tree_reference and kind == 'directory'
194
207
    def commit(self, message=None, revprops=None, *args, **kwargs):
195
208
        # mark the tree as dirty post commit - commit
196
209
        # can change the current versioned list by doing deletes.
197
 
        result = WorkingTree3.commit(self, message, revprops, *args, **kwargs)
 
210
        result = WorkingTree.commit(self, message, revprops, *args, **kwargs)
198
211
        self._make_dirty(reset_inventory=True)
199
212
        return result
200
213
 
219
232
        local_path = self.bzrdir.get_workingtree_transport(None
220
233
            ).local_abspath('dirstate')
221
234
        self._dirstate = dirstate.DirState.on_file(local_path,
222
 
            self._sha1_provider())
 
235
            self._sha1_provider(), self._worth_saving_limit())
223
236
        return self._dirstate
224
237
 
225
238
    def _sha1_provider(self):
234
247
        else:
235
248
            return None
236
249
 
 
250
    def _worth_saving_limit(self):
 
251
        """How many hash changes are ok before we must save the dirstate.
 
252
 
 
253
        :return: an integer. -1 means never save.
 
254
        """
 
255
        # FIXME: We want a WorkingTreeStack here -- vila 20110812
 
256
        conf = config.BranchStack(self.branch)
 
257
        return conf.get('bzr.workingtree.worth_saving_limit')
 
258
 
237
259
    def filter_unversioned_files(self, paths):
238
260
        """Filter out paths that are versioned.
239
261
 
369
391
        state = self.current_dirstate()
370
392
        if stat_value is None:
371
393
            try:
372
 
                stat_value = os.lstat(file_abspath)
 
394
                stat_value = osutils.lstat(file_abspath)
373
395
            except OSError, e:
374
396
                if e.errno == errno.ENOENT:
375
397
                    return None
456
478
            return False # Missing entries are not executable
457
479
        return entry[1][0][3] # Executable?
458
480
 
459
 
    if not osutils.supports_executable():
460
 
        def is_executable(self, file_id, path=None):
461
 
            """Test if a file is executable or not.
 
481
    def is_executable(self, file_id, path=None):
 
482
        """Test if a file is executable or not.
462
483
 
463
 
            Note: The caller is expected to take a read-lock before calling this.
464
 
            """
 
484
        Note: The caller is expected to take a read-lock before calling this.
 
485
        """
 
486
        if not self._supports_executable():
465
487
            entry = self._get_entry(file_id=file_id, path=path)
466
488
            if entry == (None, None):
467
489
                return False
468
490
            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
 
            """
 
491
        else:
478
492
            self._must_be_locked()
479
493
            if not path:
480
494
                path = self.id2path(file_id)
481
 
            mode = os.lstat(self.abspath(path)).st_mode
 
495
            mode = osutils.lstat(self.abspath(path)).st_mode
482
496
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
483
497
 
484
498
    def all_file_ids(self):
568
582
            return _mod_revision.NULL_REVISION
569
583
 
570
584
    def lock_read(self):
571
 
        """See Branch.lock_read, and WorkingTree.unlock."""
 
585
        """See Branch.lock_read, and WorkingTree.unlock.
 
586
 
 
587
        :return: A bzrlib.lock.LogicalLockResult.
 
588
        """
572
589
        self.branch.lock_read()
573
590
        try:
574
591
            self._control_files.lock_read()
587
604
        except:
588
605
            self.branch.unlock()
589
606
            raise
 
607
        return LogicalLockResult(self.unlock)
590
608
 
591
609
    def _lock_self_write(self):
592
610
        """This should be called after the branch is locked."""
607
625
        except:
608
626
            self.branch.unlock()
609
627
            raise
 
628
        return LogicalLockResult(self.unlock)
610
629
 
611
630
    def lock_tree_write(self):
612
 
        """See MutableTree.lock_tree_write, and WorkingTree.unlock."""
 
631
        """See MutableTree.lock_tree_write, and WorkingTree.unlock.
 
632
 
 
633
        :return: A bzrlib.lock.LogicalLockResult.
 
634
        """
613
635
        self.branch.lock_read()
614
 
        self._lock_self_write()
 
636
        return self._lock_self_write()
615
637
 
616
638
    def lock_write(self):
617
 
        """See MutableTree.lock_write, and WorkingTree.unlock."""
 
639
        """See MutableTree.lock_write, and WorkingTree.unlock.
 
640
 
 
641
        :return: A bzrlib.lock.LogicalLockResult.
 
642
        """
618
643
        self.branch.lock_write()
619
 
        self._lock_self_write()
 
644
        return self._lock_self_write()
620
645
 
621
646
    @needs_tree_write_lock
622
647
    def move(self, from_paths, to_dir, after=False):
839
864
                rollback_rename()
840
865
                raise
841
866
            result.append((from_rel, to_rel))
842
 
            state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
 
867
            state._mark_modified()
843
868
            self._make_dirty(reset_inventory=False)
844
869
 
845
870
        return result
938
963
                    all_versioned = False
939
964
                    break
940
965
            if not all_versioned:
941
 
                raise errors.PathsNotVersionedError(paths)
 
966
                raise errors.PathsNotVersionedError(
 
967
                    [p.decode('utf-8') for p in paths])
942
968
        # -- remove redundancy in supplied paths to prevent over-scanning --
943
969
        search_paths = osutils.minimum_path_selection(paths)
944
970
        # sketch:
993
1019
            found_dir_names = set(dir_name_id[:2] for dir_name_id in found)
994
1020
            for dir_name in split_paths:
995
1021
                if dir_name not in found_dir_names:
996
 
                    raise errors.PathsNotVersionedError(paths)
 
1022
                    raise errors.PathsNotVersionedError(
 
1023
                        [p.decode('utf-8') for p in paths])
997
1024
 
998
1025
        for dir_name_id, trees_info in found.iteritems():
999
1026
            for index in search_indexes:
1102
1129
                        _mod_revision.NULL_REVISION)))
1103
1130
                ghosts.append(rev_id)
1104
1131
            accepted_revisions.add(rev_id)
1105
 
        dirstate.set_parent_trees(real_trees, ghosts=ghosts)
 
1132
        updated = False
 
1133
        if (len(real_trees) == 1
 
1134
            and not ghosts
 
1135
            and self.branch.repository._format.fast_deltas
 
1136
            and isinstance(real_trees[0][1],
 
1137
                revisiontree.InventoryRevisionTree)
 
1138
            and self.get_parent_ids()):
 
1139
            rev_id, rev_tree = real_trees[0]
 
1140
            basis_id = self.get_parent_ids()[0]
 
1141
            # There are times when basis_tree won't be in
 
1142
            # self.branch.repository, (switch, for example)
 
1143
            try:
 
1144
                basis_tree = self.branch.repository.revision_tree(basis_id)
 
1145
            except errors.NoSuchRevision:
 
1146
                # Fall back to the set_parent_trees(), since we can't use
 
1147
                # _make_delta if we can't get the RevisionTree
 
1148
                pass
 
1149
            else:
 
1150
                delta = rev_tree.inventory._make_delta(basis_tree.inventory)
 
1151
                dirstate.update_basis_by_delta(delta, rev_id)
 
1152
                updated = True
 
1153
        if not updated:
 
1154
            dirstate.set_parent_trees(real_trees, ghosts=ghosts)
1106
1155
        self._make_dirty(reset_inventory=False)
1107
1156
 
1108
1157
    def _set_root_id(self, file_id):
1128
1177
 
1129
1178
    def unlock(self):
1130
1179
        """Unlock in format 4 trees needs to write the entire dirstate."""
1131
 
        # do non-implementation specific cleanup
1132
 
        self._cleanup()
1133
 
 
1134
1180
        if self._control_files._lock_count == 1:
 
1181
            # do non-implementation specific cleanup
 
1182
            self._cleanup()
 
1183
 
1135
1184
            # eventually we should do signature checking during read locks for
1136
1185
            # dirstate updates.
1137
1186
            if self._control_files._lock_mode == 'w':
1236
1285
        # have to change the legacy inventory too.
1237
1286
        if self._inventory is not None:
1238
1287
            for file_id in file_ids:
1239
 
                self._inventory.remove_recursive_id(file_id)
 
1288
                if self._inventory.has_id(file_id):
 
1289
                    self._inventory.remove_recursive_id(file_id)
1240
1290
 
1241
1291
    @needs_tree_write_lock
1242
1292
    def rename_one(self, from_rel, to_rel, after=False):
1243
1293
        """See WorkingTree.rename_one"""
1244
1294
        self.flush()
1245
 
        WorkingTree.rename_one(self, from_rel, to_rel, after)
 
1295
        super(DirStateWorkingTree, self).rename_one(from_rel, to_rel, after)
1246
1296
 
1247
1297
    @needs_tree_write_lock
1248
1298
    def apply_inventory_delta(self, changes):
1281
1331
            self._inventory = inv
1282
1332
        self.flush()
1283
1333
 
 
1334
    @needs_tree_write_lock
 
1335
    def reset_state(self, revision_ids=None):
 
1336
        """Reset the state of the working tree.
 
1337
 
 
1338
        This does a hard-reset to a last-known-good state. This is a way to
 
1339
        fix if something got corrupted (like the .bzr/checkout/dirstate file)
 
1340
        """
 
1341
        if revision_ids is None:
 
1342
            revision_ids = self.get_parent_ids()
 
1343
        if not revision_ids:
 
1344
            base_tree = self.branch.repository.revision_tree(
 
1345
                _mod_revision.NULL_REVISION)
 
1346
            trees = []
 
1347
        else:
 
1348
            trees = zip(revision_ids,
 
1349
                        self.branch.repository.revision_trees(revision_ids))
 
1350
            base_tree = trees[0][1]
 
1351
        state = self.current_dirstate()
 
1352
        # We don't support ghosts yet
 
1353
        state.set_state_from_scratch(base_tree.inventory, trees, [])
 
1354
 
1284
1355
 
1285
1356
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1286
1357
 
1291
1362
        """See dirstate.SHA1Provider.sha1()."""
1292
1363
        filters = self.tree._content_filter_stack(
1293
1364
            self.tree.relpath(osutils.safe_unicode(abspath)))
1294
 
        return internal_size_sha_file_byname(abspath, filters)[1]
 
1365
        return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
1295
1366
 
1296
1367
    def stat_and_sha1(self, abspath):
1297
1368
        """See dirstate.SHA1Provider.stat_and_sha1()."""
1301
1372
        try:
1302
1373
            statvalue = os.fstat(file_obj.fileno())
1303
1374
            if filters:
1304
 
                file_obj = filtered_input_file(file_obj, filters)
 
1375
                file_obj = _mod_filters.filtered_input_file(file_obj, filters)
1305
1376
            sha1 = osutils.size_sha_file(file_obj)[1]
1306
1377
        finally:
1307
1378
            file_obj.close()
1318
1389
    def _file_content_summary(self, path, stat_result):
1319
1390
        # This is to support the somewhat obsolete path_content_summary method
1320
1391
        # with content filtering: see
1321
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/415508>.
 
1392
        # <https://bugs.launchpad.net/bzr/+bug/415508>.
1322
1393
        #
1323
1394
        # If the dirstate cache is up to date and knows the hash and size,
1324
1395
        # return that.
1337
1408
class WorkingTree4(DirStateWorkingTree):
1338
1409
    """This is the Format 4 working tree.
1339
1410
 
1340
 
    This differs from WorkingTree3 by:
 
1411
    This differs from WorkingTree by:
1341
1412
     - Having a consolidated internal dirstate, stored in a
1342
1413
       randomly-accessible sorted file on disk.
1343
1414
     - Not having a regular inventory attribute.  One can be synthesized
1371
1442
        return views.PathBasedViews(self)
1372
1443
 
1373
1444
 
1374
 
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
 
1445
class DirStateWorkingTreeFormat(WorkingTreeFormatMetaDir):
 
1446
 
 
1447
    missing_parent_conflicts = True
 
1448
 
 
1449
    supports_versioned_directories = True
 
1450
 
 
1451
    _lock_class = LockDir
 
1452
    _lock_file_name = 'lock'
 
1453
 
 
1454
    def _open_control_files(self, a_bzrdir):
 
1455
        transport = a_bzrdir.get_workingtree_transport(None)
 
1456
        return LockableFiles(transport, self._lock_file_name,
 
1457
                             self._lock_class)
 
1458
 
1375
1459
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1376
1460
                   accelerator_tree=None, hardlink=False):
1377
1461
        """See WorkingTreeFormat.initialize().
1378
1462
 
1379
1463
        :param revision_id: allows creating a working tree at a different
1380
 
        revision than the branch is at.
 
1464
            revision than the branch is at.
1381
1465
        :param accelerator_tree: A tree which can be used for retrieving file
1382
1466
            contents more quickly than the revision tree, i.e. a workingtree.
1383
1467
            The revision tree will be used for cases where accelerator_tree's
1394
1478
        control_files = self._open_control_files(a_bzrdir)
1395
1479
        control_files.create_lock()
1396
1480
        control_files.lock_write()
1397
 
        transport.put_bytes('format', self.get_format_string(),
 
1481
        transport.put_bytes('format', self.as_string(),
1398
1482
            mode=a_bzrdir._get_file_mode())
1399
1483
        if from_branch is not None:
1400
1484
            branch = from_branch
1476
1560
        :param wt: the WorkingTree object
1477
1561
        """
1478
1562
 
 
1563
    def open(self, a_bzrdir, _found=False):
 
1564
        """Return the WorkingTree object for a_bzrdir
 
1565
 
 
1566
        _found is a private parameter, do not use it. It is used to indicate
 
1567
               if format probing has already been done.
 
1568
        """
 
1569
        if not _found:
 
1570
            # we are being called directly and must probe.
 
1571
            raise NotImplementedError
 
1572
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
1573
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
1574
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
1575
        return wt
 
1576
 
1479
1577
    def _open(self, a_bzrdir, control_files):
1480
1578
        """Open the tree itself.
1481
1579
 
1506
1604
    This format:
1507
1605
        - exists within a metadir controlling .bzr
1508
1606
        - includes an explicit version marker for the workingtree control
1509
 
          files, separate from the BzrDir format
 
1607
          files, separate from the ControlDir format
1510
1608
        - modifies the hash cache format
1511
1609
        - is new in bzr 0.15
1512
1610
        - uses a LockDir to guard access to it.
1516
1614
 
1517
1615
    _tree_class = WorkingTree4
1518
1616
 
1519
 
    def get_format_string(self):
 
1617
    @classmethod
 
1618
    def get_format_string(cls):
1520
1619
        """See WorkingTreeFormat.get_format_string()."""
1521
1620
        return "Bazaar Working Tree Format 4 (bzr 0.15)\n"
1522
1621
 
1533
1632
 
1534
1633
    _tree_class = WorkingTree5
1535
1634
 
1536
 
    def get_format_string(self):
 
1635
    @classmethod
 
1636
    def get_format_string(cls):
1537
1637
        """See WorkingTreeFormat.get_format_string()."""
1538
1638
        return "Bazaar Working Tree Format 5 (bzr 1.11)\n"
1539
1639
 
1553
1653
 
1554
1654
    _tree_class = WorkingTree6
1555
1655
 
1556
 
    def get_format_string(self):
 
1656
    @classmethod
 
1657
    def get_format_string(cls):
1557
1658
        """See WorkingTreeFormat.get_format_string()."""
1558
1659
        return "Bazaar Working Tree Format 6 (bzr 1.14)\n"
1559
1660
 
1572
1673
        return True
1573
1674
 
1574
1675
 
1575
 
class DirStateRevisionTree(Tree):
 
1676
class DirStateRevisionTree(InventoryTree):
1576
1677
    """A revision tree pulling the inventory from a dirstate.
1577
1678
    
1578
1679
    Note that this is one of the historical (ie revision) trees cached in the
1597
1698
    def annotate_iter(self, file_id,
1598
1699
                      default_revision=_mod_revision.CURRENT_REVISION):
1599
1700
        """See Tree.annotate_iter"""
1600
 
        text_key = (file_id, self.inventory[file_id].revision)
 
1701
        text_key = (file_id, self.get_file_revision(file_id))
1601
1702
        annotations = self._repository.texts.annotate(text_key)
1602
1703
        return [(key[-1], line) for (key, line) in annotations]
1603
1704
 
1604
 
    def _get_ancestors(self, default_revision):
1605
 
        return set(self._repository.get_ancestry(self._revision_id,
1606
 
                                                 topo_sorted=False))
1607
1705
    def _comparison_data(self, entry, path):
1608
1706
        """See Tree._comparison_data."""
1609
1707
        if entry is None:
1725
1823
                elif kind == 'directory':
1726
1824
                    parent_ies[(dirname + '/' + name).strip('/')] = inv_entry
1727
1825
                elif kind == 'symlink':
1728
 
                    inv_entry.executable = False
1729
 
                    inv_entry.text_size = None
1730
1826
                    inv_entry.symlink_target = utf8_decode(fingerprint)[0]
1731
1827
                elif kind == 'tree-reference':
1732
1828
                    inv_entry.reference_revision = fingerprint or None
1752
1848
        # Make sure the file exists
1753
1849
        entry = self._get_entry(file_id, path=path)
1754
1850
        if entry == (None, None): # do we raise?
1755
 
            return None
 
1851
            raise errors.NoSuchId(self, file_id)
1756
1852
        parent_index = self._get_parent_index()
1757
1853
        last_changed_revision = entry[1][parent_index][4]
1758
1854
        try:
1769
1865
            return parent_details[1]
1770
1866
        return None
1771
1867
 
 
1868
    @needs_read_lock
 
1869
    def get_file_revision(self, file_id):
 
1870
        return self.inventory[file_id].revision
 
1871
 
1772
1872
    def get_file(self, file_id, path=None):
1773
1873
        return StringIO(self.get_file_text(file_id))
1774
1874
 
1797
1897
                                       identifier))
1798
1898
        return self._repository.iter_files_bytes(repo_desired_files)
1799
1899
 
1800
 
    def get_symlink_target(self, file_id):
 
1900
    def get_symlink_target(self, file_id, path=None):
1801
1901
        entry = self._get_entry(file_id=file_id)
1802
1902
        parent_index = self._get_parent_index()
1803
1903
        if entry[1][parent_index][0] != 'l':
1832
1932
        entry = self._get_entry(file_id=file_id)[1]
1833
1933
        if entry is None:
1834
1934
            raise errors.NoSuchId(tree=self, file_id=file_id)
1835
 
        return dirstate.DirState._minikind_to_kind[entry[1][0]]
 
1935
        parent_index = self._get_parent_index()
 
1936
        return dirstate.DirState._minikind_to_kind[entry[parent_index][0]]
1836
1937
 
1837
1938
    def stored_kind(self, file_id):
1838
1939
        """See Tree.stored_kind"""
1855
1956
    def is_executable(self, file_id, path=None):
1856
1957
        ie = self.inventory[file_id]
1857
1958
        if ie.kind != "file":
1858
 
            return None
 
1959
            return False
1859
1960
        return ie.executable
1860
1961
 
 
1962
    def is_locked(self):
 
1963
        return self._locked
 
1964
 
1861
1965
    def list_files(self, include_root=False, from_dir=None, recursive=True):
1862
1966
        # We use a standard implementation, because DirStateRevisionTree is
1863
1967
        # dealing with one of the parents of the current state
1876
1980
            yield path, 'V', entry.kind, entry.file_id, entry
1877
1981
 
1878
1982
    def lock_read(self):
1879
 
        """Lock the tree for a set of operations."""
 
1983
        """Lock the tree for a set of operations.
 
1984
 
 
1985
        :return: A bzrlib.lock.LogicalLockResult.
 
1986
        """
1880
1987
        if not self._locked:
1881
1988
            self._repository.lock_read()
1882
1989
            if self._dirstate._lock_token is None:
1883
1990
                self._dirstate.lock_read()
1884
1991
                self._dirstate_locked = True
1885
1992
        self._locked += 1
 
1993
        return LogicalLockResult(self.unlock)
1886
1994
 
1887
1995
    def _must_be_locked(self):
1888
1996
        if not self._locked:
1967
2075
    def make_source_parent_tree(source, target):
1968
2076
        """Change the source tree into a parent of the target."""
1969
2077
        revid = source.commit('record tree')
1970
 
        target.branch.repository.fetch(source.branch.repository, revid)
 
2078
        target.branch.fetch(source.branch, revid)
1971
2079
        target.set_parent_ids([revid])
1972
2080
        return target.basis_tree(), target
1973
2081
 
2065
2173
                path_entries = state._entries_for_path(path)
2066
2174
                if not path_entries:
2067
2175
                    # this specified path is not present at all: error
2068
 
                    not_versioned.append(path)
 
2176
                    not_versioned.append(path.decode('utf-8'))
2069
2177
                    continue
2070
2178
                found_versioned = False
2071
2179
                # for each id at this path
2079
2187
                if not found_versioned:
2080
2188
                    # none of the indexes was not 'absent' at all ids for this
2081
2189
                    # path.
2082
 
                    not_versioned.append(path)
 
2190
                    not_versioned.append(path.decode('utf-8'))
2083
2191
            if len(not_versioned) > 0:
2084
2192
                raise errors.PathsNotVersionedError(not_versioned)
2085
2193
        # -- remove redundancy in supplied specific_files to prevent over-scanning --
2152
2260
    def update_format(self, tree):
2153
2261
        """Change the format marker."""
2154
2262
        tree._transport.put_bytes('format',
2155
 
            self.target_format.get_format_string(),
 
2263
            self.target_format.as_string(),
2156
2264
            mode=tree.bzrdir._get_file_mode())
2157
2265
 
2158
2266
 
2175
2283
    def update_format(self, tree):
2176
2284
        """Change the format marker."""
2177
2285
        tree._transport.put_bytes('format',
2178
 
            self.target_format.get_format_string(),
 
2286
            self.target_format.as_string(),
2179
2287
            mode=tree.bzrdir._get_file_mode())
2180
2288
 
2181
2289
 
2204
2312
    def update_format(self, tree):
2205
2313
        """Change the format marker."""
2206
2314
        tree._transport.put_bytes('format',
2207
 
            self.target_format.get_format_string(),
 
2315
            self.target_format.as_string(),
2208
2316
            mode=tree.bzrdir._get_file_mode())