List:Commits« Previous MessageNext Message »
From:C Miller Date:June 23 2008 3:09pm
Subject:bzr commit into mysql_plugins branch (bzrdev:116)
View as plain text  
#At file:///Users/cmiller/.bazaar/plugins/mysql/

  116 C Miller	2008-06-23 [merge]
      Merge from trunk.
added:
  sanity.py
modified:
  .bzr-mysql/default.conf
  __init__.py
  emailer.py
  hooks.py

=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	2008-05-21 22:17:24 +0000
+++ b/.bzr-mysql/default.conf	2008-06-18 10:43:25 +0000
@@ -1,5 +1,5 @@
 [MYSQL]
 tree_location = bzr+ssh://bk-internal.mysql.com/home/bk/bazaar/mysql_plugins/
-post_commit_to = mtaylor@stripped, cmiller@stripped
 post_push_to = bzr@stripped
+post_commit_to = commits@stripped, bzr@stripped
 tree_name = mysql_plugins

=== modified file '__init__.py'
--- a/__init__.py	2008-05-30 21:43:58 +0000
+++ b/__init__.py	2008-06-23 15:09:10 +0000
@@ -31,9 +31,10 @@ lazy_import(globals(), """
 import collapse
 import parent
 import hooks
+import sanity
 """)
 
-version_info = (0, 3, 6)
+version_info = (0, 3, 10)
 
 register_command(parent.cmd_parent)
 register_command(collapse.cmd_collapse)
@@ -73,6 +74,11 @@ try:
 except:
     mutter("bzr-mysql: Can't install post_push_hook")
 
+try:
+    install_hook_named_or_not("pre_commit", sanity.pre_commit_hook, "pre_commit hook that does sanity checks")
+except:
+    mutter("bzr-mysql: Can't install pre_commit_hook")
+
 
 # vim: sta
 # vi: et sw=4 ts=4

=== modified file 'emailer.py'
--- a/emailer.py	2008-05-30 10:14:30 +0000
+++ b/emailer.py	2008-06-19 00:03:41 +0000
@@ -41,6 +41,7 @@ from bzrlib.trace import mutter, note, w
 from bzrlib.email_message import EmailMessage
 from bzrlib.smtp_connection import SMTPConnection
 from bzrlib.util import bencode
+from bzrlib.osutils import get_terminal_encoding
 
 class Sendmail(object):
     def __init__(self, config):
@@ -48,12 +49,15 @@ class Sendmail(object):
         self.mailer = config.get_user_option('post_commit_mailer',
                                              False,"/usr/lib/sendmail")
 
-    def send_email(self, message):
+    def send_email(self, message, sender=None):
         """Spawn a 'sendmail' subprocess to send the email."""
         # TODO think up a good test for this, but I think it needs
         # a custom binary shipped with. RBC 20051021
 
         cmd = [ self.mailer, '-t' ]
