64
58
A mutable tree always has an associated Branch and ControlDir object - the
65
59
branch and bzrdir attributes.
67
62
def __init__(self, *args, **kw):
68
63
super(MutableTree, self).__init__(*args, **kw)
69
64
# Is this tree on a case-insensitive or case-preserving file-system?
89
84
Note that the command line normally calls smart_add instead,
90
85
which can automatically recurse.
92
This adds the files to the inventory, so that they will be
87
This adds the files to the tree, so that they will be
93
88
recorded by the next commit.
95
90
:param files: List of paths to add, relative to the base of the tree.
102
97
TODO: Perhaps callback with the ids and paths as they're added.
104
if isinstance(files, (str, text_type)):
99
if isinstance(files, str):
105
100
# XXX: Passing a single string is inconsistent and should be
107
if not (ids is None or isinstance(ids, (str, text_type))):
102
if not (ids is None or isinstance(ids, bytes)):
108
103
raise AssertionError()
109
if not (kinds is None or isinstance(kinds, (str, text_type))):
104
if not (kinds is None or isinstance(kinds, str)):
110
105
raise AssertionError()
112
107
if ids is not None:
157
152
def commit(self, message=None, revprops=None, *args, **kwargs):
158
153
# avoid circular imports
159
154
from breezy import commit
160
possible_master_transports=[]
155
possible_master_transports = []
161
156
with self.lock_write():
162
157
revprops = commit.Commit.update_revprops(
165
kwargs.pop('authors', None),
166
kwargs.get('local', False),
167
possible_master_transports)
160
kwargs.pop('authors', None),
161
kwargs.get('local', False),
162
possible_master_transports)
168
163
# args for wt.commit start at message from the Commit.commit method,
169
164
args = (message, ) + args
170
165
for hook in MutableTree.hooks['start_commit']:
172
167
committed_id = commit.Commit().commit(working_tree=self,
174
possible_master_transports=possible_master_transports,
169
possible_master_transports=possible_master_transports,
176
171
post_hook_params = PostCommitHookParams(self)
177
172
for hook in MutableTree.hooks['post_commit']:
178
173
hook(post_hook_params)
197
192
if _from_tree is None:
198
193
_from_tree = self.basis_tree()
199
194
changes = self.iter_changes(_from_tree)
201
change = next(changes)
202
# Exclude root (talk about black magic... --vila 20090629)
203
if change[4] == (None, None):
195
if self.supports_symlinks():
196
# Fast path for has_changes.
204
198
change = next(changes)
199
# Exclude root (talk about black magic... --vila 20090629)
200
if change.parent_id == (None, None):
201
change = next(changes)
203
except StopIteration:
207
# Slow path for has_changes.
208
# Handle platforms that do not support symlinks in the
209
# conditional below. This is slower than the try/except
210
# approach below that but we don't have a choice as we
211
# need to be sure that all symlinks are removed from the
212
# entire changeset. This is because in platforms that
213
# do not support symlinks, they show up as None in the
214
# working copy as compared to the repository.
215
# Also, exclude root as mention in the above fast path.
217
lambda c: c[6][0] != 'symlink' and c[4] != (None, None),
221
except StopIteration:
206
except StopIteration:
210
225
def check_changed_or_out_of_date(self, strict, opt_name,
211
226
more_error, more_warning):
290
305
raise NotImplementedError(self.mkdir)
292
def _observed_sha1(self, file_id, path, sha_and_stat):
307
def _observed_sha1(self, path, sha_and_stat):
293
308
"""Tell the tree we have observed a paths sha1.
295
310
The intent of this function is to allow trees that have a hashcache to
300
315
The default implementation does nothing.
302
:param file_id: The file id
303
317
:param path: The file path
304
318
:param sha_and_stat: The sha 1 and stat result observed.
308
def put_file_bytes_non_atomic(self, path, bytes, file_id=None):
322
def put_file_bytes_non_atomic(self, path, bytes):
309
323
"""Update the content of a file in the tree.
311
325
Note that the file is written in-place rather than being
339
353
This is designed more towards DWIM for humans than API clarity.
340
354
For the specific behaviour see the help for cmd_add().
342
:param file_list: List of zero or more paths. *NB: these are
343
interpreted relative to the process cwd, not relative to the
356
:param file_list: List of zero or more paths. *NB: these are
357
interpreted relative to the process cwd, not relative to the
344
358
tree.* (Add and most other tree methods use tree-relative
346
:param action: A reporter to be called with the inventory, parent_ie,
360
:param action: A reporter to be called with the working tree, parent_ie,
347
361
path and kind of the path being added. It may return a file_id if
348
362
a specific one should be used.
349
:param save: Save the inventory after completing the adds. If False
363
:param save: Save the changes after completing the adds. If False
350
364
this provides dry-run functionality by doing the add and not saving
352
366
:return: A tuple - files_added, ignored_files. files_added is the count
353
367
of added files, and ignored_files is a dict mapping files that were
354
368
ignored to the rule that caused them to be ignored.
388
402
raise NotImplementedError(self.copy_one)
404
def get_transform(self, pb=None):
405
"""Return a transform object for use with this tree."""
406
raise NotImplementedError(self.get_transform)
391
409
class MutableTreeHooks(hooks.Hooks):
392
410
"""A dictionary mapping a hook name to a list of callables for mutabletree
400
418
hooks.Hooks.__init__(self, "breezy.mutabletree", "MutableTree.hooks")
401
419
self.add_hook('start_commit',
402
"Called before a commit is performed on a tree. The start commit "
403
"hook is able to change the tree before the commit takes place. "
404
"start_commit is called with the breezy.mutabletree.MutableTree "
405
"that the commit is being performed on.", (1, 4))
420
"Called before a commit is performed on a tree. The start commit "
421
"hook is able to change the tree before the commit takes place. "
422
"start_commit is called with the breezy.mutabletree.MutableTree "
423
"that the commit is being performed on.", (1, 4))
406
424
self.add_hook('post_commit',
407
"Called after a commit is performed on a tree. The hook is "
408
"called with a breezy.mutabletree.PostCommitHookParams object. "
409
"The mutable tree the commit was performed on is available via "
410
"the mutable_tree attribute of that object.", (2, 0))
425
"Called after a commit is performed on a tree. The hook is "
426
"called with a breezy.mutabletree.PostCommitHookParams object. "
427
"The mutable tree the commit was performed on is available via "
428
"the mutable_tree attribute of that object.", (2, 0))
411
429
self.add_hook('pre_transform',
412
"Called before a tree transform on this tree. The hook is called "
413
"with the tree that is being transformed and the transform.",
430
"Called before a tree transform on this tree. The hook is called "
431
"with the tree that is being transformed and the transform.",
415
433
self.add_hook('post_build_tree',
416
"Called after a completely new tree is built. The hook is "
417
"called with the tree as its only argument.", (2, 5))
434
"Called after a completely new tree is built. The hook is "
435
"called with the tree as its only argument.", (2, 5))
418
436
self.add_hook('post_transform',
419
"Called after a tree transform has been performed on a tree. "
420
"The hook is called with the tree that is being transformed and "
437
"Called after a tree transform has been performed on a tree. "
438
"The hook is called with the tree that is being transformed and "
424
443
# install the default hooks into the MutableTree class.
425
444
MutableTree.hooks = MutableTreeHooks()