[PATCH] convert: make convert from cvs recognise branch points correctly [revised]

Henrik Stuart henrik.stuart at edlund.dk
Tue Apr 7 10:38:37 CDT 2009


# HG changeset patch
# User Henrik Stuart <henrik.stuart at edlund.dk>
# Date 1239117873 -7200
# Node ID b5f424625b8cefe4961d30206cfcf189bfbd9781
# Parent  777a9efdae2d291b446c5abb4c95c0f0e73462a6
convert: make convert from cvs recognise branch points correctly

This patch fixes issue 1447 by using the symbolic names for branches
in the rlog output to determine the branch point for each file and
then finding the latest possible branch point in the given changesets
such that all the file revisions match and the date is earlier than
the branch commit. For commits on non-branches, the current
functionality is maintained.

diff -r 777a9efdae2d -r b5f424625b8c hgext/convert/cvsps.py
--- a/hgext/convert/cvsps.py	Tue Apr 07 20:57:25 2009 +0200
+++ b/hgext/convert/cvsps.py	Tue Apr 07 17:24:33 2009 +0200
@@ -35,6 +35,7 @@
         .tags      - list of tags on the file
         .synthetic - is this a synthetic "file ... added on ..." revision?
         .mergepoint- the branch that has been merged from (if present in rlog output)
