13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
124
129
class TreeEntry(object):
125
130
"""An entry that implements the minimum interface used by commands.
127
This needs further inspection, it may be better to have
132
This needs further inspection, it may be better to have
128
133
InventoryEntries without ids - though that seems wrong. For now,
129
134
this is a parallel hierarchy to InventoryEntry, and needs to become
130
135
one of several things: decorates to that hierarchy, children of, or
133
138
no InventoryEntry available - i.e. for unversioned objects.
134
139
Perhaps they should be UnversionedEntry et al. ? - RBC 20051003
137
142
def __eq__(self, other):
138
143
# yes, this us ugly, TODO: best practice __eq__ style.
139
144
return (isinstance(other, TreeEntry)
140
145
and other.__class__ == self.__class__)
142
147
def kind_character(self):
230
235
wt_trans = self.bzrdir.get_workingtree_transport(None)
231
236
cache_filename = wt_trans.local_abspath('stat-cache')
232
237
self._hashcache = hashcache.HashCache(basedir, cache_filename,
233
self.bzrdir._get_file_mode())
238
self.bzrdir._get_file_mode(),
239
self._content_filter_stack_provider())
234
240
hc = self._hashcache
236
242
# is this scan needed ? it makes things kinda slow.
435
441
def has_filename(self, filename):
436
442
return osutils.lexists(self.abspath(filename))
438
def get_file(self, file_id, path=None):
439
return self.get_file_with_stat(file_id, path)[0]
444
def get_file(self, file_id, path=None, filtered=True):
445
return self.get_file_with_stat(file_id, path, filtered=filtered)[0]
441
def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
447
def get_file_with_stat(self, file_id, path=None, filtered=True,
442
449
"""See MutableTree.get_file_with_stat."""
444
451
path = self.id2path(file_id)
445
file_obj = self.get_file_byname(path)
446
return (file_obj, _fstat(file_obj.fileno()))
448
def get_file_byname(self, filename):
449
return file(self.abspath(filename), 'rb')
451
def get_file_lines(self, file_id, path=None):
452
file_obj = self.get_file_byname(path, filtered=False)
453
stat_value = _fstat(file_obj.fileno())
454
if self.supports_content_filtering() and filtered:
455
filters = self._content_filter_stack(path)
456
file_obj = filtered_input_file(file_obj, filters)
457
return (file_obj, stat_value)
459
def get_file_text(self, file_id, path=None, filtered=True):
460
return self.get_file(file_id, path=path, filtered=filtered).read()
462
def get_file_byname(self, filename, filtered=True):
463
path = self.abspath(filename)
465
if self.supports_content_filtering() and filtered:
466
filters = self._content_filter_stack(filename)
467
return filtered_input_file(f, filters)
471
def get_file_lines(self, file_id, path=None, filtered=True):
452
472
"""See Tree.get_file_lines()"""
453
file = self.get_file(file_id, path)
473
file = self.get_file(file_id, path, filtered=filtered)
455
475
return file.readlines()
534
554
def clone(self, to_bzrdir, revision_id=None):
535
555
"""Duplicate this working tree into to_bzr, including all state.
537
557
Specifically modified files are kept as modified, but
538
558
ignored and unknown files are discarded.
540
560
If you want to make a new line of development, see bzrdir.sprout()
543
If not None, the cloned tree will have its last revision set to
563
If not None, the cloned tree will have its last revision set to
544
564
revision, and difference between the source trees last revision
545
565
and this one merged in.
629
649
"""See MutableTree._add."""
630
650
# TODO: Re-adding a file that is removed in the working copy
631
651
# should probably put it back with the previous ID.
632
# the read and write working inventory should not occur in this
652
# the read and write working inventory should not occur in this
633
653
# function - they should be part of lock_write and unlock.
634
654
inv = self.inventory
635
655
for f, file_id, kind in zip(files, ids, kinds):
729
749
kind = 'tree-reference'
730
750
return kind, None, None, None
731
751
elif kind == 'symlink':
732
return ('symlink', None, None, os.readlink(abspath.encode(osutils._fs_enc)))
752
return ('symlink', None, None,
753
os.readlink(abspath.encode(osutils._fs_enc)
754
).decode(osutils._fs_enc))
734
756
return (kind, None, None, None)
748
770
def _set_merges_from_parent_ids(self, parent_ids):
749
771
merges = parent_ids[1:]
750
772
self._transport.put_bytes('pending-merges', '\n'.join(merges),
751
mode=self._control_files._file_mode)
773
mode=self.bzrdir._get_file_mode())
753
775
def _filter_parent_ids_by_ancestry(self, revision_ids):
754
776
"""Check that all merged revisions are proper 'heads'.
756
778
This will always return the first revision_id, and any merged revisions
759
781
if len(revision_ids) == 0:
760
782
return revision_ids
772
794
@needs_tree_write_lock
773
795
def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
774
796
"""Set the parent ids to revision_ids.
776
798
See also set_parent_trees. This api will try to retrieve the tree data
777
799
for each element of revision_ids from the trees repository. If you have
778
800
tree data already available, it is more efficient to use
854
876
self._must_be_locked()
855
877
my_file = rio_file(stanzas, header)
856
878
self._transport.put_file(filename, my_file,
857
mode=self._control_files._file_mode)
879
mode=self.bzrdir._get_file_mode())
859
881
@needs_write_lock # because merge pulls data into the branch.
860
882
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
1009
1032
def _directory_may_be_tree_reference(self, relpath):
1010
# as a special case, if a directory contains control files then
1033
# as a special case, if a directory contains control files then
1011
1034
# it's a tree reference, except that the root of the tree is not
1012
1035
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
1013
1036
# TODO: We could ask all the control formats whether they
1086
1109
self._serialize(self._inventory, sio)
1088
1111
self._transport.put_file('inventory', sio,
1089
mode=self._control_files._file_mode)
1112
mode=self.bzrdir._get_file_mode())
1090
1113
self._inventory_is_modified = False
1092
1115
def _kind(self, relpath):
1123
1146
# directory file_id, relative path, absolute path, reverse sorted children
1124
1147
children = os.listdir(self.basedir)
1125
1148
children.sort()
1126
# jam 20060527 The kernel sized tree seems equivalent whether we
1149
# jam 20060527 The kernel sized tree seems equivalent whether we
1127
1150
# use a deque and popleft to keep them sorted, or if we use a plain
1128
1151
# list and just reverse() them.
1129
1152
children = collections.deque(children)
1210
1233
to_dir must exist in the inventory.
1212
1235
If to_dir exists and is a directory, the files are moved into
1213
it, keeping their old names.
1236
it, keeping their old names.
1215
1238
Note that to_dir is only the last component of the new name;
1216
1239
this doesn't change the directory.
1493
1516
These are files in the working directory that are not versioned or
1494
1517
control files or ignored.
1496
# force the extras method to be fully executed before returning, to
1519
# force the extras method to be fully executed before returning, to
1497
1520
# prevent race conditions with the lock
1499
1522
[subp for subp in self.extras() if not self.is_ignored(subp)])
1509
1532
:raises: NoSuchId if any fileid is not currently versioned.
1511
1534
for file_id in file_ids:
1535
if file_id not in self._inventory:
1536
raise errors.NoSuchId(self, file_id)
1537
for file_id in file_ids:
1512
1538
if self._inventory.has_id(file_id):
1513
1539
self._inventory.remove_recursive_id(file_id)
1515
raise errors.NoSuchId(self, file_id)
1516
1540
if len(file_ids):
1517
# in the future this should just set a dirty bit to wait for the
1541
# in the future this should just set a dirty bit to wait for the
1518
1542
# final unlock. However, until all methods of workingtree start
1519
# with the current in -memory inventory rather than triggering
1543
# with the current in -memory inventory rather than triggering
1520
1544
# a read, it is more complex - we need to teach read_inventory
1521
1545
# to know when to read, and when to not read first... and possibly
1522
1546
# to save first when the in memory one may be corrupted.
1523
1547
# so for now, we just only write it if it is indeed dirty.
1524
1548
# - RBC 20060907
1525
1549
self._write_inventory(self._inventory)
1527
1551
def _iter_conflicts(self):
1528
1552
conflicted = set()
1529
1553
for info in self.list_files():
1572
1596
# reuse the revisiontree we merged against to set the new
1574
1598
parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1575
# we have to pull the merge trees out again, because
1576
# merge_inner has set the ids. - this corner is not yet
1599
# we have to pull the merge trees out again, because
1600
# merge_inner has set the ids. - this corner is not yet
1577
1601
# layered well enough to prevent double handling.
1578
1602
# XXX TODO: Fix the double handling: telling the tree about
1579
1603
# the already known parent data is wasteful.
1809
1833
path = self._basis_inventory_name()
1810
1834
sio = StringIO(xml)
1811
1835
self._transport.put_file(path, sio,
1812
mode=self._control_files._file_mode)
1836
mode=self.bzrdir._get_file_mode())
1814
1838
def _create_basis_xml_from_inventory(self, revision_id, inventory):
1815
1839
"""Create the text that will be saved in basis-inventory"""
1822
1846
# as commit already has that ready-to-use [while the format is the
1823
1847
# same, that is].
1825
# this double handles the inventory - unpack and repack -
1849
# this double handles the inventory - unpack and repack -
1826
1850
# but is easier to understand. We can/should put a conditional
1827
1851
# in here based on whether the inventory is in the latest format
1828
1852
# - perhaps we should repack all inventories on a repository
1830
1854
# the fast path is to copy the raw xml from the repository. If the
1831
# xml contains 'revision_id="', then we assume the right
1855
# xml contains 'revision_id="', then we assume the right
1832
1856
# revision_id is set. We must check for this full string, because a
1833
1857
# root node id can legitimately look like 'revision_id' but cannot
1834
1858
# contain a '"'.
1835
1859
xml = self.branch.repository.get_inventory_xml(new_revision)
1836
1860
firstline = xml.split('\n', 1)[0]
1837
if (not 'revision_id="' in firstline or
1861
if (not 'revision_id="' in firstline or
1838
1862
'format="7"' not in firstline):
1839
1863
inv = self.branch.repository.deserialise_inventory(
1840
1864
new_revision, xml)
1847
1871
"""Read the cached basis inventory."""
1848
1872
path = self._basis_inventory_name()
1849
1873
return self._transport.get_bytes(path)
1851
1875
@needs_read_lock
1852
1876
def read_working_inventory(self):
1853
1877
"""Read the working inventory.
1855
1879
:raises errors.InventoryModified: read_working_inventory will fail
1856
1880
when the current in memory inventory has been modified.
1858
# conceptually this should be an implementation detail of the tree.
1882
# conceptually this should be an implementation detail of the tree.
1859
1883
# XXX: Deprecate this.
1860
1884
# ElementTree does its own conversion from UTF-8, so open in
2058
2082
name = os.path.basename(path)
2061
# fixme, there should be a factory function inv,add_??
2085
# fixme, there should be a factory function inv,add_??
2062
2086
if kind == 'directory':
2063
2087
inv.add(InventoryDirectory(file_id, name, parent))
2064
2088
elif kind == 'file':
2082
2106
def _set_root_id(self, file_id):
2083
2107
"""Set the root id for this tree, in a format specific manner.
2085
:param file_id: The file id to assign to the root. It must not be
2109
:param file_id: The file id to assign to the root. It must not be
2086
2110
present in the current inventory or an error will occur. It must
2087
2111
not be None, but rather a valid file id.
2108
2132
def unlock(self):
2109
2133
"""See Branch.unlock.
2111
2135
WorkingTree locking just uses the Branch locking facilities.
2112
2136
This is current because all working trees have an embedded branch
2113
2137
within them. IF in the future, we were to make branch data shareable
2114
between multiple working trees, i.e. via shared storage, then we
2138
between multiple working trees, i.e. via shared storage, then we
2115
2139
would probably want to lock both the local tree, and the branch.
2117
2141
raise NotImplementedError(self.unlock)
2169
2193
# cant set that until we update the working trees last revision to be
2170
2194
# one from the new branch, because it will just get absorbed by the
2171
2195
# parent de-duplication logic.
2173
2197
# We MUST save it even if an error occurs, because otherwise the users
2174
2198
# local work is unreferenced and will appear to have been lost.
2178
2202
last_rev = self.get_parent_ids()[0]
2607
2631
self._transport.put_bytes('last-revision', revision_id,
2608
mode=self._control_files._file_mode)
2632
mode=self.bzrdir._get_file_mode())
2611
2635
@needs_tree_write_lock
2612
2636
def set_conflicts(self, conflicts):
2613
self._put_rio('conflicts', conflicts.to_stanzas(),
2637
self._put_rio('conflicts', conflicts.to_stanzas(),
2614
2638
CONFLICT_HEADER_1)
2616
2640
@needs_tree_write_lock
2665
2689
* a format string,
2666
2690
* an open routine.
2668
Formats are placed in an dict by their format string for reference
2692
Formats are placed in an dict by their format string for reference
2669
2693
during workingtree opening. Its not required that these be instances, they
2670
can be classes themselves with class methods - it simply depends on
2694
can be classes themselves with class methods - it simply depends on
2671
2695
whether state is needed for a given format or not.
2673
2697
Once a format is deprecated, just deprecate the initialize and open
2674
methods on the format class. Do not deprecate the object, as the
2698
methods on the format class. Do not deprecate the object, as the
2675
2699
object will be created every time regardless.
2864
2888
def _open_control_files(self, a_bzrdir):
2865
2889
transport = a_bzrdir.get_workingtree_transport(None)
2866
return LockableFiles(transport, self._lock_file_name,
2890
return LockableFiles(transport, self._lock_file_name,
2867
2891
self._lock_class)
2869
2893
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2870
2894
accelerator_tree=None, hardlink=False):
2871
2895
"""See WorkingTreeFormat.initialize().
2873
2897
:param revision_id: if supplied, create a working tree at a different
2874
2898
revision than the branch is at.
2875
2899
:param accelerator_tree: A tree which can be used for retrieving file
2886
2910
control_files.create_lock()
2887
2911
control_files.lock_write()
2888
2912
transport.put_bytes('format', self.get_format_string(),
2889
mode=control_files._file_mode)
2913
mode=a_bzrdir._get_file_mode())
2890
2914
if from_branch is not None:
2891
2915
branch = from_branch