14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
# TODO: Don't allow WorkingTrees to be constructed for remote branches.
17
"""WorkingTree object and friends.
19
A WorkingTree represents the editable working copy of a branch.
20
Operations which represent the WorkingTree are also done here,
21
such as renaming or adding files. The WorkingTree has an inventory
22
which is updated by these operations. A commit produces a
23
new revision based on the workingtree and its inventory.
25
At the moment every WorkingTree has its own branch. Remote
26
WorkingTrees aren't supported.
28
To get a WorkingTree, call Branch.working_tree():
32
# TODO: Don't allow WorkingTrees to be constructed for remote branches if
19
35
# FIXME: I don't know if writing out the cache from the destructor is really a
20
# good idea, because destructors are considered poor taste in Python, and
21
# it's not predictable when it will be written out.
36
# good idea, because destructors are considered poor taste in Python, and it's
37
# not predictable when it will be written out.
39
# TODO: Give the workingtree sole responsibility for the working inventory;
40
# remove the variable and references to it from the branch. This may require
41
# updating the commit code so as to update the inventory within the working
42
# copy, and making sure there's only one WorkingTree for any directory on disk.
43
# At the momenthey may alias the inventory and have old copies of it in memory.
27
from bzrlib.branch import Branch
49
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock, quotefn
29
51
from bzrlib.osutils import appendpath, file_kind, isdir, splitpath, relpath
30
from bzrlib.errors import BzrCheckError
52
from bzrlib.errors import BzrCheckError, NotVersionedError
31
53
from bzrlib.trace import mutter
33
55
class TreeEntry(object):
94
116
It is possible for a `WorkingTree` to have a filename which is
95
117
not listed in the Inventory and vice versa.
97
120
def __init__(self, basedir, branch=None):
98
121
"""Construct a WorkingTree for basedir.
105
128
from bzrlib.hashcache import HashCache
106
129
from bzrlib.trace import note, mutter
130
assert isinstance(basedir, basestring), \
131
"base directory %r is not a string" % basedir
108
132
if branch is None:
109
133
branch = Branch.open(basedir)
134
assert isinstance(branch, Branch), \
135
"branch %r is not a Branch" % branch
110
136
self._inventory = branch.inventory
111
137
self.path2id = self._inventory.path2id
112
138
self.branch = branch
398
424
def kind(self, file_id):
399
425
return file_kind(self.id2abspath(file_id))
428
"""See Branch.lock_read, and WorkingTree.unlock."""
429
return self.branch.lock_read()
431
def lock_write(self):
432
"""See Branch.lock_write, and WorkingTree.unlock."""
433
return self.branch.lock_write()
436
def remove(self, files, verbose=False):
437
"""Remove nominated files from the working inventory..
439
This does not remove their text. This does not run on XXX on what? RBC
441
TODO: Refuse to remove modified files unless --force is given?
443
TODO: Do something useful with directories.
445
TODO: Should this remove the text or not? Tough call; not
446
removing may be useful and the user can just use use rm, and
447
is the opposite of add. Removing it is consistent with most
448
other tools. Maybe an option.
450
## TODO: Normalize names
451
## TODO: Remove nested loops; better scalability
452
if isinstance(files, basestring):
457
# do this before any modifications
461
# TODO: Perhaps make this just a warning, and continue?
462
# This tends to happen when
463
raise NotVersionedError(path=f)
464
mutter("remove inventory entry %s {%s}" % (quotefn(f), fid))
466
# having remove it, it must be either ignored or unknown
467
if self.is_ignored(f):
471
show_status(new_status, inv[fid].kind, quotefn(f))
474
self.branch._write_inventory(inv)
477
"""See Branch.unlock.
479
WorkingTree locking just uses the Branch locking facilities.
480
This is current because all working trees have an embedded branch
481
within them. IF in the future, we were to make branch data shareable
482
between multiple working trees, i.e. via shared storage, then we
483
would probably want to lock both the local tree, and the branch.
485
return self.branch.unlock()
401
488
CONFLICT_SUFFIXES = ('.THIS', '.BASE', '.OTHER')
402
489
def get_conflicted_stem(path):
403
490
for suffix in CONFLICT_SUFFIXES: