Fossil SCM
Redid the logging system aka user feedback completely. Verbosity levels, influenced by the new -v switch. Indentations in the output removed, parsing by tools easier, still human readable. Adapted all users of the previous feedback code to use the new system.
Commit
be32ebcb41cfeabaf07dcc60ebbb2166fff76483
Parent
8469631cc984252…
6 files changed
+30
-48
+33
-47
+10
-26
+98
+1
+45
-41
+30
-48
| --- tools/import-cvs.tcl | ||
| +++ tools/import-cvs.tcl | ||
| @@ -42,63 +42,64 @@ | ||
| 42 | 42 | # Requirements |
| 43 | 43 | |
| 44 | 44 | package require Tcl 8.4 |
| 45 | 45 | package require cvs ; # Frontend, reading from source repository |
| 46 | 46 | package require fossil ; # Backend, writing to destination repository. |
| 47 | +package require tools::log | |
| 48 | + | |
| 49 | +::tools::log::system import | |
| 47 | 50 | |
| 48 | 51 | # ----------------------------------------------------------------------------- |
| 49 | 52 | |
| 50 | 53 | proc main {} { |
| 51 | - global argv tot nto cvs fossil ntrunk stopat | |
| 54 | + global argv tot nto cvs fossil ntrunk stopat nmax ntfmt nmfmt | |
| 52 | 55 | |
| 53 | 56 | commandline |
| 54 | 57 | |
| 55 | - fossil::feedback Write ; # Setup progress feedback from the libraries | |
| 56 | - cvs::feedback Write | |
| 57 | - | |
| 58 | 58 | cvs::at $cvs ; # Define location of CVS repository |
| 59 | 59 | cvs::scan ; # Gather revision data from the archives |
| 60 | 60 | cvs::csets ; # Group changes into sets |
| 61 | 61 | cvs::rtree ; # Build revision tree (trunk only right now). |
| 62 | 62 | |
| 63 | 63 | set tot 0.0 |
| 64 | 64 | set nto 0 |
| 65 | 65 | |
| 66 | - Write info {Importing ...} | |
| 67 | - Write info { Setting up cvs workspace and temporary fossil repository} | |
| 66 | + ::tools::log::write 0 import {Begin conversion} | |
| 67 | + ::tools::log::write 0 import {Setting up workspaces} | |
| 68 | 68 | |
| 69 | 69 | cvs::workspace ; # cd's to workspace |
| 70 | 70 | fossil::new ; # Uses cwd as workspace to connect to. |
| 71 | 71 | |
| 72 | - set ntrunk [cvs::ntrunk] | |
| 72 | + set ntrunk [cvs::ntrunk] ; set ntfmt %[string length $ntrunk]s | |
| 73 | + set nmax [cvs::ncsets] ; set nmfmt %[string length $nmax]s | |
| 74 | + | |
| 73 | 75 | cvs::foreach_cset cset [cvs::root] { |
| 74 | 76 | import $cset |
| 75 | 77 | if {$stopat == $cset} exit |
| 76 | 78 | } |
| 77 | 79 | cvs::wsclear |
| 78 | 80 | |
| 79 | - Write info " ========= [string repeat = 61]" | |
| 80 | - Write info " Imported $nto [expr {($nto == 1) ? "changeset" : "changesets"}]" | |
| 81 | - Write info " Within [format %.2f $tot] seconds (avg [format %.2f [expr {$tot/$nto}]] seconds/changeset)" | |
| 82 | - | |
| 83 | - Write info { Moving to final destination} | |
| 81 | + ::tools::log::write 0 import "========= [string repeat = 61]" | |
| 82 | + ::tools::log::write 0 import "Imported $nto [expr {($nto == 1) ? "changeset" : "changesets"}]" | |
| 83 | + ::tools::log::write 0 import "Within [format %.2f $tot] seconds (avg [format %.2f [expr {$tot/$nto}]] seconds/changeset)" | |
| 84 | 84 | |
| 85 | 85 | fossil::destination $fossil |
| 86 | 86 | |
| 87 | - Write info Ok. | |
| 87 | + ::tools::log::write 0 import Ok. | |
| 88 | 88 | return |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | |
| 92 | 92 | # ----------------------------------------------------------------------------- |
| 93 | 93 | |
| 94 | 94 | proc commandline {} { |
| 95 | - global argv cvs fossil nosign log debugcommit stopat | |
| 95 | + global argv cvs fossil nosign debugcommit stopat | |
| 96 | 96 | |
| 97 | 97 | set nosign 0 |
| 98 | 98 | set debugcommit 0 |
| 99 | 99 | set stopat {} |
| 100 | + set verbosity 0 | |
| 100 | 101 | |
| 101 | 102 | while {[string match "-*" [set opt [lindex $argv 0]]]} { |
| 102 | 103 | if {$opt eq "--nosign"} { |
| 103 | 104 | set nosign 1 |
| 104 | 105 | set argv [lrange $argv 1 end] |
| @@ -111,10 +112,16 @@ | ||
| 111 | 112 | } |
| 112 | 113 | if {$opt eq "--stopat"} { |
| 113 | 114 | set stopat [lindex $argv 1] |
| 114 | 115 | set argv [lrange $argv 2 end] |
| 115 | 116 | continue |
| 117 | + } | |
| 118 | + if {$opt eq "-v"} { | |
| 119 | + incr verbosity | |
| 120 | + ::tools::log::verbosity $verbosity | |
| 121 | + set argv [lrange $argv 1 end] | |
| 122 | + continue | |
| 116 | 123 | } |
| 117 | 124 | usage |
| 118 | 125 | } |
| 119 | 126 | if {[llength $argv] != 2} usage |
| 120 | 127 | foreach {cvs fossil} $argv break |
| @@ -127,12 +134,10 @@ | ||
| 127 | 134 | usage "CVS directory missing, not readable, or not a directory." |
| 128 | 135 | } elseif {[file exists $fossil]} { |
| 129 | 136 | usage "Fossil destination repository exists already." |
| 130 | 137 | } |
| 131 | 138 | |
| 132 | - set log [open ${fossil}.log w] | |
| 133 | - | |
| 134 | 139 | fossil::debugcommit $debugcommit |
| 135 | 140 | return |
| 136 | 141 | } |
| 137 | 142 | |
| 138 | 143 | proc usage {{text {}}} { |
| @@ -142,19 +147,18 @@ | ||
| 142 | 147 | puts stderr " $text" |
| 143 | 148 | exit |
| 144 | 149 | } |
| 145 | 150 | |
| 146 | 151 | proc import {cset} { |
| 147 | - global tot nto nosign ntrunk stopat | |
| 148 | - Write info " Importing $cset [string repeat = [expr {60 - [string length $cset]}]]" | |
| 149 | - Write info " At $nto/$ntrunk ([format %.2f [expr {$nto*100.0/$ntrunk}]]%)" | |
| 152 | + global tot nto nosign ntrunk stopat ntfmt nmfmt | |
| 153 | + ::tools::log::write 0 import "ChangeSet [format $nmfmt $cset] @ [format $ntfmt $nto]/$ntrunk ([format %6.2f [expr {$nto*100.0/$ntrunk}]]%)" | |
| 150 | 154 | |
| 151 | 155 | if {$stopat == $cset} { |
| 152 | 156 | fossil::commit 1 cvs2fossil $nosign \ |
| 153 | 157 | [cvs::wssetup $cset] \ |
| 154 | 158 | ::cvs::wsignore |
| 155 | - Write info " %% STOP" | |
| 159 | + ::tools::log::write 1 import {%% STOP} | |
| 156 | 160 | return |
| 157 | 161 | } |
| 158 | 162 | |
| 159 | 163 | set usec [lindex [time { |
| 160 | 164 | foreach {uuid ad rm ch} [fossil::commit 0 cvs2fossil $nosign \ |
| @@ -165,45 +169,23 @@ | ||
| 165 | 169 | |
| 166 | 170 | set sec [expr {$usec/1e6}] |
| 167 | 171 | set tot [expr {$tot + $sec}] |
| 168 | 172 | incr nto |
| 169 | 173 | |
| 170 | - Write info " == $uuid +${ad}-${rm}*${ch}" | |
| 171 | - Write info " in $sec seconds" | |
| 174 | + ::tools::log::write 2 import "== $uuid +${ad}-${rm}*${ch}" | |
| 175 | + ::tools::log::write 2 import "st in [format %.2f $sec] sec" | |
| 172 | 176 | |
| 173 | 177 | set avg [expr {$tot/$nto}] |
| 174 | 178 | set max [expr {$ntrunk * $avg}] |
| 175 | 179 | set rem [expr {$max - $tot}] |
| 176 | 180 | |
| 177 | - Write info " st avg [format %.2f $avg]" | |
| 178 | - Write info " st run [format %7.2f $tot] sec [format %6.2f [expr {$tot/60}]] min [format %5.2f [expr {$tot/3600}]] hr" | |
| 179 | - Write info " st end [format %7.2f $max] sec [format %6.2f [expr {$max/60}]] min [format %5.2f [expr {$max/3600}]] hr" | |
| 180 | - Write info " st rem [format %7.2f $rem] sec [format %6.2f [expr {$rem/60}]] min [format %5.2f [expr {$rem/3600}]] hr" | |
| 181 | - return | |
| 182 | -} | |
| 183 | - | |
| 184 | -# ----------------------------------------------------------------------------- | |
| 185 | - | |
| 186 | -array set fl { | |
| 187 | - debug {DEBUG } | |
| 188 | - info { } | |
| 189 | - warning {Warning} | |
| 190 | - error {ERROR } | |
| 191 | -} | |
| 192 | - | |
| 193 | -proc Write {l t} { | |
| 194 | - global fl log | |
| 195 | - | |
| 196 | - if {[string index $t 0] eq "\r"} { | |
| 197 | - puts -nonewline stdout "\r$fl($l) [string range $t 0 end-1]" | |
| 198 | - } else { | |
| 199 | - puts stdout "$fl($l) $t" | |
| 200 | - puts $log "$fl($l) $t" | |
| 201 | - } | |
| 202 | - flush stdout | |
| 181 | + ::tools::log::write 3 import "st avg [format %.2f $avg] sec" | |
| 182 | + ::tools::log::write 3 import "st run [format %7.2f $tot] sec [format %6.2f [expr {$tot/60}]] min [format %5.2f [expr {$tot/3600}]] hr" | |
| 183 | + ::tools::log::write 3 import "st end [format %7.2f $max] sec [format %6.2f [expr {$max/60}]] min [format %5.2f [expr {$max/3600}]] hr" | |
| 184 | + ::tools::log::write 3 import "st rem [format %7.2f $rem] sec [format %6.2f [expr {$rem/60}]] min [format %5.2f [expr {$rem/3600}]] hr" | |
| 203 | 185 | return |
| 204 | 186 | } |
| 205 | 187 | |
| 206 | 188 | # ----------------------------------------------------------------------------- |
| 207 | 189 | |
| 208 | 190 | main |
| 209 | 191 | exit |
| 210 | 192 |
| --- tools/import-cvs.tcl | |
| +++ tools/import-cvs.tcl | |
| @@ -42,63 +42,64 @@ | |
| 42 | # Requirements |
| 43 | |
| 44 | package require Tcl 8.4 |
| 45 | package require cvs ; # Frontend, reading from source repository |
| 46 | package require fossil ; # Backend, writing to destination repository. |
| 47 | |
| 48 | # ----------------------------------------------------------------------------- |
| 49 | |
| 50 | proc main {} { |
| 51 | global argv tot nto cvs fossil ntrunk stopat |
| 52 | |
| 53 | commandline |
| 54 | |
| 55 | fossil::feedback Write ; # Setup progress feedback from the libraries |
| 56 | cvs::feedback Write |
| 57 | |
| 58 | cvs::at $cvs ; # Define location of CVS repository |
| 59 | cvs::scan ; # Gather revision data from the archives |
| 60 | cvs::csets ; # Group changes into sets |
| 61 | cvs::rtree ; # Build revision tree (trunk only right now). |
| 62 | |
| 63 | set tot 0.0 |
| 64 | set nto 0 |
| 65 | |
| 66 | Write info {Importing ...} |
| 67 | Write info { Setting up cvs workspace and temporary fossil repository} |
| 68 | |
| 69 | cvs::workspace ; # cd's to workspace |
| 70 | fossil::new ; # Uses cwd as workspace to connect to. |
| 71 | |
| 72 | set ntrunk [cvs::ntrunk] |
| 73 | cvs::foreach_cset cset [cvs::root] { |
| 74 | import $cset |
| 75 | if {$stopat == $cset} exit |
| 76 | } |
| 77 | cvs::wsclear |
| 78 | |
| 79 | Write info " ========= [string repeat = 61]" |
| 80 | Write info " Imported $nto [expr {($nto == 1) ? "changeset" : "changesets"}]" |
| 81 | Write info " Within [format %.2f $tot] seconds (avg [format %.2f [expr {$tot/$nto}]] seconds/changeset)" |
| 82 | |
| 83 | Write info { Moving to final destination} |
| 84 | |
| 85 | fossil::destination $fossil |
| 86 | |
| 87 | Write info Ok. |
| 88 | return |
| 89 | } |
| 90 | |
| 91 | |
| 92 | # ----------------------------------------------------------------------------- |
| 93 | |
| 94 | proc commandline {} { |
| 95 | global argv cvs fossil nosign log debugcommit stopat |
| 96 | |
| 97 | set nosign 0 |
| 98 | set debugcommit 0 |
| 99 | set stopat {} |
| 100 | |
| 101 | while {[string match "-*" [set opt [lindex $argv 0]]]} { |
| 102 | if {$opt eq "--nosign"} { |
| 103 | set nosign 1 |
| 104 | set argv [lrange $argv 1 end] |
| @@ -111,10 +112,16 @@ | |
| 111 | } |
| 112 | if {$opt eq "--stopat"} { |
| 113 | set stopat [lindex $argv 1] |
| 114 | set argv [lrange $argv 2 end] |
| 115 | continue |
| 116 | } |
| 117 | usage |
| 118 | } |
| 119 | if {[llength $argv] != 2} usage |
| 120 | foreach {cvs fossil} $argv break |
| @@ -127,12 +134,10 @@ | |
| 127 | usage "CVS directory missing, not readable, or not a directory." |
| 128 | } elseif {[file exists $fossil]} { |
| 129 | usage "Fossil destination repository exists already." |
| 130 | } |
| 131 | |
| 132 | set log [open ${fossil}.log w] |
| 133 | |
| 134 | fossil::debugcommit $debugcommit |
| 135 | return |
| 136 | } |
| 137 | |
| 138 | proc usage {{text {}}} { |
| @@ -142,19 +147,18 @@ | |
| 142 | puts stderr " $text" |
| 143 | exit |
| 144 | } |
| 145 | |
| 146 | proc import {cset} { |
| 147 | global tot nto nosign ntrunk stopat |
| 148 | Write info " Importing $cset [string repeat = [expr {60 - [string length $cset]}]]" |
| 149 | Write info " At $nto/$ntrunk ([format %.2f [expr {$nto*100.0/$ntrunk}]]%)" |
| 150 | |
| 151 | if {$stopat == $cset} { |
| 152 | fossil::commit 1 cvs2fossil $nosign \ |
| 153 | [cvs::wssetup $cset] \ |
| 154 | ::cvs::wsignore |
| 155 | Write info " %% STOP" |
| 156 | return |
| 157 | } |
| 158 | |
| 159 | set usec [lindex [time { |
| 160 | foreach {uuid ad rm ch} [fossil::commit 0 cvs2fossil $nosign \ |
| @@ -165,45 +169,23 @@ | |
| 165 | |
| 166 | set sec [expr {$usec/1e6}] |
| 167 | set tot [expr {$tot + $sec}] |
| 168 | incr nto |
| 169 | |
| 170 | Write info " == $uuid +${ad}-${rm}*${ch}" |
| 171 | Write info " in $sec seconds" |
| 172 | |
| 173 | set avg [expr {$tot/$nto}] |
| 174 | set max [expr {$ntrunk * $avg}] |
| 175 | set rem [expr {$max - $tot}] |
| 176 | |
| 177 | Write info " st avg [format %.2f $avg]" |
| 178 | Write info " st run [format %7.2f $tot] sec [format %6.2f [expr {$tot/60}]] min [format %5.2f [expr {$tot/3600}]] hr" |
| 179 | Write info " st end [format %7.2f $max] sec [format %6.2f [expr {$max/60}]] min [format %5.2f [expr {$max/3600}]] hr" |
| 180 | Write info " st rem [format %7.2f $rem] sec [format %6.2f [expr {$rem/60}]] min [format %5.2f [expr {$rem/3600}]] hr" |
| 181 | return |
| 182 | } |
| 183 | |
| 184 | # ----------------------------------------------------------------------------- |
| 185 | |
| 186 | array set fl { |
| 187 | debug {DEBUG } |
| 188 | info { } |
| 189 | warning {Warning} |
| 190 | error {ERROR } |
| 191 | } |
| 192 | |
| 193 | proc Write {l t} { |
| 194 | global fl log |
| 195 | |
| 196 | if {[string index $t 0] eq "\r"} { |
| 197 | puts -nonewline stdout "\r$fl($l) [string range $t 0 end-1]" |
| 198 | } else { |
| 199 | puts stdout "$fl($l) $t" |
| 200 | puts $log "$fl($l) $t" |
| 201 | } |
| 202 | flush stdout |
| 203 | return |
| 204 | } |
| 205 | |
| 206 | # ----------------------------------------------------------------------------- |
| 207 | |
| 208 | main |
| 209 | exit |
| 210 |
| --- tools/import-cvs.tcl | |
| +++ tools/import-cvs.tcl | |
| @@ -42,63 +42,64 @@ | |
| 42 | # Requirements |
| 43 | |
| 44 | package require Tcl 8.4 |
| 45 | package require cvs ; # Frontend, reading from source repository |
| 46 | package require fossil ; # Backend, writing to destination repository. |
| 47 | package require tools::log |
| 48 | |
| 49 | ::tools::log::system import |
| 50 | |
| 51 | # ----------------------------------------------------------------------------- |
| 52 | |
| 53 | proc main {} { |
| 54 | global argv tot nto cvs fossil ntrunk stopat nmax ntfmt nmfmt |
| 55 | |
| 56 | commandline |
| 57 | |
| 58 | cvs::at $cvs ; # Define location of CVS repository |
| 59 | cvs::scan ; # Gather revision data from the archives |
| 60 | cvs::csets ; # Group changes into sets |
| 61 | cvs::rtree ; # Build revision tree (trunk only right now). |
| 62 | |
| 63 | set tot 0.0 |
| 64 | set nto 0 |
| 65 | |
| 66 | ::tools::log::write 0 import {Begin conversion} |
| 67 | ::tools::log::write 0 import {Setting up workspaces} |
| 68 | |
| 69 | cvs::workspace ; # cd's to workspace |
| 70 | fossil::new ; # Uses cwd as workspace to connect to. |
| 71 | |
| 72 | set ntrunk [cvs::ntrunk] ; set ntfmt %[string length $ntrunk]s |
| 73 | set nmax [cvs::ncsets] ; set nmfmt %[string length $nmax]s |
| 74 | |
| 75 | cvs::foreach_cset cset [cvs::root] { |
| 76 | import $cset |
| 77 | if {$stopat == $cset} exit |
| 78 | } |
| 79 | cvs::wsclear |
| 80 | |
| 81 | ::tools::log::write 0 import "========= [string repeat = 61]" |
| 82 | ::tools::log::write 0 import "Imported $nto [expr {($nto == 1) ? "changeset" : "changesets"}]" |
| 83 | ::tools::log::write 0 import "Within [format %.2f $tot] seconds (avg [format %.2f [expr {$tot/$nto}]] seconds/changeset)" |
| 84 | |
| 85 | fossil::destination $fossil |
| 86 | |
| 87 | ::tools::log::write 0 import Ok. |
| 88 | return |
| 89 | } |
| 90 | |
| 91 | |
| 92 | # ----------------------------------------------------------------------------- |
| 93 | |
| 94 | proc commandline {} { |
| 95 | global argv cvs fossil nosign debugcommit stopat |
| 96 | |
| 97 | set nosign 0 |
| 98 | set debugcommit 0 |
| 99 | set stopat {} |
| 100 | set verbosity 0 |
| 101 | |
| 102 | while {[string match "-*" [set opt [lindex $argv 0]]]} { |
| 103 | if {$opt eq "--nosign"} { |
| 104 | set nosign 1 |
| 105 | set argv [lrange $argv 1 end] |
| @@ -111,10 +112,16 @@ | |
| 112 | } |
| 113 | if {$opt eq "--stopat"} { |
| 114 | set stopat [lindex $argv 1] |
| 115 | set argv [lrange $argv 2 end] |
| 116 | continue |
| 117 | } |
| 118 | if {$opt eq "-v"} { |
| 119 | incr verbosity |
| 120 | ::tools::log::verbosity $verbosity |
| 121 | set argv [lrange $argv 1 end] |
| 122 | continue |
| 123 | } |
| 124 | usage |
| 125 | } |
| 126 | if {[llength $argv] != 2} usage |
| 127 | foreach {cvs fossil} $argv break |
| @@ -127,12 +134,10 @@ | |
| 134 | usage "CVS directory missing, not readable, or not a directory." |
| 135 | } elseif {[file exists $fossil]} { |
| 136 | usage "Fossil destination repository exists already." |
| 137 | } |
| 138 | |
| 139 | fossil::debugcommit $debugcommit |
| 140 | return |
| 141 | } |
| 142 | |
| 143 | proc usage {{text {}}} { |
| @@ -142,19 +147,18 @@ | |
| 147 | puts stderr " $text" |
| 148 | exit |
| 149 | } |
| 150 | |
| 151 | proc import {cset} { |
| 152 | global tot nto nosign ntrunk stopat ntfmt nmfmt |
| 153 | ::tools::log::write 0 import "ChangeSet [format $nmfmt $cset] @ [format $ntfmt $nto]/$ntrunk ([format %6.2f [expr {$nto*100.0/$ntrunk}]]%)" |
| 154 | |
| 155 | if {$stopat == $cset} { |
| 156 | fossil::commit 1 cvs2fossil $nosign \ |
| 157 | [cvs::wssetup $cset] \ |
| 158 | ::cvs::wsignore |
| 159 | ::tools::log::write 1 import {%% STOP} |
| 160 | return |
| 161 | } |
| 162 | |
| 163 | set usec [lindex [time { |
| 164 | foreach {uuid ad rm ch} [fossil::commit 0 cvs2fossil $nosign \ |
| @@ -165,45 +169,23 @@ | |
| 169 | |
| 170 | set sec [expr {$usec/1e6}] |
| 171 | set tot [expr {$tot + $sec}] |
| 172 | incr nto |
| 173 | |
| 174 | ::tools::log::write 2 import "== $uuid +${ad}-${rm}*${ch}" |
| 175 | ::tools::log::write 2 import "st in [format %.2f $sec] sec" |
| 176 | |
| 177 | set avg [expr {$tot/$nto}] |
| 178 | set max [expr {$ntrunk * $avg}] |
| 179 | set rem [expr {$max - $tot}] |
| 180 | |
| 181 | ::tools::log::write 3 import "st avg [format %.2f $avg] sec" |
| 182 | ::tools::log::write 3 import "st run [format %7.2f $tot] sec [format %6.2f [expr {$tot/60}]] min [format %5.2f [expr {$tot/3600}]] hr" |
| 183 | ::tools::log::write 3 import "st end [format %7.2f $max] sec [format %6.2f [expr {$max/60}]] min [format %5.2f [expr {$max/3600}]] hr" |
| 184 | ::tools::log::write 3 import "st rem [format %7.2f $rem] sec [format %6.2f [expr {$rem/60}]] min [format %5.2f [expr {$rem/3600}]] hr" |
| 185 | return |
| 186 | } |
| 187 | |
| 188 | # ----------------------------------------------------------------------------- |
| 189 | |
| 190 | main |
| 191 | exit |
| 192 |
+33
-47
| --- tools/lib/cvs.tcl | ||
| +++ tools/lib/cvs.tcl | ||
| @@ -3,59 +3,56 @@ | ||
| 3 | 3 | |
| 4 | 4 | # ----------------------------------------------------------------------------- |
| 5 | 5 | # Requirements |
| 6 | 6 | |
| 7 | 7 | package require Tcl 8.4 |
| 8 | -package require fileutil ; # Tcllib (cat) | |
| 9 | -package require rcsparser ; # Handling the RCS archive files. | |
| 8 | +package require fileutil ; # Tcllib (traverse directory hierarchy) | |
| 9 | +package require rcsparser ; # Handling the RCS archive files. | |
| 10 | +package require tools::log ; # User feedback | |
| 10 | 11 | package require struct::tree |
| 11 | 12 | |
| 12 | -namespace eval ::cvs {} | |
| 13 | +namespace eval ::cvs { | |
| 14 | + tools::log::system cvs | |
| 15 | + namespace import ::tools::log::write | |
| 16 | +} | |
| 13 | 17 | |
| 14 | 18 | # ----------------------------------------------------------------------------- |
| 15 | 19 | # API |
| 16 | 20 | |
| 17 | 21 | # Define repository directory. |
| 18 | 22 | |
| 19 | 23 | proc ::cvs::at {path} { |
| 20 | 24 | variable base [file normalize $path] |
| 25 | + write 0 cvs "Base: $base" | |
| 21 | 26 | return |
| 22 | 27 | } |
| 23 | 28 | |
| 24 | 29 | namespace eval ::cvs { |
| 25 | 30 | # Toplevel repository directory |
| 26 | 31 | variable base {} |
| 27 | 32 | } |
| 28 | 33 | |
| 29 | -# Define logging callback command | |
| 30 | - | |
| 31 | -proc ::cvs::feedback {logcmd} { | |
| 32 | - variable lc $logcmd | |
| 33 | - ::rcsparser::feedback $logcmd | |
| 34 | - return | |
| 35 | -} | |
| 36 | - | |
| 37 | 34 | # Scan repository, collect archives, parse them, and collect revision |
| 38 | 35 | # information (file, revision -> date, author, commit message) |
| 39 | 36 | |
| 40 | 37 | proc ::cvs::scan {} { |
| 41 | 38 | variable base |
| 42 | 39 | variable npaths |
| 43 | 40 | variable rpaths |
| 44 | 41 | variable timeline |
| 45 | 42 | |
| 46 | - Log info "Scanning CVS tree $base" | |
| 43 | + write 0 cvs {Scanning directory hierarchy} | |
| 47 | 44 | |
| 48 | 45 | set n 0 |
| 49 | 46 | foreach rcs [fileutil::findByPattern $base -glob *,v] { |
| 50 | 47 | set rcs [fileutil::stripPath $base $rcs] |
| 51 | 48 | # Now rcs is relative to base |
| 52 | 49 | |
| 53 | - Log info " Parsing archive $rcs" | |
| 50 | + write 1 cvs "Archive $rcs" | |
| 54 | 51 | |
| 55 | 52 | if {[string match CVSROOT* $rcs]} { |
| 56 | - Log info " => Ignoring admin file" | |
| 53 | + write 2 cvs {Ignored. Administrative file} | |
| 57 | 54 | continue |
| 58 | 55 | } |
| 59 | 56 | |
| 60 | 57 | # Derive the regular path from the rcs path. Meaning: Chop of |
| 61 | 58 | # the ",v" suffix, and remove a possible "Attic". |
| @@ -64,11 +61,12 @@ | ||
| 64 | 61 | set f [file join [file dirname [file dirname $f]] [file tail $f]] |
| 65 | 62 | if {[file exists $base/$f,v]} { |
| 66 | 63 | # We have a regular archive and an Attic archive |
| 67 | 64 | # refering to the same user visible file. Ignore the |
| 68 | 65 | # file in the Attic. |
| 69 | - Log info " => Ignoring attic for regular archive" | |
| 66 | + | |
| 67 | + write 2 cvs "Ignored. Attic superceded by regular archive" | |
| 70 | 68 | |
| 71 | 69 | # TODO/CHECK. My method of co'ing exact file revisions |
| 72 | 70 | # per the info in the collected csets has the flaw |
| 73 | 71 | # that I may have to know exactly when what archive |
| 74 | 72 | # file to use, see above. It might be better to use |
| @@ -85,12 +83,10 @@ | ||
| 85 | 83 | } |
| 86 | 84 | |
| 87 | 85 | # Get the meta data we need (revisions, timeline, messages). |
| 88 | 86 | set meta [::rcsparser::process $base/$rcs] |
| 89 | 87 | |
| 90 | - Log info " => $f" | |
| 91 | - | |
| 92 | 88 | set npaths($rcs) $f |
| 93 | 89 | set rpaths($f) $rcs |
| 94 | 90 | |
| 95 | 91 | array set p $meta |
| 96 | 92 | |
| @@ -103,11 +99,11 @@ | ||
| 103 | 99 | # seems to exist only! on its branch. The branches |
| 104 | 100 | # information is set on the revision (extend rcsparser!), |
| 105 | 101 | # symbols has a tag, refering to a branch, possibly magic. |
| 106 | 102 | |
| 107 | 103 | if {($rev eq "1.1") && ($op eq "R")} { |
| 108 | - Log info " => Dead first" | |
| 104 | + write 2 cvs {Dead root revision} | |
| 109 | 105 | } |
| 110 | 106 | |
| 111 | 107 | lappend timeline($ts) [list $op $ts $a $rev $f $cm] |
| 112 | 108 | } |
| 113 | 109 | |
| @@ -115,11 +111,11 @@ | ||
| 115 | 111 | #parray p |
| 116 | 112 | |
| 117 | 113 | incr n |
| 118 | 114 | } |
| 119 | 115 | |
| 120 | - Log info "Processed $n [expr {($n == 1) ? "file" : "files"}]" | |
| 116 | + write 0 cvs "Processed $n [expr {($n == 1) ? "file" : "files"}]" | |
| 121 | 117 | return |
| 122 | 118 | } |
| 123 | 119 | |
| 124 | 120 | namespace eval ::cvs { |
| 125 | 121 | # Path mappings. npaths: rcs file -> user file |
| @@ -143,11 +139,11 @@ | ||
| 143 | 139 | |
| 144 | 140 | array unset csets * ; array set csets {} |
| 145 | 141 | array unset cmap * ; array set cmap {} |
| 146 | 142 | set ncs 0 |
| 147 | 143 | |
| 148 | - Log info "Processing timeline" | |
| 144 | + write 0 cvs "Processing timeline" | |
| 149 | 145 | |
| 150 | 146 | set n 0 |
| 151 | 147 | CSClear |
| 152 | 148 | foreach ts [lsort -dict [array names timeline]] { |
| 153 | 149 | |
| @@ -167,13 +163,14 @@ | ||
| 167 | 163 | CSAdd $entry |
| 168 | 164 | incr n |
| 169 | 165 | } |
| 170 | 166 | } |
| 171 | 167 | |
| 172 | - Log info "Processed $n [expr {($n == 1) ? "entry" : "entries"}]" | |
| 168 | + write 0 cvs "Processed $n [expr {($n == 1) ? "entry" : "entries"}]" | |
| 169 | + | |
| 173 | 170 | set n [array size csets] |
| 174 | - Log info "Found $n [expr {($n == 1) ? "changeset" : "changesets"}]" | |
| 171 | + write 0 cvs "Found $n [expr {($n == 1) ? "changeset" : "changesets"}]" | |
| 175 | 172 | return |
| 176 | 173 | } |
| 177 | 174 | |
| 178 | 175 | |
| 179 | 176 | namespace eval ::cvs { |
| @@ -192,11 +189,11 @@ | ||
| 192 | 189 | proc ::cvs::rtree {} { |
| 193 | 190 | variable csets |
| 194 | 191 | variable rtree {} |
| 195 | 192 | variable ntrunk 0 |
| 196 | 193 | |
| 197 | - Log info "Extracting the trunk" | |
| 194 | + write 0 cvs "Extracting the trunk" | |
| 198 | 195 | |
| 199 | 196 | set rtree [struct::tree ::cvs::RT] |
| 200 | 197 | $rtree rename root 0 ; # Root is first changeset, always. |
| 201 | 198 | set trunk 0 |
| 202 | 199 | set ntrunk 1 ; # Root is on the trunk. |
| @@ -218,12 +215,12 @@ | ||
| 218 | 215 | $rtree insert $trunk end $c |
| 219 | 216 | set trunk $c |
| 220 | 217 | incr ntrunk |
| 221 | 218 | } |
| 222 | 219 | |
| 223 | - Log info "Processed $ntrunk trunk [expr {($ntrunk == 1) ? "changeset" : "changesets"}]" | |
| 224 | - Log info "Ignored $b branch [expr {($b == 1) ? "changeset" : "changesets"}]" | |
| 220 | + write 0 cvs "Processed $ntrunk trunk [expr {($ntrunk == 1) ? "changeset" : "changesets"}]" | |
| 221 | + write 0 cvs "Ignored $b branch [expr {($b == 1) ? "changeset" : "changesets"}]" | |
| 225 | 222 | return |
| 226 | 223 | } |
| 227 | 224 | |
| 228 | 225 | namespace eval ::cvs { |
| 229 | 226 | # Tree holding trunk and branch information (struct::tree). |
| @@ -237,11 +234,11 @@ | ||
| 237 | 234 | variable cwd [pwd] |
| 238 | 235 | variable workspace [fileutil::tempfile importF_cvs_ws_] |
| 239 | 236 | file delete $workspace |
| 240 | 237 | file mkdir $workspace |
| 241 | 238 | |
| 242 | - Log info " Workspace: $workspace" | |
| 239 | + write 0 cvs "Workspace: $workspace" | |
| 243 | 240 | |
| 244 | 241 | cd $workspace ; # Checkouts go here. |
| 245 | 242 | return $workspace |
| 246 | 243 | } |
| 247 | 244 | |
| @@ -266,19 +263,19 @@ | ||
| 266 | 263 | |
| 267 | 264 | # pwd = workspace |
| 268 | 265 | |
| 269 | 266 | foreach {u cm s e rd fs} $csets($c) break |
| 270 | 267 | |
| 271 | - Log info " @ $s" | |
| 268 | + write 1 cvs "@ $s" | |
| 272 | 269 | |
| 273 | 270 | foreach l [split [string trim $cm] \n] { |
| 274 | - Log info " | $l" | |
| 271 | + write 1 cvs "| $l" | |
| 275 | 272 | } |
| 276 | 273 | |
| 277 | 274 | foreach {f or} $fs { |
| 278 | 275 | foreach {op r} $or break |
| 279 | - Log info " -- $op $f $r" | |
| 276 | + write 2 cvs "$op $f $r" | |
| 280 | 277 | |
| 281 | 278 | if {$op eq "R"} { |
| 282 | 279 | # Remove file from workspace. Prune empty directories. |
| 283 | 280 | # |
| 284 | 281 | # NOTE: A dead-first file (rev 1.1 dead) will never have |
| @@ -312,11 +309,11 @@ | ||
| 312 | 309 | # a consequence the fossil repository will not |
| 313 | 310 | # contain the full history of the named file. By |
| 314 | 311 | # ignoring the problem we however get as much as |
| 315 | 312 | # is possible. |
| 316 | 313 | |
| 317 | - Log info " EE Corrupted archive file. Inaccessible revision." | |
| 314 | + write 0 cvs "EE Corrupted archive file. Inaccessible revision." | |
| 318 | 315 | continue |
| 319 | 316 | } |
| 320 | 317 | return -code error $msg |
| 321 | 318 | } |
| 322 | 319 | } |
| @@ -345,11 +342,11 @@ | ||
| 345 | 342 | set code [catch {uplevel 1 $script} res] |
| 346 | 343 | |
| 347 | 344 | # 0 - ok, 1 - error, 2 - return, 3 - break, 4 - continue |
| 348 | 345 | switch -- $code { |
| 349 | 346 | 0 {} |
| 350 | - 1 { return -errorcode $::errorcode -code error $res } | |
| 347 | + 1 { return -errorcode $::errorCode -errorinfo $::errorInfo -code error $res } | |
| 351 | 348 | 2 {} |
| 352 | 349 | 3 { return } |
| 353 | 350 | 4 {} |
| 354 | 351 | default { |
| 355 | 352 | return -code $code $result |
| @@ -373,10 +370,15 @@ | ||
| 373 | 370 | |
| 374 | 371 | proc ::cvs::ntrunk {} { |
| 375 | 372 | variable ntrunk |
| 376 | 373 | return $ntrunk |
| 377 | 374 | } |
| 375 | + | |
| 376 | +proc ::cvs::ncsets {} { | |
| 377 | + variable ncs | |
| 378 | + return $ncs | |
| 379 | +} | |
| 378 | 380 | |
| 379 | 381 | proc ::cvs::uuid {c uuid} { |
| 380 | 382 | variable rtree |
| 381 | 383 | $rtree set $c uuid $uuid |
| 382 | 384 | return |
| @@ -472,26 +474,10 @@ | ||
| 472 | 474 | puts "$b $o $f $r" |
| 473 | 475 | } |
| 474 | 476 | return |
| 475 | 477 | } |
| 476 | 478 | |
| 477 | -# ----------------------------------------------------------------------------- | |
| 478 | -# Internal helper commands | |
| 479 | - | |
| 480 | -proc ::cvs::Log {level text} { | |
| 481 | - variable lc | |
| 482 | - uplevel #0 [linsert $lc end $level $text] | |
| 483 | - return | |
| 484 | -} | |
| 485 | - | |
| 486 | -proc ::cvs::Nop {args} {} | |
| 487 | - | |
| 488 | -namespace eval ::cvs { | |
| 489 | - # Logging callback. No logging by default. | |
| 490 | - variable lc ::cvs::Nop | |
| 491 | -} | |
| 492 | - | |
| 493 | 479 | # ----------------------------------------------------------------------------- |
| 494 | 480 | # Ready |
| 495 | 481 | |
| 496 | 482 | package provide cvs 1.0 |
| 497 | 483 | return |
| 498 | 484 |
| --- tools/lib/cvs.tcl | |
| +++ tools/lib/cvs.tcl | |
| @@ -3,59 +3,56 @@ | |
| 3 | |
| 4 | # ----------------------------------------------------------------------------- |
| 5 | # Requirements |
| 6 | |
| 7 | package require Tcl 8.4 |
| 8 | package require fileutil ; # Tcllib (cat) |
| 9 | package require rcsparser ; # Handling the RCS archive files. |
| 10 | package require struct::tree |
| 11 | |
| 12 | namespace eval ::cvs {} |
| 13 | |
| 14 | # ----------------------------------------------------------------------------- |
| 15 | # API |
| 16 | |
| 17 | # Define repository directory. |
| 18 | |
| 19 | proc ::cvs::at {path} { |
| 20 | variable base [file normalize $path] |
| 21 | return |
| 22 | } |
| 23 | |
| 24 | namespace eval ::cvs { |
| 25 | # Toplevel repository directory |
| 26 | variable base {} |
| 27 | } |
| 28 | |
| 29 | # Define logging callback command |
| 30 | |
| 31 | proc ::cvs::feedback {logcmd} { |
| 32 | variable lc $logcmd |
| 33 | ::rcsparser::feedback $logcmd |
| 34 | return |
| 35 | } |
| 36 | |
| 37 | # Scan repository, collect archives, parse them, and collect revision |
| 38 | # information (file, revision -> date, author, commit message) |
| 39 | |
| 40 | proc ::cvs::scan {} { |
| 41 | variable base |
| 42 | variable npaths |
| 43 | variable rpaths |
| 44 | variable timeline |
| 45 | |
| 46 | Log info "Scanning CVS tree $base" |
| 47 | |
| 48 | set n 0 |
| 49 | foreach rcs [fileutil::findByPattern $base -glob *,v] { |
| 50 | set rcs [fileutil::stripPath $base $rcs] |
| 51 | # Now rcs is relative to base |
| 52 | |
| 53 | Log info " Parsing archive $rcs" |
| 54 | |
| 55 | if {[string match CVSROOT* $rcs]} { |
| 56 | Log info " => Ignoring admin file" |
| 57 | continue |
| 58 | } |
| 59 | |
| 60 | # Derive the regular path from the rcs path. Meaning: Chop of |
| 61 | # the ",v" suffix, and remove a possible "Attic". |
| @@ -64,11 +61,12 @@ | |
| 64 | set f [file join [file dirname [file dirname $f]] [file tail $f]] |
| 65 | if {[file exists $base/$f,v]} { |
| 66 | # We have a regular archive and an Attic archive |
| 67 | # refering to the same user visible file. Ignore the |
| 68 | # file in the Attic. |
| 69 | Log info " => Ignoring attic for regular archive" |
| 70 | |
| 71 | # TODO/CHECK. My method of co'ing exact file revisions |
| 72 | # per the info in the collected csets has the flaw |
| 73 | # that I may have to know exactly when what archive |
| 74 | # file to use, see above. It might be better to use |
| @@ -85,12 +83,10 @@ | |
| 85 | } |
| 86 | |
| 87 | # Get the meta data we need (revisions, timeline, messages). |
| 88 | set meta [::rcsparser::process $base/$rcs] |
| 89 | |
| 90 | Log info " => $f" |
| 91 | |
| 92 | set npaths($rcs) $f |
| 93 | set rpaths($f) $rcs |
| 94 | |
| 95 | array set p $meta |
| 96 | |
| @@ -103,11 +99,11 @@ | |
| 103 | # seems to exist only! on its branch. The branches |
| 104 | # information is set on the revision (extend rcsparser!), |
| 105 | # symbols has a tag, refering to a branch, possibly magic. |
| 106 | |
| 107 | if {($rev eq "1.1") && ($op eq "R")} { |
| 108 | Log info " => Dead first" |
| 109 | } |
| 110 | |
| 111 | lappend timeline($ts) [list $op $ts $a $rev $f $cm] |
| 112 | } |
| 113 | |
| @@ -115,11 +111,11 @@ | |
| 115 | #parray p |
| 116 | |
| 117 | incr n |
| 118 | } |
| 119 | |
| 120 | Log info "Processed $n [expr {($n == 1) ? "file" : "files"}]" |
| 121 | return |
| 122 | } |
| 123 | |
| 124 | namespace eval ::cvs { |
| 125 | # Path mappings. npaths: rcs file -> user file |
| @@ -143,11 +139,11 @@ | |
| 143 | |
| 144 | array unset csets * ; array set csets {} |
| 145 | array unset cmap * ; array set cmap {} |
| 146 | set ncs 0 |
| 147 | |
| 148 | Log info "Processing timeline" |
| 149 | |
| 150 | set n 0 |
| 151 | CSClear |
| 152 | foreach ts [lsort -dict [array names timeline]] { |
| 153 | |
| @@ -167,13 +163,14 @@ | |
| 167 | CSAdd $entry |
| 168 | incr n |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | Log info "Processed $n [expr {($n == 1) ? "entry" : "entries"}]" |
| 173 | set n [array size csets] |
| 174 | Log info "Found $n [expr {($n == 1) ? "changeset" : "changesets"}]" |
| 175 | return |
| 176 | } |
| 177 | |
| 178 | |
| 179 | namespace eval ::cvs { |
| @@ -192,11 +189,11 @@ | |
| 192 | proc ::cvs::rtree {} { |
| 193 | variable csets |
| 194 | variable rtree {} |
| 195 | variable ntrunk 0 |
| 196 | |
| 197 | Log info "Extracting the trunk" |
| 198 | |
| 199 | set rtree [struct::tree ::cvs::RT] |
| 200 | $rtree rename root 0 ; # Root is first changeset, always. |
| 201 | set trunk 0 |
| 202 | set ntrunk 1 ; # Root is on the trunk. |
| @@ -218,12 +215,12 @@ | |
| 218 | $rtree insert $trunk end $c |
| 219 | set trunk $c |
| 220 | incr ntrunk |
| 221 | } |
| 222 | |
| 223 | Log info "Processed $ntrunk trunk [expr {($ntrunk == 1) ? "changeset" : "changesets"}]" |
| 224 | Log info "Ignored $b branch [expr {($b == 1) ? "changeset" : "changesets"}]" |
| 225 | return |
| 226 | } |
| 227 | |
| 228 | namespace eval ::cvs { |
| 229 | # Tree holding trunk and branch information (struct::tree). |
| @@ -237,11 +234,11 @@ | |
| 237 | variable cwd [pwd] |
| 238 | variable workspace [fileutil::tempfile importF_cvs_ws_] |
| 239 | file delete $workspace |
| 240 | file mkdir $workspace |
| 241 | |
| 242 | Log info " Workspace: $workspace" |
| 243 | |
| 244 | cd $workspace ; # Checkouts go here. |
| 245 | return $workspace |
| 246 | } |
| 247 | |
| @@ -266,19 +263,19 @@ | |
| 266 | |
| 267 | # pwd = workspace |
| 268 | |
| 269 | foreach {u cm s e rd fs} $csets($c) break |
| 270 | |
| 271 | Log info " @ $s" |
| 272 | |
| 273 | foreach l [split [string trim $cm] \n] { |
| 274 | Log info " | $l" |
| 275 | } |
| 276 | |
| 277 | foreach {f or} $fs { |
| 278 | foreach {op r} $or break |
| 279 | Log info " -- $op $f $r" |
| 280 | |
| 281 | if {$op eq "R"} { |
| 282 | # Remove file from workspace. Prune empty directories. |
| 283 | # |
| 284 | # NOTE: A dead-first file (rev 1.1 dead) will never have |
| @@ -312,11 +309,11 @@ | |
| 312 | # a consequence the fossil repository will not |
| 313 | # contain the full history of the named file. By |
| 314 | # ignoring the problem we however get as much as |
| 315 | # is possible. |
| 316 | |
| 317 | Log info " EE Corrupted archive file. Inaccessible revision." |
| 318 | continue |
| 319 | } |
| 320 | return -code error $msg |
| 321 | } |
| 322 | } |
| @@ -345,11 +342,11 @@ | |
| 345 | set code [catch {uplevel 1 $script} res] |
| 346 | |
| 347 | # 0 - ok, 1 - error, 2 - return, 3 - break, 4 - continue |
| 348 | switch -- $code { |
| 349 | 0 {} |
| 350 | 1 { return -errorcode $::errorcode -code error $res } |
| 351 | 2 {} |
| 352 | 3 { return } |
| 353 | 4 {} |
| 354 | default { |
| 355 | return -code $code $result |
| @@ -373,10 +370,15 @@ | |
| 373 | |
| 374 | proc ::cvs::ntrunk {} { |
| 375 | variable ntrunk |
| 376 | return $ntrunk |
| 377 | } |
| 378 | |
| 379 | proc ::cvs::uuid {c uuid} { |
| 380 | variable rtree |
| 381 | $rtree set $c uuid $uuid |
| 382 | return |
| @@ -472,26 +474,10 @@ | |
| 472 | puts "$b $o $f $r" |
| 473 | } |
| 474 | return |
| 475 | } |
| 476 | |
| 477 | # ----------------------------------------------------------------------------- |
| 478 | # Internal helper commands |
| 479 | |
| 480 | proc ::cvs::Log {level text} { |
| 481 | variable lc |
| 482 | uplevel #0 [linsert $lc end $level $text] |
| 483 | return |
| 484 | } |
| 485 | |
| 486 | proc ::cvs::Nop {args} {} |
| 487 | |
| 488 | namespace eval ::cvs { |
| 489 | # Logging callback. No logging by default. |
| 490 | variable lc ::cvs::Nop |
| 491 | } |
| 492 | |
| 493 | # ----------------------------------------------------------------------------- |
| 494 | # Ready |
| 495 | |
| 496 | package provide cvs 1.0 |
| 497 | return |
| 498 |
| --- tools/lib/cvs.tcl | |
| +++ tools/lib/cvs.tcl | |
| @@ -3,59 +3,56 @@ | |
| 3 | |
| 4 | # ----------------------------------------------------------------------------- |
| 5 | # Requirements |
| 6 | |
| 7 | package require Tcl 8.4 |
| 8 | package require fileutil ; # Tcllib (traverse directory hierarchy) |
| 9 | package require rcsparser ; # Handling the RCS archive files. |
| 10 | package require tools::log ; # User feedback |
| 11 | package require struct::tree |
| 12 | |
| 13 | namespace eval ::cvs { |
| 14 | tools::log::system cvs |
| 15 | namespace import ::tools::log::write |
| 16 | } |
| 17 | |
| 18 | # ----------------------------------------------------------------------------- |
| 19 | # API |
| 20 | |
| 21 | # Define repository directory. |
| 22 | |
| 23 | proc ::cvs::at {path} { |
| 24 | variable base [file normalize $path] |
| 25 | write 0 cvs "Base: $base" |
| 26 | return |
| 27 | } |
| 28 | |
| 29 | namespace eval ::cvs { |
| 30 | # Toplevel repository directory |
| 31 | variable base {} |
| 32 | } |
| 33 | |
| 34 | # Scan repository, collect archives, parse them, and collect revision |
| 35 | # information (file, revision -> date, author, commit message) |
| 36 | |
| 37 | proc ::cvs::scan {} { |
| 38 | variable base |
| 39 | variable npaths |
| 40 | variable rpaths |
| 41 | variable timeline |
| 42 | |
| 43 | write 0 cvs {Scanning directory hierarchy} |
| 44 | |
| 45 | set n 0 |
| 46 | foreach rcs [fileutil::findByPattern $base -glob *,v] { |
| 47 | set rcs [fileutil::stripPath $base $rcs] |
| 48 | # Now rcs is relative to base |
| 49 | |
| 50 | write 1 cvs "Archive $rcs" |
| 51 | |
| 52 | if {[string match CVSROOT* $rcs]} { |
| 53 | write 2 cvs {Ignored. Administrative file} |
| 54 | continue |
| 55 | } |
| 56 | |
| 57 | # Derive the regular path from the rcs path. Meaning: Chop of |
| 58 | # the ",v" suffix, and remove a possible "Attic". |
| @@ -64,11 +61,12 @@ | |
| 61 | set f [file join [file dirname [file dirname $f]] [file tail $f]] |
| 62 | if {[file exists $base/$f,v]} { |
| 63 | # We have a regular archive and an Attic archive |
| 64 | # refering to the same user visible file. Ignore the |
| 65 | # file in the Attic. |
| 66 | |
| 67 | write 2 cvs "Ignored. Attic superceded by regular archive" |
| 68 | |
| 69 | # TODO/CHECK. My method of co'ing exact file revisions |
| 70 | # per the info in the collected csets has the flaw |
| 71 | # that I may have to know exactly when what archive |
| 72 | # file to use, see above. It might be better to use |
| @@ -85,12 +83,10 @@ | |
| 83 | } |
| 84 | |
| 85 | # Get the meta data we need (revisions, timeline, messages). |
| 86 | set meta [::rcsparser::process $base/$rcs] |
| 87 | |
| 88 | set npaths($rcs) $f |
| 89 | set rpaths($f) $rcs |
| 90 | |
| 91 | array set p $meta |
| 92 | |
| @@ -103,11 +99,11 @@ | |
| 99 | # seems to exist only! on its branch. The branches |
| 100 | # information is set on the revision (extend rcsparser!), |
| 101 | # symbols has a tag, refering to a branch, possibly magic. |
| 102 | |
| 103 | if {($rev eq "1.1") && ($op eq "R")} { |
| 104 | write 2 cvs {Dead root revision} |
| 105 | } |
| 106 | |
| 107 | lappend timeline($ts) [list $op $ts $a $rev $f $cm] |
| 108 | } |
| 109 | |
| @@ -115,11 +111,11 @@ | |
| 111 | #parray p |
| 112 | |
| 113 | incr n |
| 114 | } |
| 115 | |
| 116 | write 0 cvs "Processed $n [expr {($n == 1) ? "file" : "files"}]" |
| 117 | return |
| 118 | } |
| 119 | |
| 120 | namespace eval ::cvs { |
| 121 | # Path mappings. npaths: rcs file -> user file |
| @@ -143,11 +139,11 @@ | |
| 139 | |
| 140 | array unset csets * ; array set csets {} |
| 141 | array unset cmap * ; array set cmap {} |
| 142 | set ncs 0 |
| 143 | |
| 144 | write 0 cvs "Processing timeline" |
| 145 | |
| 146 | set n 0 |
| 147 | CSClear |
| 148 | foreach ts [lsort -dict [array names timeline]] { |
| 149 | |
| @@ -167,13 +163,14 @@ | |
| 163 | CSAdd $entry |
| 164 | incr n |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | write 0 cvs "Processed $n [expr {($n == 1) ? "entry" : "entries"}]" |
| 169 | |
| 170 | set n [array size csets] |
| 171 | write 0 cvs "Found $n [expr {($n == 1) ? "changeset" : "changesets"}]" |
| 172 | return |
| 173 | } |
| 174 | |
| 175 | |
| 176 | namespace eval ::cvs { |
| @@ -192,11 +189,11 @@ | |
| 189 | proc ::cvs::rtree {} { |
| 190 | variable csets |
| 191 | variable rtree {} |
| 192 | variable ntrunk 0 |
| 193 | |
| 194 | write 0 cvs "Extracting the trunk" |
| 195 | |
| 196 | set rtree [struct::tree ::cvs::RT] |
| 197 | $rtree rename root 0 ; # Root is first changeset, always. |
| 198 | set trunk 0 |
| 199 | set ntrunk 1 ; # Root is on the trunk. |
| @@ -218,12 +215,12 @@ | |
| 215 | $rtree insert $trunk end $c |
| 216 | set trunk $c |
| 217 | incr ntrunk |
| 218 | } |
| 219 | |
| 220 | write 0 cvs "Processed $ntrunk trunk [expr {($ntrunk == 1) ? "changeset" : "changesets"}]" |
| 221 | write 0 cvs "Ignored $b branch [expr {($b == 1) ? "changeset" : "changesets"}]" |
| 222 | return |
| 223 | } |
| 224 | |
| 225 | namespace eval ::cvs { |
| 226 | # Tree holding trunk and branch information (struct::tree). |
| @@ -237,11 +234,11 @@ | |
| 234 | variable cwd [pwd] |
| 235 | variable workspace [fileutil::tempfile importF_cvs_ws_] |
| 236 | file delete $workspace |
| 237 | file mkdir $workspace |
| 238 | |
| 239 | write 0 cvs "Workspace: $workspace" |
| 240 | |
| 241 | cd $workspace ; # Checkouts go here. |
| 242 | return $workspace |
| 243 | } |
| 244 | |
| @@ -266,19 +263,19 @@ | |
| 263 | |
| 264 | # pwd = workspace |
| 265 | |
| 266 | foreach {u cm s e rd fs} $csets($c) break |
| 267 | |
| 268 | write 1 cvs "@ $s" |
| 269 | |
| 270 | foreach l [split [string trim $cm] \n] { |
| 271 | write 1 cvs "| $l" |
| 272 | } |
| 273 | |
| 274 | foreach {f or} $fs { |
| 275 | foreach {op r} $or break |
| 276 | write 2 cvs "$op $f $r" |
| 277 | |
| 278 | if {$op eq "R"} { |
| 279 | # Remove file from workspace. Prune empty directories. |
| 280 | # |
| 281 | # NOTE: A dead-first file (rev 1.1 dead) will never have |
| @@ -312,11 +309,11 @@ | |
| 309 | # a consequence the fossil repository will not |
| 310 | # contain the full history of the named file. By |
| 311 | # ignoring the problem we however get as much as |
| 312 | # is possible. |
| 313 | |
| 314 | write 0 cvs "EE Corrupted archive file. Inaccessible revision." |
| 315 | continue |
| 316 | } |
| 317 | return -code error $msg |
| 318 | } |
| 319 | } |
| @@ -345,11 +342,11 @@ | |
| 342 | set code [catch {uplevel 1 $script} res] |
| 343 | |
| 344 | # 0 - ok, 1 - error, 2 - return, 3 - break, 4 - continue |
| 345 | switch -- $code { |
| 346 | 0 {} |
| 347 | 1 { return -errorcode $::errorCode -errorinfo $::errorInfo -code error $res } |
| 348 | 2 {} |
| 349 | 3 { return } |
| 350 | 4 {} |
| 351 | default { |
| 352 | return -code $code $result |
| @@ -373,10 +370,15 @@ | |
| 370 | |
| 371 | proc ::cvs::ntrunk {} { |
| 372 | variable ntrunk |
| 373 | return $ntrunk |
| 374 | } |
| 375 | |
| 376 | proc ::cvs::ncsets {} { |
| 377 | variable ncs |
| 378 | return $ncs |
| 379 | } |
| 380 | |
| 381 | proc ::cvs::uuid {c uuid} { |
| 382 | variable rtree |
| 383 | $rtree set $c uuid $uuid |
| 384 | return |
| @@ -472,26 +474,10 @@ | |
| 474 | puts "$b $o $f $r" |
| 475 | } |
| 476 | return |
| 477 | } |
| 478 | |
| 479 | # ----------------------------------------------------------------------------- |
| 480 | # Ready |
| 481 | |
| 482 | package provide cvs 1.0 |
| 483 | return |
| 484 |
+10
-26
| --- tools/lib/fossil.tcl | ||
| +++ tools/lib/fossil.tcl | ||
| @@ -3,12 +3,16 @@ | ||
| 3 | 3 | |
| 4 | 4 | # ----------------------------------------------------------------------------- |
| 5 | 5 | # Requirements |
| 6 | 6 | |
| 7 | 7 | package require Tcl 8.4 |
| 8 | +package require tools::log ; # User feedback | |
| 8 | 9 | |
| 9 | -namespace eval ::fossil {} | |
| 10 | +namespace eval ::fossil { | |
| 11 | + tools::log::system fossil | |
| 12 | + namespace import ::tools::log::write | |
| 13 | +} | |
| 10 | 14 | |
| 11 | 15 | # ----------------------------------------------------------------------------- |
| 12 | 16 | # API |
| 13 | 17 | |
| 14 | 18 | # Define repository file, and connect to workspace in CWD. |
| @@ -19,22 +23,15 @@ | ||
| 19 | 23 | |
| 20 | 24 | # pwd = workspace |
| 21 | 25 | exec $fossil new $fr ; # create and |
| 22 | 26 | exec $fossil open $fr ; # connect |
| 23 | 27 | |
| 24 | - Log info " Fossil: $fr" | |
| 28 | + write 0 fossil "Repository: $fr" | |
| 25 | 29 | |
| 26 | 30 | return $fr |
| 27 | 31 | } |
| 28 | 32 | |
| 29 | -# Define logging callback command | |
| 30 | - | |
| 31 | -proc ::fossil::feedback {logcmd} { | |
| 32 | - variable lc $logcmd | |
| 33 | - return | |
| 34 | -} | |
| 35 | - | |
| 36 | 33 | # Move generated fossil repository to final destination |
| 37 | 34 | |
| 38 | 35 | proc ::fossil::destination {path} { |
| 39 | 36 | variable fr |
| 40 | 37 | file rename $fr $path |
| @@ -85,24 +82,24 @@ | ||
| 85 | 82 | if {[IGNORE $ignore $path]} continue |
| 86 | 83 | |
| 87 | 84 | if {![file exists $path]} { |
| 88 | 85 | exec $fossil rm $path |
| 89 | 86 | incr removed |
| 90 | - Log info " ** - $path" | |
| 87 | + write 2 fossil "- $path" | |
| 91 | 88 | } else { |
| 92 | 89 | incr changed |
| 93 | - Log info " ** * $path" | |
| 90 | + write 2 fossil "* $path" | |
| 94 | 91 | } |
| 95 | 92 | } |
| 96 | 93 | |
| 97 | 94 | # Now look for unregistered added files. |
| 98 | 95 | |
| 99 | 96 | foreach path [split [exec $fossil extra] \n] { |
| 100 | 97 | if {[IGNORE $ignore $path]} continue |
| 101 | 98 | exec $fossil add $path |
| 102 | 99 | incr added |
| 103 | - Log info " ** + $path" | |
| 100 | + write 2 fossil "+ $path" | |
| 104 | 101 | } |
| 105 | 102 | |
| 106 | 103 | # Now commit, using the provided meta data, and capture the uuid |
| 107 | 104 | # of the new baseline. |
| 108 | 105 | |
| @@ -136,11 +133,11 @@ | ||
| 136 | 133 | # 'Nothing changed' can happen for changesets containing only |
| 137 | 134 | # dead-first revisions of one or more files. For fossil we |
| 138 | 135 | # re-use the last baseline. TODO: Mark them as branchpoint, |
| 139 | 136 | # and for what file. |
| 140 | 137 | |
| 141 | - Log info " UNCHANGED, keeping last" | |
| 138 | + write 1 fossil "UNCHANGED, keeping last" | |
| 142 | 139 | |
| 143 | 140 | return [list $lastuuid 0 0 0] |
| 144 | 141 | } |
| 145 | 142 | |
| 146 | 143 | set line [string trim $line] |
| @@ -155,23 +152,10 @@ | ||
| 155 | 152 | |
| 156 | 153 | proc ::fossil::IGNORE {ignore path} { |
| 157 | 154 | return [uplevel #0 [linsert $ignore end $path]] |
| 158 | 155 | } |
| 159 | 156 | |
| 160 | -proc ::fossil::Log {level text} { | |
| 161 | - variable lc | |
| 162 | - uplevel #0 [linsert $lc end $level $text] | |
| 163 | - return | |
| 164 | -} | |
| 165 | - | |
| 166 | -proc ::fossil::Nop {args} {} | |
| 167 | - | |
| 168 | -namespace eval ::fossil { | |
| 169 | - # Logging callback. No logging by default. | |
| 170 | - variable lc ::fossil::Nop | |
| 171 | -} | |
| 172 | - | |
| 173 | 157 | # ----------------------------------------------------------------------------- |
| 174 | 158 | # Ready |
| 175 | 159 | |
| 176 | 160 | package provide fossil 1.0 |
| 177 | 161 | return |
| 178 | 162 | |
| 179 | 163 | ADDED tools/lib/log.tcl |
| --- tools/lib/fossil.tcl | |
| +++ tools/lib/fossil.tcl | |
| @@ -3,12 +3,16 @@ | |
| 3 | |
| 4 | # ----------------------------------------------------------------------------- |
| 5 | # Requirements |
| 6 | |
| 7 | package require Tcl 8.4 |
| 8 | |
| 9 | namespace eval ::fossil {} |
| 10 | |
| 11 | # ----------------------------------------------------------------------------- |
| 12 | # API |
| 13 | |
| 14 | # Define repository file, and connect to workspace in CWD. |
| @@ -19,22 +23,15 @@ | |
| 19 | |
| 20 | # pwd = workspace |
| 21 | exec $fossil new $fr ; # create and |
| 22 | exec $fossil open $fr ; # connect |
| 23 | |
| 24 | Log info " Fossil: $fr" |
| 25 | |
| 26 | return $fr |
| 27 | } |
| 28 | |
| 29 | # Define logging callback command |
| 30 | |
| 31 | proc ::fossil::feedback {logcmd} { |
| 32 | variable lc $logcmd |
| 33 | return |
| 34 | } |
| 35 | |
| 36 | # Move generated fossil repository to final destination |
| 37 | |
| 38 | proc ::fossil::destination {path} { |
| 39 | variable fr |
| 40 | file rename $fr $path |
| @@ -85,24 +82,24 @@ | |
| 85 | if {[IGNORE $ignore $path]} continue |
| 86 | |
| 87 | if {![file exists $path]} { |
| 88 | exec $fossil rm $path |
| 89 | incr removed |
| 90 | Log info " ** - $path" |
| 91 | } else { |
| 92 | incr changed |
| 93 | Log info " ** * $path" |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | # Now look for unregistered added files. |
| 98 | |
| 99 | foreach path [split [exec $fossil extra] \n] { |
| 100 | if {[IGNORE $ignore $path]} continue |
| 101 | exec $fossil add $path |
| 102 | incr added |
| 103 | Log info " ** + $path" |
| 104 | } |
| 105 | |
| 106 | # Now commit, using the provided meta data, and capture the uuid |
| 107 | # of the new baseline. |
| 108 | |
| @@ -136,11 +133,11 @@ | |
| 136 | # 'Nothing changed' can happen for changesets containing only |
| 137 | # dead-first revisions of one or more files. For fossil we |
| 138 | # re-use the last baseline. TODO: Mark them as branchpoint, |
| 139 | # and for what file. |
| 140 | |
| 141 | Log info " UNCHANGED, keeping last" |
| 142 | |
| 143 | return [list $lastuuid 0 0 0] |
| 144 | } |
| 145 | |
| 146 | set line [string trim $line] |
| @@ -155,23 +152,10 @@ | |
| 155 | |
| 156 | proc ::fossil::IGNORE {ignore path} { |
| 157 | return [uplevel #0 [linsert $ignore end $path]] |
| 158 | } |
| 159 | |
| 160 | proc ::fossil::Log {level text} { |
| 161 | variable lc |
| 162 | uplevel #0 [linsert $lc end $level $text] |
| 163 | return |
| 164 | } |
| 165 | |
| 166 | proc ::fossil::Nop {args} {} |
| 167 | |
| 168 | namespace eval ::fossil { |
| 169 | # Logging callback. No logging by default. |
| 170 | variable lc ::fossil::Nop |
| 171 | } |
| 172 | |
| 173 | # ----------------------------------------------------------------------------- |
| 174 | # Ready |
| 175 | |
| 176 | package provide fossil 1.0 |
| 177 | return |
| 178 | |
| 179 | DDED tools/lib/log.tcl |
| --- tools/lib/fossil.tcl | |
| +++ tools/lib/fossil.tcl | |
| @@ -3,12 +3,16 @@ | |
| 3 | |
| 4 | # ----------------------------------------------------------------------------- |
| 5 | # Requirements |
| 6 | |
| 7 | package require Tcl 8.4 |
| 8 | package require tools::log ; # User feedback |
| 9 | |
| 10 | namespace eval ::fossil { |
| 11 | tools::log::system fossil |
| 12 | namespace import ::tools::log::write |
| 13 | } |
| 14 | |
| 15 | # ----------------------------------------------------------------------------- |
| 16 | # API |
| 17 | |
| 18 | # Define repository file, and connect to workspace in CWD. |
| @@ -19,22 +23,15 @@ | |
| 23 | |
| 24 | # pwd = workspace |
| 25 | exec $fossil new $fr ; # create and |
| 26 | exec $fossil open $fr ; # connect |
| 27 | |
| 28 | write 0 fossil "Repository: $fr" |
| 29 | |
| 30 | return $fr |
| 31 | } |
| 32 | |
| 33 | # Move generated fossil repository to final destination |
| 34 | |
| 35 | proc ::fossil::destination {path} { |
| 36 | variable fr |
| 37 | file rename $fr $path |
| @@ -85,24 +82,24 @@ | |
| 82 | if {[IGNORE $ignore $path]} continue |
| 83 | |
| 84 | if {![file exists $path]} { |
| 85 | exec $fossil rm $path |
| 86 | incr removed |
| 87 | write 2 fossil "- $path" |
| 88 | } else { |
| 89 | incr changed |
| 90 | write 2 fossil "* $path" |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | # Now look for unregistered added files. |
| 95 | |
| 96 | foreach path [split [exec $fossil extra] \n] { |
| 97 | if {[IGNORE $ignore $path]} continue |
| 98 | exec $fossil add $path |
| 99 | incr added |
| 100 | write 2 fossil "+ $path" |
| 101 | } |
| 102 | |
| 103 | # Now commit, using the provided meta data, and capture the uuid |
| 104 | # of the new baseline. |
| 105 | |
| @@ -136,11 +133,11 @@ | |
| 133 | # 'Nothing changed' can happen for changesets containing only |
| 134 | # dead-first revisions of one or more files. For fossil we |
| 135 | # re-use the last baseline. TODO: Mark them as branchpoint, |
| 136 | # and for what file. |
| 137 | |
| 138 | write 1 fossil "UNCHANGED, keeping last" |
| 139 | |
| 140 | return [list $lastuuid 0 0 0] |
| 141 | } |
| 142 | |
| 143 | set line [string trim $line] |
| @@ -155,23 +152,10 @@ | |
| 152 | |
| 153 | proc ::fossil::IGNORE {ignore path} { |
| 154 | return [uplevel #0 [linsert $ignore end $path]] |
| 155 | } |
| 156 | |
| 157 | # ----------------------------------------------------------------------------- |
| 158 | # Ready |
| 159 | |
| 160 | package provide fossil 1.0 |
| 161 | return |
| 162 | |
| 163 | DDED tools/lib/log.tcl |
+98
| --- a/tools/lib/log.tcl | ||
| +++ b/tools/lib/log.tcl | ||
| @@ -0,0 +1,98 @@ | ||
| 1 | +# ----------------------------------------------------------------------------- | |
| 2 | +# Tool packages. Logging (aka User feedback). | |
| 3 | + | |
| 4 | +# ----------------------------------------------------------------------------- | |
| 5 | +# Requirements | |
| 6 | + | |
| 7 | +package require Tcl 8.4 | |
| 8 | +namespace eval ::tools::log {} | |
| 9 | + | |
| 10 | +# ----------------------------------------------------------------------------- | |
| 11 | +# API | |
| 12 | + | |
| 13 | +# Feedback generation. | |
| 14 | +# | |
| 15 | +# tools::log::write verbosity system text - Write message to the log. | |
| 16 | +# tools::log::progress verbosity system n max -therwise a finite display. | |
| 17 | + | |
| 18 | +# Admitools::log::verbosity level - Set the verbosity ltools::log::verbosity? - Query the verbosity level of the application. | |
| 19 | +# of the application. | |
| 20 | +# vc::too callback for output | |
| 21 | +# vc::tools::log::system name - Register a system (enables tabular log formatting). | |
| 22 | + | |
| 23 | +# Callback API ( Executed at the global level). | |
| 24 | +# | |
| 25 | +# cmdprefix 'write' system text | |
| 26 | +# cmdprefix 'progress' system n max | |
| 27 | + | |
| 28 | +# Standard callbacks defined by the package itself write to stdout. | |
| 29 | + | |
| 30 | +# ----------------------------------------------------------------------------- | |
| 31 | +# API Implementation - Feedback generation. | |
| 32 | + | |
| 33 | +# Write the message 'text' to log, for the named 'system'. The message | |
| 34 | +# is written if and only if the message verbosity is less or equal the | |
| 35 | +# chosen verbositytools::log::write {verbosity system text} { | |
| 36 | + variable loglevel | |
| 37 | + variable logcmd | |
| 38 | + variable sysfmt | |
| 39 | + if {$verbosity > $loglevel} return | |
| 40 | + uplevel #0 [linsert $logcmd end write [format $sysfmt $system] $text] | |
| 41 | + return | |
| 42 | +} | |
| 43 | + | |
| 44 | +# Similar to write, especially in the handling of the verbosity, to | |
| 45 | +# drive progress displays. It signals that for some long running | |
| 46 | +# operation we are at tick 'n' of attools::log::progress {verbosity system n max} { | |
| 47 | + variable loglevel | |
| 48 | + variable logcmd | |
| 49 | + variable sysfmt | |
| 50 | + if {$verbosity > $loglevel} r------------------------------------------------------------ | |
| 51 | +# API Imple--------- | |
| 52 | +# API Implementation - Administrative operations. | |
| 53 | + | |
| 54 | +# Set verbosity to the chosen 'level'. Only messages with a level less | |
| 55 | +# or equal to this one will be shown. | |
| 56 | + | |
| 57 | +proc ::vc::tools::log::verbosity {level} { | |
| 58 | + variable loglevel | |
| 59 | + if {$level < 1} {set level 0} | |
| 60 | + stools::log::verbositypplication. | |
| 61 | +# vc::tools::log::verbosity? - Query the verbosity level of the application. | |
| 62 | +# vc::tools::log::setCmd cmdprefix - Set callback for otools::log::verbosity? {} { | |
| 63 | + variable loglevel | |
| 64 | + em (enables tabular log formatting). | |
| 65 | + | |
| 66 | +# Callback API ( Executed at the global level). | |
| 67 | +# | |
| 68 | +# cmd cmdprefix 'progress' system n max | |
| 69 | + | |
| 70 | +# Standard callbacks defined by the package itself write to stdout. | |
| 71 | + | |
| 72 | +# ----------------------------------------------------------------------------- | |
| 73 | +# API Implementation - Feedback generation. | |
| 74 | + | |
| 75 | +# Write the message 'text' to log, for t callback for outpu{name} { | |
| 76 | + variable f and only if the message verbosity is less or equal the | |
| 77 | +# chosen verbosity. A message of verbosity 0 cannot be blocked. | |
| 78 | + | |
| 79 | +proc ::vc::tools::log::write {verbosity system text} { | |
| 80 | + variable loglevel | |
| 81 | + variable logcmd | |
| 82 | + variable sysfmt | |
| 83 | + if {$verbosity > $loglevel} return | |
| 84 | + uplevel #0 [linsert $logcmd end write [format $sysfmt $system] $text] | |
| 85 | + , especially in the handling ---------------- It signals that for some long running | |
| 86 | +# operation we are at tick 'n----------------tick 'n' of at most 'max' ticks. | |
| 87 | + | |
| 88 | +proc ::vc::tools::log::progress {verbosity systemingel | |
| 89 | + variable logcmd | |
| 90 | + variable sysfmt | |
| 91 | + if {$verbosity > $loglevel} r-------------------------------------------------------- | |
| 92 | +# API Imple--------- | |
| 93 | +# API Implementation - Administrative operations. | |
| 94 | + | |
| 95 | +# Set verbosity to the chosen 'level'. Only messages with a level less | |
| 96 | +# or equal to this oools::log::verbosity {leve# ----------------------------------------------------------------------------------------------------------------------------- | |
| 97 | +# Tool packages. Loggintools::log 1.0 | |
| 98 | +return |
| --- a/tools/lib/log.tcl | |
| +++ b/tools/lib/log.tcl | |
| @@ -0,0 +1,98 @@ | |
| --- a/tools/lib/log.tcl | |
| +++ b/tools/lib/log.tcl | |
| @@ -0,0 +1,98 @@ | |
| 1 | # ----------------------------------------------------------------------------- |
| 2 | # Tool packages. Logging (aka User feedback). |
| 3 | |
| 4 | # ----------------------------------------------------------------------------- |
| 5 | # Requirements |
| 6 | |
| 7 | package require Tcl 8.4 |
| 8 | namespace eval ::tools::log {} |
| 9 | |
| 10 | # ----------------------------------------------------------------------------- |
| 11 | # API |
| 12 | |
| 13 | # Feedback generation. |
| 14 | # |
| 15 | # tools::log::write verbosity system text - Write message to the log. |
| 16 | # tools::log::progress verbosity system n max -therwise a finite display. |
| 17 | |
| 18 | # Admitools::log::verbosity level - Set the verbosity ltools::log::verbosity? - Query the verbosity level of the application. |
| 19 | # of the application. |
| 20 | # vc::too callback for output |
| 21 | # vc::tools::log::system name - Register a system (enables tabular log formatting). |
| 22 | |
| 23 | # Callback API ( Executed at the global level). |
| 24 | # |
| 25 | # cmdprefix 'write' system text |
| 26 | # cmdprefix 'progress' system n max |
| 27 | |
| 28 | # Standard callbacks defined by the package itself write to stdout. |
| 29 | |
| 30 | # ----------------------------------------------------------------------------- |
| 31 | # API Implementation - Feedback generation. |
| 32 | |
| 33 | # Write the message 'text' to log, for the named 'system'. The message |
| 34 | # is written if and only if the message verbosity is less or equal the |
| 35 | # chosen verbositytools::log::write {verbosity system text} { |
| 36 | variable loglevel |
| 37 | variable logcmd |
| 38 | variable sysfmt |
| 39 | if {$verbosity > $loglevel} return |
| 40 | uplevel #0 [linsert $logcmd end write [format $sysfmt $system] $text] |
| 41 | return |
| 42 | } |
| 43 | |
| 44 | # Similar to write, especially in the handling of the verbosity, to |
| 45 | # drive progress displays. It signals that for some long running |
| 46 | # operation we are at tick 'n' of attools::log::progress {verbosity system n max} { |
| 47 | variable loglevel |
| 48 | variable logcmd |
| 49 | variable sysfmt |
| 50 | if {$verbosity > $loglevel} r------------------------------------------------------------ |
| 51 | # API Imple--------- |
| 52 | # API Implementation - Administrative operations. |
| 53 | |
| 54 | # Set verbosity to the chosen 'level'. Only messages with a level less |
| 55 | # or equal to this one will be shown. |
| 56 | |
| 57 | proc ::vc::tools::log::verbosity {level} { |
| 58 | variable loglevel |
| 59 | if {$level < 1} {set level 0} |
| 60 | stools::log::verbositypplication. |
| 61 | # vc::tools::log::verbosity? - Query the verbosity level of the application. |
| 62 | # vc::tools::log::setCmd cmdprefix - Set callback for otools::log::verbosity? {} { |
| 63 | variable loglevel |
| 64 | em (enables tabular log formatting). |
| 65 | |
| 66 | # Callback API ( Executed at the global level). |
| 67 | # |
| 68 | # cmd cmdprefix 'progress' system n max |
| 69 | |
| 70 | # Standard callbacks defined by the package itself write to stdout. |
| 71 | |
| 72 | # ----------------------------------------------------------------------------- |
| 73 | # API Implementation - Feedback generation. |
| 74 | |
| 75 | # Write the message 'text' to log, for t callback for outpu{name} { |
| 76 | variable f and only if the message verbosity is less or equal the |
| 77 | # chosen verbosity. A message of verbosity 0 cannot be blocked. |
| 78 | |
| 79 | proc ::vc::tools::log::write {verbosity system text} { |
| 80 | variable loglevel |
| 81 | variable logcmd |
| 82 | variable sysfmt |
| 83 | if {$verbosity > $loglevel} return |
| 84 | uplevel #0 [linsert $logcmd end write [format $sysfmt $system] $text] |
| 85 | , especially in the handling ---------------- It signals that for some long running |
| 86 | # operation we are at tick 'n----------------tick 'n' of at most 'max' ticks. |
| 87 | |
| 88 | proc ::vc::tools::log::progress {verbosity systemingel |
| 89 | variable logcmd |
| 90 | variable sysfmt |
| 91 | if {$verbosity > $loglevel} r-------------------------------------------------------- |
| 92 | # API Imple--------- |
| 93 | # API Implementation - Administrative operations. |
| 94 | |
| 95 | # Set verbosity to the chosen 'level'. Only messages with a level less |
| 96 | # or equal to this oools::log::verbosity {leve# ----------------------------------------------------------------------------------------------------------------------------- |
| 97 | # Tool packages. Loggintools::log 1.0 |
| 98 | return |
| --- tools/lib/pkgIndex.tcl | ||
| +++ tools/lib/pkgIndex.tcl | ||
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | if {![package vsatisfies [package require Tcl] 8.4]} return |
| 2 | 2 | package ifneeded rcsparser 1.0 [list source [file join $dir rcsparser.tcl]] |
| 3 | 3 | package ifneeded cvs 1.0 [list source [file join $dir cvs.tcl]] |
| 4 | 4 | package ifneeded fossil 1.0 [list source [file join $dir fossil.tcl]] |
| 5 | +package ifneeded tools::log 1.0 [list source [file join $dir log.tcl]] | |
| 5 | 6 |
| --- tools/lib/pkgIndex.tcl | |
| +++ tools/lib/pkgIndex.tcl | |
| @@ -1,4 +1,5 @@ | |
| 1 | if {![package vsatisfies [package require Tcl] 8.4]} return |
| 2 | package ifneeded rcsparser 1.0 [list source [file join $dir rcsparser.tcl]] |
| 3 | package ifneeded cvs 1.0 [list source [file join $dir cvs.tcl]] |
| 4 | package ifneeded fossil 1.0 [list source [file join $dir fossil.tcl]] |
| 5 |
| --- tools/lib/pkgIndex.tcl | |
| +++ tools/lib/pkgIndex.tcl | |
| @@ -1,4 +1,5 @@ | |
| 1 | if {![package vsatisfies [package require Tcl] 8.4]} return |
| 2 | package ifneeded rcsparser 1.0 [list source [file join $dir rcsparser.tcl]] |
| 3 | package ifneeded cvs 1.0 [list source [file join $dir cvs.tcl]] |
| 4 | package ifneeded fossil 1.0 [list source [file join $dir fossil.tcl]] |
| 5 | package ifneeded tools::log 1.0 [list source [file join $dir log.tcl]] |
| 6 |
+45
-41
| --- tools/lib/rcsparser.tcl | ||
| +++ tools/lib/rcsparser.tcl | ||
| @@ -1,25 +1,53 @@ | ||
| 1 | - | |
| 2 | 1 | # ----------------------------------------------------------------------------- |
| 3 | -# Parse RCS files (,v) - ignore the deltas - we need only the commit messages | |
| 4 | -# Recursive Descent Parser | |
| 2 | +# Tool packages. Parsing RCS files. | |
| 3 | +# | |
| 4 | +# Some of the information in RCS files is skipped over, most | |
| 5 | +# importantly the actual delta texts. The users of this parser need | |
| 6 | +# only the meta-data about when revisions were added, the tree | |
| 7 | +# (branching) structure, commit messages. | |
| 8 | +# | |
| 9 | +# The parser is based on Recursive Descent. | |
| 5 | 10 | |
| 6 | 11 | # ----------------------------------------------------------------------------- |
| 7 | 12 | # Requirements |
| 8 | 13 | |
| 9 | 14 | package require Tcl 8.4 |
| 10 | -package require fileutil ; # Tcllib (cat) | |
| 15 | +package require fileutil ; # Tcllib (cat) | |
| 16 | +package require tools::log ; # User feedback | |
| 11 | 17 | |
| 12 | -namespace eval ::rcsparser {} | |
| 18 | +namespace eval ::rcsparser { | |
| 19 | + tools::log::system rcs | |
| 20 | + namespace import ::tools::log::progress | |
| 21 | +} | |
| 13 | 22 | |
| 14 | 23 | # ----------------------------------------------------------------------------- |
| 15 | 24 | # API |
| 16 | 25 | |
| 17 | -proc ::rcsparser::feedback {logcmd} { | |
| 18 | - variable lc $logcmd | |
| 19 | - return | |
| 20 | -} | |
| 26 | +# rcsparser::process file | |
| 27 | +# | |
| 28 | +# Parses the rcs file and returns a dictionary containing the meta | |
| 29 | +# data. The following keys are used | |
| 30 | +# | |
| 31 | +# Key Meaning | |
| 32 | +# --- ------- | |
| 33 | +# 'head' head revision | |
| 34 | +# 'branch' ? | |
| 35 | +# 'symbol' dict (symbol -> revision) | |
| 36 | +# 'lock' dict (symbol -> revision) | |
| 37 | +# 'comment' file comment | |
| 38 | +# 'expand' ? | |
| 39 | +# 'date' dict (revision -> date) | |
| 40 | +# 'author' dict (revision -> author) | |
| 41 | +# 'state' dict (revision -> state) | |
| 42 | +# 'parent' dict (revision -> parent revision) | |
| 43 | +# 'commit' dict (revision -> commit message) | |
| 44 | +# | |
| 45 | +# The state 'dead' has special meaning, the user should know that. | |
| 46 | + | |
| 47 | +# ----------------------------------------------------------------------------- | |
| 48 | +# API Implementation | |
| 21 | 49 | |
| 22 | 50 | proc ::rcsparser::process {path} { |
| 23 | 51 | set data [fileutil::cat -encoding binary $path] |
| 24 | 52 | array set res {} |
| 25 | 53 | set res(size) [file size $path] |
| @@ -29,36 +57,22 @@ | ||
| 29 | 57 | Admin |
| 30 | 58 | Deltas |
| 31 | 59 | Description |
| 32 | 60 | DeltaTexts |
| 33 | 61 | |
| 34 | - Feedback \r | |
| 35 | - | |
| 36 | 62 | # Remove parser state |
| 37 | 63 | catch {unset res(id)} |
| 38 | 64 | catch {unset res(lastval)} |
| 39 | 65 | unset res(size) |
| 40 | 66 | unset res(nsize) |
| 41 | 67 | unset res(done) |
| 42 | 68 | |
| 43 | - # res: 'head' -> head revision | |
| 44 | - # 'branch' -> ? | |
| 45 | - # 'symbol' -> (sym -> revision) | |
| 46 | - # 'lock' -> (sym -> revision) | |
| 47 | - # 'comment' -> file comment | |
| 48 | - # 'expand' -> ? | |
| 49 | - # 'date' -> (revision -> date) | |
| 50 | - # 'author' -> (revision -> author) | |
| 51 | - # 'state' -> (revision -> state) | |
| 52 | - # 'parent' -> (revision -> parent revision) | |
| 53 | - # 'commit' -> (revision -> commit message) | |
| 54 | - | |
| 55 | 69 | return [array get res] |
| 56 | 70 | } |
| 57 | 71 | |
| 58 | 72 | # ----------------------------------------------------------------------------- |
| 59 | -# Internal helper commands | |
| 73 | +# Internal - Recursive Descent functions implementing the syntax. | |
| 60 | 74 | |
| 61 | 75 | proc ::rcsparser::Admin {} { |
| 62 | 76 | upvar 1 data data res res |
| 63 | 77 | Head ; Branch ; Access ; Symbols ; Locks ; Strict ; Comment ; Expand |
| 64 | 78 | return |
| @@ -190,10 +204,11 @@ | ||
| 190 | 204 | Literal text ; String 1 |
| 191 | 205 | return |
| 192 | 206 | } |
| 193 | 207 | |
| 194 | 208 | # ----------------------------------------------------------------------------- |
| 209 | +# Internal - Lexicographical commands and data aquisition preparation | |
| 195 | 210 | |
| 196 | 211 | proc ::rcsparser::Ident {} { |
| 197 | 212 | upvar 1 data data res res |
| 198 | 213 | |
| 199 | 214 | #puts I@?<[string range $data 0 10]...> |
| @@ -256,10 +271,13 @@ | ||
| 256 | 271 | regexp -indices -- {^\s*([^;]*)\s*} $data match val |
| 257 | 272 | Get $val |
| 258 | 273 | Next |
| 259 | 274 | return |
| 260 | 275 | } |
| 276 | + | |
| 277 | +# ----------------------------------------------------------------------------- | |
| 278 | +# Internal - Data aquisition | |
| 261 | 279 | |
| 262 | 280 | proc ::rcsparser::Def {key} { |
| 263 | 281 | upvar 1 data data res res |
| 264 | 282 | set res($key) $res(lastval) |
| 265 | 283 | unset res(lastval) |
| @@ -294,28 +312,14 @@ | ||
| 294 | 312 | upvar 1 match match data data res res |
| 295 | 313 | foreach {s e} $match break ; incr e |
| 296 | 314 | set data [string range $data $e end] |
| 297 | 315 | set res(done) [expr {$res(size) - [string length $data]}] |
| 298 | 316 | |
| 299 | - Feedback "\r [format "%$res(nsize)s" $res(done)]/$res(size) " | |
| 300 | - return | |
| 301 | -} | |
| 302 | - | |
| 303 | -# ----------------------------------------------------------------------------- | |
| 304 | - | |
| 305 | -namespace eval ::rcsparser { | |
| 306 | - variable lc ::rcs::Nop | |
| 307 | -} | |
| 308 | - | |
| 309 | -proc ::rcsparser::Feedback {text} { | |
| 310 | - variable lc | |
| 311 | - uplevel #0 [linsert $lc end info $text] | |
| 312 | - return | |
| 313 | -} | |
| 314 | - | |
| 315 | -proc ::rcsparser::Nop {args} {} | |
| 317 | + progress 2 rcs $res(done) $res(size) | |
| 318 | + return | |
| 319 | +} | |
| 316 | 320 | |
| 317 | 321 | # ----------------------------------------------------------------------------- |
| 318 | 322 | # Ready |
| 319 | 323 | |
| 320 | 324 | package provide rcsparser 1.0 |
| 321 | 325 | return |
| 322 | 326 |
| --- tools/lib/rcsparser.tcl | |
| +++ tools/lib/rcsparser.tcl | |
| @@ -1,25 +1,53 @@ | |
| 1 | |
| 2 | # ----------------------------------------------------------------------------- |
| 3 | # Parse RCS files (,v) - ignore the deltas - we need only the commit messages |
| 4 | # Recursive Descent Parser |
| 5 | |
| 6 | # ----------------------------------------------------------------------------- |
| 7 | # Requirements |
| 8 | |
| 9 | package require Tcl 8.4 |
| 10 | package require fileutil ; # Tcllib (cat) |
| 11 | |
| 12 | namespace eval ::rcsparser {} |
| 13 | |
| 14 | # ----------------------------------------------------------------------------- |
| 15 | # API |
| 16 | |
| 17 | proc ::rcsparser::feedback {logcmd} { |
| 18 | variable lc $logcmd |
| 19 | return |
| 20 | } |
| 21 | |
| 22 | proc ::rcsparser::process {path} { |
| 23 | set data [fileutil::cat -encoding binary $path] |
| 24 | array set res {} |
| 25 | set res(size) [file size $path] |
| @@ -29,36 +57,22 @@ | |
| 29 | Admin |
| 30 | Deltas |
| 31 | Description |
| 32 | DeltaTexts |
| 33 | |
| 34 | Feedback \r |
| 35 | |
| 36 | # Remove parser state |
| 37 | catch {unset res(id)} |
| 38 | catch {unset res(lastval)} |
| 39 | unset res(size) |
| 40 | unset res(nsize) |
| 41 | unset res(done) |
| 42 | |
| 43 | # res: 'head' -> head revision |
| 44 | # 'branch' -> ? |
| 45 | # 'symbol' -> (sym -> revision) |
| 46 | # 'lock' -> (sym -> revision) |
| 47 | # 'comment' -> file comment |
| 48 | # 'expand' -> ? |
| 49 | # 'date' -> (revision -> date) |
| 50 | # 'author' -> (revision -> author) |
| 51 | # 'state' -> (revision -> state) |
| 52 | # 'parent' -> (revision -> parent revision) |
| 53 | # 'commit' -> (revision -> commit message) |
| 54 | |
| 55 | return [array get res] |
| 56 | } |
| 57 | |
| 58 | # ----------------------------------------------------------------------------- |
| 59 | # Internal helper commands |
| 60 | |
| 61 | proc ::rcsparser::Admin {} { |
| 62 | upvar 1 data data res res |
| 63 | Head ; Branch ; Access ; Symbols ; Locks ; Strict ; Comment ; Expand |
| 64 | return |
| @@ -190,10 +204,11 @@ | |
| 190 | Literal text ; String 1 |
| 191 | return |
| 192 | } |
| 193 | |
| 194 | # ----------------------------------------------------------------------------- |
| 195 | |
| 196 | proc ::rcsparser::Ident {} { |
| 197 | upvar 1 data data res res |
| 198 | |
| 199 | #puts I@?<[string range $data 0 10]...> |
| @@ -256,10 +271,13 @@ | |
| 256 | regexp -indices -- {^\s*([^;]*)\s*} $data match val |
| 257 | Get $val |
| 258 | Next |
| 259 | return |
| 260 | } |
| 261 | |
| 262 | proc ::rcsparser::Def {key} { |
| 263 | upvar 1 data data res res |
| 264 | set res($key) $res(lastval) |
| 265 | unset res(lastval) |
| @@ -294,28 +312,14 @@ | |
| 294 | upvar 1 match match data data res res |
| 295 | foreach {s e} $match break ; incr e |
| 296 | set data [string range $data $e end] |
| 297 | set res(done) [expr {$res(size) - [string length $data]}] |
| 298 | |
| 299 | Feedback "\r [format "%$res(nsize)s" $res(done)]/$res(size) " |
| 300 | return |
| 301 | } |
| 302 | |
| 303 | # ----------------------------------------------------------------------------- |
| 304 | |
| 305 | namespace eval ::rcsparser { |
| 306 | variable lc ::rcs::Nop |
| 307 | } |
| 308 | |
| 309 | proc ::rcsparser::Feedback {text} { |
| 310 | variable lc |
| 311 | uplevel #0 [linsert $lc end info $text] |
| 312 | return |
| 313 | } |
| 314 | |
| 315 | proc ::rcsparser::Nop {args} {} |
| 316 | |
| 317 | # ----------------------------------------------------------------------------- |
| 318 | # Ready |
| 319 | |
| 320 | package provide rcsparser 1.0 |
| 321 | return |
| 322 |
| --- tools/lib/rcsparser.tcl | |
| +++ tools/lib/rcsparser.tcl | |
| @@ -1,25 +1,53 @@ | |
| 1 | # ----------------------------------------------------------------------------- |
| 2 | # Tool packages. Parsing RCS files. |
| 3 | # |
| 4 | # Some of the information in RCS files is skipped over, most |
| 5 | # importantly the actual delta texts. The users of this parser need |
| 6 | # only the meta-data about when revisions were added, the tree |
| 7 | # (branching) structure, commit messages. |
| 8 | # |
| 9 | # The parser is based on Recursive Descent. |
| 10 | |
| 11 | # ----------------------------------------------------------------------------- |
| 12 | # Requirements |
| 13 | |
| 14 | package require Tcl 8.4 |
| 15 | package require fileutil ; # Tcllib (cat) |
| 16 | package require tools::log ; # User feedback |
| 17 | |
| 18 | namespace eval ::rcsparser { |
| 19 | tools::log::system rcs |
| 20 | namespace import ::tools::log::progress |
| 21 | } |
| 22 | |
| 23 | # ----------------------------------------------------------------------------- |
| 24 | # API |
| 25 | |
| 26 | # rcsparser::process file |
| 27 | # |
| 28 | # Parses the rcs file and returns a dictionary containing the meta |
| 29 | # data. The following keys are used |
| 30 | # |
| 31 | # Key Meaning |
| 32 | # --- ------- |
| 33 | # 'head' head revision |
| 34 | # 'branch' ? |
| 35 | # 'symbol' dict (symbol -> revision) |
| 36 | # 'lock' dict (symbol -> revision) |
| 37 | # 'comment' file comment |
| 38 | # 'expand' ? |
| 39 | # 'date' dict (revision -> date) |
| 40 | # 'author' dict (revision -> author) |
| 41 | # 'state' dict (revision -> state) |
| 42 | # 'parent' dict (revision -> parent revision) |
| 43 | # 'commit' dict (revision -> commit message) |
| 44 | # |
| 45 | # The state 'dead' has special meaning, the user should know that. |
| 46 | |
| 47 | # ----------------------------------------------------------------------------- |
| 48 | # API Implementation |
| 49 | |
| 50 | proc ::rcsparser::process {path} { |
| 51 | set data [fileutil::cat -encoding binary $path] |
| 52 | array set res {} |
| 53 | set res(size) [file size $path] |
| @@ -29,36 +57,22 @@ | |
| 57 | Admin |
| 58 | Deltas |
| 59 | Description |
| 60 | DeltaTexts |
| 61 | |
| 62 | # Remove parser state |
| 63 | catch {unset res(id)} |
| 64 | catch {unset res(lastval)} |
| 65 | unset res(size) |
| 66 | unset res(nsize) |
| 67 | unset res(done) |
| 68 | |
| 69 | return [array get res] |
| 70 | } |
| 71 | |
| 72 | # ----------------------------------------------------------------------------- |
| 73 | # Internal - Recursive Descent functions implementing the syntax. |
| 74 | |
| 75 | proc ::rcsparser::Admin {} { |
| 76 | upvar 1 data data res res |
| 77 | Head ; Branch ; Access ; Symbols ; Locks ; Strict ; Comment ; Expand |
| 78 | return |
| @@ -190,10 +204,11 @@ | |
| 204 | Literal text ; String 1 |
| 205 | return |
| 206 | } |
| 207 | |
| 208 | # ----------------------------------------------------------------------------- |
| 209 | # Internal - Lexicographical commands and data aquisition preparation |
| 210 | |
| 211 | proc ::rcsparser::Ident {} { |
| 212 | upvar 1 data data res res |
| 213 | |
| 214 | #puts I@?<[string range $data 0 10]...> |
| @@ -256,10 +271,13 @@ | |
| 271 | regexp -indices -- {^\s*([^;]*)\s*} $data match val |
| 272 | Get $val |
| 273 | Next |
| 274 | return |
| 275 | } |
| 276 | |
| 277 | # ----------------------------------------------------------------------------- |
| 278 | # Internal - Data aquisition |
| 279 | |
| 280 | proc ::rcsparser::Def {key} { |
| 281 | upvar 1 data data res res |
| 282 | set res($key) $res(lastval) |
| 283 | unset res(lastval) |
| @@ -294,28 +312,14 @@ | |
| 312 | upvar 1 match match data data res res |
| 313 | foreach {s e} $match break ; incr e |
| 314 | set data [string range $data $e end] |
| 315 | set res(done) [expr {$res(size) - [string length $data]}] |
| 316 | |
| 317 | progress 2 rcs $res(done) $res(size) |
| 318 | return |
| 319 | } |
| 320 | |
| 321 | # ----------------------------------------------------------------------------- |
| 322 | # Ready |
| 323 | |
| 324 | package provide rcsparser 1.0 |
| 325 | return |
| 326 |