Rev 24: Switch to using a local repository if available, in http://bazaar.launchpad.net/%7Ebzr/bzr-email/trunk

John Arbash Meinel john at arbash-meinel.com
Sat Feb 17 18:09:27 GMT 2007


At http://bazaar.launchpad.net/%7Ebzr/bzr-email/trunk

------------------------------------------------------------
revno: 24
revision-id: john at arbash-meinel.com-20070217180912-adzv4po94phzm6h4
parent: john at arbash-meinel.com-20070207223737-deytpas3j166sz72
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: email
timestamp: Sat 2007-02-17 12:09:12 -0600
message:
  Switch to using a local repository if available,
  also do most actions inside a single read lock, so the repository
  information doesn't need to be read repeatedly.
modified:
  __init__.py                    __init__.py-20051018071212-f1765ec4521cab0b
  emailer.py                     emailer.py-20070123220937-ec5y2n2oeoa0p4ue-1
  tests/testemail.py             testpublish.py-20051018071212-e3a53d78c05e0e0a
-------------- next part --------------
=== modified file '__init__.py'
--- a/__init__.py	2007-02-07 22:37:37 +0000
+++ b/__init__.py	2007-02-17 18:09:12 +0000
@@ -48,7 +48,8 @@
 
 def branch_commit_hook(local, master, old_revno, old_revid, new_revno, new_revid):
     """This is the post_commit hook that runs after commit."""
-    _emailer.EmailSender(master, new_revid, master.get_config()).send_maybe()
+    _emailer.EmailSender(master, new_revid, master.get_config(),
+                         local_branch=local).send_maybe()
 
 
 def install_hooks():

=== modified file 'emailer.py'
--- a/emailer.py	2007-01-27 14:53:08 +0000
+++ b/emailer.py	2007-02-17 18:09:12 +0000
@@ -30,11 +30,20 @@
 
     _smtplib_implementation = SMTPConnection
 
-    def __init__(self, branch, revision_id, config):
+    def __init__(self, branch, revision_id, config, local_branch=None):
         self.config = config
         self.branch = branch
-        self.revision = self.branch.repository.get_revision(revision_id)
-        self.revno = self.branch.revision_id_to_revno(revision_id)
+        self.repository = branch.repository
+        if (local_branch is not None and
+            local_branch.repository.has_revision(revision_id)):
+            self.repository = local_branch.repository
+        self._revision_id = revision_id
+        self.revision = None
+        self.revno = None
+
+    def _setup_revision_and_revno(self):
+        self.revision = self.repository.get_revision(self._revision_id)
+        self.revno = self.branch.revision_id_to_revno(self._revision_id)
 
     def body(self):
         from bzrlib.log import log_formatter, show_log
@@ -83,13 +92,13 @@
         revid_new = self.revision.revision_id
         if self.revision.parent_ids:
             revid_old = self.revision.parent_ids[0]
-            tree_new, tree_old = self.branch.repository.revision_trees((revid_new, revid_old))
+            tree_new, tree_old = self.repository.revision_trees((revid_new, revid_old))
         else:
             # revision_trees() doesn't allow None or 'null:' to be passed as a
             # revision. So we need to call revision_tree() twice.
             revid_old = _mod_revision.NULL_REVISION
-            tree_new = self.branch.repository.revision_tree(revid_new)
-            tree_old = self.branch.repository.revision_tree(revid_old)
+            tree_new = self.repository.revision_tree(revid_new)
+            tree_old = self.repository.revision_tree(revid_old)
 
         # We can use a cStringIO because show_diff_trees should only write
         # 8-bit strings. It is an error to write a Unicode string here.
@@ -154,11 +163,19 @@
         Depending on the configuration, this will either use smtplib, or it
         will call out to the 'mail' program.
         """
-        mailer = self.mailer()
-        if mailer == 'smtplib':
-            self._send_using_smtplib()
-        else:
-            self._send_using_process()
+        self.branch.lock_read()
+        self.repository.lock_read()
+        try:
+            # Do this after we have locked, to make things faster.
+            self._setup_revision_and_revno()
+            mailer = self.mailer()
+            if mailer == 'smtplib':
+                self._send_using_smtplib()
+            else:
+                self._send_using_process()
+        finally:
+            self.repository.unlock()
+            self.branch.unlock()
 
     def _send_using_process(self):
         """Spawn a 'mail' subprocess to send the email."""

=== modified file 'tests/testemail.py'
--- a/tests/testemail.py	2007-01-27 14:53:08 +0000
+++ b/tests/testemail.py	2007-02-17 18:09:12 +0000
@@ -20,6 +20,7 @@
 
 from bzrlib import (
     config,
+    tests,
     )
 from bzrlib.bzrdir import BzrDir
 from bzrlib.tests import TestCaseInTempDir
@@ -53,6 +54,7 @@
                  "post_commit_to=demo at example.com\n"
                  "post_commit_sender=Sample <foo at example.com>\n")
 
+
 class TestGetTo(TestCaseInTempDir):
 
     def test_body(self):
@@ -156,6 +158,55 @@
         my_config = self.branch.get_config()
         config_file = StringIO(text)
         (my_config._get_global_config()._get_parser(config_file))
-        return EmailSender(self.branch, 'A', my_config)
-
-
+        sender = EmailSender(self.branch, 'A', my_config)
+        # This is usually only done after the EmailSender has locked the branch
+        # and repository during send(), however, for testing, we need to do it
+        # earlier, since send() is not called.
+        sender._setup_revision_and_revno()
+        return sender
+
+
+class TestEmailerWithLocal(tests.TestCaseWithTransport):
+    """Test that Emailer will use a local branch if supplied."""
+
+    def test_local_has_revision(self):
+        master_tree = self.make_branch_and_tree('master')
+        self.build_tree(['master/a'])
+        master_tree.add('a')
+        master_tree.commit('a')
+
+        child_tree = master_tree.bzrdir.sprout('child').open_workingtree()
+        child_tree.branch.bind(master_tree.branch)
+
+        self.build_tree(['child/b'])
+        child_tree.add(['b'])
+        revision_id = child_tree.commit('b')
+
+        sender = EmailSender(master_tree.branch, revision_id,
+                             master_tree.branch.get_config(),
+                             local_branch=child_tree.branch)
+
+        # Make sure we are using the 'local_branch' repository, and not the
+        # remote one.
+        self.assertIs(child_tree.branch.repository, sender.repository)
+
+    def test_local_missing_revision(self):
+        master_tree = self.make_branch_and_tree('master')
+        self.build_tree(['master/a'])
+        master_tree.add('a')
+        master_tree.commit('a')
+
+        child_tree = master_tree.bzrdir.sprout('child').open_workingtree()
+        child_tree.branch.bind(master_tree.branch)
+
+        self.build_tree(['master/c'])
+        master_tree.add(['c'])
+        revision_id = master_tree.commit('c')
+
+        self.failIf(child_tree.branch.repository.has_revision(revision_id))
+        sender = EmailSender(master_tree.branch, revision_id,
+                             master_tree.branch.get_config(),
+                             local_branch=child_tree.branch)
+        # We should be using the master repository here, because the child
+        # repository doesn't contain the revision.
+        self.assertIs(master_tree.branch.repository, sender.repository)



More information about the bazaar-commits mailing list