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