hgext/convert/__init__.py
changeset 4589 451e91ed535e
parent 4588 9855939d0c82
child 4590 80fb4ec512b5
equal deleted inserted replaced
4588:9855939d0c82 4589:451e91ed535e
    35         self.ui = ui
    35         self.ui = ui
    36         self.opts = opts
    36         self.opts = opts
    37         self.commitcache = {}
    37         self.commitcache = {}
    38         self.mapfile = mapfile
    38         self.mapfile = mapfile
    39         self.mapfilefd = None
    39         self.mapfilefd = None
       
    40         self.authors = {}
       
    41         self.writeauthors = False
    40 
    42 
    41         self.map = {}
    43         self.map = {}
    42         try:
    44         try:
    43             origmapfile = open(self.mapfile, 'r')
    45             origmapfile = open(self.mapfile, 'r')
    44             for l in origmapfile:
    46             for l in origmapfile:
    45                 sv, dv = l[:-1].split()
    47                 sv, dv = l[:-1].split()
    46                 self.map[sv] = dv
    48                 self.map[sv] = dv
    47             origmapfile.close()
    49             origmapfile.close()
    48         except IOError:
    50         except IOError:
    49             pass
    51             pass
       
    52 
       
    53         # Read first the dst author map if any
       
    54         if  hasattr(self.dest, 'authorfile'):
       
    55             self.readauthormap(self.dest.authorfile())
       
    56         # Extend/Override with new author map if necessary
       
    57         if 'authors' in opts:
       
    58             self.readauthormap(opts.get('authors'))
       
    59             self.writeauthors = True
    50 
    60 
    51     def walktree(self, heads):
    61     def walktree(self, heads):
    52         visit = heads
    62         visit = heads
    53         known = {}
    63         known = {}
    54         parents = {}
    64         parents = {}
   129                 raise util.Abort("Could not open map file %s: %s, %s\n" % (self.mapfile, errno, strerror))
   139                 raise util.Abort("Could not open map file %s: %s, %s\n" % (self.mapfile, errno, strerror))
   130         self.map[src] = dst
   140         self.map[src] = dst
   131         self.mapfilefd.write("%s %s\n" % (src, dst))
   141         self.mapfilefd.write("%s %s\n" % (src, dst))
   132         self.mapfilefd.flush()
   142         self.mapfilefd.flush()
   133 
   143 
       
   144     def writeauthormap(self):
       
   145         if self.writeauthors == True and len(self.authors) > 0 and hasattr(self.dest, 'authorfile'):
       
   146            authorfile = self.dest.authorfile()
       
   147            self.ui.status('Writing author map file %s\n' % authorfile)
       
   148            ofile = open(authorfile, 'w+')
       
   149            for author in self.authors:
       
   150                ofile.write("%s=%s\n" % (author, self.authors[author]))
       
   151            ofile.close()
       
   152 
       
   153     def readauthormap(self, authorfile):
       
   154         try:
       
   155             afile = open(authorfile, 'r')
       
   156             for line in afile:
       
   157                 try:
       
   158                     srcauthor = line.split('=')[0].strip()
       
   159                     dstauthor = line.split('=')[1].strip()
       
   160                     if srcauthor in self.authors and dstauthor != self.authors[srcauthor]:
       
   161                         self.ui.status(
       
   162                             'Overriding mapping for author %s, was %s, will be %s\n'
       
   163                             % (srcauthor, self.authors[srcauthor], dstauthor))
       
   164                     else:
       
   165                         self.ui.debug('Mapping author %s to %s\n'
       
   166 			    % (srcauthor, dstauthor))
       
   167                     self.authors[srcauthor] = dstauthor
       
   168 		    
       
   169                 except IndexError:
       
   170                     self.ui.warn(
       
   171                         'Ignoring bad line in author file map %s: %s\n'
       
   172                         % (authorfile, line))
       
   173             afile.close()
       
   174         except IOError:
       
   175             self.ui.warn('Error reading author file map %s.\n' % authorfile)
       
   176 
   134     def copy(self, rev):
   177     def copy(self, rev):
   135         c = self.commitcache[rev]
   178         c = self.commitcache[rev]
   136         files = self.source.getchanges(rev)
   179         files = self.source.getchanges(rev)
   137 
   180 
   138         for f, v in files:
   181         for f, v in files:
   163             for c in t:
   206             for c in t:
   164                 num -= 1
   207                 num -= 1
   165                 desc = self.commitcache[c].desc
   208                 desc = self.commitcache[c].desc
   166                 if "\n" in desc:
   209                 if "\n" in desc:
   167                     desc = desc.splitlines()[0]
   210                     desc = desc.splitlines()[0]
       
   211                 author = self.commitcache[c].author
       
   212                 author = self.authors.get(author, author)
       
   213                 self.commitcache[c].author = author
   168                 self.ui.status("%d %s\n" % (num, desc))
   214                 self.ui.status("%d %s\n" % (num, desc))
   169                 self.copy(c)
   215                 self.copy(c)
   170 
   216 
   171             tags = self.source.gettags()
   217             tags = self.source.gettags()
   172             ctags = {}
   218             ctags = {}
   179                 nrev = self.dest.puttags(ctags)
   225                 nrev = self.dest.puttags(ctags)
   180                 # write another hash correspondence to override the previous
   226                 # write another hash correspondence to override the previous
   181                 # one so we don't end up with extra tag heads
   227                 # one so we don't end up with extra tag heads
   182                 if nrev:
   228                 if nrev:
   183                     self.mapentry(c, nrev)
   229                     self.mapentry(c, nrev)
       
   230 
       
   231             self.writeauthormap()
   184         finally:
   232         finally:
   185             self.cleanup()
   233             self.cleanup()
   186 
   234 
   187     def cleanup(self):
   235     def cleanup(self):
   188        if self.mapfilefd:
   236        if self.mapfilefd:
   202     be created. If <mapfile> isn't given, it will be put in a default
   250     be created. If <mapfile> isn't given, it will be put in a default
   203     location (<dest>/.hg/shamap by default)
   251     location (<dest>/.hg/shamap by default)
   204 
   252 
   205     The <mapfile> is a simple text file that maps each source commit ID to
   253     The <mapfile> is a simple text file that maps each source commit ID to
   206     the destination ID for that revision, like so:
   254     the destination ID for that revision, like so:
   207 
       
   208     <source ID> <destination ID>
   255     <source ID> <destination ID>
   209 
   256 
   210     If the file doesn't exist, it's automatically created.  It's updated
   257     If the file doesn't exist, it's automatically created.  It's updated
   211     on each commit copied, so convert-repo can be interrupted and can
   258     on each commit copied, so convert-repo can be interrupted and can
   212     be run repeatedly to copy new commits.
   259     be run repeatedly to copy new commits.
       
   260 
       
   261     The [username mapping] file is a simple text file that maps each source
       
   262     commit author to a destination commit author. It is handy for source SCMs
       
   263     that use unix logins to identify authors (eg: CVS). One line per author
       
   264     mapping and the line format is:
       
   265     srcauthor=whatever string you want
   213     '''
   266     '''
   214 
   267 
   215     srcc = converter(ui, src)
   268     srcc = converter(ui, src)
   216     if not hasattr(srcc, "getcommit"):
   269     if not hasattr(srcc, "getcommit"):
   217         raise util.Abort("%s: can't read from this repo type" % src)
   270         raise util.Abort("%s: can't read from this repo type" % src)
   255     c.convert()
   308     c.convert()
   256 
   309 
   257 cmdtable = {
   310 cmdtable = {
   258     "convert":
   311     "convert":
   259         (_convert,
   312         (_convert,
   260          [('', 'datesort', None, 'try to sort changesets by date')],
   313          [('A', 'authors', '', 'username mapping filename'),
       
   314           ('', 'datesort', None, 'try to sort changesets by date')],
   261          'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
   315          'hg convert [OPTION]... SOURCE [DEST [MAPFILE]]'),
   262 }
   316 }