~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Martin Pool
  • Date: 2006-03-10 06:29:53 UTC
  • mfrom: (1608 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1611.
  • Revision ID: mbp@sourcefrog.net-20060310062953-bc1c7ade75c89a7a
[merge] bzr.dev; pycurl not updated for readv yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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
29
29
WorkingTree.open(dir).
30
30
"""
31
31
 
32
 
 
33
 
# FIXME: I don't know if writing out the cache from the destructor is really a
34
 
# good idea, because destructors are considered poor taste in Python, and it's
35
 
# not predictable when it will be written out.
 
32
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
36
33
 
37
34
# TODO: Give the workingtree sole responsibility for the working inventory;
38
35
# remove the variable and references to it from the branch.  This may require
39
36
# updating the commit code so as to update the inventory within the working
40
37
# copy, and making sure there's only one WorkingTree for any directory on disk.
41
 
# At the momenthey may alias the inventory and have old copies of it in memory.
 
38
# At the moment they may alias the inventory and have old copies of it in
 
39
# memory.  (Now done? -- mbp 20060309)
42
40
 
43
41
from copy import deepcopy
44
42
from cStringIO import StringIO
60
58
                           WeaveRevisionNotPresent,
61
59
                           NotBranchError,
62
60
                           NoSuchFile,
63
 
                           NotVersionedError)
 
61
                           NotVersionedError,
 
62
                           MergeModifiedFormatError)
64
63
from bzrlib.inventory import InventoryEntry, Inventory
65
64
from bzrlib.lockable_files import LockableFiles, TransportLock
 
65
from bzrlib.lockdir import LockDir
66
66
from bzrlib.merge import merge_inner, transform_tree
67
67
from bzrlib.osutils import (
68
68
                            abspath,
84
84
                            )
85
85
from bzrlib.progress import DummyProgress
86
86
from bzrlib.revision import NULL_REVISION
 
87
from bzrlib.rio import RioReader, RioWriter, Stanza
87
88
from bzrlib.symbol_versioning import *
88
89
from bzrlib.textui import show_status
89
90
import bzrlib.tree
247
248
        if isinstance(self._format, WorkingTreeFormat2):
248
249
            # share control object
249
250
            self._control_files = self.branch.control_files
250
 
        elif _control_files is not None:
251
 
            assert False, "not done yet"
252
 
#            self._control_files = _control_files
253
251
        else:
254
252
            # only ready for format 3
255
253
            assert isinstance(self._format, WorkingTreeFormat3)
256
 
            self._control_files = LockableFiles(
257
 
                self.bzrdir.get_workingtree_transport(None),
258
 
                'lock', TransportLock)
259
 
 
 
254
            assert isinstance(_control_files, LockableFiles), \
 
255
                    "_control_files must be a LockableFiles, not %r" \
 
256
                    % _control_files
 
257
            self._control_files = _control_files
260
258
        # update the whole cache up front and write to disk if anything changed;
261
259
        # in the future we might want to do this more selectively
262
260
        # two possible ways offer themselves : in self._unlock, write the cache
454
452
            tree.set_last_revision(revision_id)
455
453
 
456
454
    @needs_write_lock
457
 
    def commit(self, *args, **kwargs):
 
455
    def commit(self, message=None, revprops=None, *args, **kwargs):
 
456
        # avoid circular imports
458
457
        from bzrlib.commit import Commit
 
458
        if revprops is None:
 
459
            revprops = {}
 
460
        if not 'branch-nick' in revprops:
 
461
            revprops['branch-nick'] = self.branch.nick
459
462
        # args for wt.commit start at message from the Commit.commit method,
460
463
        # but with branch a kwarg now, passing in args as is results in the
461
464
        #message being used for the branch
462
 
        args = (DEPRECATED_PARAMETER, ) + args
463
 
        Commit().commit(working_tree=self, *args, **kwargs)
 
465
        args = (DEPRECATED_PARAMETER, message, ) + args
 
466
        Commit().commit(working_tree=self, revprops=revprops, *args, **kwargs)
464
467
        self._set_inventory(self.read_working_inventory())
465
468
 
466
469
    def id2abspath(self, file_id):
600
603
    def set_pending_merges(self, rev_list):
601
604
        self._control_files.put_utf8('pending-merges', '\n'.join(rev_list))
602
605
 
 
606
    @needs_write_lock
 
607
    def set_merge_modified(self, modified_hashes):
 
608
        my_file = StringIO()
 
609
        my_file.write(MERGE_MODIFIED_HEADER_1 + '\n')
 
610
        writer = RioWriter(my_file)
 
611
        for file_id, hash in modified_hashes.iteritems():
 
612
            s = Stanza(file_id=file_id, hash=hash)
 
613
            writer.write_stanza(s)
 
614
        my_file.seek(0)
 
615
        self._control_files.put('merge-hashes', my_file)
 
616
 
 
617
    @needs_read_lock
 
618
    def merge_modified(self):
 
619
        try:
 
620
            hashfile = self._control_files.get('merge-hashes')
 
621
        except NoSuchFile:
 
622
            return {}
 
623
        merge_hashes = {}
 
624
        try:
 
625
            if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
 
626
                raise MergeModifiedFormatError()
 
627
        except StopIteration:
 
628
            raise MergeModifiedFormatError()
 
629
        for s in RioReader(hashfile):
 
630
            file_id = s.get("file_id")
 
631
            hash = s.get("hash")
 
632
            if hash == self.get_file_sha1(file_id):
 
633
                merge_hashes[file_id] = hash
 
634
        return merge_hashes
 
635
 
603
636
    def get_symlink_target(self, file_id):
604
637
        return os.readlink(self.id2abspath(file_id))
605
638
 
850
883
                else:
851
884
                    other_revision = None
852
885
                repository = self.branch.repository
853
 
                merge_inner(self.branch,
854
 
                            self.branch.basis_tree(),
855
 
                            basis_tree, 
856
 
                            this_tree=self, 
857
 
                            pb=bzrlib.ui.ui_factory.progress_bar())
 
886
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
887
                try:
 
888
                    merge_inner(self.branch,
 
889
                                self.branch.basis_tree(),
 
890
                                basis_tree, 
 
891
                                this_tree=self, 
 
892
                                pb=pb)
 
893
                finally:
 
894
                    pb.finished()
858
895
                self.set_last_revision(self.branch.last_revision())
859
896
            return count
860
897
        finally:
1234
1271
    This differs from the base WorkingTree by:
1235
1272
     - having its own file lock
1236
1273
     - having its own last-revision property.
 
1274
 
 
1275
    This is new in bzr 0.8
1237
1276
    """
1238
1277
 
1239
1278
    @needs_read_lock
1413
1452
class WorkingTreeFormat3(WorkingTreeFormat):
1414
1453
    """The second working tree format updated to record a format marker.
1415
1454
 
1416
 
    This format modified the hash cache from the format 1 hash cache.
 
1455
    This format:
 
1456
        - exists within a metadir controlling .bzr
 
1457
        - includes an explicit version marker for the workingtree control
 
1458
          files, separate from the BzrDir format
 
1459
        - modifies the hash cache format
 
1460
        - is new in bzr 0.8
 
1461
        - uses a LockDir to guard access to the repository
1417
1462
    """
1418
1463
 
1419
1464
    def get_format_string(self):
1420
1465
        """See WorkingTreeFormat.get_format_string()."""
1421
1466
        return "Bazaar-NG Working Tree format 3"
1422
1467
 
 
1468
    _lock_file_name = 'lock'
 
1469
    _lock_class = LockDir
 
1470
 
 
1471
    def _open_control_files(self, a_bzrdir):
 
1472
        transport = a_bzrdir.get_workingtree_transport(None)
 
1473
        return LockableFiles(transport, self._lock_file_name, 
 
1474
                             self._lock_class)
 
1475
 
1423
1476
    def initialize(self, a_bzrdir, revision_id=None):
1424
1477
        """See WorkingTreeFormat.initialize().
1425
1478
        
1429
1482
        if not isinstance(a_bzrdir.transport, LocalTransport):
1430
1483
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
1431
1484
        transport = a_bzrdir.get_workingtree_transport(self)
1432
 
        control_files = LockableFiles(transport, 'lock', TransportLock)
 
1485
        control_files = self._open_control_files(a_bzrdir)
 
1486
        control_files.create_lock()
1433
1487
        control_files.put_utf8('format', self.get_format_string())
1434
1488
        branch = a_bzrdir.open_branch()
1435
1489
        if revision_id is None:
1440
1494
                         inv,
1441
1495
                         _internal=True,
1442
1496
                         _format=self,
1443
 
                         _bzrdir=a_bzrdir)
 
1497
                         _bzrdir=a_bzrdir,
 
1498
                         _control_files=control_files)
1444
1499
        wt._write_inventory(inv)
1445
1500
        wt.set_root_id(inv.root.file_id)
1446
1501
        wt.set_last_revision(revision_id)
1463
1518
            raise NotImplementedError
1464
1519
        if not isinstance(a_bzrdir.transport, LocalTransport):
1465
1520
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
1521
        control_files = self._open_control_files(a_bzrdir)
1466
1522
        return WorkingTree3(a_bzrdir.root_transport.base,
1467
1523
                           _internal=True,
1468
1524
                           _format=self,
1469
 
                           _bzrdir=a_bzrdir)
 
1525
                           _bzrdir=a_bzrdir,
 
1526
                           _control_files=control_files)
1470
1527
 
1471
1528
    def __str__(self):
1472
1529
        return self.get_format_string()