Fossil SCM

Reworked the CVS handling code to have a simpler API, more like the reworked Fossil API. The API now has a form where adding the handling of branches should not require complex changes in the import controller any longer. Extended the system to allow the user to restrict the importing to a sub-directory of the chosen repository, via the new switch --project. This is required to pull a SF CVS repository apart into the various projects it may have. Example: Under Tcl we have 3 projects, namely Tcl itself, sampleextension, and Thread.

aku 2007-09-17 00:56 trunk
Commit d8c18fc148f545ddcb8769389177a892a18666e8
--- tools/import-cvs.tcl
+++ tools/import-cvs.tcl
@@ -42,10 +42,11 @@
4242
# Requirements
4343
4444
package require Tcl 8.4
4545
package require vc::tools::log ; # User Feedback
4646
package require vc::fossil::import::cvs ; # Importer Control
47
+package require vc::cvs::ws ; # CVS frontend
4748
4849
namespace eval ::import {
4950
namespace import ::vc::fossil::import::cvs::*
5051
}
5152
@@ -69,10 +70,11 @@
6970
while {[string match "-*" [set opt [this]]]} {
7071
switch -exact -- $opt {
7172
--breakat { next ; import::configure -breakat [this] }
7273
--nosign { import::configure -nosign 1 }
7374
--saveto { next ; import::configure -saveto [file normalize [this]] }
75
+ --project { next ; import::configure -project [this] }
7476
-v { incr verbosity ; ::vc::tools::log::verbosity $verbosity }
7577
-h -
7678
default usage
7779
}
7880
next
@@ -80,16 +82,12 @@
8082
8183
remainder
8284
if {[llength $argv] != 2} usage
8385
foreach {cvs fossil} $argv break
8486
85
- if {
86
- ![file exists $cvs] ||
87
- ![file readable $cvs] ||
88
- ![file isdirectory $cvs]
89
- } {
90
- usage "CVS directory missing, not readable, or not a directory."
87
+ if {![::vc::cvs::ws::check $cvs msg]} {
88
+ usage $msg
9189
} elseif {[file exists $fossil]} {
9290
usage "Fossil destination repository exists already."
9391
}
9492
9593
return
@@ -124,10 +122,11 @@
124122
global argv0
125123
puts stderr "Usage: $argv0 ?-v? ?--nosign? ?--breakat id? ?--saveto path? cvs-repository fossil-repository"
126124
if {$text eq ""} {
127125
puts stderr " --nosign: Do not sign the imported changesets."
128126
puts stderr " --breakat: Stop just before committing the identified changeset."
127
+ puts stderr " --project: Path in the CVS repository to limit the import to."
129128
puts stderr " --saveto: Save commit command to the specified file."
130129
puts stderr " -v: Increase log verbosity. Can be used multiple times."
131130
} else {
132131
puts stderr " $text"
133132
}
134133
--- tools/import-cvs.tcl
+++ tools/import-cvs.tcl
@@ -42,10 +42,11 @@
42 # Requirements
43
44 package require Tcl 8.4
45 package require vc::tools::log ; # User Feedback
46 package require vc::fossil::import::cvs ; # Importer Control
 
47
48 namespace eval ::import {
49 namespace import ::vc::fossil::import::cvs::*
50 }
51
@@ -69,10 +70,11 @@
69 while {[string match "-*" [set opt [this]]]} {
70 switch -exact -- $opt {
71 --breakat { next ; import::configure -breakat [this] }
72 --nosign { import::configure -nosign 1 }
73 --saveto { next ; import::configure -saveto [file normalize [this]] }
 
74 -v { incr verbosity ; ::vc::tools::log::verbosity $verbosity }
75 -h -
76 default usage
77 }
78 next
@@ -80,16 +82,12 @@
80
81 remainder
82 if {[llength $argv] != 2} usage
83 foreach {cvs fossil} $argv break
84
85 if {
86 ![file exists $cvs] ||
87 ![file readable $cvs] ||
88 ![file isdirectory $cvs]
89 } {
90 usage "CVS directory missing, not readable, or not a directory."
91 } elseif {[file exists $fossil]} {
92 usage "Fossil destination repository exists already."
93 }
94
95 return
@@ -124,10 +122,11 @@
124 global argv0
125 puts stderr "Usage: $argv0 ?-v? ?--nosign? ?--breakat id? ?--saveto path? cvs-repository fossil-repository"
126 if {$text eq ""} {
127 puts stderr " --nosign: Do not sign the imported changesets."
128 puts stderr " --breakat: Stop just before committing the identified changeset."
 
129 puts stderr " --saveto: Save commit command to the specified file."
130 puts stderr " -v: Increase log verbosity. Can be used multiple times."
131 } else {
132 puts stderr " $text"
133 }
134
--- tools/import-cvs.tcl
+++ tools/import-cvs.tcl
@@ -42,10 +42,11 @@
42 # Requirements
43
44 package require Tcl 8.4
45 package require vc::tools::log ; # User Feedback
46 package require vc::fossil::import::cvs ; # Importer Control
47 package require vc::cvs::ws ; # CVS frontend
48
49 namespace eval ::import {
50 namespace import ::vc::fossil::import::cvs::*
51 }
52
@@ -69,10 +70,11 @@
70 while {[string match "-*" [set opt [this]]]} {
71 switch -exact -- $opt {
72 --breakat { next ; import::configure -breakat [this] }
73 --nosign { import::configure -nosign 1 }
74 --saveto { next ; import::configure -saveto [file normalize [this]] }
75 --project { next ; import::configure -project [this] }
76 -v { incr verbosity ; ::vc::tools::log::verbosity $verbosity }
77 -h -
78 default usage
79 }
80 next
@@ -80,16 +82,12 @@
82
83 remainder
84 if {[llength $argv] != 2} usage
85 foreach {cvs fossil} $argv break
86
87 if {![::vc::cvs::ws::check $cvs msg]} {
88 usage $msg
 
 
 
 
89 } elseif {[file exists $fossil]} {
90 usage "Fossil destination repository exists already."
91 }
92
93 return
@@ -124,10 +122,11 @@
122 global argv0
123 puts stderr "Usage: $argv0 ?-v? ?--nosign? ?--breakat id? ?--saveto path? cvs-repository fossil-repository"
124 if {$text eq ""} {
125 puts stderr " --nosign: Do not sign the imported changesets."
126 puts stderr " --breakat: Stop just before committing the identified changeset."
127 puts stderr " --project: Path in the CVS repository to limit the import to."
128 puts stderr " --saveto: Save commit command to the specified file."
129 puts stderr " -v: Increase log verbosity. Can be used multiple times."
130 } else {
131 puts stderr " $text"
132 }
133
+156 -61
--- tools/lib/cvs.tcl
+++ tools/lib/cvs.tcl
@@ -19,52 +19,169 @@
1919
}
2020
2121
# -----------------------------------------------------------------------------
2222
# API
2323
24
-# Define repository directory.
24
+# vc::cvs::ws::configure key value - Configure the subsystem.
25
+# vc::cvs::ws::check src mv - Check if src is a CVS repository directory.
26
+# vc::cvs::ws::begin src - Start new workspace and return the top-
27
+# most directory co'd files are put into.
28
+# vc::cvs::ws::ncsets ?-import? - Retrieve number of csets (all/to import)
29
+# vc::cvs::ws::foreach csvar script - Run the script for each changeset, the
30
+# id of the current changeset stored in
31
+# the variable named by csvar.
32
+# vc::cvs::ws::done - Close workspace and delete it.
33
+# vc::cvs::ws::isadmin path - Check if path is an admin file of CVS
34
+# vc::cvs::ws::checkout id - Have workspace contain the changeset id.
35
+#
36
+# Configuration keys:
37
+#
38
+# -project path - Sub directory under 'src' to limit the import to.
2539
26
-proc ::vc::cvs::ws::at {path} {
27
- variable base [file normalize $path]
28
- write 0 cvs "Base: $base"
40
+# -----------------------------------------------------------------------------
41
+# API Implementation
42
+
43
+proc ::vc::cvs::ws::configure {key value} {
44
+ variable project
45
+
46
+ switch -exact -- $key {
47
+ -project { set project $value }
48
+ default {
49
+ return -code error "Unknown switch $key, expected \
50
+ -project"
51
+ }
52
+ }
53
+ return
54
+}
55
+
56
+proc ::vc::cvs::ws::check {src mv} {
57
+ variable project
58
+ upvar 1 $mv msg
59
+ if {
60
+ ![fileutil::test $src erd msg "CVS Repository"] ||
61
+ ![fileutil::test $src/CVSROOT erd msg "CVS Admin directory"] ||
62
+ (($project ne "") &&
63
+ ![fileutil::test $src/$project erd msg "Project directory"])
64
+ } {
65
+ return 0
66
+ }
67
+ return 1
68
+}
69
+
70
+proc ::vc::cvs::ws::begin {src} {
71
+ variable project
72
+ variable base
73
+
74
+ set src [file normalize $src]
75
+ if {![check $src msg]} {
76
+ return -code error $msg
77
+ }
78
+ set base $src
79
+ write 0 cvs "Base: $base"
80
+ if {$project eq ""} {
81
+ write 0 cvs "Project: <ALL>"
82
+ } else {
83
+ write 0 cvs "Project: $project"
84
+ }
85
+
86
+ # OLD api calls ... TODO rework for more structure ...
87
+ scan ; # Gather revision data from the archives
88
+ csets ; # Group changes into sets
89
+ rtree ; # Build revision tree (trunk only right now).
90
+
91
+ set w [workspace] ; # OLD api ... TODO inline
92
+ if {$project ne ""} {
93
+ set w $w/$project
94
+ file mkdir $w
95
+ }
96
+ return $w
97
+}
98
+
99
+proc ::vc::cvs::ws::done {} {
100
+ variable cwd
101
+ variable workspace
102
+ cd $cwd
103
+ file delete -force $workspace
29104
return
30105
}
31106
32
-namespace eval ::vc::cvs::ws {
33
- # Toplevel repository directory
34
- variable base {}
107
+proc ::vc::cvs::ws::foreach {cv script} {
108
+ # OLD api ... TODO inline
109
+ uplevel 1 [list ::vc::cvs::ws::foreach_cset $cv 0 $script]
110
+}
111
+
112
+proc ::vc::cvs::ws::ncsets {args} {
113
+ variable ncs
114
+ variable ntrunk
115
+
116
+ if {[llength $args] > 1} {
117
+ return -code error "wrong#args: Expected ?-import?"
118
+ } elseif {[llength $args] == 1} {
119
+ if {[set k [lindex $args 0]] ne "-import"} {
120
+ return -code "Unknown switch $k, expected -import"
121
+ } else {
122
+ return $ntrunk
123
+ }
124
+ }
125
+
126
+ return $ncs
127
+}
128
+
129
+proc ::vc::cvs::ws::isadmin {path} {
130
+ # Check if path is a CVS admin file.
131
+ if {[string match CVS/* $path]} {return 1}
132
+ if {[string match */CVS/* $path]} {return 1}
133
+ return 0
134
+}
135
+
136
+proc ::vc::cvs::ws::checkout {id} {
137
+ variable workspace ; cd $workspace
138
+ wssetup $id ; # OLD api ... TODO inline
35139
}
140
+
141
+# -----------------------------------------------------------------------------
142
+# Internals - Old API for now.
36143
37144
# Scan repository, collect archives, parse them, and collect revision
38145
# information (file, revision -> date, author, commit message)
39146
40147
proc ::vc::cvs::ws::scan {} {
148
+ variable project
41149
variable base
42150
variable npaths
43151
variable rpaths
44152
variable timeline
45153
46154
write 0 cvs {Scanning directory hierarchy}
47155
48156
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
157
+ set d $base ; if {$project ne ""} {append d /$project}
158
+
159
+ ::foreach rcs [fileutil::findByPattern $d -glob *,v] {
160
+ set rcs [fileutil::stripPath $d $rcs]
161
+ # Now rcs is relative to base/project
52162
53163
write 1 cvs "Archive $rcs"
54164
55
- if {[string match CVSROOT* $rcs]} {
165
+ if {[string match CVSROOT/* $rcs]} {
56166
write 2 cvs {Ignored. Administrative file}
57167
continue
58168
}
59169
60170
# Derive the regular path from the rcs path. Meaning: Chop of
61171
# the ",v" suffix, and remove a possible "Attic".
62172
set f [string range $rcs 0 end-2]
63173
if {"Attic" eq [lindex [file split $rcs] end-1]} {
64
- set f [file join [file dirname [file dirname $f]] [file tail $f]]
65
- if {[file exists $base/$f,v]} {
174
+
175
+ # The construction below ensures that Attic/X maps to X
176
+ # instead of ./X. Otherwise, Y/Attic/X maps to Y/X.
177
+
178
+ set fx [file dirname [file dirname $f]]
179
+ set f [file tail $f]
180
+ if {$fx ne "."} { set f [file join $fx $f] }
181
+
182
+ if {[file exists $d/$f,v]} {
66183
# We have a regular archive and an Attic archive
67184
# refering to the same user visible file. Ignore the
68185
# file in the Attic.
69186
70187
write 2 cvs "Ignored. Attic superceded by regular archive"
@@ -84,18 +201,18 @@
84201
continue
85202
}
86203
}
87204
88205
# Get the meta data we need (revisions, timeline, messages).
89
- set meta [process $base/$rcs]
206
+ set meta [process $d/$rcs]
90207
91208
set npaths($rcs) $f
92209
set rpaths($f) $rcs
93210
94211
array set p $meta
95212
96
- foreach {rev ts} $p(date) {_ a} $p(author) {_ cm} $p(commit) {_ st} $p(state) {
213
+ ::foreach {rev ts} $p(date) {_ a} $p(author) {_ cm} $p(commit) {_ st} $p(state) {
97214
set op [expr {($rev eq "1.1") ? "A" : "M"}]
98215
if {$st eq "dead"} {set op "R"}
99216
100217
# A dead-first revision is rev 1.1 with op R. For an
101218
# example see the file memchan/DEPENDENCIES. Such a file
@@ -146,20 +263,20 @@
146263
147264
write 0 cvs "Processing timeline"
148265
149266
set n 0
150267
CSClear
151
- foreach ts [lsort -dict [array names timeline]] {
268
+ ::foreach ts [lsort -dict [array names timeline]] {
152269
153270
# op tstamp author revision file commit
154271
# 0 1 2 3 4 5/end
155272
# b c a
156273
157274
set entries [lsort -index 2 [lsort -index 0 [lsort -index end $timeline($ts)]]]
158275
#puts [join $entries \n]
159276
160
- foreach entry $entries {
277
+ ::foreach entry $entries {
161278
if {![CSNone] && [CSNew $entry]} {
162279
CSSave
163280
CSClear
164281
#puts ==\n$reason
165282
}
@@ -203,12 +320,12 @@
203320
set b 0 ; # No branch csets found yet.
204321
205322
# Extracting the trunk is easy, simply by looking at the involved
206323
# version numbers.
207324
208
- foreach c [lrange [lsort -integer [array names csets]] 1 end] {
209
- foreach {u cm s e rd f} $csets($c) break
325
+ ::foreach c [lrange [lsort -integer [array names csets]] 1 end] {
326
+ ::foreach {u cm s e rd f} $csets($c) break
210327
211328
# Ignore branch changes, just count them for the statistics.
212329
if {$rd != 2} {
213330
incr b
214331
continue
@@ -243,40 +360,27 @@
243360
244361
cd $workspace ; # Checkouts go here.
245362
return $workspace
246363
}
247364
248
-proc ::vc::cvs::ws::wsignore {path} {
249
- # Ignore CVS admin files.
250
- if {[string match */CVS/* $path]} {return 1}
251
- return 0
252
-}
253
-
254
-proc ::vc::cvs::ws::wsclear {} {
255
- variable cwd
256
- variable workspace
257
- cd $cwd
258
- file delete -force $workspace
259
- return
260
-}
261
-
262365
proc ::vc::cvs::ws::wssetup {c} {
263366
variable csets
264367
variable base
368
+ variable project
265369
266370
# pwd = workspace
267371
268
- foreach {u cm s e rd fs} $csets($c) break
372
+ ::foreach {u cm s e rd fs} $csets($c) break
269373
270374
write 1 cvs "@ $s"
271375
272
- foreach l [split [string trim $cm] \n] {
376
+ ::foreach l [split [string trim $cm] \n] {
273377
write 1 cvs "| $l"
274378
}
275379
276
- foreach {f or} $fs {
277
- foreach {op r} $or break
380
+ ::foreach {f or} $fs {
381
+ ::foreach {op r} $or break
278382
write 2 cvs "$op $f $r"
279383
280384
if {$op eq "R"} {
281385
# Remove file from workspace. Prune empty directories.
282386
#
@@ -299,18 +403,19 @@
299403
}
300404
} else {
301405
# Added or modified, put the requested version of the file
302406
# into the workspace.
303407
408
+ if {$project ne ""} {set f $project/$f}
304409
if {[catch {
305410
dova -d $base co -r $r $f
306411
} msg]} {
307412
if {[string match {*invalid change text*} $msg]} {
308413
# The archive of the file is corrupted and the
309414
# chosen version not accessible due to that. We
310415
# report the problem, but otherwise ignore it. As
311
- # a consequence the fossil repository will not
416
+ # a consequence the destination repository will not
312417
# contain the full history of the named file. By
313418
# ignoring the problem we however get as much as
314419
# is possible.
315420
316421
write 0 cvs "EE Corrupted archive file. Inaccessible revision."
@@ -362,24 +467,10 @@
362467
set c [lindex [$rtree children $c] 0]
363468
}
364469
return
365470
}
366471
367
-proc ::vc::cvs::ws::root {} {
368
- return 0
369
-}
370
-
371
-proc ::vc::cvs::ws::ntrunk {} {
372
- variable ntrunk
373
- return $ntrunk
374
-}
375
-
376
-proc ::vc::cvs::ws::ncsets {} {
377
- variable ncs
378
- return $ncs
379
-}
380
-
381472
# -----------------------------------------------------------------------------
382473
# Internal helper commands: Changeset inspection and construction.
383474
384475
proc ::vc::cvs::ws::CSClear {} {
385476
upvar 1 start start end end cm cm user user files files lastd lastd
@@ -402,11 +493,11 @@
402493
proc ::vc::cvs::ws::CSNew {entry} {
403494
upvar 1 start start end end cm cm user user files files lastd lastd reason reason
404495
405496
#puts -nonewline stdout . ; flush stdout
406497
407
- foreach {op ts a rev f ecm} $entry break
498
+ ::foreach {op ts a rev f ecm} $entry break
408499
409500
# User change
410501
if {$a ne $user} {set reason user ; return 1}
411502
412503
# File already in current cset
@@ -430,12 +521,12 @@
430521
upvar 1 start start end end cm cm user user files files lastd lastd
431522
432523
set csets($ncs) [list $user $cm $start $end $lastd [array get files]]
433524
434525
# Record which revisions of a file are in what csets
435
- foreach {f or} [array get files] {
436
- foreach {_ rev} $or break
526
+ ::foreach {f or} [array get files] {
527
+ ::foreach {_ rev} $or break
437528
set cmap([list $f $rev]) $ncs
438529
}
439530
440531
#CSDump $ncs
441532
@@ -444,11 +535,11 @@
444535
}
445536
446537
proc ::vc::cvs::ws::CSAdd {entry} {
447538
upvar 1 start start end end cm cm user user files files lastd lastd
448539
449
- foreach {op ts a rev f ecm} $entry break
540
+ ::foreach {op ts a rev f ecm} $entry break
450541
451542
if {$start eq ""} {set start $ts}
452543
set end $ts
453544
set cm $ecm
454545
set user $a
@@ -457,26 +548,30 @@
457548
return
458549
}
459550
460551
proc ::vc::cvs::ws::CSDump {c} {
461552
variable csets
462
- foreach {u cm s e rd f} $csets($c) break
553
+ ::foreach {u cm s e rd f} $csets($c) break
463554
464555
puts "$u $s"; regsub -all {.} $u { } b
465556
puts "$b $e"
466
- foreach {f or} $f {
467
- foreach {o r} $or break
557
+ ::foreach {f or} $f {
558
+ ::foreach {o r} $or break
468559
puts "$b $o $f $r"
469560
}
470561
return
471562
}
472563
564
+# -----------------------------------------------------------------------------
565
+
473566
namespace eval ::vc::cvs::ws {
474
- namespace export at scan csets rtree workspace wsignore wsclear wssetup \
475
- foreach_cset root ntrunk ncsets
567
+ variable base {} ; # Toplevel repository directory
568
+ variable project {} ; # Sub directory to limit the import to.
569
+
570
+ namespace export configure begin done foreach ncsets checkout
476571
}
477572
478573
# -----------------------------------------------------------------------------
479574
# Ready
480575
481576
package provide vc::cvs::ws 1.0
482577
return
483578
--- tools/lib/cvs.tcl
+++ tools/lib/cvs.tcl
@@ -19,52 +19,169 @@
19 }
20
21 # -----------------------------------------------------------------------------
22 # API
23
24 # Define repository directory.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
26 proc ::vc::cvs::ws::at {path} {
27 variable base [file normalize $path]
28 write 0 cvs "Base: $base"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29 return
30 }
31
32 namespace eval ::vc::cvs::ws {
33 # Toplevel repository directory
34 variable base {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35 }
 
 
 
36
37 # Scan repository, collect archives, parse them, and collect revision
38 # information (file, revision -> date, author, commit message)
39
40 proc ::vc::cvs::ws::scan {} {
 
41 variable base
42 variable npaths
43 variable rpaths
44 variable timeline
45
46 write 0 cvs {Scanning directory hierarchy}
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 write 1 cvs "Archive $rcs"
54
55 if {[string match CVSROOT* $rcs]} {
56 write 2 cvs {Ignored. Administrative 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".
62 set f [string range $rcs 0 end-2]
63 if {"Attic" eq [lindex [file split $rcs] end-1]} {
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
70 write 2 cvs "Ignored. Attic superceded by regular archive"
@@ -84,18 +201,18 @@
84 continue
85 }
86 }
87
88 # Get the meta data we need (revisions, timeline, messages).
89 set meta [process $base/$rcs]
90
91 set npaths($rcs) $f
92 set rpaths($f) $rcs
93
94 array set p $meta
95
96 foreach {rev ts} $p(date) {_ a} $p(author) {_ cm} $p(commit) {_ st} $p(state) {
97 set op [expr {($rev eq "1.1") ? "A" : "M"}]
98 if {$st eq "dead"} {set op "R"}
99
100 # A dead-first revision is rev 1.1 with op R. For an
101 # example see the file memchan/DEPENDENCIES. Such a file
@@ -146,20 +263,20 @@
146
147 write 0 cvs "Processing timeline"
148
149 set n 0
150 CSClear
151 foreach ts [lsort -dict [array names timeline]] {
152
153 # op tstamp author revision file commit
154 # 0 1 2 3 4 5/end
155 # b c a
156
157 set entries [lsort -index 2 [lsort -index 0 [lsort -index end $timeline($ts)]]]
158 #puts [join $entries \n]
159
160 foreach entry $entries {
161 if {![CSNone] && [CSNew $entry]} {
162 CSSave
163 CSClear
164 #puts ==\n$reason
165 }
@@ -203,12 +320,12 @@
203 set b 0 ; # No branch csets found yet.
204
205 # Extracting the trunk is easy, simply by looking at the involved
206 # version numbers.
207
208 foreach c [lrange [lsort -integer [array names csets]] 1 end] {
209 foreach {u cm s e rd f} $csets($c) break
210
211 # Ignore branch changes, just count them for the statistics.
212 if {$rd != 2} {
213 incr b
214 continue
@@ -243,40 +360,27 @@
243
244 cd $workspace ; # Checkouts go here.
245 return $workspace
246 }
247
248 proc ::vc::cvs::ws::wsignore {path} {
249 # Ignore CVS admin files.
250 if {[string match */CVS/* $path]} {return 1}
251 return 0
252 }
253
254 proc ::vc::cvs::ws::wsclear {} {
255 variable cwd
256 variable workspace
257 cd $cwd
258 file delete -force $workspace
259 return
260 }
261
262 proc ::vc::cvs::ws::wssetup {c} {
263 variable csets
264 variable base
 
265
266 # pwd = workspace
267
268 foreach {u cm s e rd fs} $csets($c) break
269
270 write 1 cvs "@ $s"
271
272 foreach l [split [string trim $cm] \n] {
273 write 1 cvs "| $l"
274 }
275
276 foreach {f or} $fs {
277 foreach {op r} $or break
278 write 2 cvs "$op $f $r"
279
280 if {$op eq "R"} {
281 # Remove file from workspace. Prune empty directories.
282 #
@@ -299,18 +403,19 @@
299 }
300 } else {
301 # Added or modified, put the requested version of the file
302 # into the workspace.
303
 
304 if {[catch {
305 dova -d $base co -r $r $f
306 } msg]} {
307 if {[string match {*invalid change text*} $msg]} {
308 # The archive of the file is corrupted and the
309 # chosen version not accessible due to that. We
310 # report the problem, but otherwise ignore it. As
311 # a consequence the fossil repository will not
312 # contain the full history of the named file. By
313 # ignoring the problem we however get as much as
314 # is possible.
315
316 write 0 cvs "EE Corrupted archive file. Inaccessible revision."
@@ -362,24 +467,10 @@
362 set c [lindex [$rtree children $c] 0]
363 }
364 return
365 }
366
367 proc ::vc::cvs::ws::root {} {
368 return 0
369 }
370
371 proc ::vc::cvs::ws::ntrunk {} {
372 variable ntrunk
373 return $ntrunk
374 }
375
376 proc ::vc::cvs::ws::ncsets {} {
377 variable ncs
378 return $ncs
379 }
380
381 # -----------------------------------------------------------------------------
382 # Internal helper commands: Changeset inspection and construction.
383
384 proc ::vc::cvs::ws::CSClear {} {
385 upvar 1 start start end end cm cm user user files files lastd lastd
@@ -402,11 +493,11 @@
402 proc ::vc::cvs::ws::CSNew {entry} {
403 upvar 1 start start end end cm cm user user files files lastd lastd reason reason
404
405 #puts -nonewline stdout . ; flush stdout
406
407 foreach {op ts a rev f ecm} $entry break
408
409 # User change
410 if {$a ne $user} {set reason user ; return 1}
411
412 # File already in current cset
@@ -430,12 +521,12 @@
430 upvar 1 start start end end cm cm user user files files lastd lastd
431
432 set csets($ncs) [list $user $cm $start $end $lastd [array get files]]
433
434 # Record which revisions of a file are in what csets
435 foreach {f or} [array get files] {
436 foreach {_ rev} $or break
437 set cmap([list $f $rev]) $ncs
438 }
439
440 #CSDump $ncs
441
@@ -444,11 +535,11 @@
444 }
445
446 proc ::vc::cvs::ws::CSAdd {entry} {
447 upvar 1 start start end end cm cm user user files files lastd lastd
448
449 foreach {op ts a rev f ecm} $entry break
450
451 if {$start eq ""} {set start $ts}
452 set end $ts
453 set cm $ecm
454 set user $a
@@ -457,26 +548,30 @@
457 return
458 }
459
460 proc ::vc::cvs::ws::CSDump {c} {
461 variable csets
462 foreach {u cm s e rd f} $csets($c) break
463
464 puts "$u $s"; regsub -all {.} $u { } b
465 puts "$b $e"
466 foreach {f or} $f {
467 foreach {o r} $or break
468 puts "$b $o $f $r"
469 }
470 return
471 }
472
 
 
473 namespace eval ::vc::cvs::ws {
474 namespace export at scan csets rtree workspace wsignore wsclear wssetup \
475 foreach_cset root ntrunk ncsets
 
 
476 }
477
478 # -----------------------------------------------------------------------------
479 # Ready
480
481 package provide vc::cvs::ws 1.0
482 return
483
--- tools/lib/cvs.tcl
+++ tools/lib/cvs.tcl
@@ -19,52 +19,169 @@
19 }
20
21 # -----------------------------------------------------------------------------
22 # API
23
24 # vc::cvs::ws::configure key value - Configure the subsystem.
25 # vc::cvs::ws::check src mv - Check if src is a CVS repository directory.
26 # vc::cvs::ws::begin src - Start new workspace and return the top-
27 # most directory co'd files are put into.
28 # vc::cvs::ws::ncsets ?-import? - Retrieve number of csets (all/to import)
29 # vc::cvs::ws::foreach csvar script - Run the script for each changeset, the
30 # id of the current changeset stored in
31 # the variable named by csvar.
32 # vc::cvs::ws::done - Close workspace and delete it.
33 # vc::cvs::ws::isadmin path - Check if path is an admin file of CVS
34 # vc::cvs::ws::checkout id - Have workspace contain the changeset id.
35 #
36 # Configuration keys:
37 #
38 # -project path - Sub directory under 'src' to limit the import to.
39
40 # -----------------------------------------------------------------------------
41 # API Implementation
42
43 proc ::vc::cvs::ws::configure {key value} {
44 variable project
45
46 switch -exact -- $key {
47 -project { set project $value }
48 default {
49 return -code error "Unknown switch $key, expected \
50 -project"
51 }
52 }
53 return
54 }
55
56 proc ::vc::cvs::ws::check {src mv} {
57 variable project
58 upvar 1 $mv msg
59 if {
60 ![fileutil::test $src erd msg "CVS Repository"] ||
61 ![fileutil::test $src/CVSROOT erd msg "CVS Admin directory"] ||
62 (($project ne "") &&
63 ![fileutil::test $src/$project erd msg "Project directory"])
64 } {
65 return 0
66 }
67 return 1
68 }
69
70 proc ::vc::cvs::ws::begin {src} {
71 variable project
72 variable base
73
74 set src [file normalize $src]
75 if {![check $src msg]} {
76 return -code error $msg
77 }
78 set base $src
79 write 0 cvs "Base: $base"
80 if {$project eq ""} {
81 write 0 cvs "Project: <ALL>"
82 } else {
83 write 0 cvs "Project: $project"
84 }
85
86 # OLD api calls ... TODO rework for more structure ...
87 scan ; # Gather revision data from the archives
88 csets ; # Group changes into sets
89 rtree ; # Build revision tree (trunk only right now).
90
91 set w [workspace] ; # OLD api ... TODO inline
92 if {$project ne ""} {
93 set w $w/$project
94 file mkdir $w
95 }
96 return $w
97 }
98
99 proc ::vc::cvs::ws::done {} {
100 variable cwd
101 variable workspace
102 cd $cwd
103 file delete -force $workspace
104 return
105 }
106
107 proc ::vc::cvs::ws::foreach {cv script} {
108 # OLD api ... TODO inline
109 uplevel 1 [list ::vc::cvs::ws::foreach_cset $cv 0 $script]
110 }
111
112 proc ::vc::cvs::ws::ncsets {args} {
113 variable ncs
114 variable ntrunk
115
116 if {[llength $args] > 1} {
117 return -code error "wrong#args: Expected ?-import?"
118 } elseif {[llength $args] == 1} {
119 if {[set k [lindex $args 0]] ne "-import"} {
120 return -code "Unknown switch $k, expected -import"
121 } else {
122 return $ntrunk
123 }
124 }
125
126 return $ncs
127 }
128
129 proc ::vc::cvs::ws::isadmin {path} {
130 # Check if path is a CVS admin file.
131 if {[string match CVS/* $path]} {return 1}
132 if {[string match */CVS/* $path]} {return 1}
133 return 0
134 }
135
136 proc ::vc::cvs::ws::checkout {id} {
137 variable workspace ; cd $workspace
138 wssetup $id ; # OLD api ... TODO inline
139 }
140
141 # -----------------------------------------------------------------------------
142 # Internals - Old API for now.
143
144 # Scan repository, collect archives, parse them, and collect revision
145 # information (file, revision -> date, author, commit message)
146
147 proc ::vc::cvs::ws::scan {} {
148 variable project
149 variable base
150 variable npaths
151 variable rpaths
152 variable timeline
153
154 write 0 cvs {Scanning directory hierarchy}
155
156 set n 0
157 set d $base ; if {$project ne ""} {append d /$project}
158
159 ::foreach rcs [fileutil::findByPattern $d -glob *,v] {
160 set rcs [fileutil::stripPath $d $rcs]
161 # Now rcs is relative to base/project
162
163 write 1 cvs "Archive $rcs"
164
165 if {[string match CVSROOT/* $rcs]} {
166 write 2 cvs {Ignored. Administrative file}
167 continue
168 }
169
170 # Derive the regular path from the rcs path. Meaning: Chop of
171 # the ",v" suffix, and remove a possible "Attic".
172 set f [string range $rcs 0 end-2]
173 if {"Attic" eq [lindex [file split $rcs] end-1]} {
174
175 # The construction below ensures that Attic/X maps to X
176 # instead of ./X. Otherwise, Y/Attic/X maps to Y/X.
177
178 set fx [file dirname [file dirname $f]]
179 set f [file tail $f]
180 if {$fx ne "."} { set f [file join $fx $f] }
181
182 if {[file exists $d/$f,v]} {
183 # We have a regular archive and an Attic archive
184 # refering to the same user visible file. Ignore the
185 # file in the Attic.
186
187 write 2 cvs "Ignored. Attic superceded by regular archive"
@@ -84,18 +201,18 @@
201 continue
202 }
203 }
204
205 # Get the meta data we need (revisions, timeline, messages).
206 set meta [process $d/$rcs]
207
208 set npaths($rcs) $f
209 set rpaths($f) $rcs
210
211 array set p $meta
212
213 ::foreach {rev ts} $p(date) {_ a} $p(author) {_ cm} $p(commit) {_ st} $p(state) {
214 set op [expr {($rev eq "1.1") ? "A" : "M"}]
215 if {$st eq "dead"} {set op "R"}
216
217 # A dead-first revision is rev 1.1 with op R. For an
218 # example see the file memchan/DEPENDENCIES. Such a file
@@ -146,20 +263,20 @@
263
264 write 0 cvs "Processing timeline"
265
266 set n 0
267 CSClear
268 ::foreach ts [lsort -dict [array names timeline]] {
269
270 # op tstamp author revision file commit
271 # 0 1 2 3 4 5/end
272 # b c a
273
274 set entries [lsort -index 2 [lsort -index 0 [lsort -index end $timeline($ts)]]]
275 #puts [join $entries \n]
276
277 ::foreach entry $entries {
278 if {![CSNone] && [CSNew $entry]} {
279 CSSave
280 CSClear
281 #puts ==\n$reason
282 }
@@ -203,12 +320,12 @@
320 set b 0 ; # No branch csets found yet.
321
322 # Extracting the trunk is easy, simply by looking at the involved
323 # version numbers.
324
325 ::foreach c [lrange [lsort -integer [array names csets]] 1 end] {
326 ::foreach {u cm s e rd f} $csets($c) break
327
328 # Ignore branch changes, just count them for the statistics.
329 if {$rd != 2} {
330 incr b
331 continue
@@ -243,40 +360,27 @@
360
361 cd $workspace ; # Checkouts go here.
362 return $workspace
363 }
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365 proc ::vc::cvs::ws::wssetup {c} {
366 variable csets
367 variable base
368 variable project
369
370 # pwd = workspace
371
372 ::foreach {u cm s e rd fs} $csets($c) break
373
374 write 1 cvs "@ $s"
375
376 ::foreach l [split [string trim $cm] \n] {
377 write 1 cvs "| $l"
378 }
379
380 ::foreach {f or} $fs {
381 ::foreach {op r} $or break
382 write 2 cvs "$op $f $r"
383
384 if {$op eq "R"} {
385 # Remove file from workspace. Prune empty directories.
386 #
@@ -299,18 +403,19 @@
403 }
404 } else {
405 # Added or modified, put the requested version of the file
406 # into the workspace.
407
408 if {$project ne ""} {set f $project/$f}
409 if {[catch {
410 dova -d $base co -r $r $f
411 } msg]} {
412 if {[string match {*invalid change text*} $msg]} {
413 # The archive of the file is corrupted and the
414 # chosen version not accessible due to that. We
415 # report the problem, but otherwise ignore it. As
416 # a consequence the destination repository will not
417 # contain the full history of the named file. By
418 # ignoring the problem we however get as much as
419 # is possible.
420
421 write 0 cvs "EE Corrupted archive file. Inaccessible revision."
@@ -362,24 +467,10 @@
467 set c [lindex [$rtree children $c] 0]
468 }
469 return
470 }
471
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472 # -----------------------------------------------------------------------------
473 # Internal helper commands: Changeset inspection and construction.
474
475 proc ::vc::cvs::ws::CSClear {} {
476 upvar 1 start start end end cm cm user user files files lastd lastd
@@ -402,11 +493,11 @@
493 proc ::vc::cvs::ws::CSNew {entry} {
494 upvar 1 start start end end cm cm user user files files lastd lastd reason reason
495
496 #puts -nonewline stdout . ; flush stdout
497
498 ::foreach {op ts a rev f ecm} $entry break
499
500 # User change
501 if {$a ne $user} {set reason user ; return 1}
502
503 # File already in current cset
@@ -430,12 +521,12 @@
521 upvar 1 start start end end cm cm user user files files lastd lastd
522
523 set csets($ncs) [list $user $cm $start $end $lastd [array get files]]
524
525 # Record which revisions of a file are in what csets
526 ::foreach {f or} [array get files] {
527 ::foreach {_ rev} $or break
528 set cmap([list $f $rev]) $ncs
529 }
530
531 #CSDump $ncs
532
@@ -444,11 +535,11 @@
535 }
536
537 proc ::vc::cvs::ws::CSAdd {entry} {
538 upvar 1 start start end end cm cm user user files files lastd lastd
539
540 ::foreach {op ts a rev f ecm} $entry break
541
542 if {$start eq ""} {set start $ts}
543 set end $ts
544 set cm $ecm
545 set user $a
@@ -457,26 +548,30 @@
548 return
549 }
550
551 proc ::vc::cvs::ws::CSDump {c} {
552 variable csets
553 ::foreach {u cm s e rd f} $csets($c) break
554
555 puts "$u $s"; regsub -all {.} $u { } b
556 puts "$b $e"
557 ::foreach {f or} $f {
558 ::foreach {o r} $or break
559 puts "$b $o $f $r"
560 }
561 return
562 }
563
564 # -----------------------------------------------------------------------------
565
566 namespace eval ::vc::cvs::ws {
567 variable base {} ; # Toplevel repository directory
568 variable project {} ; # Sub directory to limit the import to.
569
570 namespace export configure begin done foreach ncsets checkout
571 }
572
573 # -----------------------------------------------------------------------------
574 # Ready
575
576 package provide vc::cvs::ws 1.0
577 return
578
--- tools/lib/fossil.tcl
+++ tools/lib/fossil.tcl
@@ -62,13 +62,15 @@
6262
}
6363
return
6464
}
6565
6666
proc ::vc::fossil::ws::begin {origin} {
67
- variable rp [file normalize [fileutil::tempfile import2_fsl_rp_]]
67
+ variable base [file normalize $origin]
68
+ variable rp [file normalize [fileutil::tempfile import2_fsl_rp_]]
6869
6970
cd $origin
71
+
7072
dova new $rp ; # create and ...
7173
dova open $rp ; # ... connect
7274
7375
write 0 fossil "Repository: $rp"
7476
return
@@ -81,10 +83,13 @@
8183
return
8284
}
8385
8486
proc ::vc::fossil::ws::commit {cset user timestamp message} {
8587
variable lastuuid
88
+ variable base
89
+
90
+ cd $base
8691
8792
# Commit the current state of the workspace. Scan for new and
8893
# removed files and issue the appropriate fossil add/rm commands
8994
# before actually comitting.
9095
@@ -200,10 +205,11 @@
200205
variable breakat {} ; # Do not stop
201206
variable saveto {} ; # Do not save commit message
202207
variable appname {} ; # Name of importer application using the package.
203208
variable ignore {} ; # No files to ignore.
204209
210
+ variable base {} ; # Workspace directory
205211
variable rp {} ; # Repository the package works on.
206212
variable lastuuid {} ; # Uuid of last imported changeset.
207213
208214
namespace export configure begin done commit
209215
}
210216
--- tools/lib/fossil.tcl
+++ tools/lib/fossil.tcl
@@ -62,13 +62,15 @@
62 }
63 return
64 }
65
66 proc ::vc::fossil::ws::begin {origin} {
67 variable rp [file normalize [fileutil::tempfile import2_fsl_rp_]]
 
68
69 cd $origin
 
70 dova new $rp ; # create and ...
71 dova open $rp ; # ... connect
72
73 write 0 fossil "Repository: $rp"
74 return
@@ -81,10 +83,13 @@
81 return
82 }
83
84 proc ::vc::fossil::ws::commit {cset user timestamp message} {
85 variable lastuuid
 
 
 
86
87 # Commit the current state of the workspace. Scan for new and
88 # removed files and issue the appropriate fossil add/rm commands
89 # before actually comitting.
90
@@ -200,10 +205,11 @@
200 variable breakat {} ; # Do not stop
201 variable saveto {} ; # Do not save commit message
202 variable appname {} ; # Name of importer application using the package.
203 variable ignore {} ; # No files to ignore.
204
 
205 variable rp {} ; # Repository the package works on.
206 variable lastuuid {} ; # Uuid of last imported changeset.
207
208 namespace export configure begin done commit
209 }
210
--- tools/lib/fossil.tcl
+++ tools/lib/fossil.tcl
@@ -62,13 +62,15 @@
62 }
63 return
64 }
65
66 proc ::vc::fossil::ws::begin {origin} {
67 variable base [file normalize $origin]
68 variable rp [file normalize [fileutil::tempfile import2_fsl_rp_]]
69
70 cd $origin
71
72 dova new $rp ; # create and ...
73 dova open $rp ; # ... connect
74
75 write 0 fossil "Repository: $rp"
76 return
@@ -81,10 +83,13 @@
83 return
84 }
85
86 proc ::vc::fossil::ws::commit {cset user timestamp message} {
87 variable lastuuid
88 variable base
89
90 cd $base
91
92 # Commit the current state of the workspace. Scan for new and
93 # removed files and issue the appropriate fossil add/rm commands
94 # before actually comitting.
95
@@ -200,10 +205,11 @@
205 variable breakat {} ; # Do not stop
206 variable saveto {} ; # Do not save commit message
207 variable appname {} ; # Name of importer application using the package.
208 variable ignore {} ; # No files to ignore.
209
210 variable base {} ; # Workspace directory
211 variable rp {} ; # Repository the package works on.
212 variable lastuuid {} ; # Uuid of last imported changeset.
213
214 namespace export configure begin done commit
215 }
216
--- tools/lib/importcvs.tcl
+++ tools/lib/importcvs.tcl
@@ -18,23 +18,24 @@
1818
namespace eval fossil { namespace import ::vc::fossil::ws::* }
1919
namespace eval stats { namespace import ::vc::fossil::import::stats::* }
2020
namespace eval map { namespace import ::vc::fossil::import::map::* }
2121
2222
fossil::configure -appname cvs2fossil
23
- fossil::configure -ignore ::vc::cvs::ws::wsignore
23
+ fossil::configure -ignore ::vc::cvs::ws::isadmin
2424
}
2525
2626
# -----------------------------------------------------------------------------
2727
# API
2828
2929
# Configuration
3030
#
3131
# vc::fossil::import::cvs::configure key value - Set configuration
3232
#
33
-# Legal keys: -nosign <bool>, default false
34
-# -breakat <int>, default :none:
35
-# -saveto <path>, default :none:
33
+# Legal keys: -nosign <bool>, default false
34
+# -breakat <int>, default :none:
35
+# -saveto <path>, default :none:
36
+# -limit <path>, default :none:
3637
#
3738
# Functionality
3839
#
3940
# vc::fossil::import::cvs::run src dst - Perform an import.
4041
@@ -45,10 +46,11 @@
4546
# The options are simply passed through to the fossil importer
4647
# backend.
4748
switch -exact -- $key {
4849
-breakat { fossil::configure -breakat $value }
4950
-nosign { fossil::configure -nosign $value }
51
+ -project { cvs::configure -project $value }
5052
-saveto { fossil::configure -saveto $value }
5153
default {
5254
return -code error "Unknown switch $key, expected one of \
5355
-breakat, -nosign, or -saveto"
5456
}
@@ -58,30 +60,26 @@
5860
5961
# Import the CVS repository found at directory 'src' into the new
6062
# fossil repository at 'dst'.
6163
6264
proc ::vc::fossil::import::cvs::run {src dst} {
63
- cvs::at $src ; # Define location of CVS repository
64
- cvs::scan ; # Gather revision data from the archives
65
- cvs::csets ; # Group changes into sets
66
- cvs::rtree ; # Build revision tree (trunk only right now).
67
-
68
- write 0 import {Begin conversion}
69
- write 0 import {Setting up workspaces}
70
-
7165
#B map::set {} {}
72
- cvs::workspace ; # cd's to workspace
73
- fossil::begin [pwd] ; # Uses cwd as workspace to connect to.
74
- stats::setup [cvs::ntrunk] [cvs::ncsets]
66
+
67
+ set src [file normalize $src]
68
+ set dst [file normalize $dst]
69
+
70
+ set ws [cvs::begin $src]
71
+ fossil::begin $ws
72
+ stats::setup [cvs::ncsets -import] [cvs::ncsets]
7573
76
- cvs::foreach_cset cset [cvs::root] {
74
+ cvs::foreach cset {
7775
Import1 $cset
7876
}
7977
8078
stats::done
81
- cvs::wsclear
8279
fossil::done $dst
80
+ cvs::done
8381
8482
write 0 import Ok.
8583
return
8684
}
8785
@@ -98,11 +96,11 @@
9896
return
9997
}
10098
10199
proc ::vc::fossil::import::cvs::ImportCS {cset} {
102100
#B fossil::setup [map::get [cvs::parentOf $cset]]
103
- lassign [cvs::wssetup $cset] user timestamp message
101
+ lassign [cvs::checkout $cset] user timestamp message
104102
lassign [fossil::commit $cset $user $timestamp $message] uuid ad rm ch
105103
write 2 import "== +${ad}-${rm}*${ch}"
106104
map::set $cset $uuid
107105
return
108106
}
109107
--- tools/lib/importcvs.tcl
+++ tools/lib/importcvs.tcl
@@ -18,23 +18,24 @@
18 namespace eval fossil { namespace import ::vc::fossil::ws::* }
19 namespace eval stats { namespace import ::vc::fossil::import::stats::* }
20 namespace eval map { namespace import ::vc::fossil::import::map::* }
21
22 fossil::configure -appname cvs2fossil
23 fossil::configure -ignore ::vc::cvs::ws::wsignore
24 }
25
26 # -----------------------------------------------------------------------------
27 # API
28
29 # Configuration
30 #
31 # vc::fossil::import::cvs::configure key value - Set configuration
32 #
33 # Legal keys: -nosign <bool>, default false
34 # -breakat <int>, default :none:
35 # -saveto <path>, default :none:
 
36 #
37 # Functionality
38 #
39 # vc::fossil::import::cvs::run src dst - Perform an import.
40
@@ -45,10 +46,11 @@
45 # The options are simply passed through to the fossil importer
46 # backend.
47 switch -exact -- $key {
48 -breakat { fossil::configure -breakat $value }
49 -nosign { fossil::configure -nosign $value }
 
50 -saveto { fossil::configure -saveto $value }
51 default {
52 return -code error "Unknown switch $key, expected one of \
53 -breakat, -nosign, or -saveto"
54 }
@@ -58,30 +60,26 @@
58
59 # Import the CVS repository found at directory 'src' into the new
60 # fossil repository at 'dst'.
61
62 proc ::vc::fossil::import::cvs::run {src dst} {
63 cvs::at $src ; # Define location of CVS repository
64 cvs::scan ; # Gather revision data from the archives
65 cvs::csets ; # Group changes into sets
66 cvs::rtree ; # Build revision tree (trunk only right now).
67
68 write 0 import {Begin conversion}
69 write 0 import {Setting up workspaces}
70
71 #B map::set {} {}
72 cvs::workspace ; # cd's to workspace
73 fossil::begin [pwd] ; # Uses cwd as workspace to connect to.
74 stats::setup [cvs::ntrunk] [cvs::ncsets]
 
 
 
 
75
76 cvs::foreach_cset cset [cvs::root] {
77 Import1 $cset
78 }
79
80 stats::done
81 cvs::wsclear
82 fossil::done $dst
 
83
84 write 0 import Ok.
85 return
86 }
87
@@ -98,11 +96,11 @@
98 return
99 }
100
101 proc ::vc::fossil::import::cvs::ImportCS {cset} {
102 #B fossil::setup [map::get [cvs::parentOf $cset]]
103 lassign [cvs::wssetup $cset] user timestamp message
104 lassign [fossil::commit $cset $user $timestamp $message] uuid ad rm ch
105 write 2 import "== +${ad}-${rm}*${ch}"
106 map::set $cset $uuid
107 return
108 }
109
--- tools/lib/importcvs.tcl
+++ tools/lib/importcvs.tcl
@@ -18,23 +18,24 @@
18 namespace eval fossil { namespace import ::vc::fossil::ws::* }
19 namespace eval stats { namespace import ::vc::fossil::import::stats::* }
20 namespace eval map { namespace import ::vc::fossil::import::map::* }
21
22 fossil::configure -appname cvs2fossil
23 fossil::configure -ignore ::vc::cvs::ws::isadmin
24 }
25
26 # -----------------------------------------------------------------------------
27 # API
28
29 # Configuration
30 #
31 # vc::fossil::import::cvs::configure key value - Set configuration
32 #
33 # Legal keys: -nosign <bool>, default false
34 # -breakat <int>, default :none:
35 # -saveto <path>, default :none:
36 # -limit <path>, default :none:
37 #
38 # Functionality
39 #
40 # vc::fossil::import::cvs::run src dst - Perform an import.
41
@@ -45,10 +46,11 @@
46 # The options are simply passed through to the fossil importer
47 # backend.
48 switch -exact -- $key {
49 -breakat { fossil::configure -breakat $value }
50 -nosign { fossil::configure -nosign $value }
51 -project { cvs::configure -project $value }
52 -saveto { fossil::configure -saveto $value }
53 default {
54 return -code error "Unknown switch $key, expected one of \
55 -breakat, -nosign, or -saveto"
56 }
@@ -58,30 +60,26 @@
60
61 # Import the CVS repository found at directory 'src' into the new
62 # fossil repository at 'dst'.
63
64 proc ::vc::fossil::import::cvs::run {src dst} {
 
 
 
 
 
 
 
 
65 #B map::set {} {}
66
67 set src [file normalize $src]
68 set dst [file normalize $dst]
69
70 set ws [cvs::begin $src]
71 fossil::begin $ws
72 stats::setup [cvs::ncsets -import] [cvs::ncsets]
73
74 cvs::foreach cset {
75 Import1 $cset
76 }
77
78 stats::done
 
79 fossil::done $dst
80 cvs::done
81
82 write 0 import Ok.
83 return
84 }
85
@@ -98,11 +96,11 @@
96 return
97 }
98
99 proc ::vc::fossil::import::cvs::ImportCS {cset} {
100 #B fossil::setup [map::get [cvs::parentOf $cset]]
101 lassign [cvs::checkout $cset] user timestamp message
102 lassign [fossil::commit $cset $user $timestamp $message] uuid ad rm ch
103 write 2 import "== +${ad}-${rm}*${ch}"
104 map::set $cset $uuid
105 return
106 }
107

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button