[extendedchangelog] add extra metadata in the changelog entry
authorBenoit Boissinot <benoit.boissinot@ens-lyon.org>
Mon, 02 Oct 2006 22:35:52 +0200
changeset 3233 2f35961854fb
parent 3232 394ac87f3b74
child 3234 9d13e21f4e3c
[extendedchangelog] add extra metadata in the changelog entry - add a third item in the date field that holds arbitrary key:value items
mercurial/changelog.py
--- a/mercurial/changelog.py	Mon Oct 02 22:35:37 2006 +0200
+++ b/mercurial/changelog.py	Mon Oct 02 22:35:52 2006 +0200
@@ -32,41 +32,69 @@
         revlog.__init__(self, opener, "00changelog.i", "00changelog.d",
                         defversion)
 
+    def decode_extra(self, text):
+        extra = {}
+        for l in text.split('\0'):
+            if not l:
+                continue
+            k, v = _string_unescape(l).split(':', 1)
+            extra[k] = v
+        return extra
+
+    def encode_extra(self, d):
+        items = [_string_escape(":".join(t)) for t in d.iteritems()]
+        return "\0".join(items)
+
     def extract(self, text):
         """
         format used:
-        nodeid\n  : manifest node in ascii
-        user\n    : user, no \n or \r allowed
-        time tz\n : date (time is int or float, timezone is int)
-        files\n\n : files modified by the cset, no \n or \r allowed
-        (.*)      : comment (free text, ideally utf-8)
+        nodeid\n        : manifest node in ascii
+        user\n          : user, no \n or \r allowed
+        time tz extra\n : date (time is int or float, timezone is int)
+                        : extra is metadatas, encoded and separated by '\0'
+                        : older versions ignore it
+        files\n\n       : files modified by the cset, no \n or \r allowed
+        (.*)            : comment (free text, ideally utf-8)
+
+        changelog v0 doesn't use extra
         """
         if not text:
             return (nullid, "", (0, 0), [], "")
         last = text.index("\n\n")
         desc = text[last + 2:]
-        l = text[:last].splitlines()
+        l = text[:last].split('\n')
         manifest = bin(l[0])
         user = l[1]
-        date = l[2].split(' ')
-        time = float(date.pop(0))
-        try:
-            # various tools did silly things with the time zone field.
-            timezone = int(date[0])
-        except:
-            timezone = 0
+
+        extra_data = l[2].split(' ', 2)
+        if len(extra_data) != 3:
+            time = float(extra_data.pop(0))
+            try:
+                # various tools did silly things with the time zone field.
+                timezone = int(extra_data[0])
+            except:
+                timezone = 0
+            extra = {}
+        else:
+            time, timezone, extra = extra_data
+            time, timezone = float(time), int(timezone)
+            extra = self.decode_extra(extra)
         files = l[3:]
-        return (manifest, user, (time, timezone), files, desc)
+        return (manifest, user, (time, timezone), files, desc, extra)
 
     def read(self, node):
         return self.extract(self.revision(node))
 
     def add(self, manifest, list, desc, transaction, p1=None, p2=None,
-                  user=None, date=None):
+                  user=None, date=None, extra={}):
+
         if date:
             parseddate = "%d %d" % util.parsedate(date)
         else:
             parseddate = "%d %d" % util.makedate()
+        if extra:
+            extra = self.encode_extra(extra)
+            parseddate = "%s %s" % (parseddate, extra)
         list.sort()
         l = [hex(manifest), user, parseddate] + list + ["", desc]
         text = "\n".join(l)