Check-in [6f8667b03e]
Not logged in
Overview

SHA1 Hash:6f8667b03e3a644953d6bd72e7eed9ba83881b08
Date: 2007-10-31 03:44:01
User: aku
Comment:Added code creating aggregate symbol statistics. This completes pass 2 (CollRev).
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified tools/cvs2fossil/lib/c2f_file.tcl from [bd5c5d46d2] to [a0a48d681e].

@@ -232,11 +232,12 @@
     }
 
     method done {} {
 	# Complete the revisions, branches, and tags. This includes
 	# looking for a non-trunk default branch, marking its members
-	# and linking them into the trunk.
+	# and linking them into the trunk, possibly excluding
+	# non-trunk data, and collecting aggregate symbol statistics.
 
 	$self DetermineRevisionOperations
 	$self DetermineLinesOfDevelopment
 	$self HandleNonTrunkDefaultBranch
 	$self RemoveIrrelevantDeletions
@@ -243,10 +244,12 @@
 	$self RemoveInitialBranchDeletions
 
 	if {[$myproject trunkonly]} {
 	    $self ExcludeNonTrunkInformation
 	}
+
+	$self AggregateSymbolData
 	return
     }
 
     # # ## ### ##### ######## #############
     ## State
@@ -1022,10 +1025,64 @@
 		set root [$root child]
 	    }
 	}
 
 	return [list [lsort -unique -dict $revisions] [lsort -unique -dict $symbols]]
+    }
+
+
+    method AggregateSymbolData {} {
+	# Now that the exact set of revisions (and through that
+	# branches and tags) is known we can update the aggregate
+	# symbol statistics.
+
+	foreach root [$self LinesOfDevelopment] {
+	    set lod [$root lod]
+
+	    # Note: If the LOD is the trunk the count*, etc. methods
+	    # will do nothing, as it is always present (cannot be
+	    # excluded), and is always a branch too.
+
+	    # Lines of development count as branches and have a commit
+	    # on them (root). If they are still attached to a tree we
+	    # have to compute and register possible parents.
+
+	    $lod countasbranch
+	    $lod countacommit
+
+	    if {[$root hasparentbranch]} {
+		# Note lod == [$root parentbranch]
+		$lod possibleparents
+	    }
+
+	    # For the revisions in the line we register their branches
+	    # and tags as blockers for the lod, and update the type
+	    # counters as well. As branch symbols without commits on
+	    # them are not listed as lines of development, we have to
+	    # count them here as well, as plain branches. At last we
+	    # have to compute and register the possible parents of the
+	    # tags, in case they are later converted as branches.
+
+	    while {$root ne ""} {
+		foreach branch [$root branches] {
+		    $lod blockedby $branch
+		    $branch possibleparents
+		    if {[$branch haschild]} continue
+		    $branch countasbranch
+		}
+
+		foreach tag [$root tags] {
+		    $lod blockedby $tag
+		    $tag possibleparents
+		    $tag countastag
+		}
+
+		set root [$root child]
+	    }
+	}
+
+	return
     }
 
     # # ## ### ##### ######## #############
     ## Configuration
 

Modified tools/cvs2fossil/lib/c2f_fsym.tcl from [ce3e976f91] to [605873f19e].

@@ -45,16 +45,72 @@
     method defid {} {
 	set myid [incr myidcounter]
 	return
     }
 
-    method fid {} { return $myid }
+    method fid    {} { return $myid     }
+    method symbol {} { return $mysymbol }
 
     # Symbol acessor methods.
 
     delegate method name to mysymbol
     delegate method id   to mysymbol
