448
451
def has_filename(self, filename):
449
452
return osutils.lexists(self.abspath(filename))
451
def get_file(self, file_id):
452
file_id = osutils.safe_file_id(file_id)
453
return self.get_file_byname(self.id2path(file_id))
454
def get_file(self, file_id, path=None):
456
file_id = osutils.safe_file_id(file_id)
457
path = self.id2path(file_id)
458
return self.get_file_byname(path)
455
460
def get_file_text(self, file_id):
456
461
file_id = osutils.safe_file_id(file_id)
460
465
return file(self.abspath(filename), 'rb')
463
def annotate_iter(self, file_id):
468
def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
464
469
"""See Tree.annotate_iter
466
471
This implementation will use the basis tree implementation if possible.
494
499
old.append(list(tree.annotate_iter(file_id)))
495
500
return annotate.reannotate(old, self.get_file(file_id).readlines(),
505
def _get_ancestors(self, default_revision):
506
ancestors = set([default_revision])
507
for parent_id in self.get_parent_ids():
508
ancestors.update(self.branch.repository.get_ancestry(
509
parent_id, topo_sorted=False))
500
512
def get_parent_ids(self):
501
513
"""See Tree.get_parent_ids.
793
805
self._control_files.put(filename, my_file)
795
807
@needs_write_lock # because merge pulls data into the branch.
796
def merge_from_branch(self, branch, to_revision=None):
808
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
797
810
"""Merge from a branch into this working tree.
799
812
:param branch: The branch to merge from.
824
837
merger.other_rev_id)
825
838
merger.other_branch = branch
826
839
merger.pp.next_phase()
840
if from_revision is None:
843
merger.set_base_revision(from_revision, branch)
828
844
if merger.base_rev_id == merger.other_rev_id:
829
845
raise errors.PointlessMerge
830
846
merger.backup_files = False
831
merger.merge_type = Merge3Merger
847
if merge_type is None:
848
merger.merge_type = Merge3Merger
850
merger.merge_type = merge_type
832
851
merger.set_interesting_files(None)
833
852
merger.show_base = False
834
853
merger.reprocess = False
978
997
def _serialize(self, inventory, out_file):
979
xml5.serializer_v5.write_inventory(self._inventory, out_file)
998
xml5.serializer_v5.write_inventory(self._inventory, out_file,
981
1001
def _deserialize(selt, in_file):
982
1002
return xml5.serializer_v5.read_inventory(in_file)
1774
1794
:force: Delete files and directories, even if they are changed and
1775
1795
even if the directories are not empty.
1777
## TODO: Normalize names
1779
1797
if isinstance(files, basestring):
1780
1798
files = [files]
1784
1802
new_files=set()
1785
unknown_files_in_directory=set()
1803
unknown_nested_files=set()
1787
1805
def recurse_directory_to_add_files(directory):
1788
# recurse directory and add all files
1806
# Recurse directory and add all files
1789
1807
# so we can check if they have changed.
1790
1808
for parent_info, file_infos in\
1791
1809
osutils.walkdirs(self.abspath(directory),
1793
1811
for relpath, basename, kind, lstat, abspath in file_infos:
1795
if self.path2id(relpath): #is it versioned?
1796
new_files.add(relpath)
1798
unknown_files_in_directory.add(
1799
(relpath, None, kind))
1812
# Is it versioned or ignored?
1813
if self.path2id(relpath) or self.is_ignored(relpath):
1814
# Add nested content for deletion.
1815
new_files.add(relpath)
1817
# Files which are not versioned and not ignored
1818
# should be treated as unknown.
1819
unknown_nested_files.add((relpath, None, kind))
1801
1821
for filename in files:
1802
1822
# Get file name into canonical form.
1806
1826
new_files.add(filename)
1807
1827
if osutils.isdir(abspath):
1808
1828
recurse_directory_to_add_files(filename)
1809
files = [f for f in new_files]
1830
files = list(new_files)
1811
1832
if len(files) == 0:
1812
1833
return # nothing to do
1814
1835
# Sort needed to first handle directory content before the directory
1815
1836
files.sort(reverse=True)
1838
# Bail out if we are going to delete files we shouldn't
1816
1839
if not keep_files and not force:
1817
has_changed_files = len(unknown_files_in_directory) > 0
1840
has_changed_files = len(unknown_nested_files) > 0
1818
1841
if not has_changed_files:
1819
1842
for (file_id, path, content_change, versioned, parent_id, name,
1820
1843
kind, executable) in self._iter_changes(self.basis_tree(),
1821
1844
include_unchanged=True, require_versioned=False,
1822
1845
want_unversioned=True, specific_files=files):
1823
# check if it's unknown OR changed but not deleted:
1824
if (versioned == (False, False)
1825
or (content_change and kind[1] != None)):
1846
# Check if it's an unknown (but not ignored) OR
1847
# changed (but not deleted) :
1848
if not self.is_ignored(path[1]) and (
1849
versioned == (False, False) or
1850
content_change and kind[1] != None):
1826
1851
has_changed_files = True
1829
1854
if has_changed_files:
1830
# make delta to show ALL applicable changes in error message.
1855
# Make delta show ALL applicable changes in error message.
1831
1856
tree_delta = self.changes_from(self.basis_tree(),
1857
require_versioned=False, want_unversioned=True,
1832
1858
specific_files=files)
1833
for unknown_file in unknown_files_in_directory:
1834
tree_delta.unversioned.extend((unknown_file,))
1859
for unknown_file in unknown_nested_files:
1860
if unknown_file not in tree_delta.unversioned:
1861
tree_delta.unversioned.extend((unknown_file,))
1835
1862
raise errors.BzrRemoveChangedFilesError(tree_delta)
1837
# do this before any modifications
1864
# Build inv_delta and delete files where applicaple,
1865
# do this before any modifications to inventory.
1838
1866
for f in files:
1839
1867
fid = self.path2id(f)
1842
message="%s is not versioned." % (f,)
1870
message = "%s is not versioned." % (f,)
1845
1873
# having removed it, it must be either ignored or unknown
1849
1877
new_status = '?'
1850
1878
textui.show_status(new_status, self.kind(fid), f,
1851
1879
to_file=to_file)
1853
1881
inv_delta.append((f, None, fid, None))
1854
message="removed %s" % (f,)
1882
message = "removed %s" % (f,)
1856
1884
if not keep_files:
1857
1885
abs_path = self.abspath(f)
1858
1886
if osutils.lexists(abs_path):
1859
1887
if (osutils.isdir(abs_path) and
1860
1888
len(os.listdir(abs_path)) > 0):
1861
message="%s is not empty directory "\
1862
"and won't be deleted." % (f,)
1890
osutils.rmtree(abs_path)
1892
message = "%s is not an empty directory "\
1893
"and won't be deleted." % (f,)
1864
1895
osutils.delete_any(abs_path)
1865
message="deleted %s" % (f,)
1896
message = "deleted %s" % (f,)
1866
1897
elif message is not None:
1867
# only care if we haven't done anything yet.
1868
message="%s does not exist." % (f,)
1898
# Only care if we haven't done anything yet.
1899
message = "%s does not exist." % (f,)
1870
# print only one message (if any) per file.
1901
# Print only one message (if any) per file.
1871
1902
if message is not None:
1873
1904
self.apply_inventory_delta(inv_delta)
1875
1906
@needs_tree_write_lock
1876
def revert(self, filenames, old_tree=None, backups=True,
1907
def revert(self, filenames=None, old_tree=None, backups=True,
1877
1908
pb=DummyProgress(), report_changes=False):
1878
1909
from bzrlib.conflicts import resolve
1912
symbol_versioning.warn('Using [] to revert all files is deprecated'
1913
' as of bzr 0.91. Please use None (the default) instead.',
1914
DeprecationWarning, stacklevel=2)
1879
1915
if old_tree is None:
1880
1916
old_tree = self.basis_tree()
1881
1917
conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1882
1918
report_changes)
1883
if not len(filenames):
1919
if filenames is None:
1884
1920
self.set_parent_ids(self.get_parent_ids()[:1])
1988
2024
raise NotImplementedError(self.unlock)
1990
def update(self, change_reporter=None):
2026
def update(self, change_reporter=None, possible_transports=None):
1991
2027
"""Update a working tree along its branch.
1993
2029
This will update the branch if its bound too, which means we have
2423
2462
return osutils.safe_revision_id(
2424
2463
self._control_files.get('last-revision').read())
2425
2464
except errors.NoSuchFile:
2465
return _mod_revision.NULL_REVISION
2428
2467
def _change_last_revision(self, revision_id):
2429
2468
"""See WorkingTree._change_last_revision."""