/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

Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
 
51
51
from bzrlib.atomicfile import AtomicFile
52
52
from bzrlib.branch import (Branch,
53
 
                           BzrBranchFormat4,
54
53
                           quotefn)
55
54
import bzrlib.bzrdir as bzrdir
56
55
from bzrlib.decorators import needs_read_lock, needs_write_lock
64
63
                           NotVersionedError)
65
64
from bzrlib.inventory import InventoryEntry
66
65
from bzrlib.lockable_files import LockableFiles
 
66
from bzrlib.merge import merge_inner, transform_tree
67
67
from bzrlib.osutils import (appendpath,
68
68
                            compact_date,
69
69
                            file_kind,
187
187
    not listed in the Inventory and vice versa.
188
188
    """
189
189
 
190
 
    def __init__(self, basedir='.', branch=None, _inventory=None, _control_files=None, _internal=False):
 
190
    def __init__(self, basedir='.', branch=None, _inventory=None, _control_files=None, _internal=False, _format=None):
191
191
        """Construct a WorkingTree for basedir.
192
192
 
193
193
        If the branch is not supplied, it is opened automatically.
195
195
        (branch.base is not cross checked, because for remote branches that
196
196
        would be meaningless).
197
197
        """
 
198
        self._format = _format
198
199
        if not _internal:
199
200
            # created via open etc.
200
 
            wt = WorkingTree.open(basedir, branch)
 
201
            wt = WorkingTree.open(basedir)
201
202
            self.branch = wt.branch
202
203
            self.basedir = wt.basedir
203
204
            self._control_files = wt._control_files
204
205
            self._hashcache = wt._hashcache
205
206
            self._set_inventory(wt._inventory)
 
207
            self._format = wt._format
206
208
        from bzrlib.hashcache import HashCache
207
209
        from bzrlib.trace import note, mutter
208
210
        assert isinstance(basedir, basestring), \
216
218
        self.branch = branch
217
219
        self.basedir = realpath(basedir)
218
220
        # if branch is at our basedir and is a format 6 or less
219
 
        if (isinstance(self.branch._format,
220
 
                       (BzrBranchFormat4))
 
221
        if (isinstance(self._format, WorkingTreeFormat2)
221
222
            # might be able to share control object
222
223
            and self.branch.base.split('/')[-2] == self.basedir.split('/')[-1]):
223
224
            self._control_files = self.branch.control_files
235
236
        # if needed, or, when the cache sees a change, append it to the hash
236
237
        # cache file, and have the parser take the most recent entry for a
237
238
        # given path only.
238
 
        hc = self._hashcache = HashCache(basedir)
 
239
        hc = self._hashcache = HashCache(basedir, self._control_files._file_mode)
239
240
        hc.read()
 
241
        # is this scan needed ? it makes things kinda slow.
240
242
        hc.scan()
241
243
 
242
244
        if hc.needs_write:
336
338
        """
337
339
        warn('delete WorkingTree.create', stacklevel=3)
338
340
        transport = get_transport(directory)
339
 
        if branch.bzrdir.transport.clone('..').base == transport.base:
 
341
        if branch.bzrdir.root_transport.base == transport.base:
340
342
            # same dir 
341
343
            return branch.bzrdir.create_workingtree()
342
344
        # different directory, 
378
380
        return self.abspath(self.id2path(file_id))
379
381
 
380
382
    @needs_read_lock
381
 
    def clone(self, to_directory, revision=None):
382
 
        """Copy this working tree to a new directory.
 
383
    def clone(self, to_bzrdir, revision_id=None, basis=None):
 
384
        """Duplicate this working tree into to_bzr, including all state.
383
385
        
384
 
        Currently this will make a new standalone branch at to_directory,
385
 
        but it is planned to change this to use the same branch style that this
386
 
        current tree uses (standalone if standalone, repository if repository)
387
 
        - so that this really is a clone. FIXME RBC 20060127 do this.
388
 
        FIXME MORE RBC 20060127 failed to reach consensus on this in #bzr.
 
386
        Specifically modified files are kept as modified, but
 
387
        ignored and unknown files are discarded.
389
388
 
390
 
        If you want a standalone branch, please use branch.clone(to_directory)
391
 
        followed by WorkingTree.create(cloned_branch, to_directory) which is
392
 
        the supported api to produce that.
 
389
        If you want to make a new line of development, see bzrdir.sprout()
393
390
 
394
391
        revision
395
392
            If not None, the cloned tree will have its last revision set to 
396
 
            revision, and if a branch is being copied it will be informed
397
 
            of the revision to result in. 
398
 
    
399
 
        to_directory -- The destination directory: Must not exist.
 
393
            revision, and and difference between the source trees last revision
 
394
            and this one merged in.
 
395
 
 
396
        basis
 
397
            If not None, a closer copy of a tree which may have some files in
 
398
            common, and which file content should be preferentially copied from.
400
399
        """
401
 
        to_directory = safe_unicode(to_directory)
402
 
        os.mkdir(to_directory)
403
 
        # FIXME here is where the decision to clone the branch should happen.
404
 
        if revision is None:
405
 
            revision = self.last_revision()
406
 
        cloned_branch = self.branch.clone(to_directory, revision)
407
 
        return  WorkingTree.create(cloned_branch, to_directory)
 
400
        # assumes the target bzr dir format is compatible.
 
401
        result = self._format.initialize(to_bzrdir)
 
402
        self.copy_content_into(result, revision_id)
 
403
        return result
 
404
 
 
405
    @needs_read_lock
 
406
    def copy_content_into(self, tree, revision_id=None):
 
407
        """Copy the current content and user files of this tree into tree."""
 
408
        if revision_id is None:
 
409
            transform_tree(tree, self)
 
410
        else:
 
411
            # TODO now merge from tree.last_revision to revision
 
412
            transform_tree(tree, self)
 
413
            tree.set_last_revision(revision_id)
408
414
 
409
415
    @needs_write_lock
410
416
    def commit(self, *args, **kwargs):
564
570
        else:
565
571
            return '?'
566
572
 
567
 
 
568
573
    def list_files(self):
569
574
        """Recursively list all files as (path, class, kind, id).
570
575
 
790
795
 
791
796
    @needs_write_lock
792
797
    def pull(self, source, overwrite=False):
793
 
        from bzrlib.merge import merge_inner
794
798
        source.lock_read()
795
799
        try:
796
800
            old_revision_history = self.branch.revision_history()
916
920
 
917
921
    def lock_read(self):
918
922
        """See Branch.lock_read, and WorkingTree.unlock."""
919
 
        return self.branch.lock_read()
 
923
        self.branch.lock_read()
 
924
        try:
 
925
            return self._control_files.lock_read()
 
926
        except:
 
927
            self.branch.unlock()
 
928
            raise
920
929
 
921
930
    def lock_write(self):
922
931
        """See Branch.lock_write, and WorkingTree.unlock."""
923
 
        return self.branch.lock_write()
 
932
        self.branch.lock_write()
 
933
        try:
 
934
            return self._control_files.lock_write()
 
935
        except:
 
936
            self.branch.unlock()
 
937
            raise
924
938
 
925
939
    def _basis_inventory_name(self, revision_id):
926
940
        return 'basis-inventory.%s' % revision_id
1070
1084
        # of a nasty hack; probably it's better to have a transaction object,
1071
1085
        # which can do some finalization when it's either successfully or
1072
1086
        # unsuccessfully completed.  (Denys's original patch did that.)
1073
 
        if self._hashcache.needs_write and self._control_files._lock_count==1:
 
1087
        # RBC 20060206 hookinhg into transaction will couple lock and transaction
 
1088
        # wrongly. Hookinh into unllock on the control files object is fine though.
 
1089
        
 
1090
        # TODO: split this per format so there is no ugly if block
 
1091
        if self._hashcache.needs_write and (
 
1092
            self._control_files._lock_count==1 or 
 
1093
            (self._control_files is self.branch.control_files and 
 
1094
             self._control_files._lock_count==2)):
1074
1095
            self._hashcache.write()
1075
 
        return self.branch.unlock()
 
1096
        # reverse order of locking.
 
1097
        result = self._control_files.unlock()
 
1098
        try:
 
1099
            self.branch.unlock()
 
1100
        finally:
 
1101
            return result
1076
1102
 
1077
1103
    @needs_write_lock
1078
1104
    def _write_inventory(self, inv):
1184
1210
        """See WorkingTreeFormat.initialize()."""
1185
1211
        if not isinstance(a_bzrdir.transport, LocalTransport):
1186
1212
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
1187
 
        b = a_bzrdir.open_branch()
1188
 
        r = a_bzrdir.open_repository()
1189
 
        revision = b.last_revision()
1190
 
        basis_tree = r.revision_tree(revision)
 
1213
        branch = a_bzrdir.open_branch()
 
1214
        revision = branch.last_revision()
 
1215
        basis_tree = branch.repository.revision_tree(revision)
1191
1216
        inv = basis_tree.inventory
1192
 
        wt = WorkingTree(a_bzrdir.transport.clone('..').base, b, inv, _internal=True)
 
1217
        wt = WorkingTree(a_bzrdir.root_transport.base,
 
1218
                         branch,
 
1219
                         inv,
 
1220
                         _internal=True,
 
1221
                         _format=self)
1193
1222
        wt._write_inventory(inv)
1194
1223
        wt.set_root_id(inv.root.file_id)
1195
1224
        wt.set_last_revision(revision)
1196
1225
        wt.set_pending_merges([])
1197
1226
        wt.revert([])
1198
1227
        wt.bzrdir = a_bzrdir
1199
 
        wt._format = self
1200
1228
        return wt
1201
1229
 
1202
1230
    def __init__(self):
1214
1242
            raise NotImplementedError
1215
1243
        if not isinstance(a_bzrdir.transport, LocalTransport):
1216
1244
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
1217
 
        result = WorkingTree(a_bzrdir.transport.clone('..').base, _internal=True)
 
1245
        result = WorkingTree(a_bzrdir.root_transport.base, _internal=True, _format=self)
1218
1246
        result.bzrdir = a_bzrdir
1219
 
        result._format = self
1220
1247
        return result
1221
1248
 
1222
1249
 
1237
1264
        transport = a_bzrdir.get_workingtree_transport(self)
1238
1265
        control_files = LockableFiles(transport, 'lock')
1239
1266
        control_files.put_utf8('format', self.get_format_string())
1240
 
        b = a_bzrdir.open_branch()
1241
 
        r = a_bzrdir.open_repository()
1242
 
        revision = b.last_revision()
1243
 
        basis_tree = r.revision_tree(revision)
 
1267
        branch = a_bzrdir.open_branch()
 
1268
        revision = branch.last_revision()
 
1269
        basis_tree = branch.repository.revision_tree(revision)
1244
1270
        inv = basis_tree.inventory
1245
 
        wt = WorkingTree(a_bzrdir.transport.clone('..').base, b, inv, _internal=True)
 
1271
        wt = WorkingTree(a_bzrdir.root_transport.base,
 
1272
                         branch,
 
1273
                         inv,
 
1274
                         _internal=True,
 
1275
                         _format=self)
1246
1276
        wt._write_inventory(inv)
1247
1277
        wt.set_root_id(inv.root.file_id)
1248
1278
        wt.set_last_revision(revision)
1249
1279
        wt.set_pending_merges([])
1250
1280
        wt.revert([])
1251
1281
        wt.bzrdir = a_bzrdir
1252
 
        wt._format = self
1253
1282
        return wt
1254
1283
 
1255
1284
    def __init__(self):
1267
1296
            raise NotImplementedError
1268
1297
        if not isinstance(a_bzrdir.transport, LocalTransport):
1269
1298
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
1270
 
        result = WorkingTree(a_bzrdir.transport.clone('..').base, _internal=True)
 
1299
        result = WorkingTree(a_bzrdir.root_transport.base, _internal=True, _format=self)
1271
1300
        result.bzrdir = a_bzrdir
1272
 
        result._format = self
1273
1301
        return result
1274
1302
 
1275
1303