17
17
"""WorkingTree object and friends.
19
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
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
23
new revision based on the workingtree and its inventory.
25
25
At the moment every WorkingTree has its own branch. Remote
123
125
class TreeEntry(object):
124
126
"""An entry that implements the minimum interface used by commands.
126
This needs further inspection, it may be better to have
128
This needs further inspection, it may be better to have
127
129
InventoryEntries without ids - though that seems wrong. For now,
128
130
this is a parallel hierarchy to InventoryEntry, and needs to become
129
131
one of several things: decorates to that hierarchy, children of, or
132
134
no InventoryEntry available - i.e. for unversioned objects.
133
135
Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
136
138
def __eq__(self, other):
137
139
# yes, this us ugly, TODO: best practice __eq__ style.
138
140
return (isinstance(other, TreeEntry)
139
141
and other.__class__ == self.__class__)
141
143
def kind_character(self):
225
231
wt_trans = self.bzrdir.get_workingtree_transport(None)
226
232
cache_filename = wt_trans.local_abspath('stat-cache')
227
233
self._hashcache = hashcache.HashCache(basedir, cache_filename,
228
self.bzrdir._get_file_mode())
234
self.bzrdir._get_file_mode(),
235
self._content_filter_stack_provider())
229
236
hc = self._hashcache
231
238
# is this scan needed ? it makes things kinda slow.
288
296
return self._format.supports_content_filtering()
290
298
def supports_views(self):
291
return self._format.supports_views()
299
return self.views.supports_views()
293
301
def _set_inventory(self, inv, dirty):
294
302
"""Set the internal cached inventory.
429
437
def has_filename(self, filename):
430
438
return osutils.lexists(self.abspath(filename))
432
def get_file(self, file_id, path=None):
433
return self.get_file_with_stat(file_id, path)[0]
440
def get_file(self, file_id, path=None, filtered=True):
441
return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
435
def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
443
def get_file_with_stat(self, file_id, path=None, filtered=True,
436
445
"""See MutableTree.get_file_with_stat."""
438
447
path = self.id2path(file_id)
439
file_obj = self.get_file_byname(path)
440
return (file_obj, _fstat(file_obj.fileno()))
442
def get_file_byname(self, filename):
443
return file(self.abspath(filename), 'rb')
445
def get_file_lines(self, file_id, path=None):
448
file_obj = self.get_file_byname(path, filtered=False)
449
stat_value = _fstat(file_obj.fileno())
450
if self.supports_content_filtering() and filtered:
451
filters = self._content_filter_stack(path)
452
file_obj = filtered_input_file(file_obj, filters)
453
return (file_obj, stat_value)
455
def get_file_text(self, file_id, path=None, filtered=True):
456
return self.get_file(file_id, path=path, filtered=filtered).read()
458
def get_file_byname(self, filename, filtered=True):
459
path = self.abspath(filename)
461
if self.supports_content_filtering() and filtered:
462
filters = self._content_filter_stack(filename)
463
return filtered_input_file(f, filters)
467
def get_file_lines(self, file_id, path=None, filtered=True):
446
468
"""See Tree.get_file_lines()"""
447
file = self.get_file(file_id, path)
469
file = self.get_file(file_id, path, filtered=filtered)
449
471
return file.readlines()
528
550
def clone(self, to_bzrdir, revision_id=None):
529
551
"""Duplicate this working tree into to_bzr, including all state.
531
553
Specifically modified files are kept as modified, but
532
554
ignored and unknown files are discarded.
534
556
If you want to make a new line of development, see bzrdir.sprout()
537
If not None, the cloned tree will have its last revision set to
559
If not None, the cloned tree will have its last revision set to
538
560
revision, and and difference between the source trees last revision
539
561
and this one merged in.
623
645
"""See MutableTree._add."""
624
646
# TODO: Re-adding a file that is removed in the working copy
625
647
# should probably put it back with the previous ID.
626
# the read and write working inventory should not occur in this
648
# the read and write working inventory should not occur in this
627
649
# function - they should be part of lock_write and unlock.
628
650
inv = self.inventory
629
651
for f, file_id, kind in zip(files, ids, kinds):
723
745
kind = 'tree-reference'
724
746
return kind, None, None, None
725
747
elif kind == 'symlink':
726
return ('symlink', None, None, os.readlink(abspath))
748
return ('symlink', None, None,
749
os.readlink(abspath.encode(osutils._fs_enc)
750
).decode(osutils._fs_enc))
728
752
return (kind, None, None, None)
766
790
@needs_tree_write_lock
767
791
def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
768
792
"""Set the parent ids to revision_ids.
770
794
See also set_parent_trees. This api will try to retrieve the tree data
771
795
for each element of revision_ids from the trees repository. If you have
772
796
tree data already available, it is more efficient to use
1003
1027
def _directory_may_be_tree_reference(self, relpath):
1004
# as a special case, if a directory contains control files then
1028
# as a special case, if a directory contains control files then
1005
1029
# it's a tree reference, except that the root of the tree is not
1006
1030
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1007
1031
# TODO: We could ask all the control formats whether they
1117
1141
# directory file_id, relative path, absolute path, reverse sorted children
1118
1142
children = os.listdir(self.basedir)
1119
1143
children.sort()
1120
# jam 20060527 The kernel sized tree seems equivalent whether we
1144
# jam 20060527 The kernel sized tree seems equivalent whether we
1121
1145
# use a deque and popleft to keep them sorted, or if we use a plain
1122
1146
# list and just reverse() them.
1123
1147
children = collections.deque(children)
1204
1228
to_dir must exist in the inventory.
1206
1230
If to_dir exists and is a directory, the files are moved into
1207
it, keeping their old names.
1231
it, keeping their old names.
1209
1233
Note that to_dir is only the last component of the new name;
1210
1234
this doesn't change the directory.
1487
1511
These are files in the working directory that are not versioned or
1488
1512
control files or ignored.
1490
# force the extras method to be fully executed before returning, to
1514
# force the extras method to be fully executed before returning, to
1491
1515
# prevent race conditions with the lock
1493
1517
[subp for subp in self.extras() if not self.is_ignored(subp)])
1509
1533
raise errors.NoSuchId(self, file_id)
1510
1534
if len(file_ids):
1511
# in the future this should just set a dirty bit to wait for the
1535
# in the future this should just set a dirty bit to wait for the
1512
1536
# final unlock. However, until all methods of workingtree start
1513
# with the current in -memory inventory rather than triggering
1537
# with the current in -memory inventory rather than triggering
1514
1538
# a read, it is more complex - we need to teach read_inventory
1515
1539
# to know when to read, and when to not read first... and possibly
1516
1540
# to save first when the in memory one may be corrupted.
1517
1541
# so for now, we just only write it if it is indeed dirty.
1518
1542
# - RBC 20060907
1519
1543
self._write_inventory(self._inventory)
1521
1545
def _iter_conflicts(self):
1522
1546
conflicted = set()
1523
1547
for info in self.list_files():
1566
1590
# reuse the revisiontree we merged against to set the new
1568
1592
parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1569
# we have to pull the merge trees out again, because
1570
# merge_inner has set the ids. - this corner is not yet
1593
# we have to pull the merge trees out again, because
1594
# merge_inner has set the ids. - this corner is not yet
1571
1595
# layered well enough to prevent double handling.
1572
1596
# XXX TODO: Fix the double handling: telling the tree about
1573
1597
# the already known parent data is wasteful.
1816
1840
# as commit already has that ready-to-use [while the format is the
1817
1841
# same, that is].
1819
# this double handles the inventory - unpack and repack -
1843
# this double handles the inventory - unpack and repack -
1820
1844
# but is easier to understand. We can/should put a conditional
1821
1845
# in here based on whether the inventory is in the latest format
1822
1846
# - perhaps we should repack all inventories on a repository
1824
1848
# the fast path is to copy the raw xml from the repository. If the
1825
# xml contains 'revision_id="', then we assume the right
1849
# xml contains 'revision_id="', then we assume the right
1826
1850
# revision_id is set. We must check for this full string, because a
1827
1851
# root node id can legitimately look like 'revision_id' but cannot
1828
1852
# contain a '"'.
1829
1853
xml = self.branch.repository.get_inventory_xml(new_revision)
1830
1854
firstline = xml.split('\n', 1)[0]
1831
if (not 'revision_id="' in firstline or
1855
if (not 'revision_id="' in firstline or
1832
1856
'format="7"' not in firstline):
1833
1857
inv = self.branch.repository.deserialise_inventory(
1834
1858
new_revision, xml)
1841
1865
"""Read the cached basis inventory."""
1842
1866
path = self._basis_inventory_name()
1843
1867
return self._transport.get_bytes(path)
1845
1869
@needs_read_lock
1846
1870
def read_working_inventory(self):
1847
1871
"""Read the working inventory.
1849
1873
:raises errors.InventoryModified: read_working_inventory will fail
1850
1874
when the current in memory inventory has been modified.
1852
# conceptually this should be an implementation detail of the tree.
1876
# conceptually this should be an implementation detail of the tree.
1853
1877
# XXX: Deprecate this.
1854
1878
# ElementTree does its own conversion from UTF-8, so open in
2052
2076
name = os.path.basename(path)
2055
# fixme, there should be a factory function inv,add_??
2079
# fixme, there should be a factory function inv,add_??
2056
2080
if kind == 'directory':
2057
2081
inv.add(InventoryDirectory(file_id, name, parent))
2058
2082
elif kind == 'file':
2076
2100
def _set_root_id(self, file_id):
2077
2101
"""Set the root id for this tree, in a format specific manner.
2079
:param file_id: The file id to assign to the root. It must not be
2103
:param file_id: The file id to assign to the root. It must not be
2080
2104
present in the current inventory or an error will occur. It must
2081
2105
not be None, but rather a valid file id.
2102
2126
def unlock(self):
2103
2127
"""See Branch.unlock.
2105
2129
WorkingTree locking just uses the Branch locking facilities.
2106
2130
This is current because all working trees have an embedded branch
2107
2131
within them. IF in the future, we were to make branch data shareable
2108
between multiple working trees, i.e. via shared storage, then we
2132
between multiple working trees, i.e. via shared storage, then we
2109
2133
would probably want to lock both the local tree, and the branch.
2111
2135
raise NotImplementedError(self.unlock)
2163
2187
# cant set that until we update the working trees last revision to be
2164
2188
# one from the new branch, because it will just get absorbed by the
2165
2189
# parent de-duplication logic.
2167
2191
# We MUST save it even if an error occurs, because otherwise the users
2168
2192
# local work is unreferenced and will appear to have been lost.
2172
2196
last_rev = self.get_parent_ids()[0]
2659
2683
* a format string,
2660
2684
* an open routine.
2662
Formats are placed in an dict by their format string for reference
2686
Formats are placed in an dict by their format string for reference
2663
2687
during workingtree opening. Its not required that these be instances, they
2664
can be classes themselves with class methods - it simply depends on
2688
can be classes themselves with class methods - it simply depends on
2665
2689
whether state is needed for a given format or not.
2667
2691
Once a format is deprecated, just deprecate the initialize and open
2668
methods on the format class. Do not deprecate the object, as the
2692
methods on the format class. Do not deprecate the object, as the
2669
2693
object will be created every time regardless.
2858
2882
def _open_control_files(self, a_bzrdir):
2859
2883
transport = a_bzrdir.get_workingtree_transport(None)
2860
return LockableFiles(transport, self._lock_file_name,
2884
return LockableFiles(transport, self._lock_file_name,
2861
2885
self._lock_class)
2863
2887
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2864
2888
accelerator_tree=None, hardlink=False):
2865
2889
"""See WorkingTreeFormat.initialize().
2867
2891
:param revision_id: if supplied, create a working tree at a different
2868
2892
revision than the branch is at.
2869
2893
:param accelerator_tree: A tree which can be used for retrieving file