~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree_4.py

  • Committer: John Arbash Meinel
  • Date: 2011-05-11 11:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 5851.
  • Revision ID: john@arbash-meinel.com-20110511113528-qepibuwxicjrbb2h
Break compatibility with python <2.6.

This includes auditing the code for places where we were doing
explicit 'sys.version' checks and removing them as appropriate.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 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
31
31
import errno
32
32
import stat
33
33
 
34
 
import bzrlib
35
34
from bzrlib import (
36
35
    bzrdir,
37
36
    cache_utf8,
 
37
    conflicts as _mod_conflicts,
38
38
    debug,
39
39
    dirstate,
40
40
    errors,
 
41
    filters as _mod_filters,
41
42
    generate_ids,
42
43
    osutils,
43
44
    revision as _mod_revision,
46
47
    transform,
47
48
    views,
48
49
    )
49
 
import bzrlib.branch
50
 
import bzrlib.ui
51
50
""")
52
51
 
53
52
from bzrlib.decorators import needs_read_lock, needs_write_lock
54
 
from bzrlib.filters import filtered_input_file, internal_size_sha_file_byname
55
53
from bzrlib.inventory import Inventory, ROOT_ID, entry_factory
56
54
from bzrlib.lock import LogicalLockResult
 
55
from bzrlib.lockable_files import LockableFiles
 
56
from bzrlib.lockdir import LockDir
57
57
from bzrlib.mutabletree import needs_tree_write_lock
58
58
from bzrlib.osutils import (
59
59
    file_kind,
62
62
    realpath,
63
63
    safe_unicode,
64
64
    )
65
 
from bzrlib.trace import mutter
66
65
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):
 
66
from bzrlib.tree import (
 
67
    InterTree,
 
68
    InventoryTree,
 
69
    )
 
70
from bzrlib.workingtree import (
 
71
    InventoryWorkingTree,
 
72
    WorkingTree,
 
73
    WorkingTreeFormat,
 
74
    )
 
75
 
 
76
 
 
77
class DirStateWorkingTree(InventoryWorkingTree):
 
78
 
 
79
    _DEFAULT_WORTH_SAVING_LIMIT = 10
 
80
 
73
81
    def __init__(self, basedir,
74
82
                 branch,
75
83
                 _control_files=None,
85
93
        self._format = _format
86
94
        self.bzrdir = _bzrdir
87
95
        basedir = safe_unicode(basedir)
88
 
        mutter("opening working tree %r", basedir)
 
96
        trace.mutter("opening working tree %r", basedir)
89
97
        self._branch = branch
90
98
        self.basedir = realpath(basedir)
91
99
        # if branch is at our basedir and is a format 6 or less
125
133
            state.add(f, file_id, kind, None, '')
126
134
        self._make_dirty(reset_inventory=True)
127
135
 
 
136
    def _get_check_refs(self):
 
137
        """Return the references needed to perform a check of this tree."""
 
138
        return [('trees', self.last_revision())]
 
139
 
128
140
    def _make_dirty(self, reset_inventory):
129
141
        """Make the tree state dirty.
130
142
 
182
194
 
183
195
    def _comparison_data(self, entry, path):
184
196
        kind, executable, stat_value = \
185
 
            WorkingTree3._comparison_data(self, entry, path)
 
197
            WorkingTree._comparison_data(self, entry, path)
186
198
        # it looks like a plain directory, but it's really a reference -- see
187
199
        # also kind()
188
200
        if (self._repo_supports_tree_reference and kind == 'directory'
194
206
    def commit(self, message=None, revprops=None, *args, **kwargs):
195
207
        # mark the tree as dirty post commit - commit
196
208
        # can change the current versioned list by doing deletes.
197
 
        result = WorkingTree3.commit(self, message, revprops, *args, **kwargs)
 
209
        result = WorkingTree.commit(self, message, revprops, *args, **kwargs)
198
210
        self._make_dirty(reset_inventory=True)
199
211
        return result
200
212
 
219
231
        local_path = self.bzrdir.get_workingtree_transport(None
220
232
            ).local_abspath('dirstate')
221
233
        self._dirstate = dirstate.DirState.on_file(local_path,
222
 
            self._sha1_provider())
 
234
            self._sha1_provider(), self._worth_saving_limit())
223
235
        return self._dirstate
224
236
 
225
237
    def _sha1_provider(self):
234
246
        else:
235
247
            return None
236
248
 
 
249
    def _worth_saving_limit(self):
 
250
        """How many hash changes are ok before we must save the dirstate.
 
251
 
 
252
        :return: an integer. -1 means never save.
 
253
        """
 
254
        config = self.branch.get_config()
 
255
        val = config.get_user_option('bzr.workingtree.worth_saving_limit')
 
256
        if val is None:
 
257
            val = self._DEFAULT_WORTH_SAVING_LIMIT
 
258
        else:
 
259
            try:
 
260
                val = int(val)
 
261
            except ValueError, e:
 
262
                trace.warning('Invalid config value for'
 
263
                              ' "bzr.workingtree.worth_saving_limit"'
 
264
                              ' value %r is not an integer.'
 
265
                              % (val,))
 
266
                val = self._DEFAULT_WORTH_SAVING_LIMIT
 
267
        return val
 
268
 
237
269
    def filter_unversioned_files(self, paths):
238
270
        """Filter out paths that are versioned.
239
271
 
369
401
        state = self.current_dirstate()
370
402
        if stat_value is None:
371
403
            try:
372
 
                stat_value = os.lstat(file_abspath)
 
404
                stat_value = osutils.lstat(file_abspath)
373
405
            except OSError, e:
374
406
                if e.errno == errno.ENOENT:
375
407
                    return None
478
510
            self._must_be_locked()
479
511
            if not path:
480
512
                path = self.id2path(file_id)
481
 
            mode = os.lstat(self.abspath(path)).st_mode
 
513
            mode = osutils.lstat(self.abspath(path)).st_mode
482
514
            return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
483
515
 
484
516
    def all_file_ids(self):
850
882
                rollback_rename()
851
883
                raise
852
884
            result.append((from_rel, to_rel))
853
 
            state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
 
885
            state._mark_modified()
854
886
            self._make_dirty(reset_inventory=False)
855
887
 
856
888
        return result
1254
1286
    def rename_one(self, from_rel, to_rel, after=False):
1255
1287
        """See WorkingTree.rename_one"""
1256
1288
        self.flush()
1257
 
        WorkingTree.rename_one(self, from_rel, to_rel, after)
 
1289
        super(DirStateWorkingTree, self).rename_one(from_rel, to_rel, after)
1258
1290
 
1259
1291
    @needs_tree_write_lock
1260
1292
    def apply_inventory_delta(self, changes):
1293
1325
            self._inventory = inv
1294
1326
        self.flush()
1295
1327
 
 
1328
    @needs_tree_write_lock
 
1329
    def reset_state(self, revision_ids=None):
 
1330
        """Reset the state of the working tree.
 
1331
 
 
1332
        This does a hard-reset to a last-known-good state. This is a way to
 
1333
        fix if something got corrupted (like the .bzr/checkout/dirstate file)
 
1334
        """
 
1335
        if revision_ids is None:
 
1336
            revision_ids = self.get_parent_ids()
 
1337
        if not revision_ids:
 
1338
            base_tree = self.branch.repository.revision_tree(
 
1339
                _mod_revision.NULL_REVISION)
 
1340
            trees = []
 
1341
        else:
 
1342
            trees = zip(revision_ids,
 
1343
                        self.branch.repository.revision_trees(revision_ids))
 
1344
            base_tree = trees[0][1]
 
1345
        state = self.current_dirstate()
 
1346
        # We don't support ghosts yet
 
1347
        state.set_state_from_scratch(base_tree.inventory, trees, [])
 
1348
 
1296
1349
 
1297
1350
class ContentFilterAwareSHA1Provider(dirstate.SHA1Provider):
1298
1351
 
1303
1356
        """See dirstate.SHA1Provider.sha1()."""
1304
1357
        filters = self.tree._content_filter_stack(
1305
1358
            self.tree.relpath(osutils.safe_unicode(abspath)))
1306
 
        return internal_size_sha_file_byname(abspath, filters)[1]
 
1359
        return _mod_filters.internal_size_sha_file_byname(abspath, filters)[1]
1307
1360
 
1308
1361
    def stat_and_sha1(self, abspath):
1309
1362
        """See dirstate.SHA1Provider.stat_and_sha1()."""
1313
1366
        try:
1314
1367
            statvalue = os.fstat(file_obj.fileno())
1315
1368
            if filters:
1316
 
                file_obj = filtered_input_file(file_obj, filters)
 
1369
                file_obj = _mod_filters.filtered_input_file(file_obj, filters)
1317
1370
            sha1 = osutils.size_sha_file(file_obj)[1]
1318
1371
        finally:
1319
1372
            file_obj.close()
1349
1402
class WorkingTree4(DirStateWorkingTree):
1350
1403
    """This is the Format 4 working tree.
