~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

  • Committer: NamNguyen
  • Date: 2007-08-01 06:14:14 UTC
  • mto: (2789.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 2790.
  • Revision ID: namnguyen-20070801061414-u0tzrfgcz6z604lz
``Branch.hooks`` now supports ``pre_commit`` hook.

The hook's signature is

::

  hook(local, master, old_revno, old_revid, new_revno, new_revid,
       deleted_paths, added_paths, future_revision_tree)

``deleted_paths`` and ``added_paths`` are lists of paths. Renamed paths are
recorded in both ``deleted_paths`` and ``added_paths`` (i.e. deleted then
added).

``future_revision_tree`` is obtained from ``CommitBuilder.revision_tree``
to save hooks from getting it from the branch again.

For example, hooks can get a file:

::

  for path in added_paths:
      id = future_revision_tree.path2id(path)
      if future_revision_tree.kind(id) == 'file':
          file = future_revision_tree.get_file(id)
          ...

or export a tree and do ``make check`` or similar

::

  import bzrlib.export
  bzrlib.export.export(future_revision_tree, 'tmp_space')


If the commit is to be rejected, hooks should raise an ``Exception``.

Show diffs side-by-side

added added

removed removed

Lines of Context:
235
235
        self.committer = committer
236
236
        self.strict = strict
237
237
        self.verbose = verbose
 
238
        self.deleted_paths = set()
 
239
        self.added_paths = set()
238
240
 
239
241
        if reporter is None and self.reporter is None:
240
242
            self.reporter = NullCommitReporter()
254
256
            self._check_bound_branch()
255
257
 
256
258
            # Check that the working tree is up to date
257
 
            old_revno,new_revno = self._check_out_of_date_tree()
 
259
            old_revno, new_revno = self._check_out_of_date_tree()
258
260
 
259
261
            if self.config is None:
260
262
                self.config = self.branch.get_config()
275
277
            # information in the progress bar during the relevant stages.
276
278
            self.pb_stage_name = ""
277
279
            self.pb_stage_count = 0
278
 
            self.pb_stage_total = 4
 
280
            self.pb_stage_total = 5
279
281
            if self.bound_branch:
280
282
                self.pb_stage_total += 1
281
283
            self.pb.show_pct = False
315
317
            # Add revision data to the local branch
316
318
            self.rev_id = self.builder.commit(self.message)
317
319
            
 
320
            self._process_pre_hooks(old_revno, new_revno)
 
321
            
318
322
            # Upload revision data to the master.
319
323
            # this will propagate merged revisions too if needed.
320
324
            if self.bound_branch:
335
339
            rev_tree = self.builder.revision_tree()
336
340
            self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
337
341
            self.reporter.completed(new_revno, self.rev_id)
338
 
            self._process_hooks(old_revno, new_revno)
 
342
            self._process_post_hooks(old_revno, new_revno)
339
343
        finally:
340
344
            self._cleanup()
341
345
        return self.rev_id
461
465
            new_revno = 1
462
466
        return old_revno,new_revno
463
467
 
464
 
    def _process_hooks(self, old_revno, new_revno):
465
 
        """Process any registered commit hooks."""
 
468
    def _process_pre_hooks(self, old_revno, new_revno):
 
469
        """Process any registered pre commit hooks."""
 
470
        self._set_progress_stage("Running pre commit hooks")
 
471
        self._process_hooks("pre_commit", old_revno, new_revno)
 
472
 
 
473
    def _process_post_hooks(self, old_revno, new_revno):
 
474
        """Process any registered post commit hooks."""
466
475
        # Process the post commit hooks, if any
467
476
        self._set_progress_stage("Running post commit hooks")
468
477
        # old style commit hooks - should be deprecated ? (obsoleted in
475
484
                              {'branch':self.branch,
476
485
                               'bzrlib':bzrlib,
477
486
                               'rev_id':self.rev_id})
 
487
        # process new style post commit hooks
 
488
        self._process_hooks("post_commit", old_revno, new_revno)
 
489
 
 
490
    def _process_hooks(self, hook_name, old_revno, new_revno):
478
491
        # new style commit hooks:
479
492
        if not self.bound_branch:
480
493
            hook_master = self.branch
489
502
            old_revid = self.parents[0]
490
503
        else:
491
504
            old_revid = bzrlib.revision.NULL_REVISION
492
 
        for hook in Branch.hooks['post_commit']:
 
505
        for hook in Branch.hooks[hook_name]:
493
506
            # show the running hook in the progress bar. As hooks may
494
507
            # end up doing nothing (e.g. because they are not configured by
495
508
            # the user) this is still showing progress, not showing overall
496
509
            # actions - its up to each plugin to show a UI if it want's to
497
510
            # (such as 'Emailing diff to foo@example.com').
498
 
            self.pb_stage_name = "Running post commit hooks [%s]" % \
499
 
                Branch.hooks.get_hook_name(hook)
 
511
            self.pb_stage_name = "Running %s hooks [%s]" % \
 
512
                (hook_name.replace('_', ' '), Branch.hooks.get_hook_name(hook))
500
513
            self._emit_progress()
501
514
            if 'hooks' in debug.debug_flags:
502
515
                mutter("Invoking commit hook: %r", hook)
503
 
            hook(hook_local, hook_master, old_revno, old_revid, new_revno,
504
 
                self.rev_id)
 
516
            if hook_name == "post_commit":
 
517
                hook(hook_local, hook_master, old_revno, old_revid, new_revno,
 
518
                     self.rev_id)
 
519
            elif hook_name == "pre_commit":
 
520
                future_tree = self.builder.revision_tree()
 
521
                added = list(self.added_paths)
 
522
                added.sort()
 
523
                deleted = list(self.deleted_paths)
 
524
                deleted.sort()
 
525
                hook(hook_local, hook_master,
 
526
                     old_revno, old_revid, new_revno, self.rev_id,
 
527
                     deleted, added, future_tree)
505
528
 
506
529
    def _cleanup(self):
507
530
        """Cleanup any open locks, progress bars etc."""
614
637
                ie.revision = None
615
638
                self.builder.record_entry_contents(ie, self.parent_invs, path,
616
639
                                                   self.basis_tree)
 
640
                self.added_paths.add(path)
617
641
 
618
642
        # Report what was deleted. We could skip this when no deletes are
619
643
        # detected to gain a performance win, but it arguably serves as a
621
645
        for path, ie in self.basis_inv.iter_entries():
622
646
            if ie.file_id not in self.builder.new_inventory:
623
647
                self.reporter.deleted(path)
 
648
                self.deleted_paths.add(path)
624
649
 
625
650
    def _populate_from_inventory(self, specific_files):
626
651
        """Populate the CommitBuilder by walking the working tree inventory."""
742
767
            InventoryEntry.MODIFIED_AND_RENAMED):
743
768
            old_path = self.basis_inv.id2path(ie.file_id)
744
769
            self.reporter.renamed(change, old_path, path)
 
770
            self.deleted_paths.add(old_path)
 
771
            self.added_paths.add(path)
745
772
        else:
746
773
            self.reporter.snapshot_change(change, path)
 
774
            if change == 'added' and path != '':
 
775
                self.added_paths.add(path)
747
776
 
748
777
    def _set_progress_stage(self, name, entries_title=None):
749
778
        """Set the progress stage and emit an update to the progress bar."""