+        if sender:
+            cmd.append('-f')
+            cmd.append(sender)
 
         try:
             process = subprocess.Popen( cmd,
@@ -75,7 +79,7 @@ class Sendmail(object):
             raise
         except OSError, e:
             if e.errno == errno.ENOENT:
-                raise errors.BzrError("sendmail is not installed !?")
+                raise errors.BzrError("Mailer '%s' is not installed !?" % (self.mailer))
             else:
                 raise
 
@@ -120,24 +124,25 @@ class EmailSender(object):
         self.blueprint_ids_found = list()
         self.bug_search_done = False
 
+        # We request several pieces of text from the bzr core, which it
+        # intends to be emitted to the user, and as such should (!?) already
+        # be encoded.  Since we need to deal with Unicode a few times, we
+        # must know this encoding name and later use it to decode strings.
+        self.encoding = get_terminal_encoding()
+
     def search_for_bugs(self, commit_message):
         """ scan entire log output for mentions of bugs, worklogs """
 
-        self.bug_ids_found = list(set(re.findall(r"(?i)\bbug[#:=]? ?(\d+)",
+        self.bug_ids_found = list(set(re.findall(r"(?i)\bbug[ ]*#[ ]*(\d+)",
                                                  commit_message.encode("utf8"))))
-        self.worklog_ids_found = list(set(re.findall(r"(?i)\bwl[#:=]? ?(\d+)",
+        self.worklog_ids_found = list(set(re.findall(r"(?i)\bwl[ ]*#[ ]*(\d+)",
                                                      commit_message.encode("utf8"))))
-        self.blueprint_ids_found = list(set(re.findall(r"(?i)\bblueprint[#:=]? ?(\d+)",
+        self.blueprint_ids_found = list(set(re.findall(r"(?i)\bblueprint[ ]*#[ ]*(\d+)",
                                                        commit_message.encode("utf8"))))
 
-        self.bug_ids_found.sort()
-        self.worklog_ids_found.sort()
-        self.blueprint_ids_found.sort()
-
-
-
 
     def pre_message(self):
+        # This had better be in the same encoding as the output.  :\
         the_message = self.config.get_user_option('pre_message', False,
                                                   '#At %(url)s\n\n')
         return the_message % dict(url=self.url(),
@@ -162,7 +167,7 @@ class EmailSender(object):
             return
 
         if self._diff is None:
-            self._diff = ""
+            self._diff = u""
         return self._diff
 
     def difflimit(self):
@@ -236,14 +241,13 @@ class EmailSender(object):
             alist = AddressList(to_addrs)
             to_addrs = [formataddr(x) for x in alist.addresslist]
 
+        assert isinstance(body, unicode), type(body)
+        assert isinstance(diff, unicode), type(diff)
+        message = EmailMessage(from_addr, to_addrs, subject, body + diff)
 
-        body=unicode(body)+unicode(diff)
-
-        message = EmailMessage(from_addr, to_addrs, subject, body)
         for header in headers:
             message[header[0]] = header[1]
 
-
         return message
 
     def send(self):
@@ -259,7 +263,7 @@ class EmailSender(object):
             SMTPConnection(self.config).send_email(self.get_message())
         else:
             mutter("sending using process")
-            Sendmail(self.config).send_email(self.get_message())
+            Sendmail(self.config).send_email(self.get_message(), sender=self.from_address())
 
     def headers(self, commit_message):
         the_headers = [ ('X-CSetKey',str(self.new_revid)),
@@ -271,8 +275,8 @@ class EmailSender(object):
         project = self.project()
         if project is not None:
             the_headers.append(('X-Project',project))
-        for bug_id in self.bug_ids_found:
-            the_headers.append(('X-Bug',str(bug_id)))
+        if len(self.bug_ids_found) > 0:
+            the_headers.append(('X-Bug',str(self.bug_ids_found[0])))
         for wl_id in self.worklog_ids_found:
             the_headers.append(('X-Worklog',str(wl_id)))
         for blueprint_id in self.blueprint_ids_found:
@@ -312,9 +316,9 @@ class EmailSender(object):
         return "patch-%s.diff" % (self.revno,)
 
 
-    def per_file_comments_as_string(self, a_revision):
-        """ Concatenates all file comments for inclusion in the email """
-        # see revisionview.py in bzr-gtk plugin: per-file comments are in
+    def per_file_messages_as_string(self, a_revision):
+        """ Concatenates all file messages for inclusion in the email """
+        # see revisionview.py in bzr-gtk plugin: per-file messages are in
         # property 'file-info' and bencode/decode-d.
         file_info = a_revision.properties.get('file-info', None)
         if file_info is None:
@@ -330,7 +334,7 @@ class EmailSender(object):
             message = message.replace('\n', '\n' + spacing)
             text = text + '  %s\n%s\n' % (fi['path'], message)
         if text:
-            return 'per-file comments:\n' + text
+            return 'per-file messages:\n' + text
         return ''
 
     def show_diff_trees_minus_p(self, tree_old, tree_new, diff_content):
@@ -385,10 +389,10 @@ class CommitSender(EmailSender):
         self.show_diff_trees_minus_p(tree_old, tree_new, diff_content)
         numlines = diff_content.getvalue().count('\n')+1
         if numlines <= difflimit:
-            return diff_content.getvalue()
+            return diff_content.getvalue().decode(self.encoding)
         else:
-            return ("\nDiff too large for email"
-                    " (%d lines, the limit is %d).\n"
+            return (u"\nDiff too large for email"
+                    u" (%d lines, the limit is %d).\n"
                     % (numlines, difflimit))
 
     def body(self):
@@ -400,9 +404,6 @@ class CommitSender(EmailSender):
                 rev1 = None
                 rev2 = None
 
-            # use 'replace' so that we don't abort if trying to write out
-            # in e.g. the default C locale.
-
             # We must use StringIO.StringIO because we want a Unicode string that
             # we can pass to send_email and have that do the proper encoding.
             outf = StringIO.StringIO()
@@ -421,9 +422,10 @@ class CommitSender(EmailSender):
                      verbose=True
                      )
 
-            self._body = (
-                outf.getvalue() +
-                self.per_file_comments_as_string(self.revision) )
+            outf.write(self.per_file_messages_as_string(self.revision))
+
+            # Decode the stuff planned for output to get Unicode.
+            self._body = outf.getvalue().decode(self.encoding)
 
         return self._body
 
@@ -433,6 +435,25 @@ class PushSender(EmailSender):
     def body(self):
         """ Return the bzr log to work as the 'commit message' here """
         if self._body is None:
+            # We need the revno of the old revision in-the-new-tree
+            note("Generating post-push message")
+            try:
+                # Optimized case - if it works on the old_revid, we don't need
+                # to do the slow code below.
+                self.old_revno = self.branch.revision_id_to_revno(self.old_revid)
+            except:
+                b=self.branch
+                b.lock_read()
+                g = b.repository.get_graph()
+                last = b.last_revision()
+                while True:
+                    last_but_one = b.repository.get_revision(last).parent_ids[0]
+                    introduced_by_last = g.find_unique_ancestors(last, [last_but_one])
+                    if self.old_revid in introduced_by_last:
+                        break
+                    last = last_but_one
+                self.old_revno = b.revision_id_to_revno(last)
+
             outf = StringIO.StringIO()
 
             lf = log_formatter('short',
@@ -440,12 +461,14 @@ class PushSender(EmailSender):
                                to_file=outf
                                )
 
-            mutter("Getting log information for (%s:%s)" % (self.old_revno+1,self.new_revno))
+            mutter("Getting log information for (%s:%s)" % (self.old_revno,self.new_revno))
             log.show_log(self.branch, lf, verbose=True,
                          direction='reverse',
-                         start_revision=self.old_revno+1,
+                         start_revision=self.old_revno,
                          end_revision=self.new_revno)
-            self._body = outf.getvalue()
+
+            self._body = outf.getvalue().decode(self.encoding)
+            note("Sending post-push message")
 
         return self._body
 
@@ -464,10 +487,10 @@ class PushSender(EmailSender):
             self.show_diff_trees_minus_p(tree_old, tree_new, diff_content)
             numlines = diff_content.getvalue().count('\n')+1
             if numlines <= difflimit:
-                self._diff = diff_content.getvalue()
+                self._diff = diff_content.getvalue().decode(self.encoding)
             else:
-                self._diff = ("\nDiff too large for email"
-                              " (%d lines, the limit is %d).\n"
+                self._diff = (u"\nDiff too large for email"
+                              u" (%d lines, the limit is %d).\n"
                               % (numlines, difflimit))
         return self._diff
 
@@ -482,10 +505,10 @@ class PushSender(EmailSender):
 
         vals = dict(tree=self.tree_name_or_url(),
                     user=self.user(),
-                    old_revno=self.old_revno+1,
+                    old_revno=self.old_revno,
                     new_revno=self.new_revno,
                     ref_subject=self.ref_subject())
-        if self.old_revno+1==self.new_revno:
+        if self.old_revno==self.new_revno:
             theSubject = "bzr push into %(tree)s branch (%(user)s:%(old_revno)s) %(ref_subject)s" % vals
         else:
             theSubject = "bzr push into %(tree)s branch (%(user)s:%(old_revno)s to %(new_revno)s) %(ref_subject)s" % vals

=== modified file 'hooks.py'
--- a/hooks.py	2008-05-06 01:00:18 +0000
+++ b/hooks.py	2008-06-18 13:10:28 +0000
@@ -38,22 +38,31 @@ def branch_commit_hook(local, master, ol
         emailer.CommitSender(master, old_revno, old_revid, new_revno, 
                             new_revid, PluginBranchConfig("mysql",master),
                             local_branch=local).send_maybe()
-    finally:
-        master.unlock()    
+    except Exception, e:
+        note("WARNING: Problem with post-commit email hook. ")
+        note("\t %s" % str(e))
+        note("Please see .bzr.log for more information")
+    # Can't do finally here - some people have older python 
+    master.unlock()    
 
 
 def branch_push_hook(push_result):
     """Send an email after a push"""
     if push_result.old_revid != push_result.new_revid:
         config = PluginBranchConfig("mysql", push_result.source_branch)
-        emailer.PushSender(push_result.source_branch, 
-                           push_result.old_revno, push_result.old_revid,
-                           push_result.new_revno, push_result.new_revid,
-                           config, 
-                           local_branch=push_result.local_branch,
-                           target_branch=push_result.target_branch,
-                           master_branch=push_result.master_branch,  
-                       ).send_maybe()
+        try:
+            emailer.PushSender(push_result.source_branch, 
+                               push_result.old_revno, push_result.old_revid,
+                               push_result.new_revno, push_result.new_revid,
+                               config, 
+                               local_branch=push_result.local_branch,
+                               target_branch=push_result.target_branch,
+                               master_branch=push_result.master_branch,  
+                           ).send_maybe()
+        except Exception, e:
+            note("WARNING: Problem with post-push email hook.")
+            note("\t %s" % str(e))
+
         if config.get_user_option("buildbot_location", False, None) is not None:
             try:
                 mutter("running buildbot hook")

=== added file 'sanity.py'
--- a/sanity.py	1970-01-01 00:00:00 +0000
+++ b/sanity.py	2008-06-20 16:32:51 +0000
@@ -0,0 +1,59 @@
+import sys
+import bzrlib.errors
+
+def sanity_check_file(tree, path, unresolved, potentially_unresolved):
+	file_id = tree.path2id(path)
+	state = 0
+	for ln in tree.get_file(file_id, path):
+		if ln.startswith('<<<<<<<') and not ln.startswith('<<<<<<<<'):
+			if state == 0:
+				state = 1
+			potentially_unresolved.add(path)
+		if ln.startswith('=======') and not ln.startswith('========'):
+			if state == 1:
+				state = 2
+		if ln.startswith('>>>>>>>') and not ln.startswith('>>>>>>>>'):
+			if state == 2:
+				unresolved.add(path)
+				break
+			else:
+				potentially_unresolved.add(path)
+
+def pre_commit_hook(hook_local, hook_master, old_revno, old_revid, new_revno, new_revid, tree_delta, future_tree):
+	unresolved = set([])
+	potentially_unresolved = set([])
+	
+	for oldpath, newpath, id, kind, text_modified, meta_modified in tree_delta.renamed:
+		if text_modified and kind == "file":
+			sanity_check_file(future_tree, newpath, unresolved, potentially_unresolved)
+	for path, id, kind, text_modified, meta_modified in tree_delta.modified:
+		if text_modified and kind == "file":
+			sanity_check_file(future_tree, path, unresolved, potentially_unresolved)
+	potentially_unresolved.difference_update(unresolved)
+
+	err = ''
+	if len(unresolved) > 0:
+		err += """
+
+You are committing unresolved conflicts!
+========================================
+
+Files:
+"""
+		for i in unresolved:
+			err += ' - %s\n' % (i)
+	if len(potentially_unresolved) > 0:
+		err += """
+
+You are committing files with conflict markers!
+Did you resolve a conflict incompletely?
+===============================================
+
+Files:
+"""
+		for i in potentially_unresolved:
+			err += ' - %s\n' % (i)
+		
+	if err != '':
+		raise bzrlib.errors.BzrError(err)
+

Thread
bzr commit into mysql_plugins branch (bzrdev:116) C Miller23 Jun