Diff
Not logged in

Differences From:

File tools/cvs2fossil/lib/c2f_prev.tcl part of check-in [7c43583de1] - Tinkered with the revision information transfered from a changeset to push, to the fossil accessor code, modified the logging as well. by aku on 2008-01-31 06:25:34. [view]

To:

File tools/cvs2fossil/lib/c2f_prev.tcl part of check-in [e8efbc317a] - Reworked the code determining the parent of the currently committed changeset. It should now handle the transition from vendor branch to trunk correctly. by aku on 2008-02-01 05:25:03. [view]

@@ -401,18 +401,19 @@
 	# - User doing the commit        (s.a.)
 	#
 	# - Timestamp of when committed  (command argument)
 	#
-	# - The parent changeset, if any. If there is no parent use
-	#   the empty base revision as parent.
+	# - The parent changeset, if any. If there is no parent fossil
+	#   will use the empty base revision as parent.
 	#
 	# - List of the file revisions in the changeset.
 
 	struct::list assign [$myproject getmeta $mysrcid] __ branch user message
 	struct::list assign $branch __ lodname
 
-	# Perform the import. As part of that convert the list of
-	# items in the changeset into uuids and printable data.
+	# Perform the import. As part of that we determine the parent
+	# we need, and convert the list of items in the changeset into
+	# uuids and printable data.
 
 	set uuid [Updatestate state $lodname \
 		      [$repository importrevision [$self str] \
 			   $user $message $date \
@@ -445,52 +446,100 @@
 
     proc Getparent {sv lodname project} {
 	upvar 1 $sv state
 
-	# The parent is determined via the line-of-development (LOD)
-	# information of each changeset, and the history of
-	# imports. The last changeset committed to the same LOD is
-	# taken as the parent of the current changeset. If the
-	# changeset is the first on that LOD it can be either spawned
-	# from another LOD, or detached. For the first case we
-	# retrieve the parent LOD of the current LOD symbol (*) and
-	# recheck for a committed changeset. The second case is taken
-	# if that lookup fails as well.
-	#
-	# (*) And this parent was found in previous passes when
-	#     determining the prefered parents of all the symbols.
-
-	# NOTE: The above is incomplete and buggy. Vendor-branches and
-	#       the various possibilities of its interaction with the
-	#       trunk are not fully handled.
-
-	if {[info exists state($lodname)]} {
-	    # LOD exists and has already been committed to.
+	struct::list assign [Getisdefault $myitems] isdefault lastdefaultontrunk
+
+	# See (a) below, we have to remember if the changeset is last
+	# on vendor branch also belonging to trunk even if we find a
+	# parent in the state. The caller will later (after import)
+	# make us the first trunk changeset in the state (See (**)).
+
+	if {$lastdefaultontrunk} {
+	    set state(:vendor:last:) .
+	}
+
+	# The state array holds for each line-of-development (LOD) the
+	# last committed changeset belonging to that LOD.
+
+	# (*) Standard handling if in-LOD changesets. If the LOD of
+	#     the current changeset exists in the state (= has been
+	#     committed to) then the stored changeset is the parent we
+	#     are looking for.
+
+	if {[info exists state($lodname)]} {
 	    return $state($lodname)
 	}
 
-	# LOD has not been committed to before, this is the first
-	# time. Determine the name of the parent LOD.
+	# If the LOD is not yet known the current changeset can either
+	# be
+	# (a) the root of a vendor branch,
+	# (b) the root of the trunk LOD, or
+	# (c) the first changeset in a new LOD which was spawned from
+	#     an existing LOD.
+
+	if {$isdefault} {
+	    # In case of (a) the changeset has no parent, signaled by
+	    # the empty string. We do remember if the changeset is
+	    # last on the vendor branch still belonging to trunk, for
+	    # the trunk root.
+	    return {}
+	}
+
+	if {$lodname eq ":trunk:"} {
+	    # This is case (b), and we also can be sure that there is
+	    # no vendor branch changeset which could be our
+	    # parent. That was already dealt with through the
+	    # :vendor:last: signal and code in the caller (setting
+	    # such a changeset up as parent in the state, causing the
+	    # standard LOD handler at (*) to kick in. So, no parent
+	    # here at all.
+	    return {}
+	}
+
+	# Case (c). We find the parent LOD of our LOD and take the
+	# last changeset committed to that as our parent. If that
+	# doesn't exist we have an error on our hands.
 
 	set lodname [[[$project getsymbol $lodname] parent] name]
-
-	if {[info exists state($lodname)]} {
-	    # The parental LOD has been committed to, take that last
-	    # changeset as the spawnpoint for the new LOD.
+	if {[info exists state($lodname)]} {
 	    return $state($lodname)
 	}
 
-	# The parental LOD is not defined (yet). This LOD is
-	# detached. We choose as our parent the automatic empty root
-	# baseline of the target repository.
-	return {}
+	trouble internal {Unable to determine changeset parent}
+	return
+    }
+
+    proc Getisdefault {revisions} {
+	set theset ('[join $revisions {','}]')
+
+	struct::list assign [state run [subst -nocommands -nobackslashes {
+	    SELECT R.isdefault, R.dbchild
+	    FROM   revision R
+	    WHERE  R.rid IN $theset  -- All specified revisions
+	    LIMIT 1
+	}]] def last
+
+	# TODO/CHECK: look for changesets where isdefault/dbchild is
+	# ambigous.
+
+	return [list $def [expr {$last ne ""}]]
     }
 
     proc Updatestate {sv lodname uuid} {
-	# Remember the imported changeset in the state, under our LOD.
-
 	upvar 1 $sv state
+
+	# Remember the imported changeset in the state, under our
+	# LOD. (**) And if the :vendor:last: signal is present then
+	# the revision is also the actual root of the :trunk:, so
+	# remember it as such.
+
 	set state($lodname) $uuid
+	if {[info exists state(:vendor:last:)]} {
+	    unset state(:vendor:last:)
+	    set state(:trunk:) $uuid
+	}
+
 	return $uuid
     }
 
     typemethod split {cset args} {