Fossil SCM
Started to flesh out the handling symbols and revisions coming in from the rcs parser. First fragments of revision object. Type methods for classification of revision numb ers.
Commit
bd131addb9a700df2cef390ee558ba8721fe47bb
Parent
a10f654ac719780…
2 files changed
+193
-20
+47
-2
+193
-20
| --- tools/cvs2fossil/lib/c2f_file.tcl | ||
| +++ tools/cvs2fossil/lib/c2f_file.tcl | ||
| @@ -16,10 +16,12 @@ | ||
| 16 | 16 | # # ## ### ##### ######## ############# ##################### |
| 17 | 17 | ## Requirements |
| 18 | 18 | |
| 19 | 19 | package require Tcl 8.4 ; # Required runtime. |
| 20 | 20 | package require snit ; # OO system. |
| 21 | +package require struct::set ; # Set operations. | |
| 22 | +package require vc::fossil::import::cvs::file::rev ; # CVS per file revisions. | |
| 21 | 23 | |
| 22 | 24 | # # ## ### ##### ######## ############# ##################### |
| 23 | 25 | ## |
| 24 | 26 | |
| 25 | 27 | snit::type ::vc::fossil::import::cvs::file { |
| @@ -30,11 +32,12 @@ | ||
| 30 | 32 | set mypath $path |
| 31 | 33 | set myproject $project |
| 32 | 34 | return |
| 33 | 35 | } |
| 34 | 36 | |
| 35 | - method path {} { return $mypath } | |
| 37 | + method path {} { return $mypath } | |
| 38 | + method project {} { return $myproject } | |
| 36 | 39 | |
| 37 | 40 | # # ## ### ##### ######## ############# |
| 38 | 41 | ## Methods required for the class to be a sink of the rcs parser |
| 39 | 42 | |
| 40 | 43 | method begin {} {} |
| @@ -52,11 +55,11 @@ | ||
| 52 | 55 | method extend {rev commitmsg deltarange} {} |
| 53 | 56 | |
| 54 | 57 | #method begin {} {puts begin} |
| 55 | 58 | #method sethead {h} {puts head=$h} |
| 56 | 59 | #method setprincipalbranch {b} {puts pb=$b} |
| 57 | - #method deftag {s r} {puts $s=$r } | |
| 60 | + #method deftag {s r} {puts $s=$r} | |
| 58 | 61 | #method setcomment {c} {puts comment=$c} |
| 59 | 62 | #method admindone {} {puts admindone} |
| 60 | 63 | #method def {rev date author state next branches} {puts "def $rev $date $author $state $next $branches"} |
| 61 | 64 | #method setdesc {d} {puts desc=$d} |
| 62 | 65 | #method extend {rev commitmsg deltarange} {puts "extend $commitmsg $deltarange"} |
| @@ -69,55 +72,221 @@ | ||
| 69 | 72 | } |
| 70 | 73 | |
| 71 | 74 | # # ## ### ##### ######## ############# |
| 72 | 75 | ## Implement the sink |
| 73 | 76 | |
| 74 | - method begin {} {} | |
| 75 | - method done {} {} | |
| 76 | - method admindone {} {} | |
| 77 | + method begin {} {} | |
| 78 | + method done {} {} | |
| 79 | + | |
| 80 | + method admindone {} { | |
| 81 | + # We do nothing at the boundary of admin and revision data | |
| 82 | + } | |
| 77 | 83 | |
| 78 | - method sethead {h} { | |
| 79 | - set myhead $h | |
| 84 | + method sethead {revnr} { | |
| 85 | + set myhead $revnr | |
| 80 | 86 | return |
| 81 | 87 | } |
| 82 | 88 | |
| 83 | - method setprincipalbranch {b} { | |
| 84 | - set myprincipal $b | |
| 89 | + method setprincipalbranch {branchnr} { | |
| 90 | + set myprincipal $branchnr | |
| 85 | 91 | return |
| 86 | 92 | } |
| 87 | 93 | |
| 88 | - method deftag {symbol rev} { | |
| 89 | - # Slice symbols into branches and tags, canonical numbers ... | |
| 94 | + method deftag {name revnr} { | |
| 95 | + # FUTURE: Perform symbol transformation here. | |
| 96 | + | |
| 97 | + if {[struct::set contains $mysymbols $name]} { | |
| 98 | + trouble fatal "Multiple definitions of the symbol '$name' in '$mypath'" | |
| 99 | + return | |
| 100 | + } | |
| 101 | + | |
| 102 | + struct::set add mysymbols $name | |
| 103 | + | |
| 104 | + if {[rev isbranchrevnr $revnr -> branchnr]} { | |
| 105 | + $self AddBranch $name $branchnr | |
| 106 | + } else { | |
| 107 | + $self AddTag $name $revnr | |
| 108 | + } | |
| 109 | + return | |
| 90 | 110 | } |
| 91 | 111 | |
| 92 | 112 | method setcomment {c} {# ignore} |
| 93 | 113 | method setdesc {d} {# ignore} |
| 94 | 114 | |
| 95 | - method def {rev date author state next branches} { | |
| 96 | - set myrev($rev) [list $date $author $state $next $branches] | |
| 115 | + method def {revnr date author state next branches} { | |
| 116 | + $self LookForUnlabeledBranches $branches | |
| 97 | 117 | $myproject author $author |
| 118 | + | |
| 119 | + if {[info exists myrev($revnr)]} { | |
| 120 | + trouble fatal "File $mypath contains duplicate definitions for revision $revnr." | |
| 121 | + return | |
| 122 | + } | |
| 123 | + | |
| 124 | + set myrev($revnr) [rev %AUTO% $date $author $state $self] | |
| 125 | + | |
| 126 | + RecordBasicDependencies $revnr $next | |
| 98 | 127 | return |
| 99 | 128 | } |
| 100 | 129 | |
| 101 | - method extend {rev commitmsg deltarange} { | |
| 130 | + method extend {revnr commitmsg deltarange} { | |
| 102 | 131 | set cm [string trim $commitmsg] |
| 103 | - lappend myrev($rev) $cm $deltarange | |
| 104 | 132 | $myproject cmessage $cm |
| 133 | + | |
| 134 | + set rev $myrev($revnr) | |
| 135 | + | |
| 136 | + if {[$rev hascommitmsg]} { | |
| 137 | + # Apparently repositories exist in which the delta data | |
| 138 | + # for revision 1.1 is provided several times, at least | |
| 139 | + # twice. The actual cause of this duplication is not | |
| 140 | + # known. Speculation centers on RCS/CVS bugs, or from | |
| 141 | + # manual edits of the repository which borked the | |
| 142 | + # internals. Whatever the cause, testing showed that both | |
| 143 | + # cvs and rcs use the first definition when performing a | |
| 144 | + # checkout, and we follow their lead. Side notes: 'cvs | |
| 145 | + # log' fails on such a file, and 'cvs rlog' prints the log | |
| 146 | + # message from the first delta, ignoring the second. | |
| 147 | + | |
| 148 | + log write 1 file "In file $mypath : Duplicate delta data for revision $revnr" | |
| 149 | + log write 1 file "Ignoring the duplicate" | |
| 150 | + return | |
| 151 | + } | |
| 152 | + | |
| 153 | + # Extend the revision with the new information. The revision | |
| 154 | + # object uses this to complete its meta data set. | |
| 155 | + | |
| 156 | + $rev setcommitmsg $cm | |
| 157 | + $rev settext $deltarange | |
| 158 | + | |
| 159 | + # If this is revision 1.1, we have to determine whether the | |
| 160 | + # file seems to have been created through 'cvs add' instead of | |
| 161 | + # 'cvs import'. This can be done by looking at the un- | |
| 162 | + # adulterated commit message, as CVS uses a hardwired magic | |
| 163 | + # message for the latter, i.e. "Initial revision\n", no | |
| 164 | + # period. (This fact also helps us when the time comes to | |
| 165 | + # determine whether this file might have had a default branch | |
| 166 | + # in the past.) | |
| 167 | + | |
| 168 | + if {$revnr eq ""} { | |
| 169 | + set myimported [expr {$commitmsg eq "Initial revision\n"}] | |
| 170 | + } | |
| 171 | + | |
| 172 | + # Here we also keep track of the order in which the revisions | |
| 173 | + # were added to the file. | |
| 174 | + | |
| 175 | + lappend myrevisions $rev | |
| 105 | 176 | return |
| 106 | 177 | } |
| 107 | 178 | |
| 108 | 179 | # # ## ### ##### ######## ############# |
| 109 | 180 | ## State |
| 110 | 181 | |
| 111 | - variable mypath {} ; # Path of rcs archive | |
| 112 | - variable myproject {} ; # Project object the file belongs to. | |
| 113 | - variable myrev -array {} ; # All revisions and their connections. | |
| 114 | - variable myhead {} ; # Head revision (rev number) | |
| 115 | - variable myprincipal {} ; # Principal branch (branch number) | |
| 182 | + variable mypath {} ; # Path of rcs archive | |
| 183 | + variable myproject {} ; # Project object the file belongs to. | |
| 184 | + variable myrev -array {} ; # All revisions and their connections. | |
| 185 | + variable myrevisions {} ; # Same as myrev, but a list, giving us the order | |
| 186 | + # ; # of revisions. | |
| 187 | + variable myhead {} ; # Head revision (revision number) | |
| 188 | + variable myprincipal {} ; # Principal branch (branch number) | |
| 189 | + # ; # Contrary to the name this is the default branch. | |
| 190 | + variable mydependencies {} ; # Dictionary parent -> child, dependency recorder. | |
| 191 | + variable myimported 0 ; # Boolean flag. Set iff rev 1.1 of the file seemingly | |
| 192 | + # ; # was imported instead of added normally. | |
| 193 | + variable myroot {} ; # Revision number of the root revision. Usually '1.1'. | |
| 194 | + # ; # Can be a different number, because of 'cvsadmin -o'. | |
| 195 | + variable mybranches -array {} ; # branch number -> symbol object handling the branch | |
| 196 | + variable mytags -array {} ; # revision number -> list of symbol object for the tags | |
| 197 | + # ; # associated with the revision. | |
| 198 | + variable mysymbols {} ; # Set of symbol names found in this file. | |
| 199 | + | |
| 200 | + ### TODO ### | |
| 201 | + ### File flag - executable, | |
| 202 | + ### RCS mode info (kb, kkb, ...) | |
| 116 | 203 | |
| 117 | 204 | # # ## ### ##### ######## ############# |
| 118 | 205 | ## Internal methods |
| 206 | + | |
| 207 | + method LookForUnlabeledBranches {branches} { | |
| 208 | + foreach branchrevnr $branches { | |
| 209 | + if {[catch { | |
| 210 | + set branch [$self Rev2Branch $branchrevnr] | |
| 211 | + }]} { | |
| 212 | + set branch [$self AddUnlabeledBranch [rev 2branchnr $branchrevnr]] | |
| 213 | + } | |
| 214 | + # TODO $branch child $branchrevnr - when add-unlabeled has sensible return value | |
| 215 | + } | |
| 216 | + return | |
| 217 | + } | |
| 218 | + | |
| 219 | + method Rev2Branch {revnr} { | |
| 220 | + if {[rev istrunkrevnr $revnr]} { | |
| 221 | + trouble internal "Expected a branch revision number" | |
| 222 | + } | |
| 223 | + return $mybranches([rev 2branchnr $revnr]) | |
| 224 | + } | |
| 225 | + | |
| 226 | + method AddUnlabeledBranch {branchnr} { | |
| 227 | + return [$self AddBranch unlabeled-$branchnr $branchnr] | |
| 228 | + } | |
| 229 | + | |
| 230 | + method AddBranch {name branchnr} { | |
| 231 | + if {[info exists mybranches($branchnr)]} { | |
| 232 | + log write 1 file "In '$mypath': Branch '$branchnr' named '[$mybranches($branchnr) name]'" | |
| 233 | + log write 1 file "Cannot have second name '$name', ignoring it" | |
| 234 | + return | |
| 235 | + } | |
| 236 | + set sym "" | |
| 237 | + set branch "" | |
| 238 | + #TODO set sym [$myproject getsymbol $name ] | |
| 239 | + #TODO set tag [sym %AUTO% branch $sym $branchnr] | |
| 240 | + set mybranches($branchnr) $branch | |
| 241 | + return $branch | |
| 242 | + } | |
| 243 | + | |
| 244 | + method AddTag {name revnr} { | |
| 245 | + set sym "" | |
| 246 | + set tag "" | |
| 247 | + #TODO set sym [$myproject getsymbol $name ] | |
| 248 | + #TODO set tag [sym %AUTO% tag $sym $revnr] | |
| 249 | + lappend mytags($revnr) $tag | |
| 250 | + return $tag | |
| 251 | + } | |
| 252 | + | |
| 253 | + proc RecordBasicDependencies {revnr next} { | |
| 254 | + # Handle the revision dependencies. Record them for now, do | |
| 255 | + # nothing with them yet. | |
| 256 | + | |
| 257 | + # On the trunk the 'next' field points to the previous | |
| 258 | + # revision, i.e. the _parent_ of the current one. Example: | |
| 259 | + # 1.6's next is 1.5 (modulo cvs admin -o). | |
| 260 | + | |
| 261 | + # Contrarily on a branch the 'next' field points to the | |
| 262 | + # primary _child_ of the current revision. As example, | |
| 263 | + # 1.1.3.2's 'next' will be 1.1.3.3. | |
| 264 | + | |
| 265 | + # The 'next' field actually always refers to the revision | |
| 266 | + # containing the delta needed to retrieve that revision. | |
| 267 | + | |
| 268 | + # The dependencies needed here are the logical structure, | |
| 269 | + # parent/child, and not the implementation dependent delta | |
| 270 | + # pointers. | |
| 271 | + | |
| 272 | + if {$next eq ""} return | |
| 273 | + | |
| 274 | + upvar 1 mydependencies mydependencies | |
| 275 | + | |
| 276 | + # parent -> child | |
| 277 | + if {[rev istrunkrevnr $revnr]} { | |
| 278 | + lappend mydependencies $next $revnr | |
| 279 | + } else { | |
| 280 | + lappend mydependencies $revnr $next | |
| 281 | + } | |
| 282 | + return | |
| 283 | + } | |
| 284 | + | |
| 285 | + | |
| 286 | + # # ## ### ##### ######## ############# | |
| 287 | + ## Configuration | |
| 119 | 288 | |
| 120 | 289 | pragma -hastypeinfo no ; # no type introspection |
| 121 | 290 | pragma -hasinfo no ; # no object introspection |
| 122 | 291 | pragma -hastypemethods no ; # type is not relevant. |
| 123 | 292 | pragma -simpledispatch yes ; # simple fast dispatch |
| @@ -125,12 +294,16 @@ | ||
| 125 | 294 | # # ## ### ##### ######## ############# |
| 126 | 295 | } |
| 127 | 296 | |
| 128 | 297 | namespace eval ::vc::fossil::import::cvs { |
| 129 | 298 | namespace export file |
| 299 | + namespace eval file { | |
| 300 | + # Import not required, already a child namespace. | |
| 301 | + # namespace import vc::fossil::import::cvs::file::rev | |
| 302 | + } | |
| 130 | 303 | } |
| 131 | 304 | |
| 132 | 305 | # # ## ### ##### ######## ############# ##################### |
| 133 | 306 | ## Ready |
| 134 | 307 | |
| 135 | 308 | package provide vc::fossil::import::cvs::file 1.0 |
| 136 | 309 | return |
| 137 | 310 |
| --- tools/cvs2fossil/lib/c2f_file.tcl | |
| +++ tools/cvs2fossil/lib/c2f_file.tcl | |
| @@ -16,10 +16,12 @@ | |
| 16 | # # ## ### ##### ######## ############# ##################### |
| 17 | ## Requirements |
| 18 | |
| 19 | package require Tcl 8.4 ; # Required runtime. |
| 20 | package require snit ; # OO system. |
| 21 | |
| 22 | # # ## ### ##### ######## ############# ##################### |
| 23 | ## |
| 24 | |
| 25 | snit::type ::vc::fossil::import::cvs::file { |
| @@ -30,11 +32,12 @@ | |
| 30 | set mypath $path |
| 31 | set myproject $project |
| 32 | return |
| 33 | } |
| 34 | |
| 35 | method path {} { return $mypath } |
| 36 | |
| 37 | # # ## ### ##### ######## ############# |
| 38 | ## Methods required for the class to be a sink of the rcs parser |
| 39 | |
| 40 | method begin {} {} |
| @@ -52,11 +55,11 @@ | |
| 52 | method extend {rev commitmsg deltarange} {} |
| 53 | |
| 54 | #method begin {} {puts begin} |
| 55 | #method sethead {h} {puts head=$h} |
| 56 | #method setprincipalbranch {b} {puts pb=$b} |
| 57 | #method deftag {s r} {puts $s=$r } |
| 58 | #method setcomment {c} {puts comment=$c} |
| 59 | #method admindone {} {puts admindone} |
| 60 | #method def {rev date author state next branches} {puts "def $rev $date $author $state $next $branches"} |
| 61 | #method setdesc {d} {puts desc=$d} |
| 62 | #method extend {rev commitmsg deltarange} {puts "extend $commitmsg $deltarange"} |
| @@ -69,55 +72,221 @@ | |
| 69 | } |
| 70 | |
| 71 | # # ## ### ##### ######## ############# |
| 72 | ## Implement the sink |
| 73 | |
| 74 | method begin {} {} |
| 75 | method done {} {} |
| 76 | method admindone {} {} |
| 77 | |
| 78 | method sethead {h} { |
| 79 | set myhead $h |
| 80 | return |
| 81 | } |
| 82 | |
| 83 | method setprincipalbranch {b} { |
| 84 | set myprincipal $b |
| 85 | return |
| 86 | } |
| 87 | |
| 88 | method deftag {symbol rev} { |
| 89 | # Slice symbols into branches and tags, canonical numbers ... |
| 90 | } |
| 91 | |
| 92 | method setcomment {c} {# ignore} |
| 93 | method setdesc {d} {# ignore} |
| 94 | |
| 95 | method def {rev date author state next branches} { |
| 96 | set myrev($rev) [list $date $author $state $next $branches] |
| 97 | $myproject author $author |
| 98 | return |
| 99 | } |
| 100 | |
| 101 | method extend {rev commitmsg deltarange} { |
| 102 | set cm [string trim $commitmsg] |
| 103 | lappend myrev($rev) $cm $deltarange |
| 104 | $myproject cmessage $cm |
| 105 | return |
| 106 | } |
| 107 | |
| 108 | # # ## ### ##### ######## ############# |
| 109 | ## State |
| 110 | |
| 111 | variable mypath {} ; # Path of rcs archive |
| 112 | variable myproject {} ; # Project object the file belongs to. |
| 113 | variable myrev -array {} ; # All revisions and their connections. |
| 114 | variable myhead {} ; # Head revision (rev number) |
| 115 | variable myprincipal {} ; # Principal branch (branch number) |
| 116 | |
| 117 | # # ## ### ##### ######## ############# |
| 118 | ## Internal methods |
| 119 | |
| 120 | pragma -hastypeinfo no ; # no type introspection |
| 121 | pragma -hasinfo no ; # no object introspection |
| 122 | pragma -hastypemethods no ; # type is not relevant. |
| 123 | pragma -simpledispatch yes ; # simple fast dispatch |
| @@ -125,12 +294,16 @@ | |
| 125 | # # ## ### ##### ######## ############# |
| 126 | } |
| 127 | |
| 128 | namespace eval ::vc::fossil::import::cvs { |
| 129 | namespace export file |
| 130 | } |
| 131 | |
| 132 | # # ## ### ##### ######## ############# ##################### |
| 133 | ## Ready |
| 134 | |
| 135 | package provide vc::fossil::import::cvs::file 1.0 |
| 136 | return |
| 137 |
| --- tools/cvs2fossil/lib/c2f_file.tcl | |
| +++ tools/cvs2fossil/lib/c2f_file.tcl | |
| @@ -16,10 +16,12 @@ | |
| 16 | # # ## ### ##### ######## ############# ##################### |
| 17 | ## Requirements |
| 18 | |
| 19 | package require Tcl 8.4 ; # Required runtime. |
| 20 | package require snit ; # OO system. |
| 21 | package require struct::set ; # Set operations. |
| 22 | package require vc::fossil::import::cvs::file::rev ; # CVS per file revisions. |
| 23 | |
| 24 | # # ## ### ##### ######## ############# ##################### |
| 25 | ## |
| 26 | |
| 27 | snit::type ::vc::fossil::import::cvs::file { |
| @@ -30,11 +32,12 @@ | |
| 32 | set mypath $path |
| 33 | set myproject $project |
| 34 | return |
| 35 | } |
| 36 | |
| 37 | method path {} { return $mypath } |
| 38 | method project {} { return $myproject } |
| 39 | |
| 40 | # # ## ### ##### ######## ############# |
| 41 | ## Methods required for the class to be a sink of the rcs parser |
| 42 | |
| 43 | method begin {} {} |
| @@ -52,11 +55,11 @@ | |
| 55 | method extend {rev commitmsg deltarange} {} |
| 56 | |
| 57 | #method begin {} {puts begin} |
| 58 | #method sethead {h} {puts head=$h} |
| 59 | #method setprincipalbranch {b} {puts pb=$b} |
| 60 | #method deftag {s r} {puts $s=$r} |
| 61 | #method setcomment {c} {puts comment=$c} |
| 62 | #method admindone {} {puts admindone} |
| 63 | #method def {rev date author state next branches} {puts "def $rev $date $author $state $next $branches"} |
| 64 | #method setdesc {d} {puts desc=$d} |
| 65 | #method extend {rev commitmsg deltarange} {puts "extend $commitmsg $deltarange"} |
| @@ -69,55 +72,221 @@ | |
| 72 | } |
| 73 | |
| 74 | # # ## ### ##### ######## ############# |
| 75 | ## Implement the sink |
| 76 | |
| 77 | method begin {} {} |
| 78 | method done {} {} |
| 79 | |
| 80 | method admindone {} { |
| 81 | # We do nothing at the boundary of admin and revision data |
| 82 | } |
| 83 | |
| 84 | method sethead {revnr} { |
| 85 | set myhead $revnr |
| 86 | return |
| 87 | } |
| 88 | |
| 89 | method setprincipalbranch {branchnr} { |
| 90 | set myprincipal $branchnr |
| 91 | return |
| 92 | } |
| 93 | |
| 94 | method deftag {name revnr} { |
| 95 | # FUTURE: Perform symbol transformation here. |
| 96 | |
| 97 | if {[struct::set contains $mysymbols $name]} { |
| 98 | trouble fatal "Multiple definitions of the symbol '$name' in '$mypath'" |
| 99 | return |
| 100 | } |
| 101 | |
| 102 | struct::set add mysymbols $name |
| 103 | |
| 104 | if {[rev isbranchrevnr $revnr -> branchnr]} { |
| 105 | $self AddBranch $name $branchnr |
| 106 | } else { |
| 107 | $self AddTag $name $revnr |
| 108 | } |
| 109 | return |
| 110 | } |
| 111 | |
| 112 | method setcomment {c} {# ignore} |
| 113 | method setdesc {d} {# ignore} |
| 114 | |
| 115 | method def {revnr date author state next branches} { |
| 116 | $self LookForUnlabeledBranches $branches |
| 117 | $myproject author $author |
| 118 | |
| 119 | if {[info exists myrev($revnr)]} { |
| 120 | trouble fatal "File $mypath contains duplicate definitions for revision $revnr." |
| 121 | return |
| 122 | } |
| 123 | |
| 124 | set myrev($revnr) [rev %AUTO% $date $author $state $self] |
| 125 | |
| 126 | RecordBasicDependencies $revnr $next |
| 127 | return |
| 128 | } |
| 129 | |
| 130 | method extend {revnr commitmsg deltarange} { |
| 131 | set cm [string trim $commitmsg] |
| 132 | $myproject cmessage $cm |
| 133 | |
| 134 | set rev $myrev($revnr) |
| 135 | |
| 136 | if {[$rev hascommitmsg]} { |
| 137 | # Apparently repositories exist in which the delta data |
| 138 | # for revision 1.1 is provided several times, at least |
| 139 | # twice. The actual cause of this duplication is not |
| 140 | # known. Speculation centers on RCS/CVS bugs, or from |
| 141 | # manual edits of the repository which borked the |
| 142 | # internals. Whatever the cause, testing showed that both |
| 143 | # cvs and rcs use the first definition when performing a |
| 144 | # checkout, and we follow their lead. Side notes: 'cvs |
| 145 | # log' fails on such a file, and 'cvs rlog' prints the log |
| 146 | # message from the first delta, ignoring the second. |
| 147 | |
| 148 | log write 1 file "In file $mypath : Duplicate delta data for revision $revnr" |
| 149 | log write 1 file "Ignoring the duplicate" |
| 150 | return |
| 151 | } |
| 152 | |
| 153 | # Extend the revision with the new information. The revision |
| 154 | # object uses this to complete its meta data set. |
| 155 | |
| 156 | $rev setcommitmsg $cm |
| 157 | $rev settext $deltarange |
| 158 | |
| 159 | # If this is revision 1.1, we have to determine whether the |
| 160 | # file seems to have been created through 'cvs add' instead of |
| 161 | # 'cvs import'. This can be done by looking at the un- |
| 162 | # adulterated commit message, as CVS uses a hardwired magic |
| 163 | # message for the latter, i.e. "Initial revision\n", no |
| 164 | # period. (This fact also helps us when the time comes to |
| 165 | # determine whether this file might have had a default branch |
| 166 | # in the past.) |
| 167 | |
| 168 | if {$revnr eq ""} { |
| 169 | set myimported [expr {$commitmsg eq "Initial revision\n"}] |
| 170 | } |
| 171 | |
| 172 | # Here we also keep track of the order in which the revisions |
| 173 | # were added to the file. |
| 174 | |
| 175 | lappend myrevisions $rev |
| 176 | return |
| 177 | } |
| 178 | |
| 179 | # # ## ### ##### ######## ############# |
| 180 | ## State |
| 181 | |
| 182 | variable mypath {} ; # Path of rcs archive |
| 183 | variable myproject {} ; # Project object the file belongs to. |
| 184 | variable myrev -array {} ; # All revisions and their connections. |
| 185 | variable myrevisions {} ; # Same as myrev, but a list, giving us the order |
| 186 | # ; # of revisions. |
| 187 | variable myhead {} ; # Head revision (revision number) |
| 188 | variable myprincipal {} ; # Principal branch (branch number) |
| 189 | # ; # Contrary to the name this is the default branch. |
| 190 | variable mydependencies {} ; # Dictionary parent -> child, dependency recorder. |
| 191 | variable myimported 0 ; # Boolean flag. Set iff rev 1.1 of the file seemingly |
| 192 | # ; # was imported instead of added normally. |
| 193 | variable myroot {} ; # Revision number of the root revision. Usually '1.1'. |
| 194 | # ; # Can be a different number, because of 'cvsadmin -o'. |
| 195 | variable mybranches -array {} ; # branch number -> symbol object handling the branch |
| 196 | variable mytags -array {} ; # revision number -> list of symbol object for the tags |
| 197 | # ; # associated with the revision. |
| 198 | variable mysymbols {} ; # Set of symbol names found in this file. |
| 199 | |
| 200 | ### TODO ### |
| 201 | ### File flag - executable, |
| 202 | ### RCS mode info (kb, kkb, ...) |
| 203 | |
| 204 | # # ## ### ##### ######## ############# |
| 205 | ## Internal methods |
| 206 | |
| 207 | method LookForUnlabeledBranches {branches} { |
| 208 | foreach branchrevnr $branches { |
| 209 | if {[catch { |
| 210 | set branch [$self Rev2Branch $branchrevnr] |
| 211 | }]} { |
| 212 | set branch [$self AddUnlabeledBranch [rev 2branchnr $branchrevnr]] |
| 213 | } |
| 214 | # TODO $branch child $branchrevnr - when add-unlabeled has sensible return value |
| 215 | } |
| 216 | return |
| 217 | } |
| 218 | |
| 219 | method Rev2Branch {revnr} { |
| 220 | if {[rev istrunkrevnr $revnr]} { |
| 221 | trouble internal "Expected a branch revision number" |
| 222 | } |
| 223 | return $mybranches([rev 2branchnr $revnr]) |
| 224 | } |
| 225 | |
| 226 | method AddUnlabeledBranch {branchnr} { |
| 227 | return [$self AddBranch unlabeled-$branchnr $branchnr] |
| 228 | } |
| 229 | |
| 230 | method AddBranch {name branchnr} { |
| 231 | if {[info exists mybranches($branchnr)]} { |
| 232 | log write 1 file "In '$mypath': Branch '$branchnr' named '[$mybranches($branchnr) name]'" |
| 233 | log write 1 file "Cannot have second name '$name', ignoring it" |
| 234 | return |
| 235 | } |
| 236 | set sym "" |
| 237 | set branch "" |
| 238 | #TODO set sym [$myproject getsymbol $name ] |
| 239 | #TODO set tag [sym %AUTO% branch $sym $branchnr] |
| 240 | set mybranches($branchnr) $branch |
| 241 | return $branch |
| 242 | } |
| 243 | |
| 244 | method AddTag {name revnr} { |
| 245 | set sym "" |
| 246 | set tag "" |
| 247 | #TODO set sym [$myproject getsymbol $name ] |
| 248 | #TODO set tag [sym %AUTO% tag $sym $revnr] |
| 249 | lappend mytags($revnr) $tag |
| 250 | return $tag |
| 251 | } |
| 252 | |
| 253 | proc RecordBasicDependencies {revnr next} { |
| 254 | # Handle the revision dependencies. Record them for now, do |
| 255 | # nothing with them yet. |
| 256 | |
| 257 | # On the trunk the 'next' field points to the previous |
| 258 | # revision, i.e. the _parent_ of the current one. Example: |
| 259 | # 1.6's next is 1.5 (modulo cvs admin -o). |
| 260 | |
| 261 | # Contrarily on a branch the 'next' field points to the |
| 262 | # primary _child_ of the current revision. As example, |
| 263 | # 1.1.3.2's 'next' will be 1.1.3.3. |
| 264 | |
| 265 | # The 'next' field actually always refers to the revision |
| 266 | # containing the delta needed to retrieve that revision. |
| 267 | |
| 268 | # The dependencies needed here are the logical structure, |
| 269 | # parent/child, and not the implementation dependent delta |
| 270 | # pointers. |
| 271 | |
| 272 | if {$next eq ""} return |
| 273 | |
| 274 | upvar 1 mydependencies mydependencies |
| 275 | |
| 276 | # parent -> child |
| 277 | if {[rev istrunkrevnr $revnr]} { |
| 278 | lappend mydependencies $next $revnr |
| 279 | } else { |
| 280 | lappend mydependencies $revnr $next |
| 281 | } |
| 282 | return |
| 283 | } |
| 284 | |
| 285 | |
| 286 | # # ## ### ##### ######## ############# |
| 287 | ## Configuration |
| 288 | |
| 289 | pragma -hastypeinfo no ; # no type introspection |
| 290 | pragma -hasinfo no ; # no object introspection |
| 291 | pragma -hastypemethods no ; # type is not relevant. |
| 292 | pragma -simpledispatch yes ; # simple fast dispatch |
| @@ -125,12 +294,16 @@ | |
| 294 | # # ## ### ##### ######## ############# |
| 295 | } |
| 296 | |
| 297 | namespace eval ::vc::fossil::import::cvs { |
| 298 | namespace export file |
| 299 | namespace eval file { |
| 300 | # Import not required, already a child namespace. |
| 301 | # namespace import vc::fossil::import::cvs::file::rev |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | # # ## ### ##### ######## ############# ##################### |
| 306 | ## Ready |
| 307 | |
| 308 | package provide vc::fossil::import::cvs::file 1.0 |
| 309 | return |
| 310 |
+47
-2
| --- tools/cvs2fossil/lib/c2f_frev.tcl | ||
| +++ tools/cvs2fossil/lib/c2f_frev.tcl | ||
| @@ -23,26 +23,71 @@ | ||
| 23 | 23 | |
| 24 | 24 | snit::type ::vc::fossil::import::cvs::file::rev { |
| 25 | 25 | # # ## ### ##### ######## ############# |
| 26 | 26 | ## Public API |
| 27 | 27 | |
| 28 | - constructor {} { | |
| 28 | + constructor {date author state thefile} { | |
| 29 | 29 | return |
| 30 | 30 | } |
| 31 | + | |
| 32 | + method hascommitmsg {} { | |
| 33 | + # TODO: check that we have the commit message | |
| 34 | + return 0 | |
| 35 | + } | |
| 36 | + | |
| 37 | + method setcommitmsg {cm} { | |
| 38 | + } | |
| 39 | + | |
| 40 | + method settext {text} { | |
| 41 | + } | |
| 42 | + | |
| 43 | + # # ## ### ##### ######## ############# | |
| 44 | + ## Type API | |
| 45 | + | |
| 46 | + typemethod istrunkrevnr {revnr} { | |
| 47 | + return [expr {[llength [split $revnr .]] == 1}] | |
| 48 | + } | |
| 49 | + | |
| 50 | + typemethod 2branchnr {revnr} { | |
| 51 | + # Input is a branch revision number, i.e. a revision number | |
| 52 | + # with an even number of components; for example '2.9.2.1' | |
| 53 | + # (never '2.9.2' nor '2.9.0.2'). The return value is the | |
| 54 | + # branch number (for example, '2.9.2'). For trunk revisions, | |
| 55 | + # like '3.4', we return the empty string. | |
| 56 | + | |
| 57 | + if {[$type istrunkrevnr $revnr]} { | |
| 58 | + return "" | |
| 59 | + } | |
| 60 | + return [join [lrange [split $revnr .] 0 end-1] .] | |
| 61 | + } | |
| 62 | + | |
| 63 | + typemethod isbranchrevnr {revnr _ bv} { | |
| 64 | + if {[regexp $mybranchpattern $revnr -> head tail]} { | |
| 65 | + upvar 1 $bv branchnr | |
| 66 | + set branchnr ${head}.$tail | |
| 67 | + return 1 | |
| 68 | + } | |
| 69 | + return 0 | |
| 70 | + } | |
| 31 | 71 | |
| 32 | 72 | # # ## ### ##### ######## ############# |
| 33 | 73 | ## State |
| 74 | + | |
| 75 | + typevariable mybranchpattern {^((?:\d+\.\d+\.)+)(?:0\.)?(\d+)$} | |
| 76 | + # First a nonzero even number of digit groups with trailing dot | |
| 77 | + # CVS then sticks an extra 0 in here; RCS does not. | |
| 78 | + # And the last digit group. | |
| 34 | 79 | |
| 35 | 80 | # # ## ### ##### ######## ############# |
| 36 | 81 | ## Internal methods |
| 37 | 82 | |
| 38 | 83 | # # ## ### ##### ######## ############# |
| 39 | 84 | ## Configuration |
| 40 | 85 | |
| 41 | 86 | pragma -hastypeinfo no ; # no type introspection |
| 42 | 87 | pragma -hasinfo no ; # no object introspection |
| 43 | - pragma -hastypemethods no ; # type is not relevant. | |
| 88 | + #pragma -hastypemethods no ; # type is not relevant. | |
| 44 | 89 | pragma -simpledispatch yes ; # simple fast dispatch |
| 45 | 90 | |
| 46 | 91 | # # ## ### ##### ######## ############# |
| 47 | 92 | } |
| 48 | 93 | |
| 49 | 94 |
| --- tools/cvs2fossil/lib/c2f_frev.tcl | |
| +++ tools/cvs2fossil/lib/c2f_frev.tcl | |
| @@ -23,26 +23,71 @@ | |
| 23 | |
| 24 | snit::type ::vc::fossil::import::cvs::file::rev { |
| 25 | # # ## ### ##### ######## ############# |
| 26 | ## Public API |
| 27 | |
| 28 | constructor {} { |
| 29 | return |
| 30 | } |
| 31 | |
| 32 | # # ## ### ##### ######## ############# |
| 33 | ## State |
| 34 | |
| 35 | # # ## ### ##### ######## ############# |
| 36 | ## Internal methods |
| 37 | |
| 38 | # # ## ### ##### ######## ############# |
| 39 | ## Configuration |
| 40 | |
| 41 | pragma -hastypeinfo no ; # no type introspection |
| 42 | pragma -hasinfo no ; # no object introspection |
| 43 | pragma -hastypemethods no ; # type is not relevant. |
| 44 | pragma -simpledispatch yes ; # simple fast dispatch |
| 45 | |
| 46 | # # ## ### ##### ######## ############# |
| 47 | } |
| 48 | |
| 49 |
| --- tools/cvs2fossil/lib/c2f_frev.tcl | |
| +++ tools/cvs2fossil/lib/c2f_frev.tcl | |
| @@ -23,26 +23,71 @@ | |
| 23 | |
| 24 | snit::type ::vc::fossil::import::cvs::file::rev { |
| 25 | # # ## ### ##### ######## ############# |
| 26 | ## Public API |
| 27 | |
| 28 | constructor {date author state thefile} { |
| 29 | return |
| 30 | } |
| 31 | |
| 32 | method hascommitmsg {} { |
| 33 | # TODO: check that we have the commit message |
| 34 | return 0 |
| 35 | } |
| 36 | |
| 37 | method setcommitmsg {cm} { |
| 38 | } |
| 39 | |
| 40 | method settext {text} { |
| 41 | } |
| 42 | |
| 43 | # # ## ### ##### ######## ############# |
| 44 | ## Type API |
| 45 | |
| 46 | typemethod istrunkrevnr {revnr} { |
| 47 | return [expr {[llength [split $revnr .]] == 1}] |
| 48 | } |
| 49 | |
| 50 | typemethod 2branchnr {revnr} { |
| 51 | # Input is a branch revision number, i.e. a revision number |
| 52 | # with an even number of components; for example '2.9.2.1' |
| 53 | # (never '2.9.2' nor '2.9.0.2'). The return value is the |
| 54 | # branch number (for example, '2.9.2'). For trunk revisions, |
| 55 | # like '3.4', we return the empty string. |
| 56 | |
| 57 | if {[$type istrunkrevnr $revnr]} { |
| 58 | return "" |
| 59 | } |
| 60 | return [join [lrange [split $revnr .] 0 end-1] .] |
| 61 | } |
| 62 | |
| 63 | typemethod isbranchrevnr {revnr _ bv} { |
| 64 | if {[regexp $mybranchpattern $revnr -> head tail]} { |
| 65 | upvar 1 $bv branchnr |
| 66 | set branchnr ${head}.$tail |
| 67 | return 1 |
| 68 | } |
| 69 | return 0 |
| 70 | } |
| 71 | |
| 72 | # # ## ### ##### ######## ############# |
| 73 | ## State |
| 74 | |
| 75 | typevariable mybranchpattern {^((?:\d+\.\d+\.)+)(?:0\.)?(\d+)$} |
| 76 | # First a nonzero even number of digit groups with trailing dot |
| 77 | # CVS then sticks an extra 0 in here; RCS does not. |
| 78 | # And the last digit group. |
| 79 | |
| 80 | # # ## ### ##### ######## ############# |
| 81 | ## Internal methods |
| 82 | |
| 83 | # # ## ### ##### ######## ############# |
| 84 | ## Configuration |
| 85 | |
| 86 | pragma -hastypeinfo no ; # no type introspection |
| 87 | pragma -hasinfo no ; # no object introspection |
| 88 | #pragma -hastypemethods no ; # type is not relevant. |
| 89 | pragma -simpledispatch yes ; # simple fast dispatch |
| 90 | |
| 91 | # # ## ### ##### ######## ############# |
| 92 | } |
| 93 | |
| 94 |