1351
1404
 
1352
 
    This differs from WorkingTree3 by:
 
1405
    This differs from WorkingTree by:
1353
1406
     - Having a consolidated internal dirstate, stored in a
1354
1407
       randomly-accessible sorted file on disk.
1355
1408
     - Not having a regular inventory attribute.  One can be synthesized
1383
1436
        return views.PathBasedViews(self)
1384
1437
 
1385
1438
 
1386
 
class DirStateWorkingTreeFormat(WorkingTreeFormat3):
 
1439
class DirStateWorkingTreeFormat(WorkingTreeFormat):
 
1440
 
 
1441
    missing_parent_conflicts = True
 
1442
 
 
1443
    _lock_class = LockDir
 
1444
    _lock_file_name = 'lock'
 
1445
 
 
1446
    def _open_control_files(self, a_bzrdir):
 
1447
        transport = a_bzrdir.get_workingtree_transport(None)
 
1448
        return LockableFiles(transport, self._lock_file_name,
 
1449
                             self._lock_class)
1387
1450
 
1388
1451
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
1389
1452
                   accelerator_tree=None, hardlink=False):
1489
1552
        :param wt: the WorkingTree object
1490
1553
        """
1491
1554
 
 
1555
    def open(self, a_bzrdir, _found=False):
 
1556
        """Return the WorkingTree object for a_bzrdir
 
1557
 
 
1558
        _found is a private parameter, do not use it. It is used to indicate
 
1559
               if format probing has already been done.
 
1560
        """
 
1561
        if not _found:
 
1562
            # we are being called directly and must probe.
 
1563
            raise NotImplementedError
 
1564
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
1565
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
1566
        wt = self._open(a_bzrdir, self._open_control_files(a_bzrdir))
 
1567
        return wt
 
1568
 
1492
1569
    def _open(self, a_bzrdir, control_files):
1493
1570
        """Open the tree itself.
1494
1571
 
1585
1662
        return True
1586
1663
 
1587
1664
 
1588
 
class DirStateRevisionTree(Tree):
 
1665
class DirStateRevisionTree(InventoryTree):
1589
1666
    """A revision tree pulling the inventory from a dirstate.
1590
1667
    
1591
1668
    Note that this is one of the historical (ie revision) trees cached in the
1610
1687
    def annotate_iter(self, file_id,
1611
1688
                      default_revision=_mod_revision.CURRENT_REVISION):
1612
1689
        """See Tree.annotate_iter"""
1613
 
        text_key = (file_id, self.inventory[file_id].revision)
 
1690
        text_key = (file_id, self.get_file_revision(file_id))
1614
1691
        annotations = self._repository.texts.annotate(text_key)
1615
1692
        return [(key[-1], line) for (key, line) in annotations]
1616
1693
 
1780
1857
            return parent_details[1]
1781
1858
        return None
1782
1859
 
 
1860
    @needs_read_lock
 
1861
    def get_file_revision(self, file_id):
 
1862
        return self.inventory[file_id].revision
 
1863
 
1783
1864
    def get_file(self, file_id, path=None):
1784
1865
        return StringIO(self.get_file_text(file_id))
1785
1866
 
1867
1948
    def is_executable(self, file_id, path=None):
1868
1949
        ie = self.inventory[file_id]
1869
1950
        if ie.kind != "file":
1870
 
            return None
 
1951
            return False
1871
1952
        return ie.executable
1872
1953
 
1873
1954
    def is_locked(self):
1986
2067
    def make_source_parent_tree(source, target):
1987
2068
        """Change the source tree into a parent of the target."""
1988
2069
        revid = source.commit('record tree')
1989
 
        target.branch.repository.fetch(source.branch.repository, revid)
 
2070
        target.branch.fetch(source.branch, revid)
1990
2071
        target.set_parent_ids([revid])
1991
2072
        return target.basis_tree(), target
1992
2073