Overview
SHA1 Hash: | 177a0cc55c3da003fae4aac6b4800ff73bd08cfa |
---|---|
Date: | 2007-10-17 03:15:12 |
User: | aku |
Comment: | Fix setting of myimported, wrong condition. Fix item assignment when sorting branches. Fix parent/child linkage when setting up branch dependencies. Completed processes on non-trunk default branch revisions. Added skeleton code for the deletion of superfluous revisions. |
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 [6a3824b872] to [952128b4cc].
@@ -20,10 +20,11 @@ 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::log ; # User feedback package require vc::tools::misc ; # Text formatting # # ## ### ##### ######## ############# ##################### ## @@ -175,11 +176,11 @@ # message for the latter, i.e. "Initial revision\n", no # period. (This fact also helps us when the time comes to # determine whether this file might have had a default branch # in the past.) - if {$revnr eq ""} { + if {$revnr eq "1.1"} { set myimported [expr {$commitmsg eq "Initial revision\n"}] } # Here we also keep track of the order in which the revisions # were added to the file. @@ -193,12 +194,17 @@ # looking for a non-trunk default branch, marking its members # and linking them into the trunk. DetermineRevisionOperations DetermineLinesOfDevelopment - - # list of roots ... first only one, later can become more. + HandleNonTrunkDefaultBranch + RemoveIrrelevantDeletions + RemoveInitialBranchDeletions + + if {[$myproject trunkonly]} { + ExcludeNonTrunkInformation + } return } # # ## ### ##### ######## ############# ## State @@ -246,10 +252,14 @@ # reverse of definition. I.e. a smaller # number means 'Defined earlier', means # 'Created later'. variable mytrunk {} ; # Direct reference to myproject -> trunk. + variable myroots {} ; # List of roots in the forest of + # lod's. Object references to revisions and + # branches. The latter can appear when they + # are severed from their parent. # # ## ### ##### ######## ############# ## Internal methods method RecordBranchCommits {branches} { @@ -364,10 +374,11 @@ # list this child in the parent revision. if {[$branch haschild]} { set childrevnr [$branch childrevnr] set child $myrev($childrevnr) + $branch setchild $child $child setparentbranch $branch $child setparent $rev $rev addchildonbranch $child } @@ -421,10 +432,14 @@ foreach {revnr rev} [array get myrev] { if {[$rev hasparent]} continue if {$myroot ne ""} { trouble internal "Multiple root revisions found" } set myroot $rev } + + # In the future we also need a list, as branches can become + # severed from their parent, making them their own root. + set myroots [list $myroot] return } proc DetermineRevisionOperations {} { upvar 1 myrevisions myrevisions @@ -458,10 +473,259 @@ upvar 1 self self return [$self Rev2Branch $revnr] } } + proc HandleNonTrunkDefaultBranch {} { + upvar 1 myprincipal myprincipal myroot myroot mybranches mybranches myimported myimported myroots myroots myrev myrev + + set revlist [NonTrunkDefaultRevisions] + if {![llength $revlist]} return + + AdjustNonTrunkDefaultBranch $revlist + CheckLODs + return + } + + proc NonTrunkDefaultRevisions {} { + # From cvs2svn the following explanation (with modifications + # for our algorithm): + + # Determine whether there are any non-trunk default branch + # revisions. + + # If a non-trunk default branch is determined to have existed, + # return a list of objects for all revisions that were once + # non-trunk default revisions, in dependency order (i.e. root + # first). + + # There are two cases to handle: + + # One case is simple. The RCS file lists a default branch + # explicitly in its header, such as '1.1.1'. In this case, we + # know that every revision on the vendor branch is to be + # treated as head of trunk at that point in time. + + # But there's also a degenerate case. The RCS file does not + # currently have a default branch, yet we can deduce that for + # some period in the past it probably *did* have one. For + # example, the file has vendor revisions 1.1.1.1 -> 1.1.1.96, + # all of which are dated before 1.2, and then it has 1.1.1.97 + # -> 1.1.1.100 dated after 1.2. In this case, we should + # record 1.1.1.96 as the last vendor revision to have been the + # head of the default branch. + + upvar 1 myprincipal myprincipal myroot myroot mybranches mybranches myimported myimported + + if {$myprincipal ne ""} { + # There is still a default branch; that means that all + # revisions on that branch get marked. + + log write 5 file "Found explicitly marked NTDB" + + set rnext [$myroot child] + if {$rnext ne ""} { + trouble fatal "File with default branch $myprincipal also has revision [$rnext revnr]" + return + } + + set rev [$mybranches($myprincipal) child] + set res {} + + while {$rev ne ""} { + lappend res $rev + set rev [$rev child] + } + + return $res + + } elseif {$myimported} { + # No default branch, but the file appears to have been + # imported. So our educated guess is that all revisions + # on the '1.1.1' branch with timestamps prior to the + # timestamp of '1.2' were non-trunk default branch + # revisions. + + # This really only processes standard '1.1.1.*'-style + # vendor revisions. One could conceivably have a file + # whose default branch is 1.1.3 or whatever, or was that + # at some point in time, with vendor revisions 1.1.3.1, + # 1.1.3.2, etc. But with the default branch gone now, + # we'd have no basis for assuming that the non-standard + # vendor branch had ever been the default branch anyway. + + # Note that we rely on comparisons between the timestamps + # of the revisions on the vendor branch and that of + # revision 1.2, even though the timestamps might be + # incorrect due to clock skew. We could do a slightly + # better job if we used the changeset timestamps, as it is + # possible that the dependencies that went into + # determining those timestamps are more accurate. But + # that would require an extra pass or two. + + if {![info exists mybranches(1.1.1)]} { return {} } + + log write 5 file "Deduced existence of NTDB" + + set rev [$mybranches(1.1.1) child] + set res {} + set stop [$myroot child] + + if {$stop eq ""} { + # Get everything on the branch + while {$rev ne ""} { + lappend res $rev + set rev [$rev child] + } + } else { + # Collect everything on the branch which seems to have + # been committed before the first primary child of the + # root revision. + set stopdate [$stop date] + while {$rev ne ""} { + if {[$rev date] >= $stopdate} break + lappend res $rev + set rev [$rev child] + } + } + + return $res + + } else { + return {} + } + } + + proc AdjustNonTrunkDefaultBranch {revlist} { + upvar 1 myroot myroot myimported myimported myroots myroots myrev myrev mybranches mybranches + set stop [$myroot child] ;# rev '1.2' + + log write 5 file "Adjusting NTDB containing [nsp [llength $revlist] revision]" + + # From cvs2svn the following explanation (with modifications + # for our algorithm): + + # Adjust the non-trunk default branch revisions found in the + # 'revlist'. + + # 'myimported' is a boolean flag indicating whether this file + # appears to have been imported, which also means that + # revision 1.1 has a generated log message that need not be + # preserved. 'revlist' is a list of object references for the + # revisions that have been determined to be non-trunk default + # branch revisions. + + # Note that the first revision on the default branch is + # handled strangely by CVS. If a file is imported (as opposed + # to being added), CVS creates a 1.1 revision, then creates a + # vendor branch 1.1.1 based on 1.1, then creates a 1.1.1.1 + # revision that is identical to the 1.1 revision (i.e., its + # deltatext is empty). The log message that the user typed + # when importing is stored with the 1.1.1.1 revision. The 1.1 + # revision always contains a standard, generated log message, + # 'Initial revision\n'. + + # When we detect a straightforward import like this, we want + # to handle it by deleting the 1.1 revision (which doesn't + # contain any useful information) and making 1.1.1.1 into an + # independent root in the file's dependency tree. In SVN, + # 1.1.1.1 will be added directly to the vendor branch with its + # initial content. Then in a special 'post-commit', the + # 1.1.1.1 revision is copied back to trunk. + + # If the user imports again to the same vendor branch, then CVS + # creates revisions 1.1.1.2, 1.1.1.3, etc. on the vendor branch, + # *without* counterparts in trunk (even though these revisions + # effectively play the role of trunk revisions). So after we add + # such revisions to the vendor branch, we also copy them back to + # trunk in post-commits. + + # We mark the revisions found in 'revlist' as default branch + # revisions. Also, if the root revision has a primary child + # we set that revision to depend on the last non-trunk default + # branch revision and possibly adjust its type accordingly. + + set first [lindex $revlist 0] + + log write 6 file "<[$first revnr]> [expr {$myimported ? "imported" : "not imported"}], [$first operation], [expr {[$first hastext] ? "has text" : "no text"}]" + + if {$myimported && + [$first revnr] eq "1.1.1.1" && + [$first operation] eq "change" && + ![$first hastext]} { + + set rev11 [$first parent] ; # Assert: Should be myroot. + log write 3 file "Removing irrelevant revision [$rev11 revnr]" + + # Cut out the old myroot revision. + + ldelete myroots $rev11 ; # Not a root any longer. + unset myrev([$rev11 revnr]) + + $first cutfromparent ; # Sever revision from parent revision. + if {$stop ne ""} { + $stop cutfromparent + lappend myroots $stop ; # New root, after vendor branch + } + + # Cut out the vendor branch symbol + + set vendor [$first parentbranch] + if {$vendor eq ""} { trouble internal "First NTDB revision has no branch" } + if {[$vendor parent] eq $rev11} { + unset mybranches([$vendor branchnr]) + $rev11 removebranch $vendor + $rev11 removechildonbranch $first + $first cutfromparentbranch + lappend myroots $first + } + + # Change the type of first (typically from Change to Add): + $first retype add + + # Move any tags and branches from the old to the new root. + $rev11 movesymbolsto $first + } + + # Mark all the special revisions as such + foreach rev $revlist { + log write 3 file "Revision on default branch: [$rev revnr]" + $rev isondefaultbranch + } + + if {$stop ne ""} { + # Revision 1.2 logically follows the imported revisions, + # not 1.1. Accordingly, connect it to the last NTDBR and + # possibly change its type. + + set last [lindex $revlist end] + $stop setdefaultbranchparent $last ; # Retypes the revision too. + $last setdefaultbranchchild $stop + } + return + } + + proc CheckLODs {} { + upvar 1 mybranches mybranches mytags mytags + + foreach {_ branch} [array get mybranches] { $branch checklod } + + foreach {_ taglist} [array get mytags] { + foreach tag $taglist { $tag checklod } + } + return + } + + proc RemoveIrrelevantDeletions {} { + } + + proc RemoveInitialBranchDeletions {} { + } + + proc ExcludeNonTrunkInformation {} { + } + # # ## ### ##### ######## ############# ## Configuration pragma -hastypeinfo no ; # no type introspection pragma -hasinfo no ; # no object introspection @@ -477,13 +741,14 @@ # 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::tools::misc::* namespace import ::vc::tools::trouble + namespace import ::vc::tools::log } } # # ## ### ##### ######## ############# ##################### ## Ready package provide vc::fossil::import::cvs::file 1.0 return
Modified tools/cvs2fossil/lib/c2f_frev.tcl from [00508f634d] to [89b7595516].
@@ -15,10 +15,11 @@ # # ## ### ##### ######## ############# ##################### ## Requirements package require Tcl 8.4 ; # Required runtime. package require snit ; # OO system. +package require vc::tools::misc ; # Text formatting # # ## ### ##### ######## ############# ##################### ## snit::type ::vc::fossil::import::cvs::file::rev { @@ -34,18 +35,24 @@ return } # Basic pieces ________________________ - method hasmeta {} { return [expr {$mymetaid ne ""}] } + method hasmeta {} { return [expr {$mymetaid ne ""}] } + method hastext {} { + struct::list assign $mytext s e + return [expr {$s <= $e}] + } + method setmeta {meta} { set mymetaid $meta ; return } method settext {text} { set mytext $text ; return } method setlod {lod} { set mylod $lod ; return } method revnr {} { return $myrevnr } method state {} { return $mystate } method lod {} { return $mylod } + method date {} { return $mydate } # Basic parent/child linkage __________ method hasparent {} { return [expr {$myparent ne ""}] } method haschild {} { return [expr {$mychild ne ""}] } @@ -53,10 +60,13 @@ method setparent {parent} { if {$myparent ne ""} { trouble internal "Parent already defined" } set myparent $parent return } + + method cutfromparent {} { set myparent "" ; return } + method cutfromchild {} { set mychild "" ; return } method setchild {child} { if {$mychild ne ""} { trouble internal "Child already defined" } set mychild $child return @@ -71,25 +81,31 @@ if {$myparentbranch ne ""} { trouble internal "Branch parent already defined" } set myparentbranch $branch return } + method parentbranch {} { return $myparentbranch } + method addbranch {branch} { lappend mybranches $branch - #sorted in ascending order by branch number? return } method addchildonbranch {child} { lappend mybranchchildren $child return } - # Tag linkage _________________________ - - method addtag {tag} { - lappend mytags $tag + method cutfromparentbranch {} { set myparentbranch "" ; return } + + method removebranch {branch} { + ldelete mybranches $branch + return + } + + method removechildonbranch {rev} { + ldelete mybranchchildren $rev return } method sortbranches {} { if {![llength $mybranches]} return @@ -109,15 +125,63 @@ lappend tmp [list $branch [$branch position]] } set mybranches {} foreach item [lsort -index 1 -decreasing $tmp] { - struct::list assign $item -> branch position + struct::list assign $item branch position lappend mybranches $branch } return } + + method movebranchesto {rev} { + set revlod [$rev lod] + foreach branch $mybranches { + $rev addbranch $branch + $branch setparent $rev + $branch setlod $revlod + } + foreach branchrev $mybranchchildren { + $rev addchildonbranch $branchrev + $branchrev cutfromparent + $branchrev setparent $rev + } + set mybranches {} + set mybranchchildren {} + return + } + + # Tag linkage _________________________ + + method addtag {tag} { + lappend mytags $tag + return + } + + method movetagsto {rev} { + set revlod [$rev lod] + foreach tag $mytags { + $rev addtag $tag + $tag settagrev $rev + $tag setlod $revlod + } + set mytags {} + return + } + + # general symbol operations ___________ + + method movesymbolsto {rev} { + # Move the tags and branches attached to this revision to the + # destination and fix all pointers. + + $self movetagsto $rev + $self movebranchesto $rev + return + } + + # Derived stuff _______________________ method determineoperation {} { # Look at the state of both this revision and its parent to # determine the type opf operation which was performed (add, # modify, delete, none). @@ -126,10 +190,27 @@ # giving rise to four possible types. set sdead [expr {$mystate eq "dead"}] set pdead [expr {$myparent eq "" || [$myparent state] eq "dead"}] + set myoperation $myopstate([list $pdead $sdead]) + return + } + + method operation {} { return $myoperation } + method retype {x} { set myoperation $x ; return } + + method isondefaultbranch {} { set myisondefaultbranch 1 ; return } + + method setdefaultbranchchild {rev} { set mydbchild $rev ; return } + method setdefaultbranchparent {rev} { + set mydbparent $rev + + # Retype the revision (may change from 'add' to 'change'). + + set sdead [expr {$myoperation ne "change"}] + set pdead [expr {[$rev operation] ne "change"}] set myoperation $myopstate([list $pdead $sdead]) return } # # ## ### ##### ######## ############# @@ -234,13 +315,25 @@ variable mytags {} ; # List of tags (objs) associated with this revision. # More derived data - variable myoperation {} ; # One of 'add', 'change', 'delete', or - # 'nothing'. Derived from our and its - # parent's state. + variable myoperation {} ; # One of 'add', 'change', 'delete', or + # 'nothing'. Derived from our and + # its parent's state. + variable myisondefaultbranch 0 ; # Boolean flag, set if the + # revision is on the non-trunk + # default branch, aka vendor + # branch. + variable mydbparent {} ; # Reference to the last revision + # on the vendor branch if this is + # the primary child of the + # regular root. + variable mydbchild {} ; # Reference to the primary child + # of the regular root if this is + # the last revision on the vendor + # branch. # dead(self) x dead(parent) -> operation typevariable myopstate -array { {0 0} change {0 1} delete @@ -261,12 +354,15 @@ # # ## ### ##### ######## ############# } namespace eval ::vc::fossil::import::cvs::file { namespace export rev + namespace eval rev { + namespace import ::vc::tools::misc::* + } } # # ## ### ##### ######## ############# ##################### ## Ready package provide vc::fossil::import::cvs::file::rev 1.0 return
Modified tools/cvs2fossil/lib/c2f_fsym.tcl from [85589454df] to [211201a643].
@@ -53,17 +53,20 @@ return } method setposition {n} { set mybranchposition $n ; return } method setparent {rev} { set mybranchparent $rev ; return } + method setchild {rev} { set mybranchchild $rev ; return } method branchnr {} { return $mynr } method parentrevnr {} { return $mybranchparentrevnr } method childrevnr {} { return $mybranchchildrevnr } method haschild {} { return [expr {$mybranchchildrevnr 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 } @@ -72,22 +75,26 @@ method lod {} { return $mylod } method setlod {lod} { set mylod $lod - - # Consistency check integrated. The symbol's - # line-of-development has to be same as the - # line-of-development of its source. + $self checklod + return + } + + method checklod {} { + # Consistency check. The symbol's line-of-development has to + # be same as the line-of-development of its source (parent + # revision of a branch, revision of a tag itself). switch -exact -- $mytype { branch { set slod [$mybranchparent lod] } tag { set slod [$mytagrev lod] } } if {$mylod ne $slod} { - trouble fatal "For [$mysymbol name]: LOD conflict with source, '[$mylod name]' vs. '[$slod name]'" + trouble fatal "For $mytype [$mysymbol name]: LOD conflict with source, '[$mylod name]' vs. '[$slod name]'" return } return } @@ -103,11 +110,12 @@ # symbol at the project level. variable mylod {} ; # Reference to the line-of-development # object the symbol belongs to. An # alternative idiom would be to call it the # branch the symbol is on. This reference - # is to a project-level symbol object. + # is to a project-level object (symbol or + # trunk). ## Branch symbols _____________________ variable mybranchparentrevnr {} ; # The number of the parent # revision, derived from our