hgext/convert/hg.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43085 eef9a2d67051
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
    49 
    49 
    50 
    50 
    51 class mercurial_sink(common.converter_sink):
    51 class mercurial_sink(common.converter_sink):
    52     def __init__(self, ui, repotype, path):
    52     def __init__(self, ui, repotype, path):
    53         common.converter_sink.__init__(self, ui, repotype, path)
    53         common.converter_sink.__init__(self, ui, repotype, path)
    54         self.branchnames = ui.configbool('convert', 'hg.usebranchnames')
    54         self.branchnames = ui.configbool(b'convert', b'hg.usebranchnames')
    55         self.clonebranches = ui.configbool('convert', 'hg.clonebranches')
    55         self.clonebranches = ui.configbool(b'convert', b'hg.clonebranches')
    56         self.tagsbranch = ui.config('convert', 'hg.tagsbranch')
    56         self.tagsbranch = ui.config(b'convert', b'hg.tagsbranch')
    57         self.lastbranch = None
    57         self.lastbranch = None
    58         if os.path.isdir(path) and len(os.listdir(path)) > 0:
    58         if os.path.isdir(path) and len(os.listdir(path)) > 0:
    59             try:
    59             try:
    60                 self.repo = hg.repository(self.ui, path)
    60                 self.repo = hg.repository(self.ui, path)
    61                 if not self.repo.local():
    61                 if not self.repo.local():
    62                     raise NoRepo(
    62                     raise NoRepo(
    63                         _('%s is not a local Mercurial repository') % path
    63                         _(b'%s is not a local Mercurial repository') % path
    64                     )
    64                     )
    65             except error.RepoError as err:
    65             except error.RepoError as err:
    66                 ui.traceback()
    66                 ui.traceback()
    67                 raise NoRepo(err.args[0])
    67                 raise NoRepo(err.args[0])
    68         else:
    68         else:
    69             try:
    69             try:
    70                 ui.status(_('initializing destination %s repository\n') % path)
    70                 ui.status(_(b'initializing destination %s repository\n') % path)
    71                 self.repo = hg.repository(self.ui, path, create=True)
    71                 self.repo = hg.repository(self.ui, path, create=True)
    72                 if not self.repo.local():
    72                 if not self.repo.local():
    73                     raise NoRepo(
    73                     raise NoRepo(
    74                         _('%s is not a local Mercurial repository') % path
    74                         _(b'%s is not a local Mercurial repository') % path
    75                     )
    75                     )
    76                 self.created.append(path)
    76                 self.created.append(path)
    77             except error.RepoError:
    77             except error.RepoError:
    78                 ui.traceback()
    78                 ui.traceback()
    79                 raise NoRepo(
    79                 raise NoRepo(
    80                     _("could not create hg repository %s as sink") % path
    80                     _(b"could not create hg repository %s as sink") % path
    81                 )
    81                 )
    82         self.lock = None
    82         self.lock = None
    83         self.wlock = None
    83         self.wlock = None
    84         self.filemapmode = False
    84         self.filemapmode = False
    85         self.subrevmaps = {}
    85         self.subrevmaps = {}
    86 
    86 
    87     def before(self):
    87     def before(self):
    88         self.ui.debug('run hg sink pre-conversion action\n')
    88         self.ui.debug(b'run hg sink pre-conversion action\n')
    89         self.wlock = self.repo.wlock()
    89         self.wlock = self.repo.wlock()
    90         self.lock = self.repo.lock()
    90         self.lock = self.repo.lock()
    91 
    91 
    92     def after(self):
    92     def after(self):
    93         self.ui.debug('run hg sink post-conversion action\n')
    93         self.ui.debug(b'run hg sink post-conversion action\n')
    94         if self.lock:
    94         if self.lock:
    95             self.lock.release()
    95             self.lock.release()
    96         if self.wlock:
    96         if self.wlock:
    97             self.wlock.release()
    97             self.wlock.release()
    98 
    98 
    99     def revmapfile(self):
    99     def revmapfile(self):
   100         return self.repo.vfs.join("shamap")
   100         return self.repo.vfs.join(b"shamap")
   101 
   101 
   102     def authorfile(self):
   102     def authorfile(self):
   103         return self.repo.vfs.join("authormap")
   103         return self.repo.vfs.join(b"authormap")
   104 
   104 
   105     def setbranch(self, branch, pbranches):
   105     def setbranch(self, branch, pbranches):
   106         if not self.clonebranches:
   106         if not self.clonebranches:
   107             return
   107             return
   108 
   108 
   109         setbranch = branch != self.lastbranch
   109         setbranch = branch != self.lastbranch
   110         self.lastbranch = branch
   110         self.lastbranch = branch
   111         if not branch:
   111         if not branch:
   112             branch = 'default'
   112             branch = b'default'
   113         pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
   113         pbranches = [(b[0], b[1] and b[1] or b'default') for b in pbranches]
   114 
   114 
   115         branchpath = os.path.join(self.path, branch)
   115         branchpath = os.path.join(self.path, branch)
   116         if setbranch:
   116         if setbranch:
   117             self.after()
   117             self.after()
   118             try:
   118             try:
   133         if missings:
   133         if missings:
   134             self.after()
   134             self.after()
   135             for pbranch, heads in sorted(missings.iteritems()):
   135             for pbranch, heads in sorted(missings.iteritems()):
   136                 pbranchpath = os.path.join(self.path, pbranch)
   136                 pbranchpath = os.path.join(self.path, pbranch)
   137                 prepo = hg.peer(self.ui, {}, pbranchpath)
   137                 prepo = hg.peer(self.ui, {}, pbranchpath)
   138                 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
   138                 self.ui.note(
       
   139                     _(b'pulling from %s into %s\n') % (pbranch, branch)
       
   140                 )
   139                 exchange.pull(
   141                 exchange.pull(
   140                     self.repo, prepo, [prepo.lookup(h) for h in heads]
   142                     self.repo, prepo, [prepo.lookup(h) for h in heads]
   141                 )
   143                 )
   142             self.before()
   144             self.before()
   143 
   145 
   144     def _rewritetags(self, source, revmap, data):
   146     def _rewritetags(self, source, revmap, data):
   145         fp = stringio()
   147         fp = stringio()
   146         for line in data.splitlines():
   148         for line in data.splitlines():
   147             s = line.split(' ', 1)
   149             s = line.split(b' ', 1)
   148             if len(s) != 2:
   150             if len(s) != 2:
   149                 self.ui.warn(_('invalid tag entry: "%s"\n') % line)
   151                 self.ui.warn(_(b'invalid tag entry: "%s"\n') % line)
   150                 fp.write('%s\n' % line)  # Bogus, but keep for hash stability
   152                 fp.write(b'%s\n' % line)  # Bogus, but keep for hash stability
   151                 continue
   153                 continue
   152             revid = revmap.get(source.lookuprev(s[0]))
   154             revid = revmap.get(source.lookuprev(s[0]))
   153             if not revid:
   155             if not revid:
   154                 if s[0] == nodemod.nullhex:
   156                 if s[0] == nodemod.nullhex:
   155                     revid = s[0]
   157                     revid = s[0]
   156                 else:
   158                 else:
   157                     # missing, but keep for hash stability
   159                     # missing, but keep for hash stability
   158                     self.ui.warn(_('missing tag entry: "%s"\n') % line)
   160                     self.ui.warn(_(b'missing tag entry: "%s"\n') % line)
   159                     fp.write('%s\n' % line)
   161                     fp.write(b'%s\n' % line)
   160                     continue
   162                     continue
   161             fp.write('%s %s\n' % (revid, s[1]))
   163             fp.write(b'%s %s\n' % (revid, s[1]))
   162         return fp.getvalue()
   164         return fp.getvalue()
   163 
   165 
   164     def _rewritesubstate(self, source, data):
   166     def _rewritesubstate(self, source, data):
   165         fp = stringio()
   167         fp = stringio()
   166         for line in data.splitlines():
   168         for line in data.splitlines():
   167             s = line.split(' ', 1)
   169             s = line.split(b' ', 1)
   168             if len(s) != 2:
   170             if len(s) != 2:
   169                 continue
   171                 continue
   170 
   172 
   171             revid = s[0]
   173             revid = s[0]
   172             subpath = s[1]
   174             subpath = s[1]
   173             if revid != nodemod.nullhex:
   175             if revid != nodemod.nullhex:
   174                 revmap = self.subrevmaps.get(subpath)
   176                 revmap = self.subrevmaps.get(subpath)
   175                 if revmap is None:
   177                 if revmap is None:
   176                     revmap = mapfile(
   178                     revmap = mapfile(
   177                         self.ui, self.repo.wjoin(subpath, '.hg/shamap')
   179                         self.ui, self.repo.wjoin(subpath, b'.hg/shamap')
   178                     )
   180                     )
   179                     self.subrevmaps[subpath] = revmap
   181                     self.subrevmaps[subpath] = revmap
   180 
   182 
   181                     # It is reasonable that one or more of the subrepos don't
   183                     # It is reasonable that one or more of the subrepos don't
   182                     # need to be converted, in which case they can be cloned
   184                     # need to be converted, in which case they can be cloned
   183                     # into place instead of converted.  Therefore, only warn
   185                     # into place instead of converted.  Therefore, only warn
   184                     # once.
   186                     # once.
   185                     msg = _('no ".hgsubstate" updates will be made for "%s"\n')
   187                     msg = _(b'no ".hgsubstate" updates will be made for "%s"\n')
   186                     if len(revmap) == 0:
   188                     if len(revmap) == 0:
   187                         sub = self.repo.wvfs.reljoin(subpath, '.hg')
   189                         sub = self.repo.wvfs.reljoin(subpath, b'.hg')
   188 
   190 
   189                         if self.repo.wvfs.exists(sub):
   191                         if self.repo.wvfs.exists(sub):
   190                             self.ui.warn(msg % subpath)
   192                             self.ui.warn(msg % subpath)
   191 
   193 
   192                 newid = revmap.get(revid)
   194                 newid = revmap.get(revid)
   193                 if not newid:
   195                 if not newid:
   194                     if len(revmap) > 0:
   196                     if len(revmap) > 0:
   195                         self.ui.warn(
   197                         self.ui.warn(
   196                             _("%s is missing from %s/.hg/shamap\n")
   198                             _(b"%s is missing from %s/.hg/shamap\n")
   197                             % (revid, subpath)
   199                             % (revid, subpath)
   198                         )
   200                         )
   199                 else:
   201                 else:
   200                     revid = newid
   202                     revid = newid
   201 
   203 
   202             fp.write('%s %s\n' % (revid, subpath))
   204             fp.write(b'%s %s\n' % (revid, subpath))
   203 
   205 
   204         return fp.getvalue()
   206         return fp.getvalue()
   205 
   207 
   206     def _calculatemergedfiles(self, source, p1ctx, p2ctx):
   208     def _calculatemergedfiles(self, source, p1ctx, p2ctx):
   207         """Calculates the files from p2 that we need to pull in when merging p1
   209         """Calculates the files from p2 that we need to pull in when merging p1
   230                 # since it will be covered by the existing fileset.
   232                 # since it will be covered by the existing fileset.
   231                 continue
   233                 continue
   232 
   234 
   233             # If the file requires actual merging, abort. We don't have enough
   235             # If the file requires actual merging, abort. We don't have enough
   234             # context to resolve merges correctly.
   236             # context to resolve merges correctly.
   235             if action in ['m', 'dm', 'cd', 'dc']:
   237             if action in [b'm', b'dm', b'cd', b'dc']:
   236                 raise error.Abort(
   238                 raise error.Abort(
   237                     _(
   239                     _(
   238                         "unable to convert merge commit "
   240                         b"unable to convert merge commit "
   239                         "since target parents do not merge cleanly (file "
   241                         b"since target parents do not merge cleanly (file "
   240                         "%s, parents %s and %s)"
   242                         b"%s, parents %s and %s)"
   241                     )
   243                     )
   242                     % (file, p1ctx, p2ctx)
   244                     % (file, p1ctx, p2ctx)
   243                 )
   245                 )
   244             elif action == 'k':
   246             elif action == b'k':
   245                 # 'keep' means nothing changed from p1
   247                 # 'keep' means nothing changed from p1
   246                 continue
   248                 continue
   247             else:
   249             else:
   248                 # Any other change means we want to take the p2 version
   250                 # Any other change means we want to take the p2 version
   249                 yield file
   251                 yield file
   253     ):
   255     ):
   254         files = dict(files)
   256         files = dict(files)
   255 
   257 
   256         def getfilectx(repo, memctx, f):
   258         def getfilectx(repo, memctx, f):
   257             if p2ctx and f in p2files and f not in copies:
   259             if p2ctx and f in p2files and f not in copies:
   258                 self.ui.debug('reusing %s from p2\n' % f)
   260                 self.ui.debug(b'reusing %s from p2\n' % f)
   259                 try:
   261                 try:
   260                     return p2ctx[f]
   262                     return p2ctx[f]
   261                 except error.ManifestLookupError:
   263                 except error.ManifestLookupError:
   262                     # If the file doesn't exist in p2, then we're syncing a
   264                     # If the file doesn't exist in p2, then we're syncing a
   263                     # delete, so just return None.
   265                     # delete, so just return None.
   267             except KeyError:
   269             except KeyError:
   268                 return None
   270                 return None
   269             data, mode = source.getfile(f, v)
   271             data, mode = source.getfile(f, v)
   270             if data is None:
   272             if data is None:
   271                 return None
   273                 return None
   272             if f == '.hgtags':
   274             if f == b'.hgtags':
   273                 data = self._rewritetags(source, revmap, data)
   275                 data = self._rewritetags(source, revmap, data)
   274             if f == '.hgsubstate':
   276             if f == b'.hgsubstate':
   275                 data = self._rewritesubstate(source, data)
   277                 data = self._rewritesubstate(source, data)
   276             return context.memfilectx(
   278             return context.memfilectx(
   277                 self.repo,
   279                 self.repo,
   278                 memctx,
   280                 memctx,
   279                 f,
   281                 f,
   280                 data,
   282                 data,
   281                 'l' in mode,
   283                 b'l' in mode,
   282                 'x' in mode,
   284                 b'x' in mode,
   283                 copies.get(f),
   285                 copies.get(f),
   284             )
   286             )
   285 
   287 
   286         pl = []
   288         pl = []
   287         for p in parents:
   289         for p in parents:
   308             if newrev is not None:
   310             if newrev is not None:
   309                 text = text.replace(sha1, newrev[: len(sha1)])
   311                 text = text.replace(sha1, newrev[: len(sha1)])
   310 
   312 
   311         extra = commit.extra.copy()
   313         extra = commit.extra.copy()
   312 
   314 
   313         sourcename = self.repo.ui.config('convert', 'hg.sourcename')
   315         sourcename = self.repo.ui.config(b'convert', b'hg.sourcename')
   314         if sourcename:
   316         if sourcename:
   315             extra['convert_source'] = sourcename
   317             extra[b'convert_source'] = sourcename
   316 
   318 
   317         for label in (
   319         for label in (
   318             'source',
   320             b'source',
   319             'transplant_source',
   321             b'transplant_source',
   320             'rebase_source',
   322             b'rebase_source',
   321             'intermediate-source',
   323             b'intermediate-source',
   322         ):
   324         ):
   323             node = extra.get(label)
   325             node = extra.get(label)
   324 
   326 
   325             if node is None:
   327             if node is None:
   326                 continue
   328                 continue
   327 
   329 
   328             # Only transplant stores its reference in binary
   330             # Only transplant stores its reference in binary
   329             if label == 'transplant_source':
   331             if label == b'transplant_source':
   330                 node = nodemod.hex(node)
   332                 node = nodemod.hex(node)
   331 
   333 
   332             newrev = revmap.get(node)
   334             newrev = revmap.get(node)
   333             if newrev is not None:
   335             if newrev is not None:
   334                 if label == 'transplant_source':
   336                 if label == b'transplant_source':
   335                     newrev = nodemod.bin(newrev)
   337                     newrev = nodemod.bin(newrev)
   336 
   338 
   337                 extra[label] = newrev
   339                 extra[label] = newrev
   338 
   340 
   339         if self.branchnames and commit.branch:
   341         if self.branchnames and commit.branch:
   340             extra['branch'] = commit.branch
   342             extra[b'branch'] = commit.branch
   341         if commit.rev and commit.saverev:
   343         if commit.rev and commit.saverev:
   342             extra['convert_revision'] = commit.rev
   344             extra[b'convert_revision'] = commit.rev
   343 
   345 
   344         while parents:
   346         while parents:
   345             p1 = p2
   347             p1 = p2
   346             p2 = parents.pop(0)
   348             p2 = parents.pop(0)
   347             p1ctx = self.repo[p1]
   349             p1ctx = self.repo[p1]
   371             )
   373             )
   372 
   374 
   373             # We won't know if the conversion changes the node until after the
   375             # We won't know if the conversion changes the node until after the
   374             # commit, so copy the source's phase for now.
   376             # commit, so copy the source's phase for now.
   375             self.repo.ui.setconfig(
   377             self.repo.ui.setconfig(
   376                 'phases',
   378                 b'phases',
   377                 'new-commit',
   379                 b'new-commit',
   378                 phases.phasenames[commit.phase],
   380                 phases.phasenames[commit.phase],
   379                 'convert',
   381                 b'convert',
   380             )
   382             )
   381 
   383 
   382             with self.repo.transaction("convert") as tr:
   384             with self.repo.transaction(b"convert") as tr:
   383                 if self.repo.ui.config('convert', 'hg.preserve-hash'):
   385                 if self.repo.ui.config(b'convert', b'hg.preserve-hash'):
   384                     origctx = commit.ctx
   386                     origctx = commit.ctx
   385                 else:
   387                 else:
   386                     origctx = None
   388                     origctx = None
   387                 node = nodemod.hex(self.repo.commitctx(ctx, origctx=origctx))
   389                 node = nodemod.hex(self.repo.commitctx(ctx, origctx=origctx))
   388 
   390 
   394                     if ctx.phase() < phases.draft:
   396                     if ctx.phase() < phases.draft:
   395                         phases.registernew(
   397                         phases.registernew(
   396                             self.repo, tr, phases.draft, [ctx.node()]
   398                             self.repo, tr, phases.draft, [ctx.node()]
   397                         )
   399                         )
   398 
   400 
   399             text = "(octopus merge fixup)\n"
   401             text = b"(octopus merge fixup)\n"
   400             p2 = node
   402             p2 = node
   401 
   403 
   402         if self.filemapmode and nparents == 1:
   404         if self.filemapmode and nparents == 1:
   403             man = self.repo.manifestlog.getstorage(b'')
   405             man = self.repo.manifestlog.getstorage(b'')
   404             mnode = self.repo.changelog.read(nodemod.bin(p2))[0]
   406             mnode = self.repo.changelog.read(nodemod.bin(p2))[0]
   405             closed = 'close' in commit.extra
   407             closed = b'close' in commit.extra
   406             if not closed and not man.cmp(m1node, man.revision(mnode)):
   408             if not closed and not man.cmp(m1node, man.revision(mnode)):
   407                 self.ui.status(_("filtering out empty revision\n"))
   409                 self.ui.status(_(b"filtering out empty revision\n"))
   408                 self.repo.rollback(force=True)
   410                 self.repo.rollback(force=True)
   409                 return parent
   411                 return parent
   410         return p2
   412         return p2
   411 
   413 
   412     def puttags(self, tags):
   414     def puttags(self, tags):
   414         tagparent = tagparent or nodemod.nullid
   416         tagparent = tagparent or nodemod.nullid
   415 
   417 
   416         oldlines = set()
   418         oldlines = set()
   417         for branch, heads in self.repo.branchmap().iteritems():
   419         for branch, heads in self.repo.branchmap().iteritems():
   418             for h in heads:
   420             for h in heads:
   419                 if '.hgtags' in self.repo[h]:
   421                 if b'.hgtags' in self.repo[h]:
   420                     oldlines.update(
   422                     oldlines.update(
   421                         set(self.repo[h]['.hgtags'].data().splitlines(True))
   423                         set(self.repo[h][b'.hgtags'].data().splitlines(True))
   422                     )
   424                     )
   423         oldlines = sorted(list(oldlines))
   425         oldlines = sorted(list(oldlines))
   424 
   426 
   425         newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
   427         newlines = sorted([(b"%s %s\n" % (tags[tag], tag)) for tag in tags])
   426         if newlines == oldlines:
   428         if newlines == oldlines:
   427             return None, None
   429             return None, None
   428 
   430 
   429         # if the old and new tags match, then there is nothing to update
   431         # if the old and new tags match, then there is nothing to update
   430         oldtags = set()
   432         oldtags = set()
   431         newtags = set()
   433         newtags = set()
   432         for line in oldlines:
   434         for line in oldlines:
   433             s = line.strip().split(' ', 1)
   435             s = line.strip().split(b' ', 1)
   434             if len(s) != 2:
   436             if len(s) != 2:
   435                 continue
   437                 continue
   436             oldtags.add(s[1])
   438             oldtags.add(s[1])
   437         for line in newlines:
   439         for line in newlines:
   438             s = line.strip().split(' ', 1)
   440             s = line.strip().split(b' ', 1)
   439             if len(s) != 2:
   441             if len(s) != 2:
   440                 continue
   442                 continue
   441             if s[1] not in oldtags:
   443             if s[1] not in oldtags:
   442                 newtags.add(s[1].strip())
   444                 newtags.add(s[1].strip())
   443 
   445 
   444         if not newtags:
   446         if not newtags:
   445             return None, None
   447             return None, None
   446 
   448 
   447         data = "".join(newlines)
   449         data = b"".join(newlines)
   448 
   450 
   449         def getfilectx(repo, memctx, f):
   451         def getfilectx(repo, memctx, f):
   450             return context.memfilectx(repo, memctx, f, data, False, False, None)
   452             return context.memfilectx(repo, memctx, f, data, False, False, None)
   451 
   453 
   452         self.ui.status(_("updating tags\n"))
   454         self.ui.status(_(b"updating tags\n"))
   453         date = "%d 0" % int(time.mktime(time.gmtime()))
   455         date = b"%d 0" % int(time.mktime(time.gmtime()))
   454         extra = {'branch': self.tagsbranch}
   456         extra = {b'branch': self.tagsbranch}
   455         ctx = context.memctx(
   457         ctx = context.memctx(
   456             self.repo,
   458             self.repo,
   457             (tagparent, None),
   459             (tagparent, None),
   458             "update tags",
   460             b"update tags",
   459             [".hgtags"],
   461             [b".hgtags"],
   460             getfilectx,
   462             getfilectx,
   461             "convert-repo",
   463             b"convert-repo",
   462             date,
   464             date,
   463             extra,
   465             extra,
   464         )
   466         )
   465         node = self.repo.commitctx(ctx)
   467         node = self.repo.commitctx(ctx)
   466         return nodemod.hex(node), nodemod.hex(tagparent)
   468         return nodemod.hex(node), nodemod.hex(tagparent)
   473             return
   475             return
   474         wlock = lock = tr = None
   476         wlock = lock = tr = None
   475         try:
   477         try:
   476             wlock = self.repo.wlock()
   478             wlock = self.repo.wlock()
   477             lock = self.repo.lock()
   479             lock = self.repo.lock()
   478             tr = self.repo.transaction('bookmark')
   480             tr = self.repo.transaction(b'bookmark')
   479             self.ui.status(_("updating bookmarks\n"))
   481             self.ui.status(_(b"updating bookmarks\n"))
   480             destmarks = self.repo._bookmarks
   482             destmarks = self.repo._bookmarks
   481             changes = [
   483             changes = [
   482                 (bookmark, nodemod.bin(updatedbookmark[bookmark]))
   484                 (bookmark, nodemod.bin(updatedbookmark[bookmark]))
   483                 for bookmark in updatedbookmark
   485                 for bookmark in updatedbookmark
   484             ]
   486             ]
   493 
   495 
   494     def hascommitforsplicemap(self, rev):
   496     def hascommitforsplicemap(self, rev):
   495         if rev not in self.repo and self.clonebranches:
   497         if rev not in self.repo and self.clonebranches:
   496             raise error.Abort(
   498             raise error.Abort(
   497                 _(
   499                 _(
   498                     'revision %s not found in destination '
   500                     b'revision %s not found in destination '
   499                     'repository (lookups with clonebranches=true '
   501                     b'repository (lookups with clonebranches=true '
   500                     'are not implemented)'
   502                     b'are not implemented)'
   501                 )
   503                 )
   502                 % rev
   504                 % rev
   503             )
   505             )
   504         return rev in self.repo
   506         return rev in self.repo
   505 
   507 
   506 
   508 
   507 class mercurial_source(common.converter_source):
   509 class mercurial_source(common.converter_source):
   508     def __init__(self, ui, repotype, path, revs=None):
   510     def __init__(self, ui, repotype, path, revs=None):
   509         common.converter_source.__init__(self, ui, repotype, path, revs)
   511         common.converter_source.__init__(self, ui, repotype, path, revs)
   510         self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors')
   512         self.ignoreerrors = ui.configbool(b'convert', b'hg.ignoreerrors')
   511         self.ignored = set()
   513         self.ignored = set()
   512         self.saverev = ui.configbool('convert', 'hg.saverev')
   514         self.saverev = ui.configbool(b'convert', b'hg.saverev')
   513         try:
   515         try:
   514             self.repo = hg.repository(self.ui, path)
   516             self.repo = hg.repository(self.ui, path)
   515             # try to provoke an exception if this isn't really a hg
   517             # try to provoke an exception if this isn't really a hg
   516             # repo, but some other bogus compatible-looking url
   518             # repo, but some other bogus compatible-looking url
   517             if not self.repo.local():
   519             if not self.repo.local():
   518                 raise error.RepoError
   520                 raise error.RepoError
   519         except error.RepoError:
   521         except error.RepoError:
   520             ui.traceback()
   522             ui.traceback()
   521             raise NoRepo(_("%s is not a local Mercurial repository") % path)
   523             raise NoRepo(_(b"%s is not a local Mercurial repository") % path)
   522         self.lastrev = None
   524         self.lastrev = None
   523         self.lastctx = None
   525         self.lastctx = None
   524         self._changescache = None, None
   526         self._changescache = None, None
   525         self.convertfp = None
   527         self.convertfp = None
   526         # Restrict converted revisions to startrev descendants
   528         # Restrict converted revisions to startrev descendants
   527         startnode = ui.config('convert', 'hg.startrev')
   529         startnode = ui.config(b'convert', b'hg.startrev')
   528         hgrevs = ui.config('convert', 'hg.revs')
   530         hgrevs = ui.config(b'convert', b'hg.revs')
   529         if hgrevs is None:
   531         if hgrevs is None:
   530             if startnode is not None:
   532             if startnode is not None:
   531                 try:
   533                 try:
   532                     startnode = self.repo.lookup(startnode)
   534                     startnode = self.repo.lookup(startnode)
   533                 except error.RepoError:
   535                 except error.RepoError:
   534                     raise error.Abort(
   536                     raise error.Abort(
   535                         _('%s is not a valid start revision') % startnode
   537                         _(b'%s is not a valid start revision') % startnode
   536                     )
   538                     )
   537                 startrev = self.repo.changelog.rev(startnode)
   539                 startrev = self.repo.changelog.rev(startnode)
   538                 children = {startnode: 1}
   540                 children = {startnode: 1}
   539                 for r in self.repo.changelog.descendants([startrev]):
   541                 for r in self.repo.changelog.descendants([startrev]):
   540                     children[self.repo.changelog.node(r)] = 1
   542                     children[self.repo.changelog.node(r)] = 1
   546             else:
   548             else:
   547                 self._heads = self.repo.heads()
   549                 self._heads = self.repo.heads()
   548         else:
   550         else:
   549             if revs or startnode is not None:
   551             if revs or startnode is not None:
   550                 raise error.Abort(
   552                 raise error.Abort(
   551                     _('hg.revs cannot be combined with ' 'hg.startrev or --rev')
   553                     _(
       
   554                         b'hg.revs cannot be combined with '
       
   555                         b'hg.startrev or --rev'
       
   556                     )
   552                 )
   557                 )
   553             nodes = set()
   558             nodes = set()
   554             parents = set()
   559             parents = set()
   555             for r in scmutil.revrange(self.repo, [hgrevs]):
   560             for r in scmutil.revrange(self.repo, [hgrevs]):
   556                 ctx = self.repo[r]
   561                 ctx = self.repo[r]
   633                 pass
   638                 pass
   634             except error.LookupError as e:
   639             except error.LookupError as e:
   635                 if not self.ignoreerrors:
   640                 if not self.ignoreerrors:
   636                     raise
   641                     raise
   637                 self.ignored.add(name)
   642                 self.ignored.add(name)
   638                 self.ui.warn(_('ignoring: %s\n') % e)
   643                 self.ui.warn(_(b'ignoring: %s\n') % e)
   639         return copies
   644         return copies
   640 
   645 
   641     def getcommit(self, rev):
   646     def getcommit(self, rev):
   642         ctx = self._changectx(rev)
   647         ctx = self._changectx(rev)
   643         _parents = self._parents(ctx)
   648         _parents = self._parents(ctx)
   645         optparents = [p.hex() for p in ctx.parents() if p and p not in _parents]
   650         optparents = [p.hex() for p in ctx.parents() if p and p not in _parents]
   646         crev = rev
   651         crev = rev
   647 
   652 
   648         return common.commit(
   653         return common.commit(
   649             author=ctx.user(),
   654             author=ctx.user(),
   650             date=dateutil.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
   655             date=dateutil.datestr(ctx.date(), b'%Y-%m-%d %H:%M:%S %1%2'),
   651             desc=ctx.description(),
   656             desc=ctx.description(),
   652             rev=crev,
   657             rev=crev,
   653             parents=parents,
   658             parents=parents,
   654             optparents=optparents,
   659             optparents=optparents,
   655             branch=ctx.branch(),
   660             branch=ctx.branch(),
   666     def gettags(self):
   671     def gettags(self):
   667         # This will get written to .hgtags, filter non global tags out.
   672         # This will get written to .hgtags, filter non global tags out.
   668         tags = [
   673         tags = [
   669             t
   674             t
   670             for t in self.repo.tagslist()
   675             for t in self.repo.tagslist()
   671             if self.repo.tagtype(t[0]) == 'global'
   676             if self.repo.tagtype(t[0]) == b'global'
   672         ]
   677         ]
   673         return dict(
   678         return dict(
   674             [
   679             [
   675                 (name, nodemod.hex(node))
   680                 (name, nodemod.hex(node))
   676                 for name, node in tags
   681                 for name, node in tags
   694 
   699 
   695         return ma + r
   700         return ma + r
   696 
   701 
   697     def converted(self, rev, destrev):
   702     def converted(self, rev, destrev):
   698         if self.convertfp is None:
   703         if self.convertfp is None:
   699             self.convertfp = open(self.repo.vfs.join('shamap'), 'ab')
   704             self.convertfp = open(self.repo.vfs.join(b'shamap'), b'ab')
   700         self.convertfp.write(util.tonativeeol('%s %s\n' % (destrev, rev)))
   705         self.convertfp.write(util.tonativeeol(b'%s %s\n' % (destrev, rev)))
   701         self.convertfp.flush()
   706         self.convertfp.flush()
   702 
   707 
   703     def before(self):
   708     def before(self):
   704         self.ui.debug('run hg source pre-conversion action\n')
   709         self.ui.debug(b'run hg source pre-conversion action\n')
   705 
   710 
   706     def after(self):
   711     def after(self):
   707         self.ui.debug('run hg source post-conversion action\n')
   712         self.ui.debug(b'run hg source post-conversion action\n')
   708 
   713 
   709     def hasnativeorder(self):
   714     def hasnativeorder(self):
   710         return True
   715         return True
   711 
   716 
   712     def hasnativeclose(self):
   717     def hasnativeclose(self):
   719             return None
   724             return None
   720 
   725 
   721     def getbookmarks(self):
   726     def getbookmarks(self):
   722         return bookmarks.listbookmarks(self.repo)
   727         return bookmarks.listbookmarks(self.repo)
   723 
   728 
   724     def checkrevformat(self, revstr, mapname='splicemap'):
   729     def checkrevformat(self, revstr, mapname=b'splicemap'):
   725         """ Mercurial, revision string is a 40 byte hex """
   730         """ Mercurial, revision string is a 40 byte hex """
   726         self.checkhexformat(revstr, mapname)
   731         self.checkhexformat(revstr, mapname)