55
55
class AddAction(object):
56
56
"""A class which defines what action to take when adding a file."""
58
def __init__(self, to_file=None, should_add=None, should_print=None):
58
def __init__(self, to_file=None, should_print=None):
59
59
self._to_file = to_file
60
60
if to_file is None:
61
61
self._to_file = sys.stdout
62
self.should_add = False
63
if should_add is not None:
64
self.should_add = should_add
65
62
self.should_print = False
66
63
if should_print is not None:
67
64
self.should_print = should_print
75
72
:param path: The FastPath being added
76
73
:param kind: The kind of the object being added.
79
self._add_to_inv(inv, parent_ie, path, kind)
81
self._print(inv, parent_ie, path, kind)
83
def _print(self, inv, parent_ie, path, kind):
84
"""Print a line to self._to_file for each file that would be added."""
75
if not self.should_print:
85
77
self._to_file.write('added ')
86
78
self._to_file.write(bzrlib.osutils.quotefn(path.raw_path))
87
79
self._to_file.write('\n')
89
def _add_to_inv(self, inv, parent_ie, path, kind):
90
"""Add each file to the given inventory. Produce no output."""
91
if parent_ie is not None:
92
entry = bzrlib.inventory.make_entry(
93
kind, bzrlib.osutils.basename(path.raw_path), parent_ie.file_id)
96
entry = inv.add_path(path.raw_path, kind=kind)
97
# mutter("added %r kind %r file_id={%s}", path, kind, entry.file_id)
100
82
# TODO: jam 20050105 These could be used for compatibility
101
83
# however, they bind against the current stdout, not the
102
84
# one which exists at the time they are called, so they
103
85
# don't work for the test suite.
105
add_action_null = AddAction()
106
add_action_add = AddAction(should_add=True)
107
add_action_print = AddAction(should_print=True)
108
add_action_add_and_print = AddAction(should_add=True, should_print=True)
111
def smart_add(file_list, recurse=True, action=None):
87
add_action_add = AddAction()
88
add_action_null = add_action_add
89
add_action_add_and_print = AddAction(should_print=True)
90
add_action_print = add_action_add_and_print
93
def smart_add(file_list, recurse=True, action=None, save=True):
112
94
"""Add files to version, optionally recursing into directories.
114
96
This is designed more towards DWIM for humans than API simplicity.
115
97
For the specific behaviour see the help for cmd_add().
117
99
Returns the number of files added.
100
Please see smart_add_tree for more detail.
119
102
file_list = _prepare_file_list(file_list)
120
103
tree = WorkingTree.open_containing(file_list[0])[0]
135
118
self.raw_path = path
138
def smart_add_tree(tree, file_list, recurse=True, action=None):
121
def smart_add_tree(tree, file_list, recurse=True, action=None, save=True):
139
122
"""Add files to version, optionally recursing into directories.
141
124
This is designed more towards DWIM for humans than API simplicity.
144
127
This calls reporter with each (path, kind, file_id) of added files.
146
129
Returns the number of files added.
131
:param save: Save the inventory after completing the adds. If False this
132
provides dry-run functionality by doing the add and not saving the
133
inventory. Note that the modified inventory is left in place, allowing
134
further dry-run tasks to take place. To restore the original inventory
135
call tree.read_working_inventory().
149
138
from bzrlib.errors import BadFileKindError, ForbiddenFileError
150
139
assert isinstance(recurse, bool)
151
140
if action is None:
152
action = AddAction(should_add=True)
154
143
prepared_list = _prepare_file_list(file_list)
155
144
mutter("smart add of %r, originally %r", prepared_list, file_list)
172
161
abspath = tree.abspath(rf.raw_path)
173
162
kind = bzrlib.osutils.file_kind(abspath)
174
163
if kind == 'directory':
175
# schedule the dir for later
164
# schedule the dir for scanning
176
165
user_dirs.add(rf.raw_path)
178
167
if not InventoryEntry.versionable_kind(kind):
179
168
raise BadFileKindError("cannot add %s of type %s" % (abspath, kind))
180
# we dont have a parent ie known yet.: use the relatively slower inventory
182
versioned = inv.has_filename(rf.raw_path)
185
added.extend(__add_one(tree, inv, None, rf, kind, action))
169
# ensure the named path is added, so that ignore rules in the later directory
171
# we dont have a parent ie known yet.: use the relatively slower inventory
173
versioned = inv.has_filename(rf.raw_path)
176
added.extend(__add_one(tree, inv, None, rf, kind, action))
179
# no need to walk any directories at all.
180
if len(added) > 0 and save:
181
tree._write_inventory(inv)
182
return added, ignored
187
184
# only walk the minimal parents needed: we have user_dirs to override
236
233
added.extend(__add_one(tree, inv, parent_ie, directory, kind, action))
238
if kind == 'directory' and recurse and not sub_tree:
240
if parent_ie is not None:
242
this_ie = parent_ie.children[directory.base_path]
235
if kind == 'directory' and not sub_tree:
236
if parent_ie is not None:
238
this_ie = parent_ie.children[directory.base_path]
240
# without the parent ie, use the relatively slower inventory
242
this_id = inv.path2id(directory.raw_path)
244
# without the parent ie, use the relatively slower inventory
246
this_id = inv.path2id(directory.raw_path)
250
this_ie = inv[this_id]
246
this_ie = inv[this_id]
254
248
for subf in os.listdir(abspath):
255
249
# here we could use TreeDirectory rather than
262
256
if tree.is_control_filename(subp):
263
257
mutter("skip control directory %r", subp)
258
elif subf in this_ie.children:
259
# recurse into this already versioned subdir.
260
dirs_to_add.append((FastPath(subp, subf), this_ie))
265
262
# user selection overrides ignoes
266
if subp in user_dirs:
267
dirs_to_add.append((FastPath(subp, subf), this_ie))
269
263
# ignore while selecting files - if we globbed in the
270
264
# outer loop we would ignore user files.
271
265
ignore_glob = tree.is_ignored(subp)
313
307
# generally find it very fast and not recurse after that.
314
308
added = __add_one(tree, inv, None, FastPath(dirname(path.raw_path)), 'directory', action)
315
309
parent_id = inv.path2id(dirname(path.raw_path))
316
if parent_id is not None:
310
if parent_id is None:
317
311
parent_ie = inv[inv.path2id(dirname(path.raw_path))]
313
parent_ie = inv[parent_id]
320
314
action(inv, parent_ie, path, kind)
315
#if parent_ie is not None:
316
entry = bzrlib.inventory.make_entry(
317
kind, bzrlib.osutils.basename(path.raw_path), parent_ie.file_id)
320
# entry = inv.add_path(path.raw_path, kind=kind)
322
323
return added + [path.raw_path]