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)
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})
334
self.branch.set_last_revision_info(new_revno, 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)
342
# Process the post commit hooks, if any
343
self._emit_progress_set_stage("Running post commit hooks")
344
self._process_hooks(old_revno, new_revno)
350
self._cleanup_bound_branch()
351
self.work_tree.unlock()
349
def _any_real_changes(self):
350
"""Are there real changes between new_inventory and basis?
352
For trees without rich roots, inv.root.revision changes every commit.
353
But if that is the only change, we want to treat it as though there
356
new_entries = self.builder.new_inventory.iter_entries()
357
basis_entries = self.basis_inv.iter_entries()
358
new_path, new_root_ie = new_entries.next()
359
basis_path, basis_root_ie = basis_entries.next()
361
# This is a copy of InventoryEntry.__eq__ only leaving out .revision
362
def ie_equal_no_revision(this, other):
363
return ((this.file_id == other.file_id)
364
and (this.name == other.name)
365
and (this.symlink_target == other.symlink_target)
366
and (this.text_sha1 == other.text_sha1)
367
and (this.text_size == other.text_size)
368
and (this.text_id == other.text_id)
369
and (this.parent_id == other.parent_id)
370
and (this.kind == other.kind)
371
and (this.executable == other.executable)
372
and (this.reference_revision == other.reference_revision)
374
if not ie_equal_no_revision(new_root_ie, basis_root_ie):
377
for new_ie, basis_ie in zip(new_entries, basis_entries):
378
if new_ie != basis_ie:
381
# No actual changes present
384
def _check_pointless(self):
385
if self.allow_pointless:
387
# A merge with no effect on files
388
if len(self.parents) > 1:
390
# work around the fact that a newly-initted tree does differ from its
392
if len(self.basis_inv) == 0 and len(self.builder.new_inventory) == 1:
393
raise PointlessCommit()
394
# Shortcut, if the number of entries changes, then we obviously have
396
if len(self.builder.new_inventory) != len(self.basis_inv):
398
# If length == 1, then we only have the root entry. Which means
399
# that there is no real difference (only the root could be different)
400
if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
402
raise PointlessCommit()
353
404
def _check_bound_branch(self):
354
405
"""Check to see if the local branch is bound.
391
442
self.bound_branch = self.branch
392
443
self.master_branch.lock_write()
393
444
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)
446
def _check_out_of_date_tree(self):
447
"""Check that the working tree is up to date.
449
:return: old_revision_number,new_revision_number tuple
452
first_tree_parent = self.work_tree.get_parent_ids()[0]
454
# if there are no parents, treat our parent as 'None'
455
# this is so that we still consider the master branch
456
# - in a checkout scenario the tree may have no
457
# parents but the branch may do.
458
first_tree_parent = bzrlib.revision.NULL_REVISION
459
old_revno, master_last = self.master_branch.last_revision_info()
460
if master_last != first_tree_parent:
461
if master_last != bzrlib.revision.NULL_REVISION:
462
raise errors.OutOfDateTree(self.work_tree)
463
if self.branch.repository.has_revision(first_tree_parent):
464
new_revno = old_revno + 1
466
# ghost parents never appear in revision history.
468
return old_revno,new_revno
470
def _process_hooks(self, old_revno, new_revno):
471
"""Process any registered commit hooks."""
472
# old style commit hooks - should be deprecated ? (obsoleted in
474
if self.config.post_commit() is not None:
475
hooks = self.config.post_commit().split(' ')
476
# this would be nicer with twisted.python.reflect.namedAny
478
result = eval(hook + '(branch, rev_id)',
479
{'branch':self.branch,
481
'rev_id':self.rev_id})
482
# new style commit hooks:
483
if not self.bound_branch:
484
hook_master = self.branch
487
hook_master = self.master_branch
488
hook_local = self.branch
489
# With bound branches, when the master is behind the local branch,
490
# the 'old_revno' and old_revid values here are incorrect.
491
# XXX: FIXME ^. RBC 20060206
493
old_revid = self.parents[0]
495
old_revid = bzrlib.revision.NULL_REVISION
496
for hook in Branch.hooks['post_commit']:
497
hook(hook_local, hook_master, old_revno, old_revid, new_revno,
501
"""Cleanup any open locks, progress bars etc."""
502
cleanups = [self._cleanup_bound_branch,
503
self.basis_tree.unlock,
504
self.work_tree.unlock,
506
found_exception = None
507
for cleanup in cleanups:
510
# we want every cleanup to run no matter what.
511
# so we have a catchall here, but we will raise the
512
# last encountered exception up the stack: and
513
# typically this will be useful enough.
516
if found_exception is not None:
517
# don't do a plan raise, because the last exception may have been
518
# trashed, e is our sure-to-work exception even though it loses the
519
# full traceback. XXX: RBC 20060421 perhaps we could check the
520
# exc_info and if its the same one do a plain raise otherwise
521
# 'raise e' as we do now.
403
524
def _cleanup_bound_branch(self):
404
525
"""Executed at the end of a try/finally to cleanup a bound branch.
428
554
def _gather_parents(self):
429
555
"""Record the parents of a merge for merge detection."""
430
pending_merges = self.work_tree.pending_merges()
432
self.parent_invs = []
433
self.present_parents = []
434
precursor_id = self.branch.last_revision()
436
self.parents.append(precursor_id)
437
self.parents += pending_merges
438
for revision in self.parents:
556
# TODO: Make sure that this list doesn't contain duplicate
557
# entries and the order is preserved when doing this.
558
self.parents = self.work_tree.get_parent_ids()
559
self.parent_invs = [self.basis_inv]
560
for revision in self.parents[1:]:
439
561
if self.branch.repository.has_revision(revision):
562
mutter('commit parent revision {%s}', revision)
440
563
inventory = self.branch.repository.get_inventory(revision)
441
564
self.parent_invs.append(inventory)
442
self.present_parents.append(revision)
444
def _check_parents_present(self):
445
for parent_id in self.parents:
446
mutter('commit parent revision {%s}', parent_id)
447
if not self.branch.repository.has_revision(parent_id):
448
if parent_id == self.branch.last_revision():
449
warning("parent is missing %r", parent_id)
450
raise HistoryMissing(self.branch, 'revision', parent_id)
452
mutter("commit will ghost revision %r", parent_id)
454
def _make_revision(self):
455
"""Record a new revision object for this commit."""
456
rev = Revision(timestamp=self.timestamp,
457
timezone=self.timezone,
458
committer=self.committer,
459
message=self.message,
460
inventory_sha1=self.inv_sha1,
461
revision_id=self.rev_id,
462
properties=self.revprops)
463
rev.parent_ids = self.parents
464
self.branch.repository.add_revision(self.rev_id, rev, self.new_inv, self.config)
466
def _remove_deleted(self):
467
"""Remove deleted files from the working inventories.
469
This is done prior to taking the working inventory as the
470
basis for the new committed inventory.
472
This returns true if any files
473
*that existed in the basis inventory* were deleted.
474
Files that were added and deleted
475
in the working copy don't matter.
566
mutter('commit parent ghost revision {%s}', revision)
568
def _update_builder_with_changes(self):
569
"""Update the commit builder with the data about what has changed.
477
specific = self.specific_files
571
# Build the revision inventory.
573
# This starts by creating a new empty inventory. Depending on
574
# which files are selected for commit, and what is present in the
575
# current tree, the new inventory is populated. inventory entries
576
# which are candidates for modification have their revision set to
577
# None; inventory entries that are carried over untouched have their
578
# revision set to their prior value.
580
# ESEPARATIONOFCONCERNS: this function is diffing and using the diff
581
# results to create a new inventory at the same time, which results
582
# in bugs like #46635. Any reason not to use/enhance Tree.changes_from?
585
specific_files = self.specific_files
586
mutter("Selecting files for commit with filter %s", specific_files)
587
work_inv = self.work_tree.inventory
588
assert work_inv.root is not None
589
self.pb_entries_total = len(work_inv)
591
# Check and warn about old CommitBuilders
592
entries = work_inv.iter_entries()
593
if not self.builder.record_root_entry:
594
symbol_versioning.warn('CommitBuilders should support recording'
595
' the root entry as of bzr 0.10.', DeprecationWarning,
597
self.builder.new_inventory.add(self.basis_inv.root.copy())
479
for path, ie in self.work_inv.iter_entries():
480
if specific and not is_inside_any(specific, path):
601
deleted_paths = set()
602
for path, new_ie in entries:
603
self._emit_progress_next_entry()
604
file_id = new_ie.file_id
606
# Skip files that have been deleted from the working tree.
607
# The deleted files/directories are also recorded so they
608
# can be explicitly unversioned later. Note that when a
609
# filter of specific files is given, we must only skip/record
610
# deleted files matching that filter.
611
if is_inside_any(deleted_paths, path):
482
if not self.work_tree.has_filename(path):
483
self.reporter.missing(path)
484
deleted_ids.append((path, ie.file_id))
486
deleted_ids.sort(reverse=True)
487
for path, file_id in deleted_ids:
488
del self.work_inv[file_id]
489
self.work_tree._write_inventory(self.work_inv)
491
def _store_snapshot(self):
492
"""Pass over inventory and record a snapshot.
494
Entries get a new revision when they are modified in
495
any way, which includes a merge with a new set of
496
parents that have the same entry.
498
# XXX: Need to think more here about when the user has
499
# made a specific decision on a particular value -- c.f.
501
for path, ie in self.new_inv.iter_entries():
502
previous_entries = ie.find_previous_heads(
505
self.branch.repository.get_transaction())
506
if ie.revision is None:
507
change = ie.snapshot(self.rev_id, path, previous_entries,
508
self.work_tree, self.weave_store,
509
self.branch.get_transaction())
613
if not specific_files or is_inside_any(specific_files, path):
614
if not self.work_tree.has_filename(path):
615
deleted_paths.add(path)
616
self.reporter.missing(path)
617
deleted_ids.append(file_id)
620
kind = self.work_tree.kind(file_id)
621
if kind == 'tree-reference' and self.recursive == 'down':
622
# nested tree: commit in it
623
sub_tree = WorkingTree.open(self.work_tree.abspath(path))
624
# FIXME: be more comprehensive here:
625
# this works when both trees are in --trees repository,
626
# but when both are bound to a different repository,
627
# it fails; a better way of approaching this is to
628
# finally implement the explicit-caches approach design
629
# a while back - RBC 20070306.
630
if (sub_tree.branch.repository.bzrdir.root_transport.base
632
self.work_tree.branch.repository.bzrdir.root_transport.base):
633
sub_tree.branch.repository = \
634
self.work_tree.branch.repository
636
sub_tree.commit(message=None, revprops=self.revprops,
637
recursive=self.recursive,
638
message_callback=self.message_callback,
639
timestamp=self.timestamp, timezone=self.timezone,
640
committer=self.committer,
641
allow_pointless=self.allow_pointless,
642
strict=self.strict, verbose=self.verbose,
643
local=self.local, reporter=self.reporter)
644
except errors.PointlessCommit:
646
if kind != new_ie.kind:
647
new_ie = inventory.make_entry(kind, new_ie.name,
648
new_ie.parent_id, file_id)
649
except errors.NoSuchFile:
651
# mutter('check %s {%s}', path, file_id)
652
if (not specific_files or
653
is_inside_or_parent_of_any(specific_files, path)):
654
# mutter('%s selected for commit', path)
512
self.reporter.snapshot_change(change, path)
514
def _populate_new_inv(self):
515
"""Build revision inventory.
517
This creates a new empty inventory. Depending on
518
which files are selected for commit, and what is present in the
519
current tree, the new inventory is populated. inventory entries
520
which are candidates for modification have their revision set to
521
None; inventory entries that are carried over untouched have their
522
revision set to their prior value.
524
mutter("Selecting files for commit with filter %s", self.specific_files)
525
self.new_inv = Inventory(revision_id=self.rev_id)
526
for path, new_ie in self.work_inv.iter_entries():
527
file_id = new_ie.file_id
528
mutter('check %s {%s}', path, new_ie.file_id)
529
if self.specific_files:
530
if not is_inside_any(self.specific_files, path):
531
mutter('%s not selected for commit', path)
532
self._carry_entry(file_id)
658
# mutter('%s not selected for commit', path)
659
if self.basis_inv.has_id(file_id):
660
ie = self.basis_inv[file_id].copy()
535
# this is selected, ensure its parents are too.
536
parent_id = new_ie.parent_id
537
while parent_id != ROOT_ID:
538
if not self.new_inv.has_id(parent_id):
539
ie = self._select_entry(self.work_inv[parent_id])
540
mutter('%s selected for commit because of %s',
541
self.new_inv.id2path(parent_id), path)
543
ie = self.new_inv[parent_id]
544
if ie.revision is not None:
546
mutter('%s selected for commit because of %s',
547
self.new_inv.id2path(parent_id), path)
548
parent_id = ie.parent_id
549
mutter('%s selected for commit', path)
550
self._select_entry(new_ie)
552
def _select_entry(self, new_ie):
553
"""Make new_ie be considered for committing."""
559
def _carry_entry(self, file_id):
560
"""Carry the file unchanged from the basis revision."""
561
if self.basis_inv.has_id(file_id):
562
self.new_inv.add(self.basis_inv[file_id].copy())
564
def _report_deletes(self):
565
for file_id in self.basis_inv:
566
if file_id not in self.new_inv:
567
self.reporter.deleted(self.basis_inv.id2path(file_id))
569
def _gen_revision_id(config, when):
570
"""Return new revision-id."""
571
s = '%s-%s-' % (config.user_email(), compact_date(when))
572
s += hexlify(rand_bytes(8))
662
# this entry is new and not being committed
664
self.builder.record_entry_contents(ie, self.parent_invs,
665
path, self.work_tree)
666
# describe the nature of the change that has occurred relative to
667
# the basis inventory.
668
if (self.basis_inv.has_id(ie.file_id)):
669
basis_ie = self.basis_inv[ie.file_id]
672
change = ie.describe_change(basis_ie, ie)
673
if change in (InventoryEntry.RENAMED,
674
InventoryEntry.MODIFIED_AND_RENAMED):
675
old_path = self.basis_inv.id2path(ie.file_id)
676
self.reporter.renamed(change, old_path, path)
678
self.reporter.snapshot_change(change, path)
680
# Unversion IDs that were found to be deleted
681
self.work_tree.unversion(deleted_ids)
683
# If specific files/directories were nominated, it is possible
684
# that some data from outside those needs to be preserved from
685
# the basis tree. For example, if a file x is moved from out of
686
# directory foo into directory bar and the user requests
687
# ``commit foo``, then information about bar/x must also be
690
for path, new_ie in self.basis_inv.iter_entries():
691
if new_ie.file_id in work_inv:
693
if is_inside_any(specific_files, path):
697
self.builder.record_entry_contents(ie, self.parent_invs, path,
700
# Report what was deleted. We could skip this when no deletes are
701
# detected to gain a performance win, but it arguably serves as a
702
# 'safety check' by informing the user whenever anything disappears.
703
for path, ie in self.basis_inv.iter_entries():
704
if ie.file_id not in self.builder.new_inventory:
705
self.reporter.deleted(path)
707
def _emit_progress_set_stage(self, name, show_entries=False):
708
"""Set the progress stage and emit an update to the progress bar."""
709
self.pb_stage_name = name
710
self.pb_stage_count += 1
711
self.pb_entries_show = show_entries
713
self.pb_entries_count = 0
714
self.pb_entries_total = '?'
715
self._emit_progress()
717
def _emit_progress_next_entry(self):
718
"""Emit an update to the progress bar and increment the file count."""
719
self.pb_entries_count += 1
720
self._emit_progress()
722
def _emit_progress(self):
723
if self.pb_entries_show:
724
text = "%s [Entry %d/%s] - Stage" % (self.pb_stage_name,
725
self.pb_entries_count,str(self.pb_entries_total))
727
text = "%s - Stage" % (self.pb_stage_name)
728
self.pb.update(text, self.pb_stage_count, self.pb_stage_total)