275
280
self.work_inv = self.work_tree.inventory
276
281
self.basis_tree = self.work_tree.basis_tree()
277
282
self.basis_inv = self.basis_tree.inventory
283
if specific_files is not None:
284
# Ensure specified files are versioned
285
# (We don't actually need the ids here)
286
tree.find_ids_across_trees(specific_files,
287
[self.basis_tree, self.work_tree])
278
288
# one to finish, one for rev and inventory, and one for each
279
289
# inventory entry, and the same for the new inventory.
280
290
# note that this estimate is too long when we do a partial tree
295
305
self._populate_new_inv()
296
306
self._report_deletes()
298
if not (self.allow_pointless
299
or len(self.parents) > 1
300
or self.builder.new_inventory != self.basis_inv):
301
raise PointlessCommit()
308
self._check_pointless()
303
310
self._emit_progress_update()
304
311
# TODO: Now the new inventory is known, check for conflicts and
325
332
# and now do the commit locally.
326
333
self.branch.append_revision(self.rev_id)
328
# if the builder gave us the revisiontree it created back, we
329
# could use it straight away here.
330
# TODO: implement this.
331
self.work_tree.set_parent_trees([(self.rev_id,
332
self.branch.repository.revision_tree(self.rev_id))])
335
rev_tree = self.builder.revision_tree()
336
self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
333
337
# now the work tree is up to date with the branch
335
339
self.reporter.completed(self.branch.revno(), self.rev_id)
347
351
return self.rev_id
353
def _any_real_changes(self):
354
"""Are there real changes between new_inventory and basis?
356
For trees without rich roots, inv.root.revision changes every commit.
357
But if that is the only change, we want to treat it as though there
360
new_entries = self.builder.new_inventory.iter_entries()
361
basis_entries = self.basis_inv.iter_entries()
362
new_path, new_root_ie = new_entries.next()
363
basis_path, basis_root_ie = basis_entries.next()
365
# This is a copy of InventoryEntry.__eq__ only leaving out .revision
366
def ie_equal_no_revision(this, other):
367
return ((this.file_id == other.file_id)
368
and (this.name == other.name)
369
and (this.symlink_target == other.symlink_target)
370
and (this.text_sha1 == other.text_sha1)
371
and (this.text_size == other.text_size)
372
and (this.text_id == other.text_id)
373
and (this.parent_id == other.parent_id)
374
and (this.kind == other.kind)
375
and (this.executable == other.executable)
377
if not ie_equal_no_revision(new_root_ie, basis_root_ie):
380
for new_ie, basis_ie in zip(new_entries, basis_entries):
381
if new_ie != basis_ie:
384
# No actual changes present
387
def _check_pointless(self):
388
if self.allow_pointless:
390
# A merge with no effect on files
391
if len(self.parents) > 1:
393
# Shortcut, if the number of entries changes, then we obviously have
395
if len(self.builder.new_inventory) != len(self.basis_inv):
397
# If length == 1, then we only have the root entry. Which means
398
# that there is no real difference (only the root could be different)
399
if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
401
raise PointlessCommit()
349
403
def _check_bound_branch(self):
350
404
"""Check to see if the local branch is bound.