File Annotation
Not logged in
94c39d6375 2007-11-14       aku: ## -*- tcl -*-
94c39d6375 2007-11-14       aku: # # ## ### ##### ######## ############# #####################
94c39d6375 2007-11-14       aku: ## Copyright (c) 2007 Andreas Kupries.
94c39d6375 2007-11-14       aku: #
94c39d6375 2007-11-14       aku: # This software is licensed as described in the file LICENSE, which
94c39d6375 2007-11-14       aku: # you should have received as part of this distribution.
94c39d6375 2007-11-14       aku: #
94c39d6375 2007-11-14       aku: # This software consists of voluntary contributions made by many
94c39d6375 2007-11-14       aku: # individuals.  For exact contribution history, see the revision
94c39d6375 2007-11-14       aku: # history and logs, available at http://fossil-scm.hwaci.com/fossil
94c39d6375 2007-11-14       aku: # # ## ### ##### ######## ############# #####################
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: ## Helper class for the pass 6 cycle breaker. Each instance refers to
94c39d6375 2007-11-14       aku: ## three changesets A, B, and C, with A a predecessor of B, and B
94c39d6375 2007-11-14       aku: ## predecessor of C, and the whole part of a dependency cycle.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: ## Instances analyse the file level dependencies which gave rise to
94c39d6375 2007-11-14       aku: ## the changeset dependencies of A, B, and C, with the results used by
94c39d6375 2007-11-14       aku: ## the cycle breaker algorithm to find a good location where to at
94c39d6375 2007-11-14       aku: ## least weaken and at best fully break the cycle.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: # # ## ### ##### ######## ############# #####################
94c39d6375 2007-11-14       aku: ## Requirements
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: package require Tcl 8.4                               ; # Required runtime.
94c39d6375 2007-11-14       aku: package require snit                                  ; # OO system.
94c39d6375 2007-11-14       aku: package require vc::tools::misc                       ; # Text formatting
94c39d6375 2007-11-14       aku: package require vc::tools::trouble                    ; # Error reporting.
94c39d6375 2007-11-14       aku: package require vc::tools::log                        ; # User feedback.
94c39d6375 2007-11-14       aku: package require vc::fossil::import::cvs::state        ; # State storage.
47d52d1efd 2007-11-28       aku: package require vc::fossil::import::cvs::integrity    ; # State integrity checks.
94c39d6375 2007-11-14       aku: package require vc::fossil::import::cvs::project::rev ; # Project level changesets
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: # # ## ### ##### ######## ############# #####################
94c39d6375 2007-11-14       aku: ##
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: snit::type ::vc::fossil::import::cvs::project::revlink {
94c39d6375 2007-11-14       aku:     # # ## ### ##### ######## #############
94c39d6375 2007-11-14       aku:     ## Public API
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     constructor {prev cset next} {
94c39d6375 2007-11-14       aku: 	set myprev $prev
94c39d6375 2007-11-14       aku: 	set mycset $cset
94c39d6375 2007-11-14       aku: 	set mynext $next
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# We perform the bulk of the analysis during construction. The
94c39d6375 2007-11-14       aku: 	# file revisions held by the changeset CSET can be sorted into
94c39d6375 2007-11-14       aku: 	# four categories.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# 1. Revisions whose predecessors are not in PREV, nor are
94c39d6375 2007-11-14       aku: 	#    their successors found in NEXT. These revisions do not
94c39d6375 2007-11-14       aku: 	#    count, as they did not induce any of the two dependencies
94c39d6375 2007-11-14       aku: 	#    under consideration. They can be ignored.
94c39d6375 2007-11-14       aku: 
3c0ef2c379 2007-12-05       aku: 	# 2. Revisions which have predecessors in PREV and successors
94c39d6375 2007-11-14       aku: 	#    in NEXT. They are called 'passthrough' in cvs2svn. They
94c39d6375 2007-11-14       aku: 	#    induce both dependencies under consideration and are thus
94c39d6375 2007-11-14       aku: 	#    critical in the creation of the cycle. As such they are
94c39d6375 2007-11-14       aku: 	#    also unbreakable :(
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# 3. Revisions which have predecessor in PREVE, but no
94c39d6375 2007-11-14       aku: 	#    successors in NEXT. As such they induced the incoming
94c39d6375 2007-11-14       aku: 	#    dependency, but not the outgoing one.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# 4. Revisions which have no predecessors in PREVE, but their
94c39d6375 2007-11-14       aku: 	#    successors are in NEXT. As such they induced the outgoing
94c39d6375 2007-11-14       aku: 	#    dependency, but not the incoming one.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# If we have no passthrough revisions then splitting the
94c39d6375 2007-11-14       aku: 	# changeset between categories 3 and 4, with category 1 going
94c39d6375 2007-11-14       aku: 	# wherever, will break the cycle. If category 2 revisions are
94c39d6375 2007-11-14       aku: 	# present we can still perform the split, this will however
94c39d6375 2007-11-14       aku: 	# not break the cycle, only weaken it.
94c39d6375 2007-11-14       aku: 
3c0ef2c379 2007-12-05       aku: 	# NOTE: This is the only remaining user of 'nextmap'. Look
3c0ef2c379 2007-12-05       aku: 	# into the possibility of performing the relevant counting
3c0ef2c379 2007-12-05       aku: 	# within the database.
4859304926 2007-11-29       aku: 
94c39d6375 2007-11-14       aku: 	array set csetprevmap [Invert [$myprev nextmap]]
94c39d6375 2007-11-14       aku: 	array set csetnextmap [$mycset nextmap]
94c39d6375 2007-11-14       aku: 
61829b076b 2007-11-29       aku: 	set prevrev [$myprev items]
61829b076b 2007-11-29       aku: 	set nextrev [$mynext items]
61829b076b 2007-11-29       aku: 
4859304926 2007-11-29       aku: 	foreach item [$mycset items] {
4859304926 2007-11-29       aku: 	    set rt [RT $item]
94c39d6375 2007-11-14       aku: 	    incr    mycount($rt)
4859304926 2007-11-29       aku: 	    lappend mycategory($rt) $item
94c39d6375 2007-11-14       aku: 	}
94c39d6375 2007-11-14       aku: 	return
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # Result is TRUE if and only breaking myset will do some good.
94c39d6375 2007-11-14       aku:     method breakable {} { expr  {$mycount(prev) || $mycount(next)} }
94c39d6375 2007-11-14       aku:     method passcount {} { return $mycount(pass) }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     method linkstomove {} {
94c39d6375 2007-11-14       aku: 	# Return the number of revisions that would be moved should we
94c39d6375 2007-11-14       aku: 	# split the changeset.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	set n [min2 $mycount(prev) $mycount(next)]
94c39d6375 2007-11-14       aku: 	if {$n > 0 } { return $n }
94c39d6375 2007-11-14       aku: 	return [max2 $mycount(prev) $mycount(next)]
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     method betterthan {other} {
94c39d6375 2007-11-14       aku: 	set sbreak [$self  breakable]
94c39d6375 2007-11-14       aku: 	set obreak [$other breakable]
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	if {$sbreak && !$obreak} { return 1 } ; # self is better.
94c39d6375 2007-11-14       aku: 	if {!$sbreak && $obreak} { return 0 } ; # self is worse.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# Equality. Look at the counters.
94c39d6375 2007-11-14       aku: 	# - Whichever has the lesser number of passthrough revisions
94c39d6375 2007-11-14       aku: 	#   is better, as more can be split off, weakening the cycle
94c39d6375 2007-11-14       aku: 	#   more.
94c39d6375 2007-11-14       aku: 	# - Whichever has less links to move is better.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	set opass [$other passcount]
94c39d6375 2007-11-14       aku: 	if {$mycount(pass) < $opass} { return 1 } ; # self is better.
94c39d6375 2007-11-14       aku: 	if {$mycount(pass) > $opass} { return 0 } ; # self is worse.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	set smove [$self  linkstomove]
94c39d6375 2007-11-14       aku: 	set omove [$other linkstomove]
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	if {$smove < $omove} { return 1 } ; # self is better.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	return 0 ; # Self is worse or equal, i.e. not better.
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     method break {} {
47d52d1efd 2007-11-28       aku: 	integrity assert {[$self breakable]} {Changeset [$mycset str] is not breakable.}
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	# One thing to choose when splitting CSET is where the
94c39d6375 2007-11-14       aku: 	# revision in categories 1 and 2 (none and passthrough
94c39d6375 2007-11-14       aku: 	# respectively) are moved to. This is done using the counters.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	if {!$mycount(prev)} {
94c39d6375 2007-11-14       aku: 	    # Nothing in category 3 => 1,2 go there, 4 the other.
94c39d6375 2007-11-14       aku: 	    set mycategory(prev) [concat $mycategory(none) $mycategory(pass)]
94c39d6375 2007-11-14       aku: 	} elseif {!$mycount(next)} {
94c39d6375 2007-11-14       aku: 	    # Nothing in category 4 => 1,2 go there, 3 the other.
94c39d6375 2007-11-14       aku: 	    set mycategory(next) [concat $mycategory(none) $mycategory(pass)]
94c39d6375 2007-11-14       aku: 	} elseif {$mycount(prev) < $mycount(next)} {
94c39d6375 2007-11-14       aku: 	    # Less predecessors than successors => 1,2 go to the
94c39d6375 2007-11-14       aku: 	    # sucessors.
94c39d6375 2007-11-14       aku: 	    set mycategory(next) [concat $mycategory(next) $mycategory(none) \
94c39d6375 2007-11-14       aku: 				      $mycategory(pass)]
94c39d6375 2007-11-14       aku: 	} else {
94c39d6375 2007-11-14       aku: 	    # Less successors than predecessors => 1,2 go to the
94c39d6375 2007-11-14       aku: 	    # predecessors.
94c39d6375 2007-11-14       aku: 	    set mycategory(next) [concat $mycategory(next) $mycategory(none) \
94c39d6375 2007-11-14       aku: 				      $mycategory(pass)]
94c39d6375 2007-11-14       aku: 	}
94c39d6375 2007-11-14       aku: 
59207428e2 2007-11-22       aku: 	# We now have the revisions for the two fragments to be in the
59207428e2 2007-11-22       aku: 	# (prev|next) elements of mycategory.
59207428e2 2007-11-22       aku: 
59207428e2 2007-11-22       aku: 	return [project::rev split $mycset $mycategory(prev) $mycategory(next)]
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # # ## ### ##### ######## #############
94c39d6375 2007-11-14       aku:     ## State
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     variable myprev {} ; # Reference to predecessor changeset in the link.
94c39d6375 2007-11-14       aku:     variable mycset {} ; # Reference to the main changeset of the link.
94c39d6375 2007-11-14       aku:     variable mynext {} ; # Reference to the successor changeset in the link.
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # Counters for the revision categories.
94c39d6375 2007-11-14       aku:     variable mycount -array {
94c39d6375 2007-11-14       aku: 	none 0
94c39d6375 2007-11-14       aku: 	prev 0
94c39d6375 2007-11-14       aku: 	next 0
94c39d6375 2007-11-14       aku: 	pass 0
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku:     # Lists of revisions for the various categories
94c39d6375 2007-11-14       aku:     variable mycategory -array {
94c39d6375 2007-11-14       aku: 	none {}
94c39d6375 2007-11-14       aku: 	prev {}
94c39d6375 2007-11-14       aku: 	next {}
94c39d6375 2007-11-14       aku: 	pass {}
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # # ## ### ##### ######## #############
94c39d6375 2007-11-14       aku:     ## Internal methods
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     proc RT {r} {
94c39d6375 2007-11-14       aku: 	upvar 1 csetprevmap csetprevmap csetnextmap csetnextmap prevrev prevrev nextrev nextrev
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	set inc	[expr {[info exists csetprevmap($r)]
94c39d6375 2007-11-14       aku: 		       ? [struct::set size [struct::set intersect $csetprevmap($r) $prevrev]]
94c39d6375 2007-11-14       aku: 		       : 0}]
94c39d6375 2007-11-14       aku: 	set out [expr {[info exists csetnextmap($r)]
94c39d6375 2007-11-14       aku: 		       ? [struct::set size [struct::set intersect $csetnextmap($r) $nextrev]]
94c39d6375 2007-11-14       aku: 		       : 0}]
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: 	if {$inc && $out} { return pass }
94c39d6375 2007-11-14       aku: 	if {$inc}         { return prev }
94c39d6375 2007-11-14       aku: 	if {$out}         { return next }
94c39d6375 2007-11-14       aku: 	return none
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     proc Invert {dict} {
94c39d6375 2007-11-14       aku: 	array set tmp {}
94c39d6375 2007-11-14       aku: 	foreach {k values} $dict {
94c39d6375 2007-11-14       aku: 	    foreach v $values { lappend tmp($v) $k }
94c39d6375 2007-11-14       aku: 	}
94c39d6375 2007-11-14       aku: 	return [array get tmp]
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # # ## ### ##### ######## #############
94c39d6375 2007-11-14       aku:     ## Configuration
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     pragma -hastypeinfo    no  ; # no type introspection
94c39d6375 2007-11-14       aku:     pragma -hasinfo        no  ; # no object introspection
94c39d6375 2007-11-14       aku:     pragma -simpledispatch yes ; # simple fast dispatch
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku:     # # ## ### ##### ######## #############
94c39d6375 2007-11-14       aku: }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: namespace eval ::vc::fossil::import::cvs::project {
94c39d6375 2007-11-14       aku:     namespace export revlink
94c39d6375 2007-11-14       aku:     namespace eval revlink {
94c39d6375 2007-11-14       aku: 	namespace import ::vc::fossil::import::cvs::state
47d52d1efd 2007-11-28       aku: 	namespace import ::vc::fossil::import::cvs::integrity
94c39d6375 2007-11-14       aku: 	namespace import ::vc::tools::misc::*
94c39d6375 2007-11-14       aku: 	namespace import ::vc::tools::trouble
94c39d6375 2007-11-14       aku: 	namespace eval project {
94c39d6375 2007-11-14       aku: 	    namespace import ::vc::fossil::import::cvs::project::rev
94c39d6375 2007-11-14       aku: 	}
94c39d6375 2007-11-14       aku: 	namespace import ::vc::tools::log
94c39d6375 2007-11-14       aku: 	log register csets
94c39d6375 2007-11-14       aku:     }
94c39d6375 2007-11-14       aku: }
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: # # ## ### ##### ######## ############# #####################
94c39d6375 2007-11-14       aku: ## Ready
94c39d6375 2007-11-14       aku: 
94c39d6375 2007-11-14       aku: package provide vc::fossil::import::cvs::project::revlink 1.0
94c39d6375 2007-11-14       aku: return