Check-in [1593006ef3]
Not logged in
Overview

SHA1 Hash:1593006ef37f4dcc677860ad9185acd609bf6288
Date: 2007-09-17 03:03:25
User: aku
Comment:More structuring of the CVS backend, encapsulated the management of the global timeline of events in the project in a separate package.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified tools/lib/cvs.tcl from [a7a859e048] to [57072982aa].

@@ -3,15 +3,16 @@
 
 # -----------------------------------------------------------------------------
 # Requirements
 
 package require Tcl 8.4
-package require fileutil           ; # Tcllib (traverse directory hierarchy)
-package require vc::rcs::parser    ; # Handling the RCS archive files.
-package require vc::tools::log     ; # User feedback
-package require vc::cvs::cmd       ; # Access to cvs application.
-package require vc::cvs::ws::files ; # Scan CVS repository for relevant files.
+package require fileutil              ; # Tcllib (traverse directory hierarchy)
+package require vc::rcs::parser       ; # Handling the RCS archive files.
+package require vc::tools::log        ; # User feedback
+package require vc::cvs::cmd          ; # Access to cvs application.
+package require vc::cvs::ws::files    ; # Scan CVS repository for relevant files.
+package require vc::cvs::ws::timeline ; # Manage timeline of all changes.
 package require struct::tree
 
 namespace eval ::vc::cvs::ws {
     vc::tools::log::system cvs
     namespace import ::vc::tools::log::write
@@ -68,26 +69,18 @@
     return 1
 }
 
 proc ::vc::cvs::ws::begin {src} {
     variable project
-    variable base
 
     set src [file normalize $src]
-    if {![check $src msg]} {
-	return -code error $msg
-    }
-    set base $src
-    write 0 cvs "Base:    $base"
-    if {$project eq ""} {
-	write 0 cvs "Project: <ALL>"
-    } else {
-	write 0 cvs "Project: $project"
-    }
-
-    # OLD api calls ... TODO rework for more structure ...
-    scan     ; # Gather revision data from the archives
+    if {![check $src msg]} { return -code error $msg }
+
+    DefBase $src
+    MakeTimeline [ScanArchives [files::find [RootPath]]]
+
+    # OLD api calls ... TODO rework for more structure ...
     csets    ; # Group changes into sets
     rtree    ; # Build revision tree (trunk only right now).
 
     set w [workspace]   ; # OLD api ... TODO inline
     if {$project ne ""} {
@@ -140,65 +133,101 @@
 }
 
 # -----------------------------------------------------------------------------
 # Internals - Old API for now.
 
+proc ::vc::cvs::ws::DefBase {path} {
+    variable project
+    variable base
+
+    set base $path
+
+    write 0 cvs "Base:    $base"
+    if {$project eq ""} {
+	write 0 cvs "Project: <ALL>"
+    } else {
+	write 0 cvs "Project: $project"
+    }
+    return
+}
+
+proc ::vc::cvs::ws::RootPath {} {
+    variable project
+    variable base
+
+    if {$project eq ""} {
+	return $base
+    } else {
+	return $base/$project
+    }
+}
+
 # Scan repository, collect archives, parse them, and collect revision
 # information (file, revision -> date, author, commit message)
 
-proc ::vc::cvs::ws::scan {} {
-    variable project
-    variable base
-    variable timeline
-
-    set n 0
-    set d $base ; if {$project ne ""} {append d /$project}
-
-    set files [::vc::cvs::ws::files::find $d]
-
+proc ::vc::cvs::ws::ScanArchives {files} {
     write 0 cvs "Scanning archives ..."
+
+    set d [RootPath]
+    set r {}
+    set n 0
 
     ::foreach {rcs f} $files {
 	write 1 cvs "Archive $rcs"
-
 	# Get the meta data we need (revisions, timeline, messages).
-	set meta [process $d/$rcs]
-
-	array set p $meta
-
-	::foreach {rev ts} $p(date) {_ a} $p(author) {_ cm} $p(commit) {_ st} $p(state) {
-	    set op [expr {($rev eq "1.1") ? "A" : "M"}]
-	    if {$st eq "dead"} {set op "R"}
-
-	    # A dead-first revision is rev 1.1 with op R. For an
-	    # example see the file memchan/DEPENDENCIES. Such a file
-	    # seems to exist only! on its branch. The branches
-	    # information is set on the revision (extend rcsparser!),
-	    # symbols has a tag, refering to a branch, possibly magic.
-
-	    if {($rev eq "1.1") && ($op eq "R")} {
-		write 2 cvs {Dead root revision}
-	    }
-
-	    lappend timeline($ts) [list $op $ts $a $rev $f $cm]
+	lappend r $f [process $d/$rcs]
+	incr    n
+    }
+
+    write 0 cvs "Processed [NSIPL $n file]"
+    return $r
+}
+
+proc ::vc::cvs::ws::MakeTimeline {meta} {
+    write 0 cvs "Generating coalesced timeline ..."
+
+    set n 0
+    ::foreach {f meta} $meta {
+	array set md   $meta
+	array set date $md(date)
+	array set auth $md(author)
+	array set cmsg $md(commit)
+	array set stat $md(state)
+
+	::foreach rev [lsort -dict [array names date]] {
+	    set operation [Operation $rev $stat($rev)]
+	    NoteDeadRoots $f $rev $operation
+	    timeline::add $date($rev) $f $rev $operation $auth($rev) $cmsg($rev)
+	    incr n
 	}
-
-	#unset p(commit)
-	#parray p
-
-	incr n
+	#B Extend branch management
     }
 
-    write 0 cvs "Processed $n [expr {($n == 1) ? "file" : "files"}]"
+    write 0 cvs "Generated [NSIPL $n entry entries]"
+    return
+}
+
+proc ::vc::cvs::ws::NoteDeadRoots {f rev operation} {
+    # A dead-first revision is rev 1.1 with op R. For an example see
+    # the file memchan/DEPENDENCIES. Such a file seems to exist only!
+    # on its branch. The branches information is set on the revision
+    # (extend rcsparser!), symbols has a tag, refering to a branch,
+    # possibly magic.
+
+    if {($rev eq "1.1") && ($operation eq "R")} {
+	write 2 cvs "Dead root revision: $f"
+    }
     return
 }
 
-namespace eval ::vc::cvs::ws {
-    # Timeline: tstamp -> (op, tstamp, author, revision, file, commit message)
-
-    variable timeline ; array set timeline {}
-}
+proc ::vc::cvs::ws::Operation {rev state} {
+    if {$state eq "dead"} {return "R"} ; # Removed
+    if {$rev   eq "1.1"}  {return "A"} ; # Added
+    return "M"                         ; # Modified
+}
+
+
 
 # Group single changes into changesets
 
 proc ::vc::cvs::ws::csets {} {
     variable timeline
@@ -208,38 +237,25 @@
 
     array unset csets * ; array set csets {}
     array unset cmap  * ; array set cmap  {}
     set ncs 0
 
-    write 0 cvs "Processing timeline"
-
-    set n 0
+    write 0 cvs "Generating changesets from timeline"
+
     CSClear
-    ::foreach ts [lsort -dict [array names timeline]] {
-
-	# op tstamp author revision file commit
-	# 0  1      2      3        4    5/end
-	# b         c                    a
-
-	set entries [lsort -index 2 [lsort -index 0 [lsort -index end $timeline($ts)]]]
-	#puts [join $entries \n]
-
-	::foreach entry  $entries {
-	    if {![CSNone] && [CSNew $entry]} {
-		CSSave
-		CSClear
-		#puts ==\n$reason
-	    }
-	    CSAdd $entry
-	    incr n
+    timeline::foreach date file revision operation author cmsg {
+	# API adaption
+	set entry [list $operation $date $author $revision $file $cmsg]
+
+	if {![CSNone] && [CSNew $entry]} {
+	    CSSave
+	    CSClear
 	}
+	CSAdd $entry
     }
 
-    write 0 cvs "Processed $n [expr {($n == 1) ? "entry" : "entries"}]"
-
-    set n [array size csets]
-    write 0 cvs "Found     $n [expr {($n == 1) ? "changeset" : "changesets"}]"
+    write 0 cvs "Found [NSIPL [array size csets] changeset]"
     return
 }
 
 
 namespace eval ::vc::cvs::ws {
@@ -506,10 +522,19 @@
     ::foreach {f or} $f {
 	::foreach {o r} $or break
 	puts "$b $o $f $r"
     }
     return
+}
+
+proc ::vc::cvs::ws::NSIPL {n singular {plural {}}} {
+    return "$n [SIPL $n $singular $plural]"
+}
+proc ::vc::cvs::ws::SIPL {n singular {plural {}}} {
+    if {$n == 1} {return $singular}
+    if {$plural eq ""} {set plural ${singular}s}
+    return $plural
 }
 
 # -----------------------------------------------------------------------------
 
 namespace eval ::vc::cvs::ws {

Modified tools/lib/cvs_files.tcl from [605edf3ab3] to [24c1271ded].

@@ -9,11 +9,10 @@
 package require vc::tools::log     ; # User feedback
 
 namespace eval ::vc::cvs::ws::files {
     namespace import ::vc::tools::log::write
     namespace import ::vc::tools::log::progress
-    namespace import ::vc::tools::log::verbosity?
 }
 
 # -----------------------------------------------------------------------------
 # API
 

Added tools/lib/cvs_timeline.tcl version [24ba5c2cd7]

@@ -1,1 +1,85 @@
+# -----------------------------------------------------------------------------
+# Repository management (CVS), timeline of events.
+
+# -----------------------------------------------------------------------------
+# Requirements
+
+package require Tcl 8.4
+
+namespace eval ::vc::cvs::ws::timeline {}
+
+# -----------------------------------------------------------------------------
+# API
+
+# vc::cvs::ws::timeline::add     date file revision operation author commit-msg
+# vc::cvs::ws::timeline::foreach date file revision operation author commit-msg script
+
+# Add entries to the timeline, and iterate over the timeline in proper order.
+
+# -----------------------------------------------------------------------------
+# API Implementation
+
+proc ::vc::cvs::ws::timeline::add {date file revision operation author cmsg} {
+    variable timeline
+    lappend timeline($date) [list $file $revision $operation $author $cmsg]
+    return
+}
+
+proc ::vc::cvs::ws::timeline::foreach {dv fv rv ov av cv script} {
+    upvar 1 $dv date $fv file $rv revision $ov operation $av author $cv cmsg
+    variable timeline
+
+    ::foreach date [lsort -dict [array names timeline]] {
+	# file revision operation author commitmsg
+	# 0    1        2         3      4/end
+	#               b         c      a
+
+	set entries [lsort -index 3 \
+			 [lsort -index 2 \
+			      [lsort -index end \
+				   $timeline($date)]]]
+	#puts [join $entries \n]
+
+	::foreach entry $entries {
+	    lassign $entry file revision operation author cmsg
+	    set code [catch {uplevel 1 $script} res]
+
+	    # 0 - ok, 1 - error, 2 - return, 3 - break, 4 - continue
+	    switch -- $code {
+		0 {}
+		1 { return -errorcode $::errorCode -errorinfo $::errorInfo -code error $res }
+		2 {}
+		3 { return }
+		4 {}
+		default {
+		    return -code $code $result
+		}
+	    }
+	}
+    }
+    return
+}
+
+# -----------------------------------------------------------------------------
+# Internals
+
+proc ::vc::cvs::ws::timeline::lassign {l args} {
+    ::foreach v $args {upvar 1 $v $v}
+    ::foreach $args $l break
+    return
+}
+
+namespace eval ::vc::cvs::ws::timeline {
+    # Timeline: map (date -> list (file revision operation author commitmsg))
+
+    variable  timeline
+    array set timeline {}
+
+    namespace export add
+}
+
+# -----------------------------------------------------------------------------
+# Ready
 
+package provide vc::cvs::ws::timeline 1.0
+return

Modified tools/lib/pkgIndex.tcl from [5bdfea38bf] to [acc6b0f0f5].

@@ -1,11 +1,12 @@
 if {![package vsatisfies [package require Tcl] 8.4]} return
 package ifneeded vc::rcs::parser           1.0 [list source [file join $dir rcsparser.tcl]]
 package ifneeded vc::cvs::cmd              1.0 [list source [file join $dir cvs_cmd.tcl]]
 package ifneeded vc::cvs::ws               1.0 [list source [file join $dir cvs.tcl]]
 package ifneeded vc::cvs::ws::files        1.0 [list source [file join $dir cvs_files.tcl]]
+package ifneeded vc::cvs::ws::timeline     1.0 [list source [file join $dir cvs_timeline.tcl]]
 package ifneeded vc::fossil::cmd           1.0 [list source [file join $dir fossil_cmd.tcl]]
 package ifneeded vc::fossil::ws            1.0 [list source [file join $dir fossil.tcl]]
 package ifneeded vc::fossil::import::cvs   1.0 [list source [file join $dir importcvs.tcl]]
 package ifneeded vc::fossil::import::stats 1.0 [list source [file join $dir import_statistics.tcl]]
 package ifneeded vc::fossil::import::map   1.0 [list source [file join $dir import_map.tcl]]
 package ifneeded vc::tools::log            1.0 [list source [file join $dir log.tcl]]