Overview
SHA1 Hash: | cb70cf4ad69d891a24b9499cfbbd75f132954ba1 |
---|---|
Date: | 2007-10-13 05:39:00 |
User: | aku |
Comment: | The basic work of setting up and linking revisions, tags, and branches is complete. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified tools/cvs2fossil/lib/c2f_file.tcl from [f38b4ceaf7] to [880ea7b085].
@@ -19,10 +19,12 @@ package require Tcl 8.4 ; # Required runtime. package require snit ; # OO system. package require struct::set ; # Set operations. package require vc::fossil::import::cvs::file::rev ; # CVS per file revisions. package require vc::fossil::import::cvs::file::sym ; # CVS per file symbols. +package require vc::tools::trouble ; # Error reporting. +package require vc::tools::misc ; # Text formatting # # ## ### ##### ######## ############# ##################### ## snit::type ::vc::fossil::import::cvs::file { @@ -97,11 +99,11 @@ method admindone {} { # We do nothing at the boundary of admin and revision data } method def {revnr date author state next branches} { - $self LookForUnlabeledBranches $branches + $self RecordBranchCommits $branches $myproject author $author if {[info exists myrev($revnr)]} { trouble fatal "File $mypath contains duplicate definitions for revision $revnr." return @@ -112,10 +114,20 @@ RecordBasicDependencies $revnr $next return } method defdone {} { + # This is all done after the revision tree has been extracted + # from the file, before the commit mesages and delta texts are + # processed. + + ProcessPrimaryDependencies + ProcessBranchDependencies + SortBranches + ProcessTagDependencies + DetermineTheRootRevision + return } method setdesc {d} {# ignore} method extend {revnr commitmsg deltarange} { @@ -146,11 +158,11 @@ $rev setcommitmsg $cm $rev settext $deltarange if {![rev istrunkrevnr $revnr]} { - $rev setbranch [[$self Rev2Branch $revnr] name] + $rev setbranchname [[$self Rev2Branch $revnr] name] } # If this is revision 1.1, we have to determine whether the # file seems to have been created through 'cvs add' instead of # 'cvs import'. This can be done by looking at the un- @@ -174,43 +186,68 @@ method done {} {} # # ## ### ##### ######## ############# ## State - variable mypath {} ; # Path of rcs archive - variable myproject {} ; # Project object the file belongs to. - variable myrev -array {} ; # All revisions and their connections. - variable myrevisions {} ; # Same as myrev, but a list, giving us the order - # ; # of revisions. + variable mypath {} ; # Path of our rcs archive. + variable myproject {} ; # Reference to the project object + # the file belongs to. + variable myrev -array {} ; # Maps revision number to the + # associated revision object. + variable myrevisions {} ; # Same as myrev, but a list, + # giving us the order of + # revisions. variable myhead {} ; # Head revision (revision number) - variable myprincipal {} ; # Principal branch (branch number) - # ; # Contrary to the name this is the default branch. - variable mydependencies {} ; # Dictionary parent -> child, dependency recorder. - variable myimported 0 ; # Boolean flag. Set iff rev 1.1 of the file seemingly - # ; # was imported instead of added normally. - variable myroot {} ; # Revision number of the root revision. Usually '1.1'. - # ; # Can be a different number, because of 'cvsadmin -o'. - variable mybranches -array {} ; # branch number -> symbol object handling the branch - variable mytags -array {} ; # revision number -> list of symbol object for the tags - # ; # associated with the revision. - variable mysymbols {} ; # Set of symbol names found in this file. + variable myprincipal {} ; # Principal branch (branch number). + # Contrary to the name this is the + # default branch. + variable mydependencies {} ; # Dictionary parent -> child, + # records primary dependencies. + variable myimported 0 ; # Boolean flag. Set if and only if + # rev 1.1 of the file seemingly + # was imported instead of added + # normally. + variable myroot {} ; # Reference to the revision object + # holding the root revision. Its + # number usually is '1.1'. Can be + # a different number, because of + # gaps created via 'cvsadmin -o'. + variable mybranches -array {} ; # Maps branch number to the symbol + # object handling the branch. + variable mytags -array {} ; # Maps revision number to the list + # of symbol objects for the tags + # associated with the revision. + variable mysymbols {} ; # Set of the symbol names found in + # this file. + + variable mybranchcnt 0 ; # Counter for branches, to record their + # order of definition. This also defines + # their order of creation, which is the + # reverse of definition. I.e. a smaller + # number means 'Defined earlier', means + # 'Created later'. ### TODO ### ### File flag - executable, ### RCS mode info (kb, kkb, ...) # # ## ### ##### ######## ############# ## Internal methods - method LookForUnlabeledBranches {branches} { + method RecordBranchCommits {branches} { foreach branchrevnr $branches { if {[catch { set branch [$self Rev2Branch $branchrevnr] }]} { set branch [$self AddUnlabeledBranch [rev 2branchnr $branchrevnr]] } - # TODO $branch child $branchrevnr - when add-unlabeled has sensible return value + + # Record the commit, just as revision number for + # now. ProcesBranchDependencies will extend that ito a + # proper object reference. + + $branch setchildrevnr $branchrevnr } return } method Rev2Branch {revnr} { @@ -229,10 +266,11 @@ log write 1 file "In '$mypath': Branch '$branchnr' named '[$mybranches($branchnr) name]'" log write 1 file "Cannot have second name '$name', ignoring it" return } set branch [sym %AUTO% branch $branchnr [$myproject getsymbol $name]] + $branch setposition [incr mybranchcnt] set mybranches($branchnr) $branch return $branch } method AddTag {name revnr} { @@ -271,10 +309,101 @@ lappend mydependencies $revnr $next } return } + proc ProcessPrimaryDependencies {} { + upvar 1 mydependencies mydependencies myrev myrev + + foreach {parentrevnr childrevnr} $mydependencies { + set parent $myrev($parentrevnr) + set child $myrev($childrevnr) + $parent setchild $child + $child setparent $parent + } + return + } + + proc ProcessBranchDependencies {} { + upvar 1 mybranches mybranches myrev myrev + + foreach {branchnr branch} [array get mybranches] { + set revnr [$branch parentrevnr] + + if {![info exists myrev($revnr)]} { + log write 1 file "In '$mypath': The branch '[$branch name]' references" + log write 1 file "the bogus revision '$revnr' and will be ignored." + $branch destroy + unset mybranches($branchnr) + } else { + set rev $myrev($revnr) + $rev addbranch $branch + + # If revisions were committed on the branch we store a + # reference to the branch there, and further declare + # the first child's parent to be branch's parent, and + # list this child in the parent revision. + + if {[$branch haschild]} { + set childrevnr [$branch childrevnr] + set child $myrev($childrevnr) + + $child setparentbranch $branch + $child setparent $rev + $rev addchildonbranch $child + } + } + } + return + } + + proc SortBranches {} { + upvar 1 myrev myrev + + foreach {revnr rev} [array get myrev] { + $rev sortbranches + } + return + } + + proc ProcessTagDependencies {} { + upvar 1 mytags mytags myrev myrev + + foreach {revnr taglist} [array get mytags] { + if {![info exists myrev($revnr)]} { + set n [llength $taglist] + log write 1 file "In '$mypath': The following [nsp $n tag] reference" + log write 1 file "the bogus revision '$revnr' and will be ignored." + foreach tag $taglist { + log write 1 file " [$tag name]" + $tag destroy + } + unset mytags($revnr) + } else { + set rev $myrev($revnr) + foreach tag $taglist { $rev addtag $tag } + } + } + return + } + + proc DetermineTheRootRevision {} { + upvar 1 myrev myrev myroot myroot + + # The root is the one revision which has no parent. By + # checking all revisions we ensure that we can detect and + # report the case of multiple roots. Without that we could + # simply take one revision and follow the parent links to + # their root (sic!). + + foreach {revnr rev} [array get myrev] { + if {[$rev hasparent]} continue + if {$myroot ne ""} { trouble internal "Multiple root revisions found" } + set myroot $rev + } + return + } # # ## ### ##### ######## ############# ## Configuration pragma -hastypeinfo no ; # no type introspection @@ -287,15 +416,17 @@ namespace eval ::vc::fossil::import::cvs { namespace export file namespace eval file { # Import not required, already a child namespace. - # namespace import vc::fossil::import::cvs::file::rev - # namespace import vc::fossil::import::cvs::file::sym + # namespace import ::vc::fossil::import::cvs::file::rev + # namespace import ::vc::fossil::import::cvs::file::sym + namespace import ::vc::tools::misc::* + namespace import ::vc::tools::trouble } } # # ## ### ##### ######## ############# ##################### ## Ready package provide vc::fossil::import::cvs::file 1.0 return
Modified tools/cvs2fossil/lib/c2f_frev.tcl from [867793964e] to [a8af3a8bac].
@@ -24,41 +24,115 @@ snit::type ::vc::fossil::import::cvs::file::rev { # # ## ### ##### ######## ############# ## Public API constructor {revnr date author state thefile} { - set myrevnr $revnr - set mydate $date - set myauthor $author - set mystate $state - set myfile $thefile + set myrevnr $revnr + set mydate $date + set myorigdate $date + set myauthor $author + set mystate $state + set myfile $thefile return } + + # Basic pieces ________________________ method hascommitmsg {} { return $myhascm } - method setcommitmsg {cm} { - set mycommitmsg $cm - set myhascm 1 + method setcommitmsg {cm} { set mycommitmsg $cm ; set myhascm 1 ; return } + method settext {text} { set mytext $text ; return } + method setbranchname {name} { set mybranchname $name ; return } + + method revnr {} { return $myrevnr } + + # Basic parent/child linkage __________ + + method hasparent {} { return [expr {$myparent ne ""}] } + method haschild {} { return [expr {$mychild ne ""}] } + + method setparent {parent} { + if {$myparent ne ""} { trouble internal "Parent already defined" } + set myparent $parent + return + } + + method setchild {child} { + if {$mychild ne ""} { trouble internal "Child already defined" } + set mychild $child + return + } + + method parent {} { return $myparent } + method child {} { return $mychild } + + # Branch linkage ______________________ + + method setparentbranch {branch} { + if {$myparentbranch ne ""} { trouble internal "Branch parent already defined" } + set myparentbranch $branch + return + } + + method addbranch {branch} { + lappend mybranches $branch + #sorted in ascending order by branch number? + return + } + + method addchildonbranch {child} { + lappend mybranchchildren $child return } - method settext {text} { - set mytext $text + # Tag linkage _________________________ + + method addtag {tag} { + lappend mytags $tag return } - method setbranch {branchnr} { - set mybranchnr $branchnr + method sortbranches {} { + if {![llength $mybranches]} return + + # Sort the branches spawned by this revision in creation + # order. To help in this our file gave all branches a position + # id, in order of their definition by the RCS archive. + # + # The creation order is (apparently) the reverse of the + # definition order. (If a branch is created then deleted, a + # later branch can be assigned the recycled branch number; + # therefore branch numbers are not an indication of creation + # order.) + + set tmp {} + foreach branch $mybranches { + lappend tmp [list $branch [$branch position]] + } + + set mybranches {} + foreach item [lsort -index 1 -decreasing $tmp] { + struct::list assign $item -> branch position + lappend mybranches $branch + } return } # # ## ### ##### ######## ############# ## Type API typemethod istrunkrevnr {revnr} { return [expr {[llength [split $revnr .]] == 2}] + } + + typemethod isbranchrevnr {revnr _ bv} { + if {[regexp $mybranchpattern $revnr -> head tail]} { + upvar 1 $bv branchnr + set branchnr ${head}$tail + return 1 + } + return 0 } typemethod 2branchnr {revnr} { # Input is a branch revision number, i.e. a revision number # with an even number of components; for example '2.9.2.1' @@ -70,17 +144,13 @@ return "" } return [join [lrange [split $revnr .] 0 end-1] .] } - typemethod isbranchrevnr {revnr _ bv} { - if {[regexp $mybranchpattern $revnr -> head tail]} { - upvar 1 $bv branchnr - set branchnr ${head}$tail - return 1 - } - return 0 + typemethod 2branchparentrevnr {branchnr} { + # Chop the last segment off + return [join [lrange [split $branchnr .] 0 end-1] .] } # # ## ### ##### ######## ############# ## State @@ -89,22 +159,61 @@ # CVS then sticks an extra 0 in here; RCS does not. # And the last digit group. variable myrevnr {} ; # Revision number of the revision. variable mydate {} ; # Timestamp of the revision, seconds since epoch + variable myorigdate {} ; # Original unmodified timestamp. variable mystate {} ; # State of the revision. variable myfile {} ; # Ref to the file object the revision belongs to. variable myhascm 0 ; # Bool flag, set when the commit msg was set. variable mytext {} ; # Range of the (delta) text for this revision in the file. # The meta data block used later to group revisions into changesets. # The project name factors into this as well, but is not stored # here. The name is acessible via myfile's project. - variable myauthor {} ; # Name of the user who committed the revision. - variable mycommitmsg {} ; # The message entered as part of the commit. - variable mybranchnr {} ; # The number of the branch the commit was done on. + variable myauthor {} ; # Name of the user who committed the revision. + variable mycommitmsg {} ; # The message entered as part of the commit. + variable mybranchname {} ; # The name of the branch the revision was committed on. + + # Basic parent/child linkage (lines of development) + + variable myparent {} ; # Ref to parent revision object. Link required because of + # ; # 'cvsadmin -o', which can create arbitrary gaps in the + # ; # numbering sequence. This is in the same line of development + # ; # Note: For the first revision on a branch the revision + # ; # it was spawned from is the parent. Only the root revision + # ; # of myfile's revision tree has nothing set here. + # ; # + + variable mychild {} ; # Ref to the primary child revision object, i.e. the next + # ; # revision in the same line of development. + + # Branch linkage ____________________ + + variable mybranches {} ; # List of the branches (objs) spawned by this revision. + variable myparentbranch {} ; # For the first revision on a branch the relevant + # ; # branch object. This also allows us to determine if + # ; # myparent is in the same LOD, or the revision the + # ; # branch spawned from. + + # List of the revision objects of the first commits on any + # branches spawned by this revision on which commits occurred. + # This dependency is kept explicitly because otherwise a + # revision-only topological sort would miss the dependency that + # exists via -> mybranches. + + variable mybranchchildren {} ; # List of the revisions (objs) which are the first + # ; # commits on any of the branches spawned from this + # ; # revision. The dependency is kept explicitly to + # ; # ensure that a revision-only topological sort will + # ; # not miss it, as it otherwise exists only via + # ; # mybranches. + + # Tag linkage ________________________ + + variable mytags {} ; # List of tags (objs) associated with this revision. # # ## ### ##### ######## ############# ## Internal methods # # ## ### ##### ######## #############
Modified tools/cvs2fossil/lib/c2f_fsym.tcl from [d0212d4c6d] to [f9d277d79e].
@@ -15,10 +15,12 @@ # # ## ### ##### ######## ############# ##################### ## Requirements package require Tcl 8.4 ; # Required runtime. package require snit ; # OO system. +package require vc::tools::trouble ; # Error reporting. +package require vc::fossil::import::cvs::file::rev ; # CVS per file revisions. # # ## ### ##### ######## ############# ##################### ## snit::type ::vc::fossil::import::cvs::file::sym { @@ -27,24 +29,86 @@ constructor {symtype nr symbol} { set mytype $symtype set mynr $nr set mysymbol $symbol + + switch -exact -- $mytype { + branch { SetupBranch } + tag { } + default { trouble internal "Bad symbol type '$mytype'" } + } + return + } + + # Symbol acessor methods. + + delegate method name to mysymbol + + # Branch acessor methods. + + method setchildrevnr {revnr} { + if {$mybranchchildrevnr ne ""} { trouble internal "Child already defined" } + set mybranchchildrevnr $revnr return } - delegate method name to mysymbol + method setposition {n} { set mybranchposition $n } + + method branchnr {} { return $mynr } + method parentrevnr {} { return $mybranchparentrevnr } + method childrevnr {} { return $mybranchchildrevnr } + + method haschild {} { return [expr {$mybranchchildrevnr ne ""}] } + method child {} { return $mybranchchild } + + method position {} { return $mybranchposition } + + # Tag acessor methods. + + method tagrevnr {} { return $mynr } # # ## ### ##### ######## ############# ## State + ## Basic, all symbols _________________ + variable mytype {} ; # Symbol type, 'tag', or 'branch'. - variable mynr {} ; # Revision number of a 'tag', branch number of a 'branch'. - variable mysymbol {} ; # Ref to symbol object at project level. + variable mynr {} ; # Revision number of a 'tag', branch number + # of a 'branch'. + variable mysymbol {} ; # Reference to the symbol object of this + # symbol at the project level. + + ## Branch symbols _____________________ + + variable mybranchparentrevnr {} ; # The number of the parent + # revision, derived from our + # branch number (mynr). + variable mybranchparent {} ; # Reference to the revision + # (object) which spawns the + # branch. + variable mybranchchildrevnr {} ; # Number of the first revision + # committed on this branch. + variable mybranchchild {} ; # Reference to the revision + # (object) first committed on + # this branch. + variable mybranchposition {} ; # Relative id of the branch in + # the file, to sort into + # creation order. + + ## Tag symbols ________________________ + + # ... nothing special ... (only mynr, see basic) # # ## ### ##### ######## ############# ## Internal methods + + proc SetupBranch {} { + upvar 1 mybranchparentrevnr mybranchparentrevnr mynr mynr + set mybranchparentrevnr [rev 2branchparentrevnr $mynr] + return + } # # ## ### ##### ######## ############# ## Configuration pragma -hastypeinfo no ; # no type introspection @@ -54,12 +118,16 @@ # # ## ### ##### ######## ############# } namespace eval ::vc::fossil::import::cvs::file { namespace export sym + namespace eval sym { + namespace import ::vc::fossil::import::cvs::file::rev + namespace import ::vc::tools::trouble + } } # # ## ### ##### ######## ############# ##################### ## Ready package provide vc::fossil::import::cvs::file::sym 1.0 return