+
+    # Symbol aggregation methods
+
+    delegate method countasbranch to mysymbol
+    delegate method countastag    to mysymbol
+    delegate method countacommit  to mysymbol
+
+    method blockedby {fsymbol} {
+	$mysymbol blockedby [$fsymbol symbol]
+	return
+    }
+
+    method possibleparents {} {
+	switch -exact -- $mytype {
+	    branch { $self BranchParents }
+	    tag    { $self TagParents    }
+	}
+	return
+    }
+
+    method BranchParents {} {
+	# The "obvious" parent of a branch is the branch holding the
+	# revision spawning the branch. Any other branches that are
+	# rooted at the same revision and were committed earlier than
+	# the branch are also possible parents.
+
+	$mysymbol possibleparent [[$mybranchparent lod] symbol]
+
+	foreach branch [$mybranchparent branches] {
+	    # A branch cannot be its own parent. Nor can a branch
+	    # created after this one be its parent. This means that we
+	    # can abort the loop when we have reached ourselves in the
+	    # list of branches. Here the order of file::rev.mybranches
+	    # comes into play, as created by file::rev::sortbranches.
+
+	    if {$branch eq $self} break
+	    $mysymbol possibleparent [$branch symbol]
+	}
+	return
+    }
+
+    method TagParents {} {
+	# The "obvious" parent of a tag is the branch holding the
+	# revision spawning the tag. Branches that are spawned by the
+	# same revision are also possible parents.
+
+	$mysymbol possibleparent [[$mytagrev lod] symbol]
+
+	foreach branch [$mytagrev branches] {
+	    $mysymbol possibleparent [$branch symbol]
+	}
+	return
+    }
+
+    #
 
     method istrunk {} { return 0 }
 
     # Branch acessor methods.
 
@@ -75,11 +131,10 @@
     method haschildrev {} { return [expr {$mybranchchildrevnr ne ""}] }
     method haschild    {} { return [expr {$mybranchchild ne ""}] }
     method parent      {} { return $mybranchparent }
     method child       {} { return $mybranchchild }
     method position    {} { return $mybranchposition }
-
 
     # Tag acessor methods.
 
     method tagrevnr  {}    { return $mynr }
     method settagrev {rev} {set mytagrev $rev ; return }

Modified tools/cvs2fossil/lib/c2f_pcollrev.tcl from [46bf84e9d5] to [e14d8add6b].

@@ -186,18 +186,25 @@
 
 	    UNIQUE (pid, name) -- Symbols are unique within the project
 	}
 
 	state writing blocker {
+	    -- For each symbol we save which other symbols are
+	    -- blocking its removal (if the user asks for it).
+
 	    sid INTEGER  NOT NULL  REFERENCES symbol, --
 	    bid INTEGER  NOT NULL  REFERENCES symbol, -- Sprouted from sid, blocks it.
 	    UNIQUE (sid, bid)
 	}
 
 	state writing parent {
+	    -- For each symbol we save which other symbols can act as
+	    -- a possible parent in some file, and how often.
+
 	    sid INTEGER  NOT NULL  REFERENCES symbol, --
 	    pid INTEGER  NOT NULL  REFERENCES symbol, -- Possible parent of sid
+	    n   INTEGER  NOT NULL,                    -- How often pid can act as parent.
 	    UNIQUE (sid, pid)
 	}
 
 	state writing meta {
 	    -- Meta data of revisions. See revision.mid for the
@@ -283,10 +290,12 @@
 		    $file persist
 		}
 
 		$file drop
 	    }
+
+	    $project purgeghostsymbols
 	}
 
 	repository printrevstatistics
 	repository persistrev
 
