183
171
working_tree=None,
175
message_callback=None,
187
177
"""Commit working copy as a new revision.
189
branch -- the deprecated branch to commit to. New callers should pass in
192
message -- the commit message, a mandatory parameter
194
timestamp -- if not None, seconds-since-epoch for a
195
postdated/predated commit.
197
specific_files -- If true, commit only those files.
199
rev_id -- If set, use this as the new revision id.
179
:param message: the commit message (it or message_callback is required)
181
:param timestamp: if not None, seconds-since-epoch for a
182
postdated/predated commit.
184
:param specific_files: If true, commit only those files.
186
:param rev_id: If set, use this as the new revision id.
200
187
Useful for test or import commands that need to tightly
201
188
control what revisions are assigned. If you duplicate
202
189
a revision id that exists elsewhere it is your own fault.
203
190
If null (default), a time/random revision id is generated.
205
allow_pointless -- If true (default), commit even if nothing
192
:param allow_pointless: If true (default), commit even if nothing
206
193
has changed and no merges are recorded.
208
strict -- If true, don't allow a commit if the working tree
195
:param strict: If true, don't allow a commit if the working tree
209
196
contains unknown files.
211
revprops -- Properties for new revision
198
:param revprops: Properties for new revision
212
199
:param local: Perform a local only commit.
200
:param recursive: If set to 'down', commit in any subtrees that have
201
pending changes of any sort during this commit.
214
203
mutter('preparing to commit')
216
if deprecated_passed(branch):
217
warn("Commit.commit (branch, ...): The branch parameter is "
218
"deprecated as of bzr 0.8. Please use working_tree= instead.",
219
DeprecationWarning, stacklevel=2)
221
self.work_tree = self.branch.bzrdir.open_workingtree()
222
elif working_tree is None:
223
raise BzrError("One of branch and working_tree must be passed into commit().")
205
if working_tree is None:
206
raise BzrError("working_tree must be passed into commit().")
225
208
self.work_tree = working_tree
226
209
self.branch = self.work_tree.branch
228
raise BzrError("The message keyword parameter is required for commit().")
210
if getattr(self.work_tree, 'requires_rich_root', lambda: False)():
211
if not self.branch.repository.supports_rich_root():
212
raise errors.RootNotRich()
213
if message_callback is None:
214
if message is not None:
215
if isinstance(message, str):
216
message = message.decode(bzrlib.user_encoding)
217
message_callback = lambda x: message
219
raise BzrError("The message or message_callback keyword"
220
" parameter is required for commit().")
230
self.weave_store = self.branch.repository.weave_store
231
222
self.bound_branch = None
232
223
self.local = local
233
224
self.master_branch = None
234
225
self.master_locked = False
236
227
self.specific_files = specific_files
237
228
self.allow_pointless = allow_pointless
239
if revprops is not None:
240
self.revprops.update(revprops)
229
self.recursive = recursive
230
self.revprops = revprops
231
self.message_callback = message_callback
232
self.timestamp = timestamp
233
self.timezone = timezone
234
self.committer = committer
236
self.verbose = verbose
242
238
if reporter is None and self.reporter is None:
243
239
self.reporter = NullCommitReporter()
245
241
self.reporter = reporter
247
243
self.work_tree.lock_write()
244
self.pb = bzrlib.ui.ui_factory.nested_progress_bar()
245
self.basis_tree = self.work_tree.basis_tree()
246
self.basis_tree.lock_read()
249
# setup the bound branch variables as needed.
248
# Cannot commit with conflicts present.
249
if len(self.work_tree.conflicts()) > 0:
250
raise ConflictsInTree
252
# Setup the bound branch variables as needed.
250
253
self._check_bound_branch()
252
# check for out of date working trees
253
# if we are bound, then self.branch is the master branch and this
254
# test is thus all we need.
255
if self.work_tree.last_revision() != self.master_branch.last_revision():
256
raise errors.OutOfDateTree(self.work_tree)
255
# Check that the working tree is up to date
256
old_revno,new_revno = self._check_out_of_date_tree()
259
259
# raise an exception as soon as we find a single unknown.
260
260
for unknown in self.work_tree.unknowns():
261
261
raise StrictCommitFailed()
263
if timestamp is None:
264
self.timestamp = time.time()
266
self.timestamp = long(timestamp)
268
263
if self.config is None:
269
self.config = bzrlib.config.BranchConfig(self.branch)
272
self.rev_id = _gen_revision_id(self.config, self.timestamp)
276
if committer is None:
277
self.committer = self.config.username()
279
assert isinstance(committer, basestring), type(committer)
280
self.committer = committer
283
self.timezone = local_time_offset()
285
self.timezone = int(timezone)
287
if isinstance(message, str):
288
message = message.decode(bzrlib.user_encoding)
264
self.config = self.branch.get_config()
266
# If provided, ensure the specified files are versioned
267
if specific_files is not None:
268
# Note: We don't actually need the IDs here. This routine
269
# is being called because it raises PathNotVerisonedError
270
# as a side effect of finding the IDs.
271
# XXX: Dont we have filter_unversioned to do this more
273
tree.find_ids_across_trees(specific_files,
274
[self.basis_tree, self.work_tree])
276
# Setup the progress bar. As the number of files that need to be
277
# committed in unknown, progress is reported as stages.
278
# We keep track of entries separately though and include that
279
# information in the progress bar during the relevant stages.
280
self.pb_stage_name = ""
281
self.pb_stage_count = 0
282
self.pb_stage_total = 4
283
if self.bound_branch:
284
self.pb_stage_total += 1
285
self.pb.show_pct = False
286
self.pb.show_spinner = False
287
self.pb.show_eta = False
288
self.pb.show_count = True
289
self.pb.show_bar = False
291
# After a merge, a selected file commit is not supported.
292
# See 'bzr help merge' for an explanation as to why.
293
self.basis_inv = self.basis_tree.inventory
294
self._gather_parents()
295
if len(self.parents) > 1 and self.specific_files:
296
raise errors.CannotCommitSelectedFileMerge(self.specific_files)
298
# Collect the changes
299
self._emit_progress_set_stage("Collecting changes", show_entries=True)
300
self.builder = self.branch.get_commit_builder(self.parents,
301
self.config, timestamp, timezone, committer, revprops, rev_id)
302
self._update_builder_with_changes()
303
self._check_pointless()
305
# TODO: Now the new inventory is known, check for conflicts.
306
# ADHB 2006-08-08: If this is done, populate_new_inv should not add
307
# weave lines, because nothing should be recorded until it is known
308
# that commit will succeed.
309
self._emit_progress_set_stage("Saving data locally")
310
self.builder.finish_inventory()
312
# Prompt the user for a commit message if none provided
313
message = message_callback(self)
289
314
assert isinstance(message, unicode), type(message)
290
315
self.message = message
291
316
self._escape_commit_message()
293
self.work_inv = self.work_tree.inventory
294
self.basis_tree = self.work_tree.basis_tree()
295
self.basis_inv = self.basis_tree.inventory
297
self._gather_parents()
298
if len(self.parents) > 1 and self.specific_files:
299
raise NotImplementedError('selected-file commit of merges is not supported yet')
300
self._check_parents_present()
302
self._remove_deleted()
303
self._populate_new_inv()
304
self._store_snapshot()
305
self._report_deletes()
307
if not (self.allow_pointless
308
or len(self.parents) > 1
309
or self.new_inv != self.basis_inv):
310
raise PointlessCommit()
312
if len(self.work_tree.conflicts())>0:
313
raise ConflictsInTree
315
self.inv_sha1 = self.branch.repository.add_inventory(
320
self._make_revision()
321
# revision data is in the local branch now.
323
# upload revision data to the master.
324
# this will propogate merged revisions too if needed.
318
# Add revision data to the local branch
319
self.rev_id = self.builder.commit(self.message)
321
# Upload revision data to the master.
322
# this will propagate merged revisions too if needed.
325
323
if self.bound_branch:
324
self._emit_progress_set_stage("Uploading data to master branch")
326
325
self.master_branch.repository.fetch(self.branch.repository,
327
326
revision_id=self.rev_id)
328
327
# now the master has the revision data
329
# 'commit' to the master first so a timeout here causes the local
330
# branch to be out of date
331
self.master_branch.append_revision(self.rev_id)
328
# 'commit' to the master first so a timeout here causes the
329
# local branch to be out of date
330
self.master_branch.set_last_revision_info(new_revno,
333
333
# and now do the commit locally.
334
self.branch.append_revision(self.rev_id)
334
self.branch.set_last_revision_info(new_revno, self.rev_id)
336
self.work_tree.set_pending_merges([])
337
self.work_tree.set_last_revision(self.rev_id)
338
# now the work tree is up to date with the branch
340
self.reporter.completed(self.branch.revno(), self.rev_id)
341
if self.config.post_commit() is not None:
342
hooks = self.config.post_commit().split(' ')
343
# this would be nicer with twisted.python.reflect.namedAny
345
result = eval(hook + '(branch, rev_id)',
346
{'branch':self.branch,
348
'rev_id':self.rev_id})
336
# Make the working tree up to date with the branch
337
self._emit_progress_set_stage("Updating the working tree")
338
rev_tree = self.builder.revision_tree()
339
self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
340
self.reporter.completed(new_revno, self.rev_id)
341
self._process_hooks(old_revno, new_revno)
350
self._cleanup_bound_branch()
351
self.work_tree.unlock()
346
def _any_real_changes(self):
347
"""Are there real changes between new_inventory and basis?
349
For trees without rich roots, inv.root.revision changes every commit.
350
But if that is the only change, we want to treat it as though there
353
new_entries = self.builder.new_inventory.iter_entries()
354
basis_entries = self.basis_inv.iter_entries()
355
new_path, new_root_ie = new_entries.next()
356
basis_path, basis_root_ie = basis_entries.next()
358
# This is a copy of InventoryEntry.__eq__ only leaving out .revision
359
def ie_equal_no_revision(this, other):
360
return ((this.file_id == other.file_id)
361
and (this.name == other.name)
362
and (this.symlink_target == other.symlink_target)
363
and (this.text_sha1 == other.text_sha1)
364
and (this.text_size == other.text_size)
365
and (this.text_id == other.text_id)
366
and (this.parent_id == other.parent_id)
367
and (this.kind == other.kind)
368
and (this.executable == other.executable)
369
and (this.reference_revision == other.reference_revision)
371
if not ie_equal_no_revision(new_root_ie, basis_root_ie):
374
for new_ie, basis_ie in zip(new_entries, basis_entries):
375
if new_ie != basis_ie:
378
# No actual changes present
381
def _check_pointless(self):
382
if self.allow_pointless:
384
# A merge with no effect on files
385
if len(self.parents) > 1:
387
# work around the fact that a newly-initted tree does differ from its
389
if len(self.basis_inv) == 0 and len(self.builder.new_inventory) == 1:
390
raise PointlessCommit()
391
# Shortcut, if the number of entries changes, then we obviously have
393
if len(self.builder.new_inventory) != len(self.basis_inv):
395
# If length == 1, then we only have the root entry. Which means
396
# that there is no real difference (only the root could be different)
397
if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
399
raise PointlessCommit()
353
401
def _check_bound_branch(self):
354
402
"""Check to see if the local branch is bound.
391
439
self.bound_branch = self.branch
392
440
self.master_branch.lock_write()
393
441
self.master_locked = True
395
#### # Check to see if we have any pending merges. If we do
396
#### # those need to be pushed into the master branch
397
#### pending_merges = self.work_tree.pending_merges()
398
#### if pending_merges:
399
#### for revision_id in pending_merges:
400
#### self.master_branch.repository.fetch(self.bound_branch.repository,
401
#### revision_id=revision_id)
443
def _check_out_of_date_tree(self):
444
"""Check that the working tree is up to date.
446
:return: old_revision_number,new_revision_number tuple
449
first_tree_parent = self.work_tree.get_parent_ids()[0]
451
# if there are no parents, treat our parent as 'None'
452
# this is so that we still consider the master branch
453
# - in a checkout scenario the tree may have no
454
# parents but the branch may do.
455
first_tree_parent = bzrlib.revision.NULL_REVISION
456
old_revno, master_last = self.master_branch.last_revision_info()
457
if master_last != first_tree_parent:
458
if master_last != bzrlib.revision.NULL_REVISION:
459
raise errors.OutOfDateTree(self.work_tree)
460
if self.branch.repository.has_revision(first_tree_parent):
461
new_revno = old_revno + 1
463
# ghost parents never appear in revision history.
465
return old_revno,new_revno
467
def _process_hooks(self, old_revno, new_revno):
468
"""Process any registered commit hooks."""
469
# Process the post commit hooks, if any
470
self._emit_progress_set_stage("Running post commit hooks")
471
# old style commit hooks - should be deprecated ? (obsoleted in
473
if self.config.post_commit() is not None:
474
hooks = self.config.post_commit().split(' ')
475
# this would be nicer with twisted.python.reflect.namedAny
477
result = eval(hook + '(branch, rev_id)',
478
{'branch':self.branch,
480
'rev_id':self.rev_id})
481
# new style commit hooks:
482
if not self.bound_branch:
483
hook_master = self.branch
486
hook_master = self.master_branch
487
hook_local = self.branch
488
# With bound branches, when the master is behind the local branch,
489
# the 'old_revno' and old_revid values here are incorrect.
490
# XXX: FIXME ^. RBC 20060206
492
old_revid = self.parents[0]
494
old_revid = bzrlib.revision.NULL_REVISION
495
for hook in Branch.hooks['post_commit']:
496
# show the running hook in the progress bar. As hooks may
497
# end up doing nothing (e.g. because they are not configured by
498
# the user) this is still showing progress, not showing overall
499
# actions - its up to each plugin to show a UI if it want's to
500
# (such as 'Emailing diff to foo@example.com').
501
self.pb_stage_name = "Running post commit hooks [%s]" % \
502
Branch.hooks.get_hook_name(hook)
503
self._emit_progress()
504
hook(hook_local, hook_master, old_revno, old_revid, new_revno,
508
"""Cleanup any open locks, progress bars etc."""
509
cleanups = [self._cleanup_bound_branch,
510
self.basis_tree.unlock,
511
self.work_tree.unlock,
513
found_exception = None
514
for cleanup in cleanups:
517
# we want every cleanup to run no matter what.
518
# so we have a catchall here, but we will raise the
519
# last encountered exception up the stack: and
520
# typically this will be useful enough.
523
if found_exception is not None:
524
# don't do a plan raise, because the last exception may have been
525
# trashed, e is our sure-to-work exception even though it loses the
526
# full traceback. XXX: RBC 20060421 perhaps we could check the
527
# exc_info and if its the same one do a plain raise otherwise
528
# 'raise e' as we do now.
403
531
def _cleanup_bound_branch(self):
404
532
"""Executed at the end of a try/finally to cleanup a bound branch.
433
561
def _gather_parents(self):
434
562
"""Record the parents of a merge for merge detection."""
435
pending_merges = self.work_tree.pending_merges()
437
self.parent_invs = []
438
self.present_parents = []
439
precursor_id = self.branch.last_revision()
441
self.parents.append(precursor_id)
442
self.parents += pending_merges
443
for revision in self.parents:
563
# TODO: Make sure that this list doesn't contain duplicate
564
# entries and the order is preserved when doing this.
565
self.parents = self.work_tree.get_parent_ids()
566
self.parent_invs = [self.basis_inv]
567
for revision in self.parents[1:]:
444
568
if self.branch.repository.has_revision(revision):
569
mutter('commit parent revision {%s}', revision)
445
570
inventory = self.branch.repository.get_inventory(revision)
446
571
self.parent_invs.append(inventory)
447
self.present_parents.append(revision)
449
def _check_parents_present(self):
450
for parent_id in self.parents:
451
mutter('commit parent revision {%s}', parent_id)
452
if not self.branch.repository.has_revision(parent_id):
453
if parent_id == self.branch.last_revision():
454
warning("parent is missing %r", parent_id)
455
raise HistoryMissing(self.branch, 'revision', parent_id)
457
mutter("commit will ghost revision %r", parent_id)
459
def _make_revision(self):
460
"""Record a new revision object for this commit."""
461
rev = Revision(timestamp=self.timestamp,
462
timezone=self.timezone,
463
committer=self.committer,
464
message=self.message,
465
inventory_sha1=self.inv_sha1,
466
revision_id=self.rev_id,
467
properties=self.revprops)
468
rev.parent_ids = self.parents
469
self.branch.repository.add_revision(self.rev_id, rev, self.new_inv, self.config)
471
def _remove_deleted(self):
472
"""Remove deleted files from the working inventories.
474
This is done prior to taking the working inventory as the
475
basis for the new committed inventory.
477
This returns true if any files
478
*that existed in the basis inventory* were deleted.
479
Files that were added and deleted
480
in the working copy don't matter.
573
mutter('commit parent ghost revision {%s}', revision)
575
def _update_builder_with_changes(self):
576
"""Update the commit builder with the data about what has changed.
482
specific = self.specific_files
578
# Build the revision inventory.
580
# This starts by creating a new empty inventory. Depending on
581
# which files are selected for commit, and what is present in the
582
# current tree, the new inventory is populated. inventory entries
583
# which are candidates for modification have their revision set to
584
# None; inventory entries that are carried over untouched have their
585
# revision set to their prior value.
587
# ESEPARATIONOFCONCERNS: this function is diffing and using the diff
588
# results to create a new inventory at the same time, which results
589
# in bugs like #46635. Any reason not to use/enhance Tree.changes_from?
592
specific_files = self.specific_files
593
mutter("Selecting files for commit with filter %s", specific_files)
594
work_inv = self.work_tree.inventory
595
assert work_inv.root is not None
596
self.pb_entries_total = len(work_inv)
598
# Check and warn about old CommitBuilders
599
entries = work_inv.iter_entries()
600
if not self.builder.record_root_entry:
601
symbol_versioning.warn('CommitBuilders should support recording'
602
' the root entry as of bzr 0.10.', DeprecationWarning,
604
self.builder.new_inventory.add(self.basis_inv.root.copy())
484
for path, ie in self.work_inv.iter_entries():
485
if specific and not is_inside_any(specific, path):
608
deleted_paths = set()
609
for path, new_ie in entries:
610
self._emit_progress_next_entry()
611
file_id = new_ie.file_id
613
# Skip files that have been deleted from the working tree.
614
# The deleted files/directories are also recorded so they
615
# can be explicitly unversioned later. Note that when a
616
# filter of specific files is given, we must only skip/record
617
# deleted files matching that filter.
618
if is_inside_any(deleted_paths, path):
487
if not self.work_tree.has_filename(path):
488
self.reporter.missing(path)
489
deleted_ids.append((path, ie.file_id))
491
deleted_ids.sort(reverse=True)
492
for path, file_id in deleted_ids:
493
del self.work_inv[file_id]
494
self.work_tree._write_inventory(self.work_inv)
496
def _store_snapshot(self):
497
"""Pass over inventory and record a snapshot.
499
Entries get a new revision when they are modified in
500
any way, which includes a merge with a new set of
501
parents that have the same entry.
503
# XXX: Need to think more here about when the user has
504
# made a specific decision on a particular value -- c.f.
506
for path, ie in self.new_inv.iter_entries():
507
previous_entries = ie.find_previous_heads(
510
self.branch.repository.get_transaction())
511
if ie.revision is None:
512
change = ie.snapshot(self.rev_id, path, previous_entries,
513
self.work_tree, self.weave_store,
514
self.branch.get_transaction())
620
if not specific_files or is_inside_any(specific_files, path):
621
if not self.work_tree.has_filename(path):
622
deleted_paths.add(path)
623
self.reporter.missing(path)
624
deleted_ids.append(file_id)
627
kind = self.work_tree.kind(file_id)
628
if kind == 'tree-reference' and self.recursive == 'down':
629
# nested tree: commit in it
630
sub_tree = WorkingTree.open(self.work_tree.abspath(path))
631
# FIXME: be more comprehensive here:
632
# this works when both trees are in --trees repository,
633
# but when both are bound to a different repository,
634
# it fails; a better way of approaching this is to
635
# finally implement the explicit-caches approach design
636
# a while back - RBC 20070306.
637
if (sub_tree.branch.repository.bzrdir.root_transport.base
639
self.work_tree.branch.repository.bzrdir.root_transport.base):
640
sub_tree.branch.repository = \
641
self.work_tree.branch.repository
643
sub_tree.commit(message=None, revprops=self.revprops,
644
recursive=self.recursive,
645
message_callback=self.message_callback,
646
timestamp=self.timestamp, timezone=self.timezone,
647
committer=self.committer,
648
allow_pointless=self.allow_pointless,
649
strict=self.strict, verbose=self.verbose,
650
local=self.local, reporter=self.reporter)
651
except errors.PointlessCommit:
653
if kind != new_ie.kind:
654
new_ie = inventory.make_entry(kind, new_ie.name,
655
new_ie.parent_id, file_id)
656
except errors.NoSuchFile:
658
# mutter('check %s {%s}', path, file_id)
659
if (not specific_files or
660
is_inside_or_parent_of_any(specific_files, path)):
661
# mutter('%s selected for commit', path)
517
self.reporter.snapshot_change(change, path)
519
def _populate_new_inv(self):
520
"""Build revision inventory.
522
This creates a new empty inventory. Depending on
523
which files are selected for commit, and what is present in the
524
current tree, the new inventory is populated. inventory entries
525
which are candidates for modification have their revision set to
526
None; inventory entries that are carried over untouched have their
527
revision set to their prior value.
529
mutter("Selecting files for commit with filter %s", self.specific_files)
530
self.new_inv = Inventory(revision_id=self.rev_id)
531
for path, new_ie in self.work_inv.iter_entries():
532
file_id = new_ie.file_id
533
mutter('check %s {%s}', path, new_ie.file_id)
534
if self.specific_files:
535
if not is_inside_any(self.specific_files, path):
536
mutter('%s not selected for commit', path)
537
self._carry_entry(file_id)
665
# mutter('%s not selected for commit', path)
666
if self.basis_inv.has_id(file_id):
667
ie = self.basis_inv[file_id].copy()
540
# this is selected, ensure its parents are too.
541
parent_id = new_ie.parent_id
542
while parent_id != ROOT_ID:
543
if not self.new_inv.has_id(parent_id):
544
ie = self._select_entry(self.work_inv[parent_id])
545
mutter('%s selected for commit because of %s',
546
self.new_inv.id2path(parent_id), path)
548
ie = self.new_inv[parent_id]
549
if ie.revision is not None:
551
mutter('%s selected for commit because of %s',
552
self.new_inv.id2path(parent_id), path)
553
parent_id = ie.parent_id
554
mutter('%s selected for commit', path)
555
self._select_entry(new_ie)
557
def _select_entry(self, new_ie):
558
"""Make new_ie be considered for committing."""
564
def _carry_entry(self, file_id):
565
"""Carry the file unchanged from the basis revision."""
566
if self.basis_inv.has_id(file_id):
567
self.new_inv.add(self.basis_inv[file_id].copy())
569
def _report_deletes(self):
570
for file_id in self.basis_inv:
571
if file_id not in self.new_inv:
572
self.reporter.deleted(self.basis_inv.id2path(file_id))
574
def _gen_revision_id(config, when):
575
"""Return new revision-id."""
576
s = '%s-%s-' % (config.user_email(), compact_date(when))
577
s += hexlify(rand_bytes(8))
669
# this entry is new and not being committed
671
self.builder.record_entry_contents(ie, self.parent_invs,
672
path, self.work_tree)
673
# describe the nature of the change that has occurred relative to
674
# the basis inventory.
675
if (self.basis_inv.has_id(ie.file_id)):
676
basis_ie = self.basis_inv[ie.file_id]
679
change = ie.describe_change(basis_ie, ie)
680
if change in (InventoryEntry.RENAMED,
681
InventoryEntry.MODIFIED_AND_RENAMED):
682
old_path = self.basis_inv.id2path(ie.file_id)
683
self.reporter.renamed(change, old_path, path)
685
self.reporter.snapshot_change(change, path)
687
# Unversion IDs that were found to be deleted
688
self.work_tree.unversion(deleted_ids)
690
# If specific files/directories were nominated, it is possible
691
# that some data from outside those needs to be preserved from
692
# the basis tree. For example, if a file x is moved from out of
693
# directory foo into directory bar and the user requests
694
# ``commit foo``, then information about bar/x must also be
697
for path, new_ie in self.basis_inv.iter_entries():
698
if new_ie.file_id in work_inv:
700
if is_inside_any(specific_files, path):
704
self.builder.record_entry_contents(ie, self.parent_invs, path,
707
# Report what was deleted. We could skip this when no deletes are
708
# detected to gain a performance win, but it arguably serves as a
709
# 'safety check' by informing the user whenever anything disappears.
710
for path, ie in self.basis_inv.iter_entries():
711
if ie.file_id not in self.builder.new_inventory:
712
self.reporter.deleted(path)
714
def _emit_progress_set_stage(self, name, show_entries=False):
715
"""Set the progress stage and emit an update to the progress bar."""
716
self.pb_stage_name = name
717
self.pb_stage_count += 1
718
self.pb_entries_show = show_entries
720
self.pb_entries_count = 0
721
self.pb_entries_total = '?'
722
self._emit_progress()
724
def _emit_progress_next_entry(self):
725
"""Emit an update to the progress bar and increment the file count."""
726
self.pb_entries_count += 1
727
self._emit_progress()
729
def _emit_progress(self):
730
if self.pb_entries_show:
731
text = "%s [Entry %d/%s] - Stage" % (self.pb_stage_name,
732
self.pb_entries_count,str(self.pb_entries_total))
734
text = "%s - Stage" % (self.pb_stage_name)
735
self.pb.update(text, self.pb_stage_count, self.pb_stage_total)