[PATCH 4 of 6] Add support for username mapping

Edouard Gomez ed.gomez at free.fr
Thu Jun 7 16:50:21 CDT 2007


# HG changeset patch
# User Edouard Gomez <ed.gomez at free.fr>
# Date 1181250965 -7200
# Node ID 537e4260a38347d32765c8fdfb6510288c0b0698
# Parent  8b4f7b0f7b0d92883ef7063e8b164f2564cd1716
Add support for username mapping

Allows mapping usernames to new ones during conversion process.
 - Use -A option for first import
 - Then at the end of the conversion process and if the destination
   repo supports authorfile attribute, author map content is copied
   to the file pointed by the authorfile call.
 - On incremental conversions w/o any -A option specified, the
   destination authorfile, if any, gets read automatically.

EG: This allows mapping unix system usernames used in CVS accounts
    to a more typical "Firstname Lastname <address at server.org>" pair.

diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -445,6 +445,9 @@ class convert_mercurial(converter_sink):
     def mapfile(self):
         return os.path.join(self.path, ".hg", "shamap")
 
+    def authorfile(self):
+        return os.path.join(self.path, ".hg", "authormap")
+
     def getheads(self):
         h = self.repo.changelog.heads()
         return [ hg.hex(x) for x in h ]
@@ -540,6 +543,7 @@ class convert(object):
         self.commitcache = {}
         self.mapfile = mapfile
         self.mapfilefd = None
+        self.authors = {}
 
         self.map = {}
         try:
@@ -550,6 +554,23 @@ class convert(object):
             origmapfile.close()
         except IOError:
             pass
+
+        authorfile = None
+        if 'authors' in opts:
+            authorfile = opts.get('authors')
+        elif hasattr(dest, 'authorfile'):
+            authorfile = dest.authorsfile()
+
+        try:
+            afile = open(authorfile, 'rb')
+            for line in afile:
+                try:
+                    self.authors[line.split('=')[0].strip()] = line.split('=')[1].strip()
+                except IndexError:
+                    pass
+            afile.close()
+        except IOError:
+           pass
 
     def walktree(self, heads):
         visit = heads
@@ -633,6 +654,13 @@ class convert(object):
         self.mapfilefd.write("%s %s\n" % (src, dst))
         self.mapfilefd.flush()
 
+    def writeauthormap(self):
+        if len(self.authors) > 0 and hasattr(self.dest, 'authorfile'):
+           ofile = open(self.dest.authorfile(), 'w+')
+           for author in self.authors:
+               ofile.write("%s=%s\n" % (author, self.authors[author]))
+           ofile.close()
+
     def copy(self, rev):
         c = self.commitcache[rev]
         files = self.source.getchanges(rev)
@@ -667,6 +695,9 @@ class convert(object):
             if "\n" in desc:
                 desc = desc.splitlines()[0]
             self.ui.status("%d %s\n" % (num, desc))
+            author = self.commitcache[c].author
+            if author in self.authors:
+                self.commitcache[c].author = self.authors[author]
             self.copy(c)
 
         tags = self.source.gettags()
@@ -682,6 +713,8 @@ class convert(object):
             # one so we don't end up with extra tag heads
             if nrev:
                 self.mapentry(c, nrev)
+
+        self.writeauthormap()
 
     def cleanup(self):
        if self.mapfilefd:
@@ -739,6 +772,7 @@ def _convert(ui, src, dest=None, mapfile
 
 cmdtable = {
     "convert": (_convert,
-                [('', 'datesort', None, 'try to sort changesets by date')],
+                [('A', 'authors', '', 'username mapping filename'),
+                 ('', 'datesort', None, 'try to sort changesets by date')],
                 'hg convert [OPTIONS] <src> [dst [map]]'),
 }


More information about the Mercurial-devel mailing list