Fossil SCM

Completed pass 6, wrote the code performing the breaking of cycles. Done by analysing each triple of changesets in the cycle at the file dependency level to see which revisions can be sorted apart. Added some additional utility routines. Extended the changeset class with the accessors required by the cycle breaker.

aku 2007-11-14 05:11 trunk
Commit 94c39d63758d78dc26b3ad5c2fdd285ea37047d1
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -15,17 +15,18 @@
1515
## dependency tree.
1616
1717
# # ## ### ##### ######## ############# #####################
1818
## Requirements
1919
20
-package require Tcl 8.4 ; # Required runtime.
21
-package require snit ; # OO system.
22
-package require struct::graph ; # Graph handling.
23
-package require struct::list ; # Higher order list operations.
24
-package require vc::tools::log ; # User feedback.
25
-package require vc::fossil::import::cvs::state ; # State storage.
26
-package require vc::fossil::import::cvs::project::rev ; # Project level changesets
20
+package require Tcl 8.4 ; # Required runtime.
21
+package require snit ; # OO system.
22
+package require struct::graph ; # Graph handling.
23
+package require struct::list ; # Higher order list operations.
24
+package require vc::tools::log ; # User feedback.
25
+package require vc::fossil::import::cvs::state ; # State storage.
26
+package require vc::fossil::import::cvs::project::rev ; # Project level changesets
27
+package require vc::fossil::import::cvs::project::revlink ; # Cycle links.
2728
2829
# # ## ### ##### ######## ############# #####################
2930
## Register the pass with the management
3031
3132
vc::fossil::import::cvs::pass define \
@@ -65,20 +66,22 @@
6566
typemethod run {} {
6667
# Pass manager interface. Executed to perform the
6768
# functionality of the pass.
6869
6970
state reading revision
71
+ state reading changeset
72
+ state reading csrevision
7073
7174
# We create a graph of the revision changesets, using the file
7275
# level dependencies to construct a first approximation of
7376
# them at the project level. Then look for cycles in that
7477
# graph and break them.
7578
7679
# 1. Create nodes for all relevant changesets and a mapping
7780
# from the revisions to their changesets/nodes.
7881
79
- log write 3 brkrcycle {Creating changeset graph, filling with nodes}
82
+ log write 3 breakrcycle {Creating changeset graph, filling with nodes}
8083
8184
set dg [struct::graph dg]
8285
8386
state transaction {
8487
foreach cset [project::rev all] {
@@ -90,11 +93,11 @@
9093
9194
# 2. Find for all relevant changeset their revisions and their
9295
# dependencies. Map the latter back to changesets and
9396
# construct the corresponding arcs.
9497
95
- log write 3 brkrcycle {Setting up node dependencies}
98
+ log write 3 breakrcycle {Setting up node dependencies}
9699
97100
state transaction {
98101
foreach cset [project::rev all] {
99102
if {[$cset bysymbol]} continue
100103
foreach succ [$cset successors] {
@@ -107,21 +110,21 @@
107110
# the nodes which have no predecessors, in order from
108111
# oldest to youngest, saving and removing dependencies. If
109112
# we find no nodes without predecessors we have a cycle,
110113
# and work on breaking it.
111114
112
- log write 3 brkrcycle {Computing changeset order, breaking cycles}
115
+ log write 3 breakrcycle {Computing changeset order, breaking cycles}
113116
114117
InitializeCandidates $dg
115118
state transaction {
116119
while {1} {
117120
while {[WithoutPredecessor $dg n]} {
118121
SaveAndRemove $dg $n
119122
}
120123
if {![llength [dg nodes]]} break
121
- set cycle [FindCycle $dg]
122
- BreakCycle $dg $cycle
124
+ BreakCycle $dg [FindCycle $dg]
125
+ InitializeCandidates $dg
123126
}
124127
}
125128
126129
return
127130
}
@@ -224,20 +227,76 @@
224227
while {1} {
225228
# Stop searching when we have seen the current node
226229
# already, the circle has been closed.
227230
if {[info exists seen($start)]} break
228231
lappend path $start
229
- set seen($start) [llength $path]
232
+ set seen($start) [expr {[llength $path]-1}]
230233
# Choose arbitrary predecessor
231234
set start [lindex [$dg nodes -in $start] 0]
232235
}
233236
234237
return [struct::list reverse [lrange $path $seen($start) end]]
235238
}
236239
240
+ proc ID {cset} { return "<[$cset id]>" }
241
+
237242
proc BreakCycle {dg cycle} {
238
- trouble internal "Break cycle <$cycle>"
243
+ # The cycle we have gotten is broken by breaking apart one or
244
+ # more of the changesets in the cycle. This causes us to
245
+ # create one or more changesets which are to be committed,
246
+ # added to the graph, etc. pp.
247
+
248
+ set cprint [join [struct::list map $cycle [myproc ID]] { }]
249
+
250
+ lappend cycle [lindex $cycle 0] [lindex $cycle 1]
251
+ set bestlink {}
252
+ set bestnode {}
253
+
254
+ foreach \
255
+ prev [lrange $cycle 0 end-2] \
256
+ cset [lrange $cycle 1 end-1] \
257
+ next [lrange $cycle 2 end] {
258
+
259
+ # Each triple PREV -> CSET -> NEXT of changesets, a
260
+ # 'link' in the cycle, is analysed and the best
261
+ # location where to at least weaken the cycle is
262
+ # chosen for further processing.
263
+
264
+ set link [project::revlink %AUTO% $prev $cset $next]
265
+ if {$bestlink eq ""} {
266
+ set bestlink $link
267
+ set bestnode $cset
268
+ } elseif {[$link betterthan $bestlink]} {
269
+ $bestlink destroy
270
+ set bestlink $link
271
+ set bestnode $cset
272
+ } else {
273
+ $link destroy
274
+ }
275
+ }
276
+
277
+ log write 5 breakrcycle "Breaking cycle ($cprint) by splitting changeset <[$bestnode id]>"
278
+
279
+ set newcsets [$bestlink break]
280
+ $bestlink destroy
281
+
282
+ # At this point the old changeset (BESTNODE) is gone
283
+ # already. We remove it from the graph as well and then enter
284
+ # the fragments generated for it.
285
+
286
+ $dg node delete $bestnode
287
+
288
+ foreach cset $newcsets {
289
+ dg node insert $cset
290
+ dg node set $cset timerange [$cset timerange]
291
+ }
292
+
293
+ foreach cset $newcsets {
294
+ foreach succ [$cset successors] {
295
+ dg arc insert $cset $succ
296
+ }
297
+ }
239298
return
240299
}
241300
242301
typevariable at 0 ; # Counter for commit ids for the changesets.
243302
typevariable bottom {} ; # List of candidate nodes for committing.
@@ -256,16 +315,17 @@
256315
namespace export breakrcycle
257316
namespace eval breakrcycle {
258317
namespace import ::vc::fossil::import::cvs::state
259318
namespace eval project {
260319
namespace import ::vc::fossil::import::cvs::project::rev
320
+ namespace import ::vc::fossil::import::cvs::project::revlink
261321
}
262322
namespace import ::vc::tools::log
263
- log register brkrcycle
323
+ log register breakrcycle
264324
}
265325
}
266326
267327
# # ## ### ##### ######## ############# #####################
268328
## Ready
269329
270330
package provide vc::fossil::import::cvs::pass::breakrcycle 1.0
271331
return
272332
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -15,17 +15,18 @@
15 ## dependency tree.
16
17 # # ## ### ##### ######## ############# #####################
18 ## Requirements
19
20 package require Tcl 8.4 ; # Required runtime.
21 package require snit ; # OO system.
22 package require struct::graph ; # Graph handling.
23 package require struct::list ; # Higher order list operations.
24 package require vc::tools::log ; # User feedback.
25 package require vc::fossil::import::cvs::state ; # State storage.
26 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
 
27
28 # # ## ### ##### ######## ############# #####################
29 ## Register the pass with the management
30
31 vc::fossil::import::cvs::pass define \
@@ -65,20 +66,22 @@
65 typemethod run {} {
66 # Pass manager interface. Executed to perform the
67 # functionality of the pass.
68
69 state reading revision
 
 
70
71 # We create a graph of the revision changesets, using the file
72 # level dependencies to construct a first approximation of
73 # them at the project level. Then look for cycles in that
74 # graph and break them.
75
76 # 1. Create nodes for all relevant changesets and a mapping
77 # from the revisions to their changesets/nodes.
78
79 log write 3 brkrcycle {Creating changeset graph, filling with nodes}
80
81 set dg [struct::graph dg]
82
83 state transaction {
84 foreach cset [project::rev all] {
@@ -90,11 +93,11 @@
90
91 # 2. Find for all relevant changeset their revisions and their
92 # dependencies. Map the latter back to changesets and
93 # construct the corresponding arcs.
94
95 log write 3 brkrcycle {Setting up node dependencies}
96
97 state transaction {
98 foreach cset [project::rev all] {
99 if {[$cset bysymbol]} continue
100 foreach succ [$cset successors] {
@@ -107,21 +110,21 @@
107 # the nodes which have no predecessors, in order from
108 # oldest to youngest, saving and removing dependencies. If
109 # we find no nodes without predecessors we have a cycle,
110 # and work on breaking it.
111
112 log write 3 brkrcycle {Computing changeset order, breaking cycles}
113
114 InitializeCandidates $dg
115 state transaction {
116 while {1} {
117 while {[WithoutPredecessor $dg n]} {
118 SaveAndRemove $dg $n
119 }
120 if {![llength [dg nodes]]} break
121 set cycle [FindCycle $dg]
122 BreakCycle $dg $cycle
123 }
124 }
125
126 return
127 }
@@ -224,20 +227,76 @@
224 while {1} {
225 # Stop searching when we have seen the current node
226 # already, the circle has been closed.
227 if {[info exists seen($start)]} break
228 lappend path $start
229 set seen($start) [llength $path]
230 # Choose arbitrary predecessor
231 set start [lindex [$dg nodes -in $start] 0]
232 }
233
234 return [struct::list reverse [lrange $path $seen($start) end]]
235 }
236
 
 
237 proc BreakCycle {dg cycle} {
238 trouble internal "Break cycle <$cycle>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239 return
240 }
241
242 typevariable at 0 ; # Counter for commit ids for the changesets.
243 typevariable bottom {} ; # List of candidate nodes for committing.
@@ -256,16 +315,17 @@
256 namespace export breakrcycle
257 namespace eval breakrcycle {
258 namespace import ::vc::fossil::import::cvs::state
259 namespace eval project {
260 namespace import ::vc::fossil::import::cvs::project::rev
 
261 }
262 namespace import ::vc::tools::log
263 log register brkrcycle
264 }
265 }
266
267 # # ## ### ##### ######## ############# #####################
268 ## Ready
269
270 package provide vc::fossil::import::cvs::pass::breakrcycle 1.0
271 return
272
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -15,17 +15,18 @@
15 ## dependency tree.
16
17 # # ## ### ##### ######## ############# #####################
18 ## Requirements
19
20 package require Tcl 8.4 ; # Required runtime.
21 package require snit ; # OO system.
22 package require struct::graph ; # Graph handling.
23 package require struct::list ; # Higher order list operations.
24 package require vc::tools::log ; # User feedback.
25 package require vc::fossil::import::cvs::state ; # State storage.
26 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
27 package require vc::fossil::import::cvs::project::revlink ; # Cycle links.
28
29 # # ## ### ##### ######## ############# #####################
30 ## Register the pass with the management
31
32 vc::fossil::import::cvs::pass define \
@@ -65,20 +66,22 @@
66 typemethod run {} {
67 # Pass manager interface. Executed to perform the
68 # functionality of the pass.
69
70 state reading revision
71 state reading changeset
72 state reading csrevision
73
74 # We create a graph of the revision changesets, using the file
75 # level dependencies to construct a first approximation of
76 # them at the project level. Then look for cycles in that
77 # graph and break them.
78
79 # 1. Create nodes for all relevant changesets and a mapping
80 # from the revisions to their changesets/nodes.
81
82 log write 3 breakrcycle {Creating changeset graph, filling with nodes}
83
84 set dg [struct::graph dg]
85
86 state transaction {
87 foreach cset [project::rev all] {
@@ -90,11 +93,11 @@
93
94 # 2. Find for all relevant changeset their revisions and their
95 # dependencies. Map the latter back to changesets and
96 # construct the corresponding arcs.
97
98 log write 3 breakrcycle {Setting up node dependencies}
99
100 state transaction {
101 foreach cset [project::rev all] {
102 if {[$cset bysymbol]} continue
103 foreach succ [$cset successors] {
@@ -107,21 +110,21 @@
110 # the nodes which have no predecessors, in order from
111 # oldest to youngest, saving and removing dependencies. If
112 # we find no nodes without predecessors we have a cycle,
113 # and work on breaking it.
114
115 log write 3 breakrcycle {Computing changeset order, breaking cycles}
116
117 InitializeCandidates $dg
118 state transaction {
119 while {1} {
120 while {[WithoutPredecessor $dg n]} {
121 SaveAndRemove $dg $n
122 }
123 if {![llength [dg nodes]]} break
124 BreakCycle $dg [FindCycle $dg]
125 InitializeCandidates $dg
126 }
127 }
128
129 return
130 }
@@ -224,20 +227,76 @@
227 while {1} {
228 # Stop searching when we have seen the current node
229 # already, the circle has been closed.
230 if {[info exists seen($start)]} break
231 lappend path $start
232 set seen($start) [expr {[llength $path]-1}]
233 # Choose arbitrary predecessor
234 set start [lindex [$dg nodes -in $start] 0]
235 }
236
237 return [struct::list reverse [lrange $path $seen($start) end]]
238 }
239
240 proc ID {cset} { return "<[$cset id]>" }
241
242 proc BreakCycle {dg cycle} {
243 # The cycle we have gotten is broken by breaking apart one or
244 # more of the changesets in the cycle. This causes us to
245 # create one or more changesets which are to be committed,
246 # added to the graph, etc. pp.
247
248 set cprint [join [struct::list map $cycle [myproc ID]] { }]
249
250 lappend cycle [lindex $cycle 0] [lindex $cycle 1]
251 set bestlink {}
252 set bestnode {}
253
254 foreach \
255 prev [lrange $cycle 0 end-2] \
256 cset [lrange $cycle 1 end-1] \
257 next [lrange $cycle 2 end] {
258
259 # Each triple PREV -> CSET -> NEXT of changesets, a
260 # 'link' in the cycle, is analysed and the best
261 # location where to at least weaken the cycle is
262 # chosen for further processing.
263
264 set link [project::revlink %AUTO% $prev $cset $next]
265 if {$bestlink eq ""} {
266 set bestlink $link
267 set bestnode $cset
268 } elseif {[$link betterthan $bestlink]} {
269 $bestlink destroy
270 set bestlink $link
271 set bestnode $cset
272 } else {
273 $link destroy
274 }
275 }
276
277 log write 5 breakrcycle "Breaking cycle ($cprint) by splitting changeset <[$bestnode id]>"
278
279 set newcsets [$bestlink break]
280 $bestlink destroy
281
282 # At this point the old changeset (BESTNODE) is gone
283 # already. We remove it from the graph as well and then enter
284 # the fragments generated for it.
285
286 $dg node delete $bestnode
287
288 foreach cset $newcsets {
289 dg node insert $cset
290 dg node set $cset timerange [$cset timerange]
291 }
292
293 foreach cset $newcsets {
294 foreach succ [$cset successors] {
295 dg arc insert $cset $succ
296 }
297 }
298 return
299 }
300
301 typevariable at 0 ; # Counter for commit ids for the changesets.
302 typevariable bottom {} ; # List of candidate nodes for committing.
@@ -256,16 +315,17 @@
315 namespace export breakrcycle
316 namespace eval breakrcycle {
317 namespace import ::vc::fossil::import::cvs::state
318 namespace eval project {
319 namespace import ::vc::fossil::import::cvs::project::rev
320 namespace import ::vc::fossil::import::cvs::project::revlink
321 }
322 namespace import ::vc::tools::log
323 log register breakrcycle
324 }
325 }
326
327 # # ## ### ##### ######## ############# #####################
328 ## Ready
329
330 package provide vc::fossil::import::cvs::pass::breakrcycle 1.0
331 return
332
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -44,26 +44,34 @@
4444
return
4545
}
4646
4747
method id {} { return $myid }
4848
method revisions {} { return $myrevisions }
49
+ method data {} { return [list $myproject $mytype $mysrcid] }
4950
5051
method setid {id} { set myid $id ; return }
5152
5253
method bysymbol {} { return [expr {$mytype eq "sym"}] }
5354
method byrevision {} { return [expr {$mytype eq "rev"}] }
5455
5556
method successors {} {
5657
# NOTE / FUTURE: Possible bottleneck.
57
- array set dependencies {}
58
- PullSuccessorRevisions dependencies $myrevisions
5958
set csets {}
60
- foreach {_ child} [array get dependencies] {
61
- lappend csets $myrevmap($child)
59
+ foreach {_ children} [$self nextmap] {
60
+ foreach child $children {
61
+ lappend csets $myrevmap($child)
62
+ }
6263
}
6364
return [lsort -unique $csets]
6465
}
66
+
67
+ method nextmap {} {
68
+ if {[llength $mynextmap]} { return $mynextmap }
69
+ PullSuccessorRevisions tmp $myrevisions
70
+ set mynextmap [array get tmp]
71
+ return $mynextmap
72
+ }
6573
6674
method breakinternaldependencies {} {
6775
# This method inspects the changesets for internal
6876
# dependencies. Nothing is done if there are no
6977
# such. Otherwise the changeset is split into a set of
@@ -84,11 +92,11 @@
8492
8593
# Array of dependencies (parent -> child). This is pulled from
8694
# the state, and limited to successors within the changeset.
8795
8896
array set dependencies {}
89
- PullSuccessorRevisions dependencies $myrevisions
97
+ PullInternalSuccessorRevisions dependencies $myrevisions
9098
if {![array size dependencies]} {return 0} ; # Nothing to break.
9199
92100
log write 6 csets ...<$myid>.......................................................
93101
94102
# We have internal dependencies to break. We now iterate over
@@ -231,19 +239,41 @@
231239
SELECT MIN(R.date), MAX(R.date)
232240
FROM revision R
233241
WHERE R.rid IN $theset
234242
"]
235243
}
244
+
245
+ method drop {} {
246
+ state transaction {
247
+ state run {
248
+ DELETE FROM changeset WHERE cid = $myid;
249
+ DELETE FROM csrevision WHERE cid = $myid;
250
+ }
251
+ }
252
+ foreach r $myrevisions { unset myrevmap($r) }
253
+ set pos [lsearch -exact $mychangesets $self]
254
+ set mychangesets [lreplace $mychangesets $pos $pos]
255
+ return
256
+ }
236257
237258
# # ## ### ##### ######## #############
238259
## State
239260
240
- variable myid ; # Id of the cset for the persistent state.
241
- variable myproject ; # Reference of the project object the changeset belongs to.
242
- variable mytype ; # rev or sym, where the cset originated from.
243
- variable mysrcid ; # id of the metadata or symbol the cset is based on.
244
- variable myrevisions ; # List of the file level revisions in the cset.
261
+ variable myid {} ; # Id of the cset for the persistent
262
+ # state.
263
+ variable myproject {} ; # Reference of the project object the
264
+ # changeset belongs to.
265
+ variable mytype {} ; # rev or sym, where the cset originated
266
+ # from.
267
+ variable mysrcid {} ; # Id of the metadata or symbol the cset
268
+ # is based on.
269
+ variable myrevisions {} ; # List of the file level revisions in
270
+ # the cset.
271
+ variable mynextmap {} ; # Dictionary mapping from the revisions
272
+ # to their successors. Cache to avoid
273
+ # loading this from the state more than
274
+ # once.
245275
246276
# # ## ### ##### ######## #############
247277
## Internal methods
248278
249279
typevariable mycounter 0 ; # Id counter for csets.
@@ -254,11 +284,11 @@
254284
SELECT tid, name FROM cstype;
255285
}] { set mycstype($name) $tid }
256286
return
257287
}
258288
259
- proc PullSuccessorRevisions {dv revisions} {
289
+ proc PullInternalSuccessorRevisions {dv revisions} {
260290
upvar 1 $dv dependencies
261291
set theset ('[join $revisions {','}]')
262292
263293
foreach {rid child} [state run "
264294
-- Primary children
@@ -284,11 +314,42 @@
284314
"] {
285315
# Consider moving this to the integrity module.
286316
if {$rid == $child} {
287317
trouble internal "Revision $rid depends on itself."
288318
}
289
- set dependencies($rid) $child
319
+ lappend dependencies($rid) $child
320
+ }
321
+ }
322
+
323
+ proc PullSuccessorRevisions {dv revisions} {
324
+ upvar 1 $dv dependencies
325
+ set theset ('[join $revisions {','}]')
326
+
327
+ foreach {rid child} [state run "
328
+ -- Primary children
329
+ SELECT R.rid, R.child
330
+ FROM revision R
331
+ WHERE R.rid IN $theset
332
+ AND R.child IS NOT NULL
333
+ UNION
334
+ -- Transition NTDB to trunk
335
+ SELECT R.rid, R.dbchild
336
+ FROM revision R
337
+ WHERE R.rid IN $theset
338
+ AND R.dbchild IS NOT NULL
339
+ UNION
340
+ -- Secondary (branch) children
341
+ SELECT R.rid, B.brid
342
+ FROM revision R, revisionbranchchildren B
343
+ WHERE R.rid IN $theset
344
+ AND R.rid = B.rid
345
+ "] {
346
+ # Consider moving this to the integrity module.
347
+ if {$rid == $child} {
348
+ trouble internal "Revision $rid depends on itself."
349
+ }
350
+ lappend dependencies($rid) $child
290351
}
291352
}
292353
293354
proc InitializeBreakState {revisions} {
294355
upvar 1 pos pos cross cross range range depc depc delta delta \
@@ -318,11 +379,11 @@
318379
# to ensure that the following loop runs correctly.
319380
#
320381
# Note 2: start == end is not possible. It indicates a
321382
# self-dependency due to the uniqueness of positions,
322383
# and that is something we have ruled out already, see
323
- # PullSuccessorRevisions.
384
+ # PullInternalSuccessorRevisions.
324385
325386
foreach {rid child} [array get dependencies] {
326387
set dkey [list $rid $child]
327388
set start $pos($rid)
328389
set end $pos($child)
329390
330391
ADDED tools/cvs2fossil/lib/c2f_prevlink.tcl
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -44,26 +44,34 @@
44 return
45 }
46
47 method id {} { return $myid }
48 method revisions {} { return $myrevisions }
 
49
50 method setid {id} { set myid $id ; return }
51
52 method bysymbol {} { return [expr {$mytype eq "sym"}] }
53 method byrevision {} { return [expr {$mytype eq "rev"}] }
54
55 method successors {} {
56 # NOTE / FUTURE: Possible bottleneck.
57 array set dependencies {}
58 PullSuccessorRevisions dependencies $myrevisions
59 set csets {}
60 foreach {_ child} [array get dependencies] {
61 lappend csets $myrevmap($child)
 
 
62 }
63 return [lsort -unique $csets]
64 }
 
 
 
 
 
 
 
65
66 method breakinternaldependencies {} {
67 # This method inspects the changesets for internal
68 # dependencies. Nothing is done if there are no
69 # such. Otherwise the changeset is split into a set of
@@ -84,11 +92,11 @@
84
85 # Array of dependencies (parent -> child). This is pulled from
86 # the state, and limited to successors within the changeset.
87
88 array set dependencies {}
89 PullSuccessorRevisions dependencies $myrevisions
90 if {![array size dependencies]} {return 0} ; # Nothing to break.
91
92 log write 6 csets ...<$myid>.......................................................
93
94 # We have internal dependencies to break. We now iterate over
@@ -231,19 +239,41 @@
231 SELECT MIN(R.date), MAX(R.date)
232 FROM revision R
233 WHERE R.rid IN $theset
234 "]
235 }
 
 
 
 
 
 
 
 
 
 
 
 
 
236
237 # # ## ### ##### ######## #############
238 ## State
239
240 variable myid ; # Id of the cset for the persistent state.
241 variable myproject ; # Reference of the project object the changeset belongs to.
242 variable mytype ; # rev or sym, where the cset originated from.
243 variable mysrcid ; # id of the metadata or symbol the cset is based on.
244 variable myrevisions ; # List of the file level revisions in the cset.
 
 
 
 
 
 
 
 
 
245
246 # # ## ### ##### ######## #############
247 ## Internal methods
248
249 typevariable mycounter 0 ; # Id counter for csets.
@@ -254,11 +284,11 @@
254 SELECT tid, name FROM cstype;
255 }] { set mycstype($name) $tid }
256 return
257 }
258
259 proc PullSuccessorRevisions {dv revisions} {
260 upvar 1 $dv dependencies
261 set theset ('[join $revisions {','}]')
262
263 foreach {rid child} [state run "
264 -- Primary children
@@ -284,11 +314,42 @@
284 "] {
285 # Consider moving this to the integrity module.
286 if {$rid == $child} {
287 trouble internal "Revision $rid depends on itself."
288 }
289 set dependencies($rid) $child
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290 }
291 }
292
293 proc InitializeBreakState {revisions} {
294 upvar 1 pos pos cross cross range range depc depc delta delta \
@@ -318,11 +379,11 @@
318 # to ensure that the following loop runs correctly.
319 #
320 # Note 2: start == end is not possible. It indicates a
321 # self-dependency due to the uniqueness of positions,
322 # and that is something we have ruled out already, see
323 # PullSuccessorRevisions.
324
325 foreach {rid child} [array get dependencies] {
326 set dkey [list $rid $child]
327 set start $pos($rid)
328 set end $pos($child)
329
330 DDED tools/cvs2fossil/lib/c2f_prevlink.tcl
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -44,26 +44,34 @@
44 return
45 }
46
47 method id {} { return $myid }
48 method revisions {} { return $myrevisions }
49 method data {} { return [list $myproject $mytype $mysrcid] }
50
51 method setid {id} { set myid $id ; return }
52
53 method bysymbol {} { return [expr {$mytype eq "sym"}] }
54 method byrevision {} { return [expr {$mytype eq "rev"}] }
55
56 method successors {} {
57 # NOTE / FUTURE: Possible bottleneck.
 
 
58 set csets {}
59 foreach {_ children} [$self nextmap] {
60 foreach child $children {
61 lappend csets $myrevmap($child)
62 }
63 }
64 return [lsort -unique $csets]
65 }
66
67 method nextmap {} {
68 if {[llength $mynextmap]} { return $mynextmap }
69 PullSuccessorRevisions tmp $myrevisions
70 set mynextmap [array get tmp]
71 return $mynextmap
72 }
73
74 method breakinternaldependencies {} {
75 # This method inspects the changesets for internal
76 # dependencies. Nothing is done if there are no
77 # such. Otherwise the changeset is split into a set of
@@ -84,11 +92,11 @@
92
93 # Array of dependencies (parent -> child). This is pulled from
94 # the state, and limited to successors within the changeset.
95
96 array set dependencies {}
97 PullInternalSuccessorRevisions dependencies $myrevisions
98 if {![array size dependencies]} {return 0} ; # Nothing to break.
99
100 log write 6 csets ...<$myid>.......................................................
101
102 # We have internal dependencies to break. We now iterate over
@@ -231,19 +239,41 @@
239 SELECT MIN(R.date), MAX(R.date)
240 FROM revision R
241 WHERE R.rid IN $theset
242 "]
243 }
244
245 method drop {} {
246 state transaction {
247 state run {
248 DELETE FROM changeset WHERE cid = $myid;
249 DELETE FROM csrevision WHERE cid = $myid;
250 }
251 }
252 foreach r $myrevisions { unset myrevmap($r) }
253 set pos [lsearch -exact $mychangesets $self]
254 set mychangesets [lreplace $mychangesets $pos $pos]
255 return
256 }
257
258 # # ## ### ##### ######## #############
259 ## State
260
261 variable myid {} ; # Id of the cset for the persistent
262 # state.
263 variable myproject {} ; # Reference of the project object the
264 # changeset belongs to.
265 variable mytype {} ; # rev or sym, where the cset originated
266 # from.
267 variable mysrcid {} ; # Id of the metadata or symbol the cset
268 # is based on.
269 variable myrevisions {} ; # List of the file level revisions in
270 # the cset.
271 variable mynextmap {} ; # Dictionary mapping from the revisions
272 # to their successors. Cache to avoid
273 # loading this from the state more than
274 # once.
275
276 # # ## ### ##### ######## #############
277 ## Internal methods
278
279 typevariable mycounter 0 ; # Id counter for csets.
@@ -254,11 +284,11 @@
284 SELECT tid, name FROM cstype;
285 }] { set mycstype($name) $tid }
286 return
287 }
288
289 proc PullInternalSuccessorRevisions {dv revisions} {
290 upvar 1 $dv dependencies
291 set theset ('[join $revisions {','}]')
292
293 foreach {rid child} [state run "
294 -- Primary children
@@ -284,11 +314,42 @@
314 "] {
315 # Consider moving this to the integrity module.
316 if {$rid == $child} {
317 trouble internal "Revision $rid depends on itself."
318 }
319 lappend dependencies($rid) $child
320 }
321 }
322
323 proc PullSuccessorRevisions {dv revisions} {
324 upvar 1 $dv dependencies
325 set theset ('[join $revisions {','}]')
326
327 foreach {rid child} [state run "
328 -- Primary children
329 SELECT R.rid, R.child
330 FROM revision R
331 WHERE R.rid IN $theset
332 AND R.child IS NOT NULL
333 UNION
334 -- Transition NTDB to trunk
335 SELECT R.rid, R.dbchild
336 FROM revision R
337 WHERE R.rid IN $theset
338 AND R.dbchild IS NOT NULL
339 UNION
340 -- Secondary (branch) children
341 SELECT R.rid, B.brid
342 FROM revision R, revisionbranchchildren B
343 WHERE R.rid IN $theset
344 AND R.rid = B.rid
345 "] {
346 # Consider moving this to the integrity module.
347 if {$rid == $child} {
348 trouble internal "Revision $rid depends on itself."
349 }
350 lappend dependencies($rid) $child
351 }
352 }
353
354 proc InitializeBreakState {revisions} {
355 upvar 1 pos pos cross cross range range depc depc delta delta \
@@ -318,11 +379,11 @@
379 # to ensure that the following loop runs correctly.
380 #
381 # Note 2: start == end is not possible. It indicates a
382 # self-dependency due to the uniqueness of positions,
383 # and that is something we have ruled out already, see
384 # PullInternalSuccessorRevisions.
385
386 foreach {rid child} [array get dependencies] {
387 set dkey [list $rid $child]
388 set start $pos($rid)
389 set end $pos($child)
390
391 DDED tools/cvs2fossil/lib/c2f_prevlink.tcl
--- a/tools/cvs2fossil/lib/c2f_prevlink.tcl
+++ b/tools/cvs2fossil/lib/c2f_prevlink.tcl
@@ -0,0 +1,180 @@
1
+## -*- tcl -*-
2
+# # ## ### ##### ## -*- tcl -*-
3
+# # ## ### ##### ######## ############# #####################
4
+## Copyright (c) 2007 Andreas Kupries.
5
+#
6
+# This software is licensed as described in the file LICENSE, which
7
+# you should have received as part of this distribution.
8
+#
9
+# This software consists of voluntary contributions made by many
10
+# individuals. For exact contribution history, see the revision
11
+# history and logs, available at http://fossil-scm.hwaci.com/fossil
12
+# # ## ### ##### ######## ############# #####################
13
+
14
+## Helper class for the pass 6 cycle breaker. Each instance refers to
15
+## three changesets A, B, and C, with A a predecessor of B, and B
16
+## predecessor of C, and the whole part of a dependency cycle.
17
+
18
+## Instances analyse the file level dependencies which gave rise to
19
+## the changeset dependencies of A, B, and C, with the results used ####### ############# #####################
20
+## Copyright (c) 2007 Andreas Kupries.
21
+#
22
+# This software is licensed as described in the file LICENSE, which
23
+# you should have received as part of this distribution.
24
+#
25
+# This software consists of voluntary contributions made by many
26
+# individuals. For exact contribution history, see the revision
27
+# history and logs, available at http://fossil-scm.hwaci.com/fossil
28
+# # ## ### ##### ######## ############# #####################
29
+
30
+## Helper class for the pass 6 cycle breaker. Each instance refers to
31
+## three changesets A, B, and C, with A a predecessor of B, and B
32
+## predecessort best fully break the cycle.
33
+
34
+# # ## ### ##### ######## ############# #####################
35
+## Requirements
36
+
37
+package require Tcl 8.4 ; # Required runtime.
38
+package require snit ; # OO system.
39
+package require vc::tools::misc ; # Text formatting
40
+package require vc::tools::trouble ; # Error reporting.
41
+package require vc::tools::log ; # User feedback.
42
+package require vc::fossil::import::cvs::state ; # State storage.
43
+package require vc::fossil::import::cvs::integrity ; # State integrity checks.
44
+package require vc::fossil::import::cvs::project::rev ; # Project level changesets
45
+
46
+# # ## ### ##### ######## ############# #####################
47
+##
48
+
49
+snit::type ::vc::fossil::import::cvs::project::revlink {
50
+ # # ## ### ##### ######## #############
51
+ ## Public API
52
+
53
+ constructor {prev cset next} {
54
+ set myprev $prev
55
+ set mycset $cset
56
+ set mynext $next
57
+
58
+ # We perform the bulk of the analysis during construction. The
59
+ # file revisions held by the changeset CSET can be sorted into
60
+ # four categories.
61
+
62
+ # 1. Revisions whose predecessors are not in PREV, nor are
63
+ # their successors found in NEXT. These revisions do not
64
+ # count, as they did not induce any of the two dependencies
65
+ # under consideration. Thf {!(prev) $mycount(next
66
+ trouble internal "than {other} {"
67
+
68
+ set sbreak [$self breakable]
69
+ set obreak [$other breakable]
70
+
71
+ if {$sbreak && !$obreak} { return 1 } ; # self is better.
72
+ if {!$sbreak && $obreak} { return 0 } ; # self is worse.
73
+
74
+ # Equality. Look at the counters.
75
+ # - Whichever has the lesser number of passthrough revisions
76
+ # is better, as more can be split off, weakening the cycle
77
+ # more.
78
+ # - Whichever has less links to move is better.
79
+
80
+ set opass [$other passcount]
81
+ if {$mycount(pass) < $opass} { return 1 } ; # self is better.
82
+ if {$mycount(pass) > $opass} { return 0 } ; # self is worse.
83
+
84
+ set smove [$self linkstomove]
85
+ set omove [$other linkstomove]
86
+
87
+ if {$smove < $omove} { return 1 } ; # self is better.
88
+
89
+ return 0 ; # Self is worse or equal, i.e. not better.
90
+ }
91
+
92
+ method bre<[$mycset id]>split in the mycategory(prev|nehole part of a dependency cycle.
93
+
94
+## Instances analyse the file level dependencies which gave rise to
95
+## the changeset dependencies of A, B, and C, with the results used ####### ############# #####################
96
+## Copyright (c) 2007 Andreas Kupries.
97
+#
98
+# This software is licensed as described in the file LICENSE, which
99
+# you should have received as part of this distribution.
100
+#
101
+# This software consists of voluntary contributions made by many
102
+# individuals. For exact contribution history, see the revision
103
+# history and logs, available at http://fossil-scm.hwaci.com/fossil
104
+# # ## ### ##### ######## ############# #####################
105
+
106
+## Helper class for the pass 6 cycle breaker. Each instance refers to
107
+## three changesets A, B, and C, with A a predecessor of B, and B
108
+## predecessort best fully break the cycle.
109
+
110
+# # ## ### ##### ######## ############# #####################
111
+## Requirements
112
+
113
+package require Tcl 8.4 ; # Required runtime.
114
+package require snit ; # OO system.
115
+package require vc::tools::misc ; # Text formatting
116
+package require vc::tools::trouble ; # Error reporting.
117
+package require vc::tools::log ; # User feedback.
118
+package require vc::fossil::import::cvs::state ; # State storage.
119
+package require vc::fossil::import::cvs::integrity ; # State integrity checks.
120
+package require vc::fossil::import::cvs::project::rev ; # Project level changesets
121
+
122
+# # ## ### ##### ######## ############# #####################
123
+##
124
+
125
+snit::type ::vc::fossil::import::cvs::project::revlink {
126
+ # # ## ### ##### ######## #############
127
+ ## Public API
128
+
129
+ constructor {prev cset next} {
130
+ set myprev $prev
131
+ set mycset $cset
132
+ set mynext $next
133
+
134
+ # We perform the bulk of the analysis during construction. The
135
+ # file revisions held by the changeset CSET can be sorted into
136
+ # four categories.
137
+
138
+ # 1. Revisions whose predecessors are not in PREV, nor are
139
+ # their successors found in NEXT. These revisions do not
140
+ # count, as they did not induce any of the two dependencies
141
+ # under consideration. Thf {!(prev) $mycount(next
142
+ trouble internal "than {other} {"
143
+
144
+ set sbreak [$self breakable]
145
+ set obreak [$other breakable]
146
+
147
+ if {$sbreak && !$obreak} { return 1 } ; # self is better.
148
+ if {!$sbreak && $obreak} { return 0 } ; # self is worse.
149
+
150
+ # Equality. Look at the counters.
151
+ # - Whichever has the lesser number of passthrough revisions
152
+ # is better, as more can be split off, weakening the cycle
153
+ # more.
154
+ # - Whichever has less links to move is better.
155
+
156
+ set opass [$other passcount]
157
+ if {$mycount(pass) < $opass} { return 1 } ; # self is better.
158
+ if {$mycount(pass) > $opass} { return 0 } ; # self is worse.
159
+
160
+ set smove [$self linkstomove]
161
+ set omove [$other linkstomove]
162
+
163
+ if {$smove < $omove} { return 1 } ; # self is better.
164
+
165
+ return 0 ; # Self is worse or equal, i.e. not better.
166
+ }
167
+
168
+ method bre<[$mycset id]>new changesets the
169
+ # old one is dropped from all databases, in and out of memory,
170
+ # and then destroyed.
171
+
172
+ struct::list assign [$mycset data] project cstype cssrc
173
+ $mycset drop
174
+ $mycset destroy
175
+
176
+ set newcsets {}
177
+ lappend newcsets [project::rev %AUTO% $project $cstype $cssrc $mycategory(prev)]
178
+ lappend newcsets [project::rev %AUext)]
179
+
180
+ foreach c $newcsets { $c p
--- a/tools/cvs2fossil/lib/c2f_prevlink.tcl
+++ b/tools/cvs2fossil/lib/c2f_prevlink.tcl
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/tools/cvs2fossil/lib/c2f_prevlink.tcl
+++ b/tools/cvs2fossil/lib/c2f_prevlink.tcl
@@ -0,0 +1,180 @@
1 ## -*- tcl -*-
2 # # ## ### ##### ## -*- tcl -*-
3 # # ## ### ##### ######## ############# #####################
4 ## Copyright (c) 2007 Andreas Kupries.
5 #
6 # This software is licensed as described in the file LICENSE, which
7 # you should have received as part of this distribution.
8 #
9 # This software consists of voluntary contributions made by many
10 # individuals. For exact contribution history, see the revision
11 # history and logs, available at http://fossil-scm.hwaci.com/fossil
12 # # ## ### ##### ######## ############# #####################
13
14 ## Helper class for the pass 6 cycle breaker. Each instance refers to
15 ## three changesets A, B, and C, with A a predecessor of B, and B
16 ## predecessor of C, and the whole part of a dependency cycle.
17
18 ## Instances analyse the file level dependencies which gave rise to
19 ## the changeset dependencies of A, B, and C, with the results used ####### ############# #####################
20 ## Copyright (c) 2007 Andreas Kupries.
21 #
22 # This software is licensed as described in the file LICENSE, which
23 # you should have received as part of this distribution.
24 #
25 # This software consists of voluntary contributions made by many
26 # individuals. For exact contribution history, see the revision
27 # history and logs, available at http://fossil-scm.hwaci.com/fossil
28 # # ## ### ##### ######## ############# #####################
29
30 ## Helper class for the pass 6 cycle breaker. Each instance refers to
31 ## three changesets A, B, and C, with A a predecessor of B, and B
32 ## predecessort best fully break the cycle.
33
34 # # ## ### ##### ######## ############# #####################
35 ## Requirements
36
37 package require Tcl 8.4 ; # Required runtime.
38 package require snit ; # OO system.
39 package require vc::tools::misc ; # Text formatting
40 package require vc::tools::trouble ; # Error reporting.
41 package require vc::tools::log ; # User feedback.
42 package require vc::fossil::import::cvs::state ; # State storage.
43 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
44 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
45
46 # # ## ### ##### ######## ############# #####################
47 ##
48
49 snit::type ::vc::fossil::import::cvs::project::revlink {
50 # # ## ### ##### ######## #############
51 ## Public API
52
53 constructor {prev cset next} {
54 set myprev $prev
55 set mycset $cset
56 set mynext $next
57
58 # We perform the bulk of the analysis during construction. The
59 # file revisions held by the changeset CSET can be sorted into
60 # four categories.
61
62 # 1. Revisions whose predecessors are not in PREV, nor are
63 # their successors found in NEXT. These revisions do not
64 # count, as they did not induce any of the two dependencies
65 # under consideration. Thf {!(prev) $mycount(next
66 trouble internal "than {other} {"
67
68 set sbreak [$self breakable]
69 set obreak [$other breakable]
70
71 if {$sbreak && !$obreak} { return 1 } ; # self is better.
72 if {!$sbreak && $obreak} { return 0 } ; # self is worse.
73
74 # Equality. Look at the counters.
75 # - Whichever has the lesser number of passthrough revisions
76 # is better, as more can be split off, weakening the cycle
77 # more.
78 # - Whichever has less links to move is better.
79
80 set opass [$other passcount]
81 if {$mycount(pass) < $opass} { return 1 } ; # self is better.
82 if {$mycount(pass) > $opass} { return 0 } ; # self is worse.
83
84 set smove [$self linkstomove]
85 set omove [$other linkstomove]
86
87 if {$smove < $omove} { return 1 } ; # self is better.
88
89 return 0 ; # Self is worse or equal, i.e. not better.
90 }
91
92 method bre<[$mycset id]>split in the mycategory(prev|nehole part of a dependency cycle.
93
94 ## Instances analyse the file level dependencies which gave rise to
95 ## the changeset dependencies of A, B, and C, with the results used ####### ############# #####################
96 ## Copyright (c) 2007 Andreas Kupries.
97 #
98 # This software is licensed as described in the file LICENSE, which
99 # you should have received as part of this distribution.
100 #
101 # This software consists of voluntary contributions made by many
102 # individuals. For exact contribution history, see the revision
103 # history and logs, available at http://fossil-scm.hwaci.com/fossil
104 # # ## ### ##### ######## ############# #####################
105
106 ## Helper class for the pass 6 cycle breaker. Each instance refers to
107 ## three changesets A, B, and C, with A a predecessor of B, and B
108 ## predecessort best fully break the cycle.
109
110 # # ## ### ##### ######## ############# #####################
111 ## Requirements
112
113 package require Tcl 8.4 ; # Required runtime.
114 package require snit ; # OO system.
115 package require vc::tools::misc ; # Text formatting
116 package require vc::tools::trouble ; # Error reporting.
117 package require vc::tools::log ; # User feedback.
118 package require vc::fossil::import::cvs::state ; # State storage.
119 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
120 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
121
122 # # ## ### ##### ######## ############# #####################
123 ##
124
125 snit::type ::vc::fossil::import::cvs::project::revlink {
126 # # ## ### ##### ######## #############
127 ## Public API
128
129 constructor {prev cset next} {
130 set myprev $prev
131 set mycset $cset
132 set mynext $next
133
134 # We perform the bulk of the analysis during construction. The
135 # file revisions held by the changeset CSET can be sorted into
136 # four categories.
137
138 # 1. Revisions whose predecessors are not in PREV, nor are
139 # their successors found in NEXT. These revisions do not
140 # count, as they did not induce any of the two dependencies
141 # under consideration. Thf {!(prev) $mycount(next
142 trouble internal "than {other} {"
143
144 set sbreak [$self breakable]
145 set obreak [$other breakable]
146
147 if {$sbreak && !$obreak} { return 1 } ; # self is better.
148 if {!$sbreak && $obreak} { return 0 } ; # self is worse.
149
150 # Equality. Look at the counters.
151 # - Whichever has the lesser number of passthrough revisions
152 # is better, as more can be split off, weakening the cycle
153 # more.
154 # - Whichever has less links to move is better.
155
156 set opass [$other passcount]
157 if {$mycount(pass) < $opass} { return 1 } ; # self is better.
158 if {$mycount(pass) > $opass} { return 0 } ; # self is worse.
159
160 set smove [$self linkstomove]
161 set omove [$other linkstomove]
162
163 if {$smove < $omove} { return 1 } ; # self is better.
164
165 return 0 ; # Self is worse or equal, i.e. not better.
166 }
167
168 method bre<[$mycset id]>new changesets the
169 # old one is dropped from all databases, in and out of memory,
170 # and then destroyed.
171
172 struct::list assign [$mycset data] project cstype cssrc
173 $mycset drop
174 $mycset destroy
175
176 set newcsets {}
177 lappend newcsets [project::rev %AUTO% $project $cstype $cssrc $mycategory(prev)]
178 lappend newcsets [project::rev %AUext)]
179
180 foreach c $newcsets { $c p
--- tools/cvs2fossil/lib/misc.tcl
+++ tools/cvs2fossil/lib/misc.tcl
@@ -37,20 +37,41 @@
3737
3838
proc nsp {n singular {plural {}}} {
3939
return "$n [sp $n $singular $plural]"
4040
}
4141
42
- # Find maximum in a list.
42
+ # Find maximum/minimum in a list.
4343
4444
proc max {list} {
4545
set max -1
4646
foreach e $list {
4747
if {$e < $max} continue
4848
set max $e
4949
}
5050
return $max
5151
}
52
+
53
+ proc min {list} {
54
+ set min {}
55
+ foreach e $list {
56
+ if {$min == {}} {
57
+ set min $e
58
+ } elseif {$e > $min} continue
59
+ set min $e
60
+ }
61
+ return $min
62
+ }
63
+
64
+ proc max2 {a b} {
65
+ if {$a > $b} { return $a }
66
+ return $b
67
+ }
68
+
69
+ proc min2 {a b} {
70
+ if {$a < $b} { return $a }
71
+ return $b
72
+ }
5273
5374
proc ldelete {lv item} {
5475
upvar 1 $lv list
5576
set pos [lsearch -exact $list $item]
5677
if {$pos < 0} return
@@ -67,13 +88,13 @@
6788
6889
# # ## ### ##### ######## #############
6990
}
7091
7192
namespace eval ::vc::tools::misc {
72
- namespace export sp nsp max ldelete striptrailingslash
93
+ namespace export sp nsp max min max2 min2 ldelete striptrailingslash
7394
}
7495
7596
# -----------------------------------------------------------------------------
7697
# Ready
7798
7899
package provide vc::tools::misc 1.0
79100
return
80101
--- tools/cvs2fossil/lib/misc.tcl
+++ tools/cvs2fossil/lib/misc.tcl
@@ -37,20 +37,41 @@
37
38 proc nsp {n singular {plural {}}} {
39 return "$n [sp $n $singular $plural]"
40 }
41
42 # Find maximum in a list.
43
44 proc max {list} {
45 set max -1
46 foreach e $list {
47 if {$e < $max} continue
48 set max $e
49 }
50 return $max
51 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
53 proc ldelete {lv item} {
54 upvar 1 $lv list
55 set pos [lsearch -exact $list $item]
56 if {$pos < 0} return
@@ -67,13 +88,13 @@
67
68 # # ## ### ##### ######## #############
69 }
70
71 namespace eval ::vc::tools::misc {
72 namespace export sp nsp max ldelete striptrailingslash
73 }
74
75 # -----------------------------------------------------------------------------
76 # Ready
77
78 package provide vc::tools::misc 1.0
79 return
80
--- tools/cvs2fossil/lib/misc.tcl
+++ tools/cvs2fossil/lib/misc.tcl
@@ -37,20 +37,41 @@
37
38 proc nsp {n singular {plural {}}} {
39 return "$n [sp $n $singular $plural]"
40 }
41
42 # Find maximum/minimum in a list.
43
44 proc max {list} {
45 set max -1
46 foreach e $list {
47 if {$e < $max} continue
48 set max $e
49 }
50 return $max
51 }
52
53 proc min {list} {
54 set min {}
55 foreach e $list {
56 if {$min == {}} {
57 set min $e
58 } elseif {$e > $min} continue
59 set min $e
60 }
61 return $min
62 }
63
64 proc max2 {a b} {
65 if {$a > $b} { return $a }
66 return $b
67 }
68
69 proc min2 {a b} {
70 if {$a < $b} { return $a }
71 return $b
72 }
73
74 proc ldelete {lv item} {
75 upvar 1 $lv list
76 set pos [lsearch -exact $list $item]
77 if {$pos < 0} return
@@ -67,13 +88,13 @@
88
89 # # ## ### ##### ######## #############
90 }
91
92 namespace eval ::vc::tools::misc {
93 namespace export sp nsp max min max2 min2 ldelete striptrailingslash
94 }
95
96 # -----------------------------------------------------------------------------
97 # Ready
98
99 package provide vc::tools::misc 1.0
100 return
101
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -19,10 +19,11 @@
1919
package ifneeded vc::fossil::import::cvs::pass::initcsets 1.0 [list source [file join $dir c2f_pinitcsets.tcl]]
2020
package ifneeded vc::fossil::import::cvs::pass::breakrcycle 1.0 [list source [file join $dir c2f_pbreakrcycle.tcl]]
2121
package ifneeded vc::fossil::import::cvs::project 1.0 [list source [file join $dir c2f_project.tcl]]
2222
package ifneeded vc::fossil::import::cvs::project::lodmgr 1.0 [list source [file join $dir c2f_plodmgr.tcl]]
2323
package ifneeded vc::fossil::import::cvs::project::rev 1.0 [list source [file join $dir c2f_prev.tcl]]
24
+package ifneeded vc::fossil::import::cvs::project::revlink 1.0 [list source [file join $dir c2f_prevlink.tcl]]
2425
package ifneeded vc::fossil::import::cvs::project::sym 1.0 [list source [file join $dir c2f_psym.tcl]]
2526
package ifneeded vc::fossil::import::cvs::project::trunk 1.0 [list source [file join $dir c2f_ptrunk.tcl]]
2627
package ifneeded vc::fossil::import::cvs::repository 1.0 [list source [file join $dir c2f_repository.tcl]]
2728
package ifneeded vc::fossil::import::cvs::state 1.0 [list source [file join $dir c2f_state.tcl]]
2829
package ifneeded vc::rcs::parser 1.0 [list source [file join $dir rcsparser.tcl]]
2930
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -19,10 +19,11 @@
19 package ifneeded vc::fossil::import::cvs::pass::initcsets 1.0 [list source [file join $dir c2f_pinitcsets.tcl]]
20 package ifneeded vc::fossil::import::cvs::pass::breakrcycle 1.0 [list source [file join $dir c2f_pbreakrcycle.tcl]]
21 package ifneeded vc::fossil::import::cvs::project 1.0 [list source [file join $dir c2f_project.tcl]]
22 package ifneeded vc::fossil::import::cvs::project::lodmgr 1.0 [list source [file join $dir c2f_plodmgr.tcl]]
23 package ifneeded vc::fossil::import::cvs::project::rev 1.0 [list source [file join $dir c2f_prev.tcl]]
 
24 package ifneeded vc::fossil::import::cvs::project::sym 1.0 [list source [file join $dir c2f_psym.tcl]]
25 package ifneeded vc::fossil::import::cvs::project::trunk 1.0 [list source [file join $dir c2f_ptrunk.tcl]]
26 package ifneeded vc::fossil::import::cvs::repository 1.0 [list source [file join $dir c2f_repository.tcl]]
27 package ifneeded vc::fossil::import::cvs::state 1.0 [list source [file join $dir c2f_state.tcl]]
28 package ifneeded vc::rcs::parser 1.0 [list source [file join $dir rcsparser.tcl]]
29
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -19,10 +19,11 @@
19 package ifneeded vc::fossil::import::cvs::pass::initcsets 1.0 [list source [file join $dir c2f_pinitcsets.tcl]]
20 package ifneeded vc::fossil::import::cvs::pass::breakrcycle 1.0 [list source [file join $dir c2f_pbreakrcycle.tcl]]
21 package ifneeded vc::fossil::import::cvs::project 1.0 [list source [file join $dir c2f_project.tcl]]
22 package ifneeded vc::fossil::import::cvs::project::lodmgr 1.0 [list source [file join $dir c2f_plodmgr.tcl]]
23 package ifneeded vc::fossil::import::cvs::project::rev 1.0 [list source [file join $dir c2f_prev.tcl]]
24 package ifneeded vc::fossil::import::cvs::project::revlink 1.0 [list source [file join $dir c2f_prevlink.tcl]]
25 package ifneeded vc::fossil::import::cvs::project::sym 1.0 [list source [file join $dir c2f_psym.tcl]]
26 package ifneeded vc::fossil::import::cvs::project::trunk 1.0 [list source [file join $dir c2f_ptrunk.tcl]]
27 package ifneeded vc::fossil::import::cvs::repository 1.0 [list source [file join $dir c2f_repository.tcl]]
28 package ifneeded vc::fossil::import::cvs::state 1.0 [list source [file join $dir c2f_state.tcl]]
29 package ifneeded vc::rcs::parser 1.0 [list source [file join $dir rcsparser.tcl]]
30

Keyboard Shortcuts

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