I realize now that there are certain fundamental incompatibilities between cvs tags and hg tags.
In cvs, a version of a file have tags associated with its different versions.
In hg, a version is an alias for a changeset . In other words the state of the working files at some snapshot in time
The distinction is subtle, but important.
It is possible to make a tagged release in cvs of a version that does not represent a snapshot in time. This is not possible in hg.
Of course one could apply patches to get replicas. However, this would create a lot of new heads on the repository with arguably little benefit (assuming the cvs repo is still kept around for posterity).
I'm afraid a perfect conversion from cvs to mercurial is not practical. Ry4an's solution would work for those who care only about recreating the versions. I am more interested in the history and evolution of the source files.
I wrote the following script to simply munge all the cvs tags in the $CVSROOT prior to the conversion. e.g tag "v321" becomes "v321_prehg". That way developers will know those tags are not-authoritative and they must go back to the read-only cvs tree.
#!/usr/bin/python
import os
import sys
import stat
def die(msg):
sys.stderr.write(msg)
sys.exit(1)
cvsroot =os.getenv("CVSROOT")
if cvsroot is None:
die("CVSROOT not defined" )
print "CVSROOT=%s" % cvsroot
for rcsfile in os.popen("find %s -name '*,v'" % cvsroot).xreadlines():
rcsfile = rcsfile.replace('\n','')
print "rcsfile:%s" % rcsfile
st=os.stat(rcsfile)
if st.st_mode & stat.S_IWUSR == 0:
os.chmod(rcsfile,st.st_mode | stat.S_IWUSR)
f = open(rcsfile,"r")
inlines=f.readlines()
f.close()
outlines=[]
insymbols=False
symbolsDone=False
for l in inlines:
if insymbols and not symbolsDone:
if l.find('\t') == 0:#tag line
l= l.replace(":","_prehg:",1)
else:
symbolsDone=True
else:
if l == "symbols\n":
insymbols=True
outlines.append(l)
f = open(rcsfile,"w")
f.writelines( outlines )
f.close()