contrib/convert-repo
changeset 3955 9af4b853ed4d
parent 3954 fad134931327
child 3957 558f52943cd2
equal deleted inserted replaced
3954:fad134931327 3955:9af4b853ed4d
    27 os.environ["HGENCODING"] = "utf-8"
    27 os.environ["HGENCODING"] = "utf-8"
    28 from mercurial import hg, ui, util, fancyopts
    28 from mercurial import hg, ui, util, fancyopts
    29 
    29 
    30 class Abort(Exception): pass
    30 class Abort(Exception): pass
    31 class NoRepo(Exception): pass
    31 class NoRepo(Exception): pass
       
    32 
       
    33 class commit:
       
    34     def __init__(self, **parts):
       
    35         for x in "author date desc parents".split():
       
    36             if not x in parts:
       
    37                 abort("commit missing field %s\n" % x)
       
    38         self.__dict__.update(parts)
    32 
    39 
    33 quiet = 0
    40 quiet = 0
    34 def status(msg):
    41 def status(msg):
    35     if not quiet: sys.stdout.write(str(msg))
    42     if not quiet: sys.stdout.write(str(msg))
    36 
    43 
    56         cvs = os.path.join(path, "CVS")
    63         cvs = os.path.join(path, "CVS")
    57         if not os.path.exists(cvs):
    64         if not os.path.exists(cvs):
    58             raise NoRepo("couldn't open CVS repo %s" % path)
    65             raise NoRepo("couldn't open CVS repo %s" % path)
    59 
    66 
    60         self.changeset = {}
    67         self.changeset = {}
       
    68         self.files = {}
    61         self.tags = {}
    69         self.tags = {}
    62         self.lastbranch = {}
    70         self.lastbranch = {}
    63         self.parent = {}
    71         self.parent = {}
    64         self.socket = None
    72         self.socket = None
    65         self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
    73         self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
   110                     else:
   118                     else:
   111                         log += l
   119                         log += l
   112                 elif state == 2:
   120                 elif state == 2:
   113                     if l == "\n": #
   121                     if l == "\n": #
   114                         state = 0
   122                         state = 0
   115                         self.changeset[id] = (date, author, log, files)
   123                         p = [self.parent[id]]
       
   124                         if id == "1":
       
   125                             p = []
       
   126                         c = commit(author=author, date=date, parents=p,
       
   127                                    desc=log, branch=branch)
       
   128                         self.changeset[id] = c
       
   129                         self.files[id] = files
   116                     else:
   130                     else:
   117                         file,rev = l[1:-2].rsplit(':',1)
   131                         file,rev = l[1:-2].rsplit(':',1)
   118                         rev = rev.split("->")[1]
   132                         rev = rev.split("->")[1]
   119                         files[file] = rev
   133                         files[file] = rev
   120 
   134 
   214                         abort("unknown CVS response: %s\n" % l)
   228                         abort("unknown CVS response: %s\n" % l)
   215                 else:
   229                 else:
   216                     abort("unknown CVS response: %s\n" % line)
   230                     abort("unknown CVS response: %s\n" % line)
   217 
   231 
   218     def getchanges(self, rev):
   232     def getchanges(self, rev):
   219         files = self.changeset[rev][3]
   233         files = self.files[rev]
   220         cl = [ (f, r, 0) for f,r in files.items() ]
   234         cl = [ (f, r, 0) for f,r in files.items() ]
   221         cl.sort()
   235         cl.sort()
   222         return cl
   236         return cl
   223 
   237 
   224     def recode(self, text):
   238     def recode(self, text):
   225         return text.decode(self.encoding, "replace").encode("utf-8")
   239         return text.decode(self.encoding, "replace").encode("utf-8")
   226 
   240 
   227     def getcommit(self, rev):
   241     def getcommit(self, rev):
   228         cs = self.changeset[rev]
   242         return self.changeset[rev]
   229         parents = [self.parent[rev]]
       
   230         if rev == "1":
       
   231             parents = []
       
   232         return (parents, cs[1], cs[0], cs[2])
       
   233 
   243 
   234     def gettags(self):
   244     def gettags(self):
   235         return self.tags
   245         return self.tags
   236 
   246 
   237 class convert_git:
   247 class convert_git:
   292             if n == "parent": parents.append(v)
   302             if n == "parent": parents.append(v)
   293 
   303 
   294         tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
   304         tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
   295         tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
   305         tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
   296         date = tm + " " + str(tz)
   306         date = tm + " " + str(tz)
   297         return (parents, author, date, message)
   307 
       
   308         c = commit(parents=parents, date=date, author=author, desc=message)
       
   309         return c
   298 
   310 
   299     def gettags(self):
   311     def gettags(self):
   300         tags = {}
   312         tags = {}
   301         for f in os.listdir(self.path + "/refs/tags"):
   313         for f in os.listdir(self.path + "/refs/tags"):
   302             try:
   314             try:
   336             os.unlink(self.repo.wjoin(f))
   348             os.unlink(self.repo.wjoin(f))
   337             #self.repo.remove([f])
   349             #self.repo.remove([f])
   338         except:
   350         except:
   339             pass
   351             pass
   340 
   352 
   341     def putcommit(self, files, parents, author, dest, text):
   353     def putcommit(self, files, parents, commit):
   342         seen = {}
   354         seen = {}
   343         pl = []
   355         pl = []
   344         for p in parents:
   356         for p in parents:
   345             if p not in seen:
   357             if p not in seen:
   346                 pl.append(p)
   358                 pl.append(p)
   349 
   361 
   350         if len(parents) < 2: parents.append("0" * 40)
   362         if len(parents) < 2: parents.append("0" * 40)
   351         if len(parents) < 2: parents.append("0" * 40)
   363         if len(parents) < 2: parents.append("0" * 40)
   352         p2 = parents.pop(0)
   364         p2 = parents.pop(0)
   353 
   365 
       
   366         text = commit.desc
       
   367         extra = {}
       
   368         try:
       
   369             extra["branch"] = commit.branch
       
   370         except AttributeError:
       
   371             pass
       
   372 
   354         while parents:
   373         while parents:
   355             p1 = p2
   374             p1 = p2
   356             p2 = parents.pop(0)
   375             p2 = parents.pop(0)
   357             a = self.repo.rawcommit(files, text, author, dest,
   376             a = self.repo.rawcommit(files, text, commit.author, commit.date,
   358                                     hg.bin(p1), hg.bin(p2))
   377                                     hg.bin(p1), hg.bin(p2), extra=extra)
   359             text = "(octopus merge fixup)\n"
   378             text = "(octopus merge fixup)\n"
   360             p2 = hg.hex(self.repo.changelog.tip())
   379             p2 = hg.hex(self.repo.changelog.tip())
   361 
   380 
   362         return p2
   381         return p2
   363 
   382 
   423         while visit:
   442         while visit:
   424             n = visit.pop(0)
   443             n = visit.pop(0)
   425             if n in known or n in self.map: continue
   444             if n in known or n in self.map: continue
   426             known[n] = 1
   445             known[n] = 1
   427             self.commitcache[n] = self.source.getcommit(n)
   446             self.commitcache[n] = self.source.getcommit(n)
   428             cp = self.commitcache[n][0]
   447             cp = self.commitcache[n].parents
   429             for p in cp:
   448             for p in cp:
   430                 parents.setdefault(n, []).append(p)
   449                 parents.setdefault(n, []).append(p)
   431                 visit.append(p)
   450                 visit.append(p)
   432 
   451 
   433         return parents
   452         return parents
   474                         visit.insert(0, c)
   493                         visit.insert(0, c)
   475 
   494 
   476         return s
   495         return s
   477 
   496 
   478     def copy(self, rev):
   497     def copy(self, rev):
   479         p, a, d, t = self.commitcache[rev]
   498         c = self.commitcache[rev]
   480         files = self.source.getchanges(rev)
   499         files = self.source.getchanges(rev)
   481 
   500 
   482         for f,v,e in files:
   501         for f,v,e in files:
   483             try:
   502             try:
   484                 data = self.source.getfile(f, v)
   503                 data = self.source.getfile(f, v)
   485             except IOError, inst:
   504             except IOError, inst:
   486                 self.dest.delfile(f)
   505                 self.dest.delfile(f)
   487             else:
   506             else:
   488                 self.dest.putfile(f, e, data)
   507                 self.dest.putfile(f, e, data)
   489 
   508 
   490         r = [self.map[v] for v in p]
   509         r = [self.map[v] for v in c.parents]
   491         f = [f for f,v,e in files]
   510         f = [f for f,v,e in files]
   492         self.map[rev] = self.dest.putcommit(f, r, a, d, t)
   511         self.map[rev] = self.dest.putcommit(f, r, c)
   493         file(self.mapfile, "a").write("%s %s\n" % (rev, self.map[rev]))
   512         file(self.mapfile, "a").write("%s %s\n" % (rev, self.map[rev]))
   494 
   513 
   495     def convert(self):
   514     def convert(self):
   496         status("scanning source...\n")
   515         status("scanning source...\n")
   497         heads = self.source.getheads()
   516         heads = self.source.getheads()
   503         c = None
   522         c = None
   504 
   523 
   505         status("converting...\n")
   524         status("converting...\n")
   506         for c in t:
   525         for c in t:
   507             num -= 1
   526             num -= 1
   508             desc = self.commitcache[c][3]
   527             desc = self.commitcache[c].desc
   509             if "\n" in desc:
   528             if "\n" in desc:
   510                 desc = desc.splitlines()[0]
   529                 desc = desc.splitlines()[0]
   511             status("%d %s\n" % (num, desc))
   530             status("%d %s\n" % (num, desc))
   512             self.copy(c)
   531             self.copy(c)
   513 
   532