1763
1769
@needs_tree_write_lock
1764
def remove(self, files, verbose=False, to_file=None, keep_files=True,
1766
"""Remove nominated files from the working inventor.
1768
:files: File paths relative to the basedir.
1769
:keep_files: If true, the files will also be kept.
1770
:force: Delete files and directories, even if they are changed and
1771
even if the directories are not empty.
1770
def remove(self, files, verbose=False, to_file=None):
1771
"""Remove nominated files from the working inventory..
1773
This does not remove their text. This does not run on XXX on what? RBC
1775
TODO: Refuse to remove modified files unless --force is given?
1777
TODO: Do something useful with directories.
1779
TODO: Should this remove the text or not? Tough call; not
1780
removing may be useful and the user can just use use rm, and
1781
is the opposite of add. Removing it is consistent with most
1782
other tools. Maybe an option.
1773
1784
## TODO: Normalize names
1785
## TODO: Remove nested loops; better scalability
1775
1786
if isinstance(files, basestring):
1776
1787
files = [files]
1781
unknown_files_in_directory=set()
1783
def recurse_directory_to_add_files(directory):
1784
# recurse directory and add all files
1785
# so we can check if they have changed.
1786
for parent_info, file_infos in\
1787
osutils.walkdirs(self.abspath(directory),
1789
for relpath, basename, kind, lstat, abspath in file_infos:
1791
if self.path2id(relpath): #is it versioned?
1792
new_files.add(relpath)
1794
unknown_files_in_directory.add(
1795
(relpath, None, kind))
1797
for filename in files:
1798
# Get file name into canonical form.
1799
abspath = self.abspath(filename)
1800
filename = self.relpath(abspath)
1801
if len(filename) > 0:
1802
new_files.add(filename)
1803
if osutils.isdir(abspath):
1804
recurse_directory_to_add_files(filename)
1805
files = [f for f in new_files]
1807
# Sort needed to first handle directory content before the directory
1808
files.sort(reverse=True)
1809
if not keep_files and not force:
1810
tree_delta = self.changes_from(self.basis_tree(),
1811
specific_files=files)
1812
for unknown_file in unknown_files_in_directory:
1813
tree_delta.unversioned.extend((unknown_file,))
1814
if bool(tree_delta.modified
1816
or tree_delta.renamed
1817
or tree_delta.kind_changed
1818
or tree_delta.unversioned):
1819
raise errors.BzrRemoveChangedFilesError(tree_delta)
1789
inv = self.inventory
1821
1791
# do this before any modifications
1822
1792
for f in files:
1823
fid = self.path2id(f)
1793
fid = inv.path2id(f)
1826
message="%s is not versioned." % (f,)
1795
note("%s is not versioned."%f)
1829
# having removed it, it must be either ignored or unknown
1798
# having remove it, it must be either ignored or unknown
1830
1799
if self.is_ignored(f):
1831
1800
new_status = 'I'
1833
1802
new_status = '?'
1834
textui.show_status(new_status, self.kind(fid), f,
1803
textui.show_status(new_status, inv[fid].kind, f,
1835
1804
to_file=to_file)
1837
inv_delta.append((f, None, fid, None))
1838
message="removed %s" % (f,)
1841
abs_path = self.abspath(f)
1842
if osutils.lexists(abs_path):
1843
if (osutils.isdir(abs_path) and
1844
len(os.listdir(abs_path)) > 0):
1845
message="%s is not empty directory "\
1846
"and won't be deleted." % (f,)
1848
osutils.delete_any(abs_path)
1849
message="deleted %s" % (f,)
1850
elif message is not None:
1851
# only care if we haven't done anything yet.
1852
message="%s does not exist." % (f,)
1854
# print only one message (if any) per file.
1855
if message is not None:
1857
self.apply_inventory_delta(inv_delta)
1807
self._write_inventory(inv)
1859
1809
@needs_tree_write_lock
1860
1810
def revert(self, filenames, old_tree=None, backups=True,
2152
2106
def walkdirs(self, prefix=""):
2153
2107
"""Walk the directories of this tree.
2155
returns a generator which yields items in the form:
2156
((curren_directory_path, fileid),
2157
[(file1_path, file1_name, file1_kind, (lstat), file1_id,
2160
2109
This API returns a generator, which is only valid during the current
2161
2110
tree transaction - within a single lock_read or lock_write duration.
2163
If the tree is not locked, it may cause an error to be raised,
2164
depending on the tree implementation.
2112
If the tree is not locked, it may cause an error to be raised, depending
2113
on the tree implementation.
2166
2115
disk_top = self.abspath(prefix)
2167
2116
if disk_top.endswith('/'):