Patch for monotone.py

Mike Rogers MRogers at tntech.edu
Fri Nov 28 19:28:56 CST 2008


The CS department at TTU has been using Monotone for a couple of years now as our revision control system.  However, due to its lack of popularity (and thus lack of tool support), we are contemplating moving to Bazaar, Git, or Mercurial.

To experiment with Mercurial, I needed to import our Monotone repositories.  However, when using "hg convert", the extension would seemingly "lose" Monotone certs.  After inspecting monotone.py in the extensions directory, I found that the the Python script was splitting the certs at double newlines.  Our repositories have comments in the changelogs (which are just certs) with double newlines.

I have fixed the script so that it no longer splits the Monotone certs string.  Now it uses a regular expression to find the first key-value pair, iterating though the whole string of certs until no more key-value pairs are found.

Here is the patch - I hope its useful.  Thanks.

Mike Rogers
Associate Professor
Computer Science Department
Tennessee Technological University


# HG changeset patch
# User mrogers at tntech.edu
# Date 1227920754 21600
# Node ID b91ac08390cca41067f356f84e5cef2842a15d8e
# Parent  b965605dfb2ed188a54d4aca18ac3ae5b0726953
Changes to monotone.py.  Now "hg convert" handles monotone changelog certs more robustly.

diff -r b965605dfb2e -r b91ac08390cc hgext/convert/monotone.py
--- a/hgext/convert/monotone.py	Sat Nov 15 15:51:26 2008 +0100
+++ b/hgext/convert/monotone.py	Fri Nov 28 19:05:54 2008 -0600
@@ -16,7 +16,7 @@
 
         # regular expressions for parsing monotone output
         space    = r'\s*'
-        name     = r'\s+"((?:\\"|[^"])*)"\s*'
+        name     = r'\s+"((?:[^"]|\\")*)"\s*'
         value    = name
         revision = r'\s+\[(\w+)\]\s*'
         lines    = r'(?:.|\n)+'
@@ -29,6 +29,7 @@
         self.delete_re   = re.compile(space + "delete" + name)
         self.tag_re      = re.compile(space + "tag" + name + "revision" + revision)
         self.cert_re     = re.compile(lines + space + "name" + name + "value" + value)
+	self.nvpair      = re.compile("name" + name + "value" + value)
 
         attr = space + "file" + lines + space + "attr" + space
         self.attr_execute_re = re.compile(attr  + '"mtn:execute"' + space + '"true"')
@@ -98,14 +99,16 @@
     def mtngetcerts(self, rev):
         certs = {"author":"<missing>", "date":"<missing>",
             "changelog":"<missing>", "branch":"<missing>"}
-        cert_list = self.mtnrun("certs", rev).split('\n\n      key "')
-        for e in cert_list:
-            m = self.cert_re.match(e)
-            if m:
-                name, value = m.groups()
-                value = value.replace(r'\"', '"')
-                value = value.replace(r'\\', '\\')
-                certs[name] = value
+        all_certs = self.mtnrun("certs", rev)
+
+	haveMore = True
+        while haveMore:
+            m = self.nvpair.search(all_certs)
+            if m == None:
+                haveMore = False
+            else:
+                certs[m.group(1)] = m.group(2)
+                all_certs = all_certs[m.end()+1:]
         return certs
 
     def mtnrenamefiles(self, files, fromdir, todir):



More information about the Mercurial-devel mailing list