Check-in [131f051880]
Not logged in
Overview

SHA1 Hash:131f0518802152fa2842d773b4470282800dd8ad
Date: 2007-11-09 06:28:19
User: aku
Comment:Moved the paranoid integrity checks of pass 2 into a separate package for use by other passes, and changed pass 4 to also run these checks, albeit in a (slightly) relaxed form. See the comments at the point of call for the reason. This completes pass 4.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Added tools/cvs2fossil/lib/c2f_integrity.tcl version [f5cf3c5637]

@@ -1,1 +1,321 @@
+## -*- tcl -*-
+# # ## ### ##### ######## ############# #####################
+## Copyright (c) 2007 Andreas Kupries.
+#
+# This software is licensed as described in the file LICENSE, which
+# you should have received as part of this distribution.
+#
+# This software consists of voluntary contributions made by many
+# individuals.  For exact contribution history, see the revision
+# history and logs, available at http://fossil-scm.hwaci.com/fossil
+# # ## ### ##### ######## ############# #####################
+
+## This package holds a number of integrity checks done on the
+## persistent state. This is used by the passes II and IV.
+
+# # ## ### ##### ######## ############# #####################
+## Requirements
+
+package require Tcl 8.4                               ; # Required runtime.
+package require snit                                  ; # OO system.
+package require vc::tools::trouble                    ; # Error reporting.
+package require vc::tools::log                        ; # User feedback.
+package require vc::fossil::import::cvs::state        ; # State storage.
+
+# # ## ### ##### ######## ############# #####################
+##
+
+snit::type ::vc::fossil::import::cvs::integrity {
+    # # ## ### ##### ######## #############
+    ## Public API
+
+    typemethod strict {} {
+	set n 0
+	AllButMeta
+	Meta
+	return
+    }
+
+    typemethod metarelaxed {} {
+	set n 0
+	AllButMeta
+	return
+    }
+
+    # # ## ### ##### ######## #############
+    ## Internal methods
+
+    proc AllButMeta {} {
+	# This code performs a number of paranoid checks of the
+	# database, searching for inconsistent cross-references.
+	log write 4 integrity {Check database consistency}
+
+	upvar 1 n n ; # Counter for the checks (we print an id before
+		      # the main label).
+
+	# Find all revisions which disagree with their line of
+	# development about the project they are owned by.
+	Check \
+	    {Revisions and their LODs have to be in the same project} \
+	    {disagrees with its LOD about owning project} {
+		SELECT F.name, R.rev
+		FROM revision R, file F, symbol S
+		WHERE R.fid = F.fid
+		AND   R.lod = S.sid
+		AND   F.pid != S.pid
+		;
+	    }
+	# Find all revisions which disgree with their meta data about
+	# the project they are owned by.
+	Check \
+	    {Revisions and their meta data have to be in the same project} \
+	    {disagrees with its meta data about owning project} {
+		SELECT F.name, R.rev
+		FROM revision R, file F, meta M
+		WHERE R.fid = F.fid
+		AND   R.mid = M.mid
+		AND   F.pid != M.pid
+		;
+	    }
+	# Find all revisions with a primary child which disagrees
+	# about the file they belong to.
+	Check \
+	    {Revisions and their primary children have to be in the same file} \
+	    {disagrees with its primary child about the owning file} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.child IS NOT NULL
+		AND   R.child = C.rid
+		AND   C.fid != R.fid
+		;
+	    }
+
+	# Find all revisions with a branch parent symbol whose parent
+	# disagrees about the file they belong to.
+	Check \
+	    {Revisions and their branch children have to be in the same file} \
+	    {at the beginning of its branch and its parent disagree about the owning file} {
+		SELECT F.name, R.rev
+		FROM revision R, revision P, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NOT NULL
+		AND   R.parent = P.rid
+		AND   R.fid != P.fid
+		;
+	    }
+	# Find all revisions with a non-NTDB child which disagrees
+	# about the file they belong to.
+	Check \
+	    {Revisions and their non-NTDB children have to be in the same file} \
+	    {disagrees with its non-NTDB child about the owning file} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.dbchild IS NOT NULL
+		AND   R.dbchild = C.rid
+		AND   C.fid != R.fid
+		;
+	    }
+	# Find all revisions which have a primary child, but the child
+	# does not have them as parent.
+	Check \
+	    {Revisions have to be parents of their primary children} \
+	    {is not the parent of its primary child} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.child IS NOT NULL
+		AND   R.child = C.rid
+		AND   C.parent != R.rid
+		;
+	    }
+	# Find all revisions which have a primrary child, but the
+	# child has a branch parent symbol making them brach starters.
+	Check \
+	    {Primary children of revisions must not start branches} \
+	    {is parent of a primary child which is the beginning of a branch} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.child IS NOT NULL
+		AND   R.child = C.rid
+		AND   C.bparent IS NOT NULL
+		;
+	    }
+	# Find all revisions without branch parent symbol which have a
+	# parent, but the parent does not have them as primary child.
+	Check \
+	    {Revisions have to be primary children of their parents, if any} \
+	    {is not the child of its parent} {
+		SELECT F.name, R.rev
+		FROM revision R, revision P, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NULL
+		AND   R.parent IS NOT NULL
+		AND   R.parent = P.rid
+		AND   P.child != R.rid
+		;
+	    }
+	# Find all revisions with a branch parent symbol which do not
+	# have a parent.
+	Check \
+	    {Branch starting revisions have to have a parent} \
+	    {at the beginning of its branch has no parent} {
+		SELECT F.name, R.rev
+		FROM revision R, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NOT NULL
+		AND   R.parent IS NULL
+		;
+	    }
+	# Find all revisions with a branch parent symbol whose parent
+	# has them as primary child.
+	Check \
+	    {Branch starting revisions must not be primary children of their parents} \
+	    {at the beginning of its branch is the primary child of its parent} {
+		SELECT F.name, R.rev
+		FROM revision R, revision P, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NOT NULL
+		AND   R.parent IS NOT NULL
+		AND   R.parent = P.rid
+		AND   P.child = R.rid
+		;
+	    }
+	# Find all revisions with a non-NTDB child which are not on
+	# the NTDB.
+	Check \
+	    {NTDB to trunk transition has to begin on NTDB} \
+	    {has a non-NTDB child, yet is not on the NTDB} {
+		SELECT F.name, R.rev
+		FROM revision R, file F
+		WHERE R.fid = F.fid
+		AND   R.dbchild IS NOT NULL
+		AND   NOT R.isdefault
+		;
+	    }
+	# Find all revisions with a NTDB parent which are on the NTDB.
+	Check \
+	    {NTDB to trunk transition has to end on non-NTDB} \
+	    {has a NTDB parent, yet is on the NTDB} {
+		SELECT F.name, R.rev
+		FROM revision R, file F
+		WHERE R.fid = F.fid
+		AND   R.dbparent IS NOT NULL
+		AND   R.isdefault
+		;
+	    }
+	# Find all revisions with a child which disagrees about the
+	# line of development they belong to.
+	Check \
+	    {Revisions and their primary children have to be in the same LOD} \
+	    {and its primary child disagree about their LOD} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.child IS NOT NULL
+		AND   R.child = C.rid
+		AND   C.lod != R.lod
+		;
+	    }
+	# Find all revisions with a non-NTDB child which agrees about
+	# the line of development they belong to.
+	Check \
+	    {NTDB and trunk revisions have to be in different LODs} \
+	    {on NTDB and its non-NTDB child wrongly agree about their LOD} {
+		SELECT F.name, R.rev
+		FROM revision R, revision C, file F
+		WHERE R.fid = F.fid
+		AND   R.dbchild IS NOT NULL
+		AND   R.dbchild = C.rid
+		AND   C.lod = R.lod
+		;
+	    }
+	# Find all revisions with a branch parent symbol which is not
+	# their LOD.
+	Check \
+	    {Branch starting revisions have to have their LOD as branch parent symbol} \
+	    {at the beginning of its branch does not have the branch symbol as its LOD} {
+		SELECT F.name, R.rev
+		FROM revision R, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NOT NULL
+		AND   R.lod != R.bparent
+		;
+	    }
+	# Find all revisions with a branch parent symbol whose parent
+	# is in the same line of development.
+	Check \
+	    {Revisions and their branch children have to be in different LODs} \
+	    {at the beginning of its branch and its parent wrongly agree about their LOD} {
+		SELECT F.name, R.rev
+		FROM revision R, revision P, file F
+		WHERE R.fid = F.fid
+		AND   R.bparent IS NOT NULL
+		AND   R.parent = P.rid
+		AND   R.lod = P.lod
+		;
+	    }
+	return
+    }
+
+    proc Meta {} {
+	# This code performs a number of paranoid checks of the
+	# database, searching for inconsistent cross-references.
+	log write 4 integrity {Check database consistency}
+
+	upvar 1 n n ; # Counter for the checks (we print an id before
+		      # the main label).
+
+	# Find all revisions which disgree with their meta data about
+	# the branch/line of development they belong to.
+	Check \
+	    {Revisions and their meta data have to be in the same LOD} \
+	    {disagrees with its meta data about owning LOD} {
+		SELECT F.name, R.rev
+		FROM revision R, meta M, file F
+		WHERE R.mid = M.mid
+		AND   R.lod != M.bid
+		AND   R.fid = F.fid
+		;
+	    }
+	return
+    }
+
+    proc Check {header label sql} {
+	upvar 1 n n
+	set ok 1
+	foreach {fname revnr} [state run $sql] {
+	    set ok 0
+	    trouble fatal "$fname <$revnr> $label"
+	}
+	log write 5 integrity "\[[format %02d [incr n]]\] [expr {$ok ? "Ok    " : "Failed"}] ... $header"
+	return
+    }
+
+    # # ## ### ##### ######## #############
+    ## Configuration
+
+    pragma -hasinstances   no ; # singleton
+    pragma -hastypeinfo    no ; # no introspection
+    pragma -hastypedestroy no ; # immortal
+
+    # # ## ### ##### ######## #############
+}
+
+namespace eval ::vc::fossil::import::cvs {
+    namespace export integrity
+    namespace eval integrity {
+	namespace import ::vc::fossil::import::cvs::state
+	namespace import ::vc::tools::trouble
+	namespace import ::vc::tools::log
+	log register integrity
+    }
+}
+
+# # ## ### ##### ######## ############# #####################
+## Ready
 