+        .branchesto- list of branches that are branched to from here
     '''
     def __init__(self, **entries):
         self.__dict__.update(entries)
@@ -378,6 +379,8 @@
             # clean up the results and save in the log.
             store = False
             e.tags = util.sort([scache(x) for x in tags.get(e.revision, [])])
+            e.branchesto = [tag for tag in branchmap if len(branchmap[tag].split('.')) > 2 and branchmap[tag].split('.')[-2] == '0' and e.revision == tuple([int(x) for x in branchmap[tag].split('.')[:-2]])]
+
             e.comment = scache('\n'.join(e.comment))
 
             revn = len(e.revision)
@@ -582,6 +585,7 @@
 
     versions = {}    # changeset index where we saw any particular file version
     branches = {}    # changeset index where we saw a branch
+    has_logentry_without_branchesto = False # variable to only output warning for missing branchesto once
     n = len(changesets)
     i = 0
     while i<n:
@@ -599,8 +603,38 @@
 
         c.parents = []
         if p is not None:
+            parent_idx = p
             p = changesets[p]
 
+            if p is not None:
+                if c.branch != p.branch:
+                    earliest_commit = min([l.date for l in log if l.branch == c.branch]) # necessary as the first commit on a branch can be broken into multiple bites
+
+                    q = parent_idx
+                    seen_branched_files = util.set([e.file for e in c.entries]) # already in p at the latest
+                    while q + 1 < i: # only need to search up to current
+                        qcs = changesets[q + 1]
+
+                        if qcs.date >= earliest_commit:
+                            break
+
+                        if any([e.file in seen_branched_files for e in qcs.entries]):
+                            break # we cannot progress past this place
+
+                        branchesto = getattr(e, 'branchesto', None)
+                        if branchesto == None and not has_logentry_without_branchesto:
+                            has_logentry_without_branchesto = True
+                            ui.warn(_("CVS cache has been compiled without correct branch information.\n"
+                                "If you have branches in your CVS repository it is strongly adviced to\n"
+                                "delete the cache and start over.\n"))
+                        if branchesto == None:
+                            branchesto = []
+                        seen_branched_files |= util.set([e.file for e in qcs.entries if c.branch in branchesto])
+                                
+                        q += 1
+
+                    p = changesets[q]
+
             # Ensure no changeset has a synthetic changeset as a parent.
             while p.synthetic:
                 assert len(p.parents) <= 1, \
diff -r 777a9efdae2d -r b5f424625b8c tests/test-convert-cvs-branchpoints
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-cvs-branchpoints	Tue Apr 07 17:24:33 2009 +0200
@@ -0,0 +1,157 @@
+#!/bin/bash
+
+"$TESTDIR/hghave" cvs || exit 80
+
+cvscall()
+{
+    cvs -f "$@"
+}
+
+createmaster()
+{
+    rm -rf master
+    mkdir master
+    pushd master > /dev/null
+    export CVSROOT=`pwd`
+    popd > /dev/null
+    cvscall -q -d "$CVSROOT" init
+    mkdir -p master/work
+    rm -rf work
+    cvscall -q -d "$CVSROOT" co -d work work
+}
+
+hgcvsps()
+{
+    hg debugcvsps -x --parents work | sed -e 's/Author:.*/Author:/' -e 's/Date:.*/Date:/'
+}
+
+echo "[extensions]" >> $HGRCPATH
+echo "convert = " >> $HGRCPATH
+echo "graphlog = " >> $HGRCPATH
+echo "[convert]" >> $HGRCPATH
+echo "cvsps=builtin" >> $HGRCPATH
+
+createvar0()
+{
+    echo Creating 1447 var 0
+    createmaster
+    pushd work > /dev/null
+    echo a > a.txt
+    echo b > b.txt
+    cvscall -q add *.txt
+    cvscall -q ci -m "initial" | sed 's/.*,v.*/checking in/g'
+    echo "b fix" >> b.txt
+    cvscall -q ci -m "b fix" | sed 's/.*,v.*/checking in/g'
+    echo "a fix" >> a.txt
+    cvscall -q ci -m "a fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q rtag -b BRANCH work
+    cvscall -q up -r BRANCH
+    echo "b branch fix" >> b.txt
+    cvscall -q ci -m "b branch fix" | sed 's/.*,v.*/checking in/g'
+    hgcvsps
+    popd > /dev/null
+}
+
+createvar1()
+{
+    echo Creating 1447 var 1
+    createmaster
+    pushd work > /dev/null
+    echo a > a.txt
+    echo b > b.txt
+    cvscall -q add *.txt
+    cvscall -q ci -m "initial" | sed 's/.*,v.*/checking in/g'
+    echo "b fix" >> b.txt
+    cvscall -q ci -m "b fix" | sed 's/.*,v.*/checking in/g'
+    echo "a fix" >> a.txt
+    cvscall -q ci -m "a fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q tag FOO
+    echo "b fix 2" >> b.txt
+    cvscall -q ci -m "b fix 2" | sed 's/.*,v.*/checking in/g'
+    cvscall -q up -r 1.2 *.txt
+    cvscall -q rtag -b -r FOO BRANCH work
+    cvscall -q up -r BRANCH
+    echo "b branch fix" >> b.txt
+    cvscall -q ci -m "b branch fix" | sed 's/.*,v.*/checking in/g'
+    hgcvsps
+    popd > /dev/null
+}
+
+createvar2()
+{
+    echo Creating 1447 var 2
+    createmaster
+    pushd work > /dev/null
+    echo a > a.txt
+    echo b > b.txt
+    cvscall -q add *.txt
+    cvscall -q ci -m "initial" | sed 's/.*,v.*/checking in/g'
+    echo "b fix" >> b.txt
+    cvscall -q ci -m "b fix" | sed 's/.*,v.*/checking in/g'
+    echo "a fix" >> a.txt
+    cvscall -q ci -m "a fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q tag FOO
+    echo "a fix 2" >> a.txt
+    cvscall -q ci -m "a fix 2" | sed 's/.*,v.*/checking in/g'
+    cvscall -q up -r 1.2 *.txt
+    cvscall -q rtag -b -r FOO BRANCH work
+    cvscall -q up -r BRANCH
+    echo "b branch fix" >> b.txt
+    cvscall -q ci -m "b branch fix" | sed 's/.*,v.*/checking in/g'
+    hgcvsps
+    popd > /dev/null
+}
+
+createvar3()
+{
+    echo Creating 1447 var 3
+    createmaster
+    pushd work > /dev/null
+    echo a > a.txt
+    echo b > b.txt
+    cvscall -q add *.txt
+    cvscall -q ci -m "initial" | sed 's/.*,v.*/checking in/g'
+    echo "b fix" >> b.txt
+    cvscall -q ci -m "b fix" | sed 's/.*,v.*/checking in/g'
+    echo "a fix" >> a.txt
+    cvscall -q ci -m "a fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q rtag -b BRANCH work
+    cvscall -q up -r BRANCH
+    echo "b branch fix" >> b.txt
+    cvscall -q ci -m "b branch fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q up -A
+    echo "b fix 2" >> b.txt
+    cvscall -q ci -m "b fix 2" | sed 's/.*,v.*/checking in/g'
+    hgcvsps
+    popd > /dev/null
+}
+
+createvar4()
+{
+    echo Creating 1447 var 3
+    createmaster
+    pushd work > /dev/null
+    echo a > a.txt
+    echo b > b.txt
+    cvscall -q add *.txt
+    cvscall -q ci -m "initial" | sed 's/.*,v.*/checking in/g'
+    echo "b fix" >> b.txt
+    cvscall -q ci -m "b fix" | sed 's/.*,v.*/checking in/g'
+    echo "a fix" >> a.txt
+    cvscall -q ci -m "a fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q rtag -b BRANCH work
+    cvscall -q up -r BRANCH
+    echo "b branch fix" >> b.txt
+    cvscall -q ci -m "b branch fix" | sed 's/.*,v.*/checking in/g'
+    cvscall -q up -A
+    echo "a fix 2" >> a.txt
+    cvscall -q ci -m "a fix 2" | sed 's/.*,v.*/checking in/g'
+    hgcvsps
+    popd > /dev/null
+}
+
+createvar0
+createvar1
+createvar2
+createvar3
+createvar4
diff -r 777a9efdae2d -r b5f424625b8c tests/test-convert-cvs-branchpoints.out
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-convert-cvs-branchpoints.out	Tue Apr 07 17:24:33 2009 +0200
@@ -0,0 +1,408 @@
+Creating 1447 var 0
+cvs add: use `cvs commit' to add these files permanently
+checking in
+initial revision: 1.1
+checking in
+initial revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2.2.1; previous revision: 1.2
+collecting CVS rlog
+5 log entries
+creating changesets
+4 changeset entries
+---------------------
+PatchSet 1 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Log:
+initial
+
+Members: 
+	a.txt:INITIAL->1.1 
+	b.txt:INITIAL->1.1 
+
+---------------------
+PatchSet 2 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 1
+Log:
+b fix
+
+Members: 
+	b.txt:1.1->1.2 
+
+---------------------
+PatchSet 3 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 2
+Log:
+a fix
+
+Members: 
+	a.txt:1.1->1.2 
+
+---------------------
+PatchSet 4 
+Date:
+Author:
+Branch: BRANCH
+Tag: (none) 
+Parent: 3
+Log:
+b branch fix
+
+Members: 
+	b.txt:1.2->1.2.2.1 
+
+Creating 1447 var 1
+cvs add: use `cvs commit' to add these files permanently
+checking in
+initial revision: 1.1
+checking in
+initial revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+T a.txt
+T b.txt
+checking in
+new revision: 1.3; previous revision: 1.2
+U b.txt
+checking in
+new revision: 1.2.2.1; previous revision: 1.2
+collecting CVS rlog
+6 log entries
+creating changesets
+5 changeset entries
+---------------------
+PatchSet 1 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Log:
+initial
+
+Members: 
+	a.txt:INITIAL->1.1 
+	b.txt:INITIAL->1.1 
+
+---------------------
+PatchSet 2 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 1
+Log:
+b fix
+
+Members: 
+	b.txt:1.1->1.2 
+
+---------------------
+PatchSet 3 
+Date:
+Author:
+Branch: HEAD
+Tag: FOO 
+Parent: 2
+Log:
+a fix
+
+Members: 
+	a.txt:1.1->1.2 
+
+---------------------
+PatchSet 4 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 3
+Log:
+b fix 2
+
+Members: 
+	b.txt:1.2->1.3 
+
+---------------------
+PatchSet 5 
+Date:
+Author:
+Branch: BRANCH
+Tag: (none) 
+Parent: 3
+Log:
+b branch fix
+
+Members: 
+	b.txt:1.2->1.2.2.1 
+
+Creating 1447 var 2
+cvs add: use `cvs commit' to add these files permanently
+checking in
+initial revision: 1.1
+checking in
+initial revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+T a.txt
+T b.txt
+checking in
+new revision: 1.3; previous revision: 1.2
+U a.txt
+checking in
+new revision: 1.2.2.1; previous revision: 1.2
+collecting CVS rlog
+6 log entries
+creating changesets
+5 changeset entries
+---------------------
+PatchSet 1 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Log:
+initial
+
+Members: 
+	a.txt:INITIAL->1.1 
+	b.txt:INITIAL->1.1 
+
+---------------------
+PatchSet 2 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 1
+Log:
+b fix
+
+Members: 
+	b.txt:1.1->1.2 
+
+---------------------
+PatchSet 3 
+Date:
+Author:
+Branch: HEAD
+Tag: FOO 
+Parent: 2
+Log:
+a fix
+
+Members: 
+	a.txt:1.1->1.2 
+
+---------------------
+PatchSet 4 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 3
+Log:
+a fix 2
+
+Members: 
+	a.txt:1.2->1.3 
+
+---------------------
+PatchSet 5 
+Date:
+Author:
+Branch: BRANCH
+Tag: (none) 
+Parent: 3
+Log:
+b branch fix
+
+Members: 
+	b.txt:1.2->1.2.2.1 
+
+Creating 1447 var 3
+cvs add: use `cvs commit' to add these files permanently
+checking in
+initial revision: 1.1
+checking in
+initial revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2.2.1; previous revision: 1.2
+U b.txt
+checking in
+new revision: 1.3; previous revision: 1.2
+collecting CVS rlog
+6 log entries
+creating changesets
+5 changeset entries
+---------------------
+PatchSet 1 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Log:
+initial
+
+Members: 
+	a.txt:INITIAL->1.1 
+	b.txt:INITIAL->1.1 
+
+---------------------
+PatchSet 2 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 1
+Log:
+b fix
+
+Members: 
+	b.txt:1.1->1.2 
+
+---------------------
+PatchSet 3 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 2
+Log:
+a fix
+
+Members: 
+	a.txt:1.1->1.2 
+
+---------------------
+PatchSet 4 
+Date:
+Author:
+Branch: BRANCH
+Tag: (none) 
+Parent: 3
+Log:
+b branch fix
+
+Members: 
+	b.txt:1.2->1.2.2.1 
+
+---------------------
+PatchSet 5 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 3
+Log:
+b fix 2
+
+Members: 
+	b.txt:1.2->1.3 
+
+Creating 1447 var 3
+cvs add: use `cvs commit' to add these files permanently
+checking in
+initial revision: 1.1
+checking in
+initial revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2; previous revision: 1.1
+checking in
+new revision: 1.2.2.1; previous revision: 1.2
+U b.txt
+checking in
+new revision: 1.3; previous revision: 1.2
+collecting CVS rlog
+6 log entries
+creating changesets
+5 changeset entries
+---------------------
+PatchSet 1 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Log:
+initial
+
+Members: 
+	a.txt:INITIAL->1.1 
+	b.txt:INITIAL->1.1 
+
+---------------------
+PatchSet 2 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 1
+Log:
+b fix
+
+Members: 
+	b.txt:1.1->1.2 
+
+---------------------
+PatchSet 3 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 2
+Log:
+a fix
+
+Members: 
+	a.txt:1.1->1.2 
+
+---------------------
+PatchSet 4 
+Date:
+Author:
+Branch: BRANCH
+Tag: (none) 
+Parent: 3
+Log:
+b branch fix
+
+Members: 
+	b.txt:1.2->1.2.2.1 
+
+---------------------
+PatchSet 5 
+Date:
+Author:
+Branch: HEAD
+Tag: (none) 
+Parent: 3
+Log:
+a fix 2
+
+Members: 
+	a.txt:1.2->1.3 
+


More information about the Mercurial-devel mailing list