176
message_callback=None):
176
message_callback=None,
177
178
"""Commit working copy as a new revision.
179
branch -- the deprecated branch to commit to. New callers should pass in
182
180
message -- the commit message (it or message_callback is required)
184
182
timestamp -- if not None, seconds-since-epoch for a
201
199
revprops -- Properties for new revision
202
200
:param local: Perform a local only commit.
201
:param recursive: If set to 'down', commit in any subtrees that have
202
pending changes of any sort during this commit.
204
204
mutter('preparing to commit')
206
if deprecated_passed(branch):
207
symbol_versioning.warn("Commit.commit (branch, ...): The branch parameter is "
208
"deprecated as of bzr 0.8. Please use working_tree= instead.",
209
DeprecationWarning, stacklevel=2)
211
self.work_tree = self.branch.bzrdir.open_workingtree()
212
elif working_tree is None:
213
raise BzrError("One of branch and working_tree must be passed into commit().")
206
if working_tree is None:
207
raise BzrError("working_tree must be passed into commit().")
215
209
self.work_tree = working_tree
216
210
self.branch = self.work_tree.branch
211
if getattr(self.work_tree, 'requires_rich_root', lambda: False)():
212
if not self.branch.repository.supports_rich_root():
213
raise errors.RootNotRich()
217
214
if message_callback is None:
218
215
if message is not None:
219
216
if isinstance(message, str):
230
227
self.rev_id = None
231
228
self.specific_files = specific_files
232
229
self.allow_pointless = allow_pointless
230
self.recursive = recursive
231
self.revprops = revprops
232
self.message_callback = message_callback
233
self.timestamp = timestamp
234
self.timezone = timezone
235
self.committer = committer
236
self.specific_files = specific_files
238
self.verbose = verbose
234
241
if reporter is None and self.reporter is None:
235
242
self.reporter = NullCommitReporter()
239
246
self.work_tree.lock_write()
240
247
self.pb = bzrlib.ui.ui_factory.nested_progress_bar()
248
self.basis_tree = self.work_tree.basis_tree()
249
self.basis_tree.lock_read()
242
251
# Cannot commit with conflicts present.
243
252
if len(self.work_tree.conflicts())>0:
254
263
# this is so that we still consier the master branch
255
264
# - in a checkout scenario the tree may have no
256
265
# parents but the branch may do.
257
first_tree_parent = None
258
master_last = self.master_branch.last_revision()
259
if (master_last is not None and
260
master_last != first_tree_parent):
261
raise errors.OutOfDateTree(self.work_tree)
266
first_tree_parent = bzrlib.revision.NULL_REVISION
267
old_revno, master_last = self.master_branch.last_revision_info()
268
if master_last != first_tree_parent:
269
if master_last != bzrlib.revision.NULL_REVISION:
270
raise errors.OutOfDateTree(self.work_tree)
271
if self.branch.repository.has_revision(first_tree_parent):
272
new_revno = old_revno + 1
274
# ghost parents never appear in revision history.
264
277
# raise an exception as soon as we find a single unknown.
265
278
for unknown in self.work_tree.unknowns():
269
282
self.config = self.branch.get_config()
271
284
self.work_inv = self.work_tree.inventory
272
self.basis_tree = self.work_tree.basis_tree()
273
285
self.basis_inv = self.basis_tree.inventory
274
286
if specific_files is not None:
275
287
# Ensure specified files are versioned
276
288
# (We don't actually need the ids here)
277
tree.find_ids_across_trees(specific_files,
289
# XXX: Dont we have filter_unversioned to do this more
291
tree.find_ids_across_trees(specific_files,
278
292
[self.basis_tree, self.work_tree])
279
293
# one to finish, one for rev and inventory, and one for each
280
294
# inventory entry, and the same for the new inventory.
289
303
raise NotImplementedError('selected-file commit of merges is not supported yet: files %r',
290
304
self.specific_files)
292
self.builder = self.branch.get_commit_builder(self.parents,
306
self.builder = self.branch.get_commit_builder(self.parents,
293
307
self.config, timestamp, timezone, committer, revprops, rev_id)
295
309
self._remove_deleted()
323
337
# now the master has the revision data
324
338
# 'commit' to the master first so a timeout here causes the local
325
339
# branch to be out of date
326
self.master_branch.append_revision(self.rev_id)
340
self.master_branch.set_last_revision_info(new_revno,
328
343
# and now do the commit locally.
329
self.branch.append_revision(self.rev_id)
344
self.branch.set_last_revision_info(new_revno, self.rev_id)
331
346
rev_tree = self.builder.revision_tree()
332
347
self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
333
348
# now the work tree is up to date with the branch
335
self.reporter.completed(self.branch.revno(), self.rev_id)
350
self.reporter.completed(new_revno, self.rev_id)
336
351
# old style commit hooks - should be deprecated ? (obsoleted in
338
353
if self.config.post_commit() is not None:
351
366
hook_master = self.master_branch
352
367
hook_local = self.branch
353
new_revno = self.branch.revno()
354
368
# With bound branches, when the master is behind the local branch,
355
369
# the 'old_revno' and old_revid values here are incorrect.
356
370
# XXX: FIXME ^. RBC 20060206
357
old_revno = new_revno - 1
359
372
old_revid = self.parents[0]
390
403
and (this.parent_id == other.parent_id)
391
404
and (this.kind == other.kind)
392
405
and (this.executable == other.executable)
406
and (this.reference_revision == other.reference_revision)
394
408
if not ie_equal_no_revision(new_root_ie, basis_root_ie):
521
536
# TODO: Make sure that this list doesn't contain duplicate
522
537
# entries and the order is preserved when doing this.
523
538
self.parents = self.work_tree.get_parent_ids()
524
self.parent_invs = []
525
for revision in self.parents:
539
self.parent_invs = [self.basis_inv]
540
for revision in self.parents[1:]:
526
541
if self.branch.repository.has_revision(revision):
527
542
mutter('commit parent revision {%s}', revision)
528
543
inventory = self.branch.repository.get_inventory(revision)
585
600
file_id = new_ie.file_id
587
602
kind = self.work_tree.kind(file_id)
603
if kind == 'tree-reference' and self.recursive == 'down':
604
# nested tree: commit in it
605
sub_tree = WorkingTree.open(self.work_tree.abspath(path))
606
# FIXME: be more comprehensive here:
607
# this works when both trees are in --trees repository,
608
# but when both are bound to a different repository,
609
# it fails; a better way of approaching this is to
610
# finally implement the explicit-caches approach design
611
# a while back - RBC 20070306.
612
if (sub_tree.branch.repository.bzrdir.root_transport.base
614
self.work_tree.branch.repository.bzrdir.root_transport.base):
615
sub_tree.branch.repository = \
616
self.work_tree.branch.repository
618
sub_tree.commit(message=None, revprops=self.revprops,
619
recursive=self.recursive,
620
message_callback=self.message_callback,
621
timestamp=self.timestamp, timezone=self.timezone,
622
committer=self.committer,
623
allow_pointless=self.allow_pointless,
624
strict=self.strict, verbose=self.verbose,
625
local=self.local, reporter=self.reporter)
626
except errors.PointlessCommit:
588
628
if kind != new_ie.kind:
589
629
new_ie = inventory.make_entry(kind, new_ie.name,
590
630
new_ie.parent_id, file_id)