@@ -312,11 +321,11 @@
 	return
     }
 
     proc Paranoia {} {
 	# This code performs a number of paranoid checks of the
-	# database for inconsistent cross-references.
+	# database, searching for inconsistent cross-references.
 	log write 4 collrev {Check database consistency}
 
 	set n 0 ; # Counter for the checks (we print an id before the
 		  # main label).
 

Modified tools/cvs2fossil/lib/c2f_project.tcl from [00f1aee876] to [95678098d7].

@@ -19,10 +19,11 @@
 package require snit                                    ; # OO system.
 package require vc::fossil::import::cvs::file           ; # CVS archive file.
 package require vc::fossil::import::cvs::state          ; # State storage.
 package require vc::fossil::import::cvs::project::sym   ; # Per project symbols.
 package require vc::fossil::import::cvs::project::trunk ; # Per project trunk, main lod
+package require vc::tools::log                          ; # User feedback
 package require struct::list                            ; # Advanced list operations..
 
 # # ## ### ##### ######## ############# #####################
 ##
 
@@ -32,10 +33,11 @@
 
     constructor {path r} {
 	set mybase       $path
 	set myrepository $r
 	set mytrunk      [trunk %AUTO% $self]
+	set mysymbol([$mytrunk name]) $mytrunk
 	return
     }
 
     method base  {} { return $mybase  }
     method trunk {} { return $mytrunk }
@@ -74,10 +76,25 @@
 	if {![info exists mysymbol($name)]} {
 	    set mysymbol($name) \
 		[sym %AUTO% $name [$myrepository defsymbol $myid $name] $self]
 	}
 	return $mysymbol($name)
+    }
+
+    method purgeghostsymbols {} {
+	set changes 1
+	while {$changes} {
+	    set changes 0
+	    foreach {name symbol} [array get mysymbol] {
+		if {![$symbol isghost]} continue
+		log write 3 project "$mybase: Deleting ghost symbol '$name'"
+		$symbol destroy
+		unset mysymbol($name)
+		set changes 1
+	    }
+	}
+	return
     }
 
     # pass I persistence
     method persist {} {
 	TheFiles ; # Force id assignment.
@@ -177,10 +194,11 @@
 }
 
 namespace eval ::vc::fossil::import::cvs {
     namespace export project
     namespace eval project {
+	namespace import ::vc::tools::log
 	namespace import ::vc::fossil::import::cvs::file
 	namespace import ::vc::fossil::import::cvs::state
 	# Import not required, already a child namespace.
 	# namespace import ::vc::fossil::import::cvs::project::sym
     }

Modified tools/cvs2fossil/lib/c2f_psym.tcl from [6432e54926] to [ec9334ebb7].

@@ -15,10 +15,11 @@
 # # ## ### ##### ######## ############# #####################
 ## Requirements
 
 package require Tcl 8.4                                 ; # Required runtime.
 package require snit                                    ; # OO system.
+package require struct::set                             ; # Set handling.
 package require vc::fossil::import::cvs::state          ; # State storage.
 
 # # ## ### ##### ######## ############# #####################
 ##
 
@@ -35,22 +36,68 @@
 
     method name {} { return $myname }
     method id   {} { return $myid   }
 
     # # ## ### ##### ######## #############
+    ## Symbol statistics
+
+    method countasbranch {} { incr mybranchcount ; return }
+    method countastag    {} { incr mytagcount    ; return }
+    method countacommit  {} { incr mycommitcount ; return }
+
+    method blockedby {symbol} {
+	# Remember the symbol as preventing the removal of this
+	# symbol. Ot is a tag or branch that spawned from a revision
+	# on this symbol.
+
+	struct::set include myblockers $symbol
+	return
+    }
+
+    method possibleparent {symbol} {
+	if {[info exists mypparent($symbol)]} {
+	    incr mypparent($symbol)
+	} else {
+	    set  mypparent($symbol) 1
+	}
+	return
+    }
+
+    method isghost {} {
+	# Checks if this symbol (as line of development) never
+	# existed.
+
+	if {$mycommitcount > 0}         { return 0 }
+	if {[llength $myblockers]}      { return 0 }
+	if {[array size mypparent] > 0} { return 0 }
+
+	return 1
+    }
+
+    # # ## ### ##### ######## #############
 
     method persistrev {} {
 	set pid [$myproject id]
 
-	# TODO: Compute the various counts. All the necessary
-	# TODO: information is already in the database. Actually it
-	# TODO: never was in memory.
-
 	state transaction {
 	    state run {
-		INSERT INTO symbol ( sid,   pid,  name,   type,     tag_count, branch_count, commit_count)
-		VALUES             ($myid, $pid, $myname, $myundef, 0,         0,            0);
+		INSERT INTO symbol ( sid,   pid,  name,   type,     tag_count,   branch_count,   commit_count)
+		VALUES             ($myid, $pid, $myname, $myundef, $mytagcount, $mybranchcount, $mycommitcount);
+	    }
+	    foreach symbol $myblockers {
+		set bid [$symbol id]
+		state run {
+		    INSERT INTO blocker (sid,   bid)
+		    VALUES              ($myid, $bid);
+		}
+	    }
+	    foreach {symbol count} [array get mypparent] {
+		set pid [$symbol id]
+		state run {
+		    INSERT INTO parent (sid,   pid,  n)
+		    VALUES             ($myid, $pid, $count);
+		}
 	    }
 	}
 	return
     }
 
@@ -61,10 +108,21 @@
 			    # containing the symbol.
     variable myname    {} ; # The symbol's name
     variable myid      {} ; # Repository wide numeric id of the
 			    # symbol. This implicitly encodes the
 			    # project as well.
+
+    variable mybranchcount 0 ; # Count how many uses as branch.
+    variable mytagcount    0 ; # Count how many uses as tag.
+    variable mycommitcount 0 ; # Count how many files did a commit on the symbol.
+
+    variable myblockers   {} ; # List (Set) of the symbols which block
+			       # the exclusion of this symbol.
+
+    variable mypparent -array {} ; # Maps from symbols to the number
+				   # of files in which it could have
+				   # been a parent of this symbol.
 
     typevariable mytag    1 ; # Code for symbols which are tags.
     typevariable mybranch 2 ; # Code for symbols which are branches.
     typevariable myundef  3 ; # Code for symbols of unknown type.
 

Modified tools/cvs2fossil/lib/c2f_ptrunk.tcl from [186b2dcb0d] to [7dec41a873].

@@ -24,23 +24,41 @@
 snit::type ::vc::fossil::import::cvs::project::trunk {
     # # ## ### ##### ######## #############
     ## Public API
 
     constructor {project} {
-	set myid [[$project getsymbol $myname] id]
+	set mysymbol [$project getsymbol $myname]
+	set myid     [$mysymbol id]
 	return
+    }
+
+    destructor {
+	$mysymbol destroy
     }
 
     method name    {} { return $myname }
     method id      {} { return $myid   }
     method istrunk {} { return 1 }
+    method symbol  {} { return $self }
+
+    method countasbranch {} {}
+    method countastag    {} {}
+    method countacommit  {} {}
+
+    method blockedby      {symbol} {}
+    method possibleparent {symbol} {}
+
+    method isghost {} { return 0 }
+
+    delegate method persistrev to mysymbol
 
     # # ## ### ##### ######## #############
     ## State
 
-    typevariable myname :trunk: ; # Name shared by all trunk symbols.
-    variable     myid   {}      ; # The trunk's symbol id.
+    typevariable myname   :trunk: ; # Name shared by all trunk symbols.
+    variable     myid     {}      ; # The trunk's symbol id.
+    variable     mysymbol {}      ; # The symbol underneath the trunk.
 
     # # ## ### ##### ######## #############
     ## Internal methods
 
     # # ## ### ##### ######## #############
@@ -47,11 +65,10 @@
     ## Configuration
 
     pragma -hastypeinfo    no  ; # no type introspection
     pragma -hasinfo        no  ; # no object introspection
     pragma -hastypemethods no  ; # type is not relevant.
-    pragma -simpledispatch yes ; # simple fast dispatch
 
     # # ## ### ##### ######## #############
 }
 
 namespace eval ::vc::fossil::import::cvs::project {