+package provide vc::fossil::import::cvs::integrity 1.0
+return

Modified tools/cvs2fossil/lib/c2f_pcollrev.tcl from [3d675ee00a] to [978a2b3f74].

@@ -21,10 +21,11 @@
 package require vc::tools::trouble                    ; # Error reporting.
 package require vc::tools::log                        ; # User feedback.
 package require vc::fossil::import::cvs::pass         ; # Pass management.
 package require vc::fossil::import::cvs::repository   ; # Repository management.
 package require vc::fossil::import::cvs::state        ; # State storage.
+package require vc::fossil::import::cvs::integrity    ; # State integrity checks.
 package require vc::fossil::import::cvs::project::sym ; # Project level symbols.
 package require vc::fossil::import::cvs::file::rev    ; # File level revisions.
 package require vc::rcs::parser                       ; # Rcs archive data extraction.
 
 # # ## ### ##### ######## ############# #####################
@@ -327,12 +328,12 @@
 	    $project purgeghostsymbols
 	}
 
 	repository printrevstatistics
 	repository persistrev
-
-	Paranoia
+	integrity  strict
+
 	log write 1 collrev "Scan completed"
 	return
     }
 
     typemethod discard {} {
@@ -608,10 +609,11 @@
     namespace export collrev
     namespace eval collrev {
 	namespace import ::vc::rcs::parser
 	namespace import ::vc::fossil::import::cvs::repository
 	namespace import ::vc::fossil::import::cvs::state
+	namespace import ::vc::fossil::import::cvs::integrity
 	namespace eval project {
 	    namespace import ::vc::fossil::import::cvs::project::sym
 	}
 	namespace eval file {
 	    namespace import ::vc::fossil::import::cvs::file::rev

Modified tools/cvs2fossil/lib/c2f_pfiltersym.tcl from [3dc3d0fe9b] to [53988122b9].

@@ -20,10 +20,11 @@
 package require Tcl 8.4                               ; # Required runtime.
 package require snit                                  ; # OO system.
 package require vc::tools::misc                       ; # Text formatting.
 package require vc::tools::log                        ; # User feedback.
 package require vc::fossil::import::cvs::state        ; # State storage.
+package require vc::fossil::import::cvs::integrity    ; # State storage integrity checks.
 package require vc::fossil::import::cvs::project::sym ; # Project level symbols
 
 # # ## ### ##### ######## ############# #####################
 ## Register the pass with the management
 
@@ -79,11 +80,23 @@
 	    FilterExcludedSymbols
 	    MutateSymbols
 	    AdjustParents
 	    RefineSymbols
 
-	    # Consider a rerun of the pass 2 paranoia checks.
+	    # Strict integrity enforces that all meta entries are in
+	    # the same LOD as the revision using them. At this point
+	    # this may not be true any longer. If a NTDB was excluded
+	    # then all revisions it shared with the trunk were moved
+	    # to the trunk LOD, however their meta entries will still
+	    # refer to the now gone LOD symbol. This is fine however,
+	    # it will not affect our ability to use the meta entries
+	    # to distinguish and group revisions into changesets. It
+	    # should be noted that we cannot simply switch the meta
+	    # entries over to the trunk either, as that may cause the
+	    # modified entries to violate the unique-ness constrain
+	    # set on that table.
+	    integrity metarelaxed
 	}
 
 	log write 1 filtersym "Filtering completed"
 	return
     }
@@ -478,10 +491,11 @@
 
 namespace eval ::vc::fossil::import::cvs::pass {
     namespace export filtersym
     namespace eval filtersym {
 	namespace import ::vc::fossil::import::cvs::state
+	namespace import ::vc::fossil::import::cvs::integrity
 	namespace eval project {
 	    namespace import ::vc::fossil::import::cvs::project::sym
 	}
 	namespace import ::vc::tools::misc::nsp
 	namespace import ::vc::tools::log

Modified tools/cvs2fossil/lib/pkgIndex.tcl from [d11a0332fc] to [9cd7a5dc5f].

@@ -8,10 +8,11 @@
 package ifneeded vc::fossil::import::cvs::file::lodmgr    1.0 [list source [file join $dir c2f_flodmgr.tcl]]
 package ifneeded vc::fossil::import::cvs::file::rev       1.0 [list source [file join $dir c2f_frev.tcl]]
 package ifneeded vc::fossil::import::cvs::file::sym       1.0 [list source [file join $dir c2f_fsym.tcl]]
 package ifneeded vc::fossil::import::cvs::file::trunk     1.0 [list source [file join $dir c2f_ftrunk.tcl]]
 package ifneeded vc::fossil::import::cvs::option          1.0 [list source [file join $dir c2f_option.tcl]]
+package ifneeded vc::fossil::import::cvs::integrity       1.0 [list source [file join $dir c2f_integrity.tcl]]
 package ifneeded vc::fossil::import::cvs::pass            1.0 [list source [file join $dir c2f_pass.tcl]]
 package ifneeded vc::fossil::import::cvs::pass::collar    1.0 [list source [file join $dir c2f_pcollar.tcl]]
 package ifneeded vc::fossil::import::cvs::pass::collrev   1.0 [list source [file join $dir c2f_pcollrev.tcl]]
 package ifneeded vc::fossil::import::cvs::pass::collsym   1.0 [list source [file join $dir c2f_pcollsym.tcl]]
 package ifneeded vc::fossil::import::cvs::pass::filtersym 1.0 [list source [file join $dir c2f_pfiltersym.tcl]]