79
79
# used on media which doesn't differentiate the case of names.
80
80
self.case_sensitive = True
82
def is_control_filename(self, filename):
83
"""True if filename is the name of a control file in this tree.
85
:param filename: A filename within the tree. This is a relative path
86
from the root of this tree.
88
This is true IF and ONLY IF the filename is part of the meta data
89
that bzr controls in this tree. I.E. a random .bzr directory placed
90
on disk will not be a control file for this tree.
92
raise NotImplementedError(self.is_control_filename)
94
82
@needs_tree_write_lock
95
83
def add(self, files, ids=None, kinds=None):
96
84
"""Add paths to the set of versioned paths.
184
173
:seealso Inventory.apply_delta: For details on the changes parameter.
186
raise NotImplementedError(self.apply_inventory_delta)
177
inv.apply_delta(changes)
178
self._write_inventory(inv)
188
180
@needs_write_lock
189
181
def commit(self, message=None, revprops=None, *args,
191
183
# avoid circular imports
192
184
from bzrlib import commit
193
187
possible_master_transports=[]
194
revprops = commit.Commit.update_revprops(
197
kwargs.pop('authors', None),
198
kwargs.pop('author', None),
188
if not 'branch-nick' in revprops:
189
revprops['branch-nick'] = self.branch._get_nick(
199
190
kwargs.get('local', False),
200
191
possible_master_transports)
192
authors = kwargs.pop('authors', None)
193
author = kwargs.pop('author', None)
194
if authors is not None:
195
if author is not None:
196
raise AssertionError('Specifying both author and authors '
197
'is not allowed. Specify just authors instead')
198
if 'author' in revprops or 'authors' in revprops:
199
# XXX: maybe we should just accept one of them?
200
raise AssertionError('author property given twice')
202
for individual in authors:
203
if '\n' in individual:
204
raise AssertionError('\\n is not a valid character '
205
'in an author identity')
206
revprops['authors'] = '\n'.join(authors)
207
if author is not None:
208
symbol_versioning.warn('The parameter author was deprecated'
209
' in version 1.13. Use authors instead',
211
if 'author' in revprops or 'authors' in revprops:
212
# XXX: maybe we should just accept one of them?
213
raise AssertionError('author property given twice')
215
raise AssertionError('\\n is not a valid character '
216
'in an author identity')
217
revprops['authors'] = author
201
218
# args for wt.commit start at message from the Commit.commit method,
202
219
args = (message, ) + args
203
220
for hook in MutableTree.hooks['start_commit']:
371
394
raise NotImplementedError(self.set_parent_trees)
373
def smart_add(self, file_list, recurse=True, action=None, save=True):
374
"""Version file_list, optionally recursing into directories.
376
This is designed more towards DWIM for humans than API clarity.
377
For the specific behaviour see the help for cmd_add().
379
:param file_list: List of zero or more paths. *NB: these are
380
interpreted relative to the process cwd, not relative to the
381
tree.* (Add and most other tree methods use tree-relative
383
:param action: A reporter to be called with the inventory, parent_ie,
384
path and kind of the path being added. It may return a file_id if
385
a specific one should be used.
386
:param save: Save the inventory after completing the adds. If False
387
this provides dry-run functionality by doing the add and not saving
389
:return: A tuple - files_added, ignored_files. files_added is the count
390
of added files, and ignored_files is a dict mapping files that were
391
ignored to the rule that caused them to be ignored.
393
raise NotImplementedError(self.smart_add)
395
def update_basis_by_delta(self, new_revid, delta):
396
"""Update the parents of this tree after a commit.
398
This gives the tree one parent, with revision id new_revid. The
399
inventory delta is applied to the current basis tree to generate the
400
inventory for the parent new_revid, and all other parent trees are
403
All the changes in the delta should be changes synchronising the basis
404
tree with some or all of the working tree, with a change to a directory
405
requiring that its contents have been recursively included. That is,
406
this is not a general purpose tree modification routine, but a helper
407
for commit which is not required to handle situations that do not arise
410
See the inventory developers documentation for the theory behind
413
:param new_revid: The new revision id for the trees parent.
414
:param delta: An inventory delta (see apply_inventory_delta) describing
415
the changes from the current left most parent revision to new_revid.
417
raise NotImplementedError(self.update_basis_by_delta)
420
class MutableInventoryTree(MutableTree,tree.InventoryTree):
422
@needs_tree_write_lock
423
def apply_inventory_delta(self, changes):
424
"""Apply changes to the inventory as an atomic operation.
426
:param changes: An inventory delta to apply to the working tree's
429
:seealso Inventory.apply_delta: For details on the changes parameter.
433
inv.apply_delta(changes)
434
self._write_inventory(inv)
436
def _fix_case_of_inventory_path(self, path):
437
"""If our tree isn't case sensitive, return the canonical path"""
438
if not self.case_sensitive:
439
path = self.get_canonical_inventory_path(path)
442
@needs_tree_write_lock
443
def smart_add(self, file_list, recurse=True, action=None, save=True):
444
"""Version file_list, optionally recursing into directories.
446
This is designed more towards DWIM for humans than API clarity.
447
For the specific behaviour see the help for cmd_add().
449
:param file_list: List of zero or more paths. *NB: these are
450
interpreted relative to the process cwd, not relative to the
451
tree.* (Add and most other tree methods use tree-relative
396
@needs_tree_write_lock
397
def smart_add(self, file_list, recurse=True, action=None, save=True):
398
"""Version file_list, optionally recursing into directories.
400
This is designed more towards DWIM for humans than API clarity.
401
For the specific behaviour see the help for cmd_add().
453
403
:param action: A reporter to be called with the inventory, parent_ie,
454
404
path and kind of the path being added. It may return a file_id if
455
405
a specific one should be used.
710
647
"""Create the default hooks.
713
hooks.Hooks.__init__(self, "bzrlib.mutabletree", "MutableTree.hooks")
714
self.add_hook('start_commit',
650
hooks.Hooks.__init__(self)
651
self.create_hook(hooks.HookPoint('start_commit',
715
652
"Called before a commit is performed on a tree. The start commit "
716
653
"hook is able to change the tree before the commit takes place. "
717
654
"start_commit is called with the bzrlib.mutabletree.MutableTree "
718
"that the commit is being performed on.", (1, 4))
719
self.add_hook('post_commit',
655
"that the commit is being performed on.", (1, 4), None))
656
self.create_hook(hooks.HookPoint('post_commit',
720
657
"Called after a commit is performed on a tree. The hook is "
721
658
"called with a bzrlib.mutabletree.PostCommitHookParams object. "
722
659
"The mutable tree the commit was performed on is available via "
723
"the mutable_tree attribute of that object.", (2, 0))
660
"the mutable_tree attribute of that object.", (2, 0), None))
726
663
# install the default hooks into the MutableTree class.
803
740
file_id or None to generate a new file id
806
# if the parent exists, but isn't a directory, we have to do the
807
# kind change now -- really the inventory shouldn't pretend to know
808
# the kind of wt files, but it does.
809
if parent_ie.kind != 'directory':
810
# nb: this relies on someone else checking that the path we're using
811
# doesn't contain symlinks.
812
new_parent_ie = _mod_inventory.make_entry('directory', parent_ie.name,
813
parent_ie.parent_id, parent_ie.file_id)
814
del inv[parent_ie.file_id]
815
inv.add(new_parent_ie)
816
parent_ie = new_parent_ie
817
743
file_id = file_id_callback(inv, parent_ie, path, kind)
818
744
entry = inv.make_entry(kind, path.base_path, parent_ie.file_id,