Fossil SCM

The performance was still not satisfying, even with faster recomputing of successors. Doing it multiple times (Building the graph in each breaker and sort passes) eats time. Caching in memory blows the memory. Chosen solution: Cache this information in the database. Created a new pass 'CsetDeps' which is run between 'InitCsets' and 'BreakRevCsetCycles' (i.e. changeset creation and first breaker pass). It computes the changeset dependencies from the file-level dependencies once and saves the result in the state, in the new table 'cssuccessor'. Now the breaker and sort passes can get the information quickly, with virtually no effort. The dependencies are recomputed incrementally when a changeset is split by one of the breaker passes, for its fragments and its predecessors. The loop check is now trivial, and integrated into the successor computation, with the heavy lifting for the detailed analysis and reporting moved down into the type-dependent SQL queries. The relevant new method is 'loops'. Now that the loop check is incremental the pass based checks have been removed from the integrity module, and the option '--loopcheck' has been eliminated. For paranoia the graph setup and modification code got its loop check reinstated as an assert, redusing the changeset report code. Renumbered the breaker and sort passes. A number of places, like graph setup and traversal, loading of changesets, etc. got feedback indicators to show their progress. The selection of revision and symbol changesets for the associated breaker passes was a bit on the slow side. We now keep changeset lists sorted by type (during loading or general construction) and access them directly.

aku 2007-12-02 20:04 trunk
Commit 00bf8c198ee6db85e9ec3868df1b6649695ae0e3
--- tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
+++ tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
@@ -102,12 +102,16 @@
102102
# and work on breaking it.
103103
104104
log write 3 cyclebreaker {Traverse changesets}
105105
106106
InitializeCandidates $dg
107
+
108
+ set k 0
109
+ set max [llength [$dg nodes]]
107110
while {1} {
108111
while {[WithoutPredecessor $dg n]} {
112
+ log progress 2 cyclebreaker $k $max ; incr k
109113
MarkWatch $dg
110114
ProcessedHook $dg $n $myat
111115
$dg node delete $n
112116
incr myat
113117
ShowPendingNodes
@@ -205,14 +209,13 @@
205209
foreach succ [$cset successors] {
206210
# Changesets may have dependencies outside of the
207211
# chosen set. These are ignored
208212
if {![$dg node exists $succ]} continue
209213
$dg arc insert $cset $succ
210
- if {$succ eq $cset} {
211
- $cset loopcheck
212
- trouble internal "[$cset str] depends on itself"
213
- }
214
+ integrity assert {
215
+ $succ ne $cset
216
+ } {[$cset reportloop 0]Changeset loop was not detected during creation}
214217
}
215218
incr n
216219
}
217220
218221
if {$log} {
@@ -429,14 +432,13 @@
429432
foreach succ [$cset successors] {
430433
# The new changesets may have dependencies outside of
431434
# the chosen set. These are ignored
432435
if {![$dg node exists $succ]} continue
433436
$dg arc insert $cset $succ
434
- if {$succ eq $cset} {
435
- $cset loopcheck
436
- trouble internal "[$cset str] depends on itself"
437
- }
437
+ integrity assert {
438
+ $succ ne $cset
439
+ } {[$cset reportloop 0]Changeset loop was not detected during creation}
438440
}
439441
}
440442
foreach cset $pre {
441443
foreach succ [$cset successors] {
442444
# Note that the arc may already exist in the graph. If
@@ -555,12 +557,12 @@
555557
}
556558
557559
namespace eval ::vc::fossil::import::cvs {
558560
namespace export cyclebreaker
559561
namespace eval cyclebreaker {
562
+ namespace import ::vc::fossil::import::cvs::integrity
560563
namespace eval project {
561
- namespace import ::vc::fossil::import::cvs::integrity
562564
namespace import ::vc::fossil::import::cvs::project::rev
563565
namespace import ::vc::fossil::import::cvs::project::revlink
564566
}
565567
namespace import ::vc::tools::misc::*
566568
namespace import ::vc::tools::log
567569
--- tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
+++ tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
@@ -102,12 +102,16 @@
102 # and work on breaking it.
103
104 log write 3 cyclebreaker {Traverse changesets}
105
106 InitializeCandidates $dg
 
 
 
107 while {1} {
108 while {[WithoutPredecessor $dg n]} {
 
109 MarkWatch $dg
110 ProcessedHook $dg $n $myat
111 $dg node delete $n
112 incr myat
113 ShowPendingNodes
@@ -205,14 +209,13 @@
205 foreach succ [$cset successors] {
206 # Changesets may have dependencies outside of the
207 # chosen set. These are ignored
208 if {![$dg node exists $succ]} continue
209 $dg arc insert $cset $succ
210 if {$succ eq $cset} {
211 $cset loopcheck
212 trouble internal "[$cset str] depends on itself"
213 }
214 }
215 incr n
216 }
217
218 if {$log} {
@@ -429,14 +432,13 @@
429 foreach succ [$cset successors] {
430 # The new changesets may have dependencies outside of
431 # the chosen set. These are ignored
432 if {![$dg node exists $succ]} continue
433 $dg arc insert $cset $succ
434 if {$succ eq $cset} {
435 $cset loopcheck
436 trouble internal "[$cset str] depends on itself"
437 }
438 }
439 }
440 foreach cset $pre {
441 foreach succ [$cset successors] {
442 # Note that the arc may already exist in the graph. If
@@ -555,12 +557,12 @@
555 }
556
557 namespace eval ::vc::fossil::import::cvs {
558 namespace export cyclebreaker
559 namespace eval cyclebreaker {
 
560 namespace eval project {
561 namespace import ::vc::fossil::import::cvs::integrity
562 namespace import ::vc::fossil::import::cvs::project::rev
563 namespace import ::vc::fossil::import::cvs::project::revlink
564 }
565 namespace import ::vc::tools::misc::*
566 namespace import ::vc::tools::log
567
--- tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
+++ tools/cvs2fossil/lib/c2f_cyclebreaker.tcl
@@ -102,12 +102,16 @@
102 # and work on breaking it.
103
104 log write 3 cyclebreaker {Traverse changesets}
105
106 InitializeCandidates $dg
107
108 set k 0
109 set max [llength [$dg nodes]]
110 while {1} {
111 while {[WithoutPredecessor $dg n]} {
112 log progress 2 cyclebreaker $k $max ; incr k
113 MarkWatch $dg
114 ProcessedHook $dg $n $myat
115 $dg node delete $n
116 incr myat
117 ShowPendingNodes
@@ -205,14 +209,13 @@
209 foreach succ [$cset successors] {
210 # Changesets may have dependencies outside of the
211 # chosen set. These are ignored
212 if {![$dg node exists $succ]} continue
213 $dg arc insert $cset $succ
214 integrity assert {
215 $succ ne $cset
216 } {[$cset reportloop 0]Changeset loop was not detected during creation}
 
217 }
218 incr n
219 }
220
221 if {$log} {
@@ -429,14 +432,13 @@
432 foreach succ [$cset successors] {
433 # The new changesets may have dependencies outside of
434 # the chosen set. These are ignored
435 if {![$dg node exists $succ]} continue
436 $dg arc insert $cset $succ
437 integrity assert {
438 $succ ne $cset
439 } {[$cset reportloop 0]Changeset loop was not detected during creation}
 
440 }
441 }
442 foreach cset $pre {
443 foreach succ [$cset successors] {
444 # Note that the arc may already exist in the graph. If
@@ -555,12 +557,12 @@
557 }
558
559 namespace eval ::vc::fossil::import::cvs {
560 namespace export cyclebreaker
561 namespace eval cyclebreaker {
562 namespace import ::vc::fossil::import::cvs::integrity
563 namespace eval project {
 
564 namespace import ::vc::fossil::import::cvs::project::rev
565 namespace import ::vc::fossil::import::cvs::project::revlink
566 }
567 namespace import ::vc::tools::misc::*
568 namespace import ::vc::tools::log
569
--- tools/cvs2fossil/lib/c2f_integrity.tcl
+++ tools/cvs2fossil/lib/c2f_integrity.tcl
@@ -51,25 +51,17 @@
5151
set n 0
5252
AllButMeta
5353
return
5454
}
5555
56
- typemethod changesets {csets} {
56
+ typemethod changesets {} {
5757
log write 4 integrity {Check database consistency}
5858
5959
set n 0
6060
RevisionChangesets
6161
TagChangesets
6262
BranchChangesets
63
- trouble abort? ; # Avoid expensive check if anything found before
64
-
65
- LoopCheck $csets
66
- return
67
- }
68
-
69
- typemethod loopcheckon {} {
70
- set myloopcheck 1
7163
return
7264
}
7365
7466
# # ## ### ##### ######## #############
7567
## Internal methods
@@ -769,24 +761,10 @@
769761
AND T.tid = C.type
770762
}
771763
return
772764
}
773765
774
- proc LoopCheck {csets} {
775
- ::variable myloopcheck
776
- if {!$myloopcheck} return
777
-
778
- log write 4 integrity {Checking changesets for self-references}
779
-
780
- foreach cset $csets {
781
- if {[$cset loopcheck]} {
782
- trouble fatal "[$cset str] depends on itself"
783
- }
784
- }
785
- return
786
- }
787
-
788766
proc ___UnusedChangesetChecks___ {} {
789767
# This code performs a number of paranoid checks of the
790768
# database, searching for inconsistent changeset/revision
791769
# information.
792770
@@ -903,17 +881,10 @@
903881
}
904882
log write 5 integrity {\[[format %02d [incr n]]\] [expr {$ok ? "Ok " : "Failed"}] ... $header}
905883
return
906884
}
907885
908
- # # ## ### ##### ######## #############
909
-
910
- typevariable myloopcheck 0 ; # Boolean flag. Controls whether
911
- # 'integrity changesets' looks for
912
- # changesets with loops or not.
913
- # Default is to not look for them.
914
-
915886
# # ## ### ##### ######## #############
916887
## Configuration
917888
918889
pragma -hasinstances no ; # singleton
919890
pragma -hastypeinfo no ; # no introspection
920891
--- tools/cvs2fossil/lib/c2f_integrity.tcl
+++ tools/cvs2fossil/lib/c2f_integrity.tcl
@@ -51,25 +51,17 @@
51 set n 0
52 AllButMeta
53 return
54 }
55
56 typemethod changesets {csets} {
57 log write 4 integrity {Check database consistency}
58
59 set n 0
60 RevisionChangesets
61 TagChangesets
62 BranchChangesets
63 trouble abort? ; # Avoid expensive check if anything found before
64
65 LoopCheck $csets
66 return
67 }
68
69 typemethod loopcheckon {} {
70 set myloopcheck 1
71 return
72 }
73
74 # # ## ### ##### ######## #############
75 ## Internal methods
@@ -769,24 +761,10 @@
769 AND T.tid = C.type
770 }
771 return
772 }
773
774 proc LoopCheck {csets} {
775 ::variable myloopcheck
776 if {!$myloopcheck} return
777
778 log write 4 integrity {Checking changesets for self-references}
779
780 foreach cset $csets {
781 if {[$cset loopcheck]} {
782 trouble fatal "[$cset str] depends on itself"
783 }
784 }
785 return
786 }
787
788 proc ___UnusedChangesetChecks___ {} {
789 # This code performs a number of paranoid checks of the
790 # database, searching for inconsistent changeset/revision
791 # information.
792
@@ -903,17 +881,10 @@
903 }
904 log write 5 integrity {\[[format %02d [incr n]]\] [expr {$ok ? "Ok " : "Failed"}] ... $header}
905 return
906 }
907
908 # # ## ### ##### ######## #############
909
910 typevariable myloopcheck 0 ; # Boolean flag. Controls whether
911 # 'integrity changesets' looks for
912 # changesets with loops or not.
913 # Default is to not look for them.
914
915 # # ## ### ##### ######## #############
916 ## Configuration
917
918 pragma -hasinstances no ; # singleton
919 pragma -hastypeinfo no ; # no introspection
920
--- tools/cvs2fossil/lib/c2f_integrity.tcl
+++ tools/cvs2fossil/lib/c2f_integrity.tcl
@@ -51,25 +51,17 @@
51 set n 0
52 AllButMeta
53 return
54 }
55
56 typemethod changesets {} {
57 log write 4 integrity {Check database consistency}
58
59 set n 0
60 RevisionChangesets
61 TagChangesets
62 BranchChangesets
 
 
 
 
 
 
 
 
63 return
64 }
65
66 # # ## ### ##### ######## #############
67 ## Internal methods
@@ -769,24 +761,10 @@
761 AND T.tid = C.type
762 }
763 return
764 }
765
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766 proc ___UnusedChangesetChecks___ {} {
767 # This code performs a number of paranoid checks of the
768 # database, searching for inconsistent changeset/revision
769 # information.
770
@@ -903,17 +881,10 @@
881 }
882 log write 5 integrity {\[[format %02d [incr n]]\] [expr {$ok ? "Ok " : "Failed"}] ... $header}
883 return
884 }
885
 
 
 
 
 
 
 
886 # # ## ### ##### ######## #############
887 ## Configuration
888
889 pragma -hasinstances no ; # singleton
890 pragma -hastypeinfo no ; # no introspection
891
--- tools/cvs2fossil/lib/c2f_option.tcl
+++ tools/cvs2fossil/lib/c2f_option.tcl
@@ -47,11 +47,10 @@
4747
# -q, --quiet
4848
# --state (conversion status, ala config.cache)
4949
# --trunk-only
5050
# --exclude, --force-tag, --force-branch
5151
# --batch
52
- # --loopcheck
5352
5453
# -o, --output
5554
# --dry-run
5655
# --symbol-transform RE:XX
5756
@@ -82,11 +81,10 @@
8281
--force-tag { project::sym forcetag [Value arguments] }
8382
--force-branch { project::sym forcebranch [Value arguments] }
8483
--batch { log noprogress }
8584
--dots { cyclebreaker dotsto [Value arguments] }
8685
--watch { cyclebreaker watch [Value arguments] }
87
- --loopcheck { integrity loopcheckon }
8886
default {
8987
Usage $badoption$option\n$gethelp
9088
}
9189
}
9290
}
@@ -149,12 +147,10 @@
149147
trouble info ""
150148
trouble info " --dots PATH Write the changeset graphs before, after,"
151149
trouble info " and during breaking the of cycles to the"
152150
trouble info " direcotry PATH, using GraphViz's dot format"
153151
trouble info ""
154
- trouble info " --loopcheck Activate the expensive search for change-"
155
- trouble info " with loops, i.e. depending on themselves."
156152
157153
# --project, --cache
158154
# ...
159155
return
160156
}
161157
--- tools/cvs2fossil/lib/c2f_option.tcl
+++ tools/cvs2fossil/lib/c2f_option.tcl
@@ -47,11 +47,10 @@
47 # -q, --quiet
48 # --state (conversion status, ala config.cache)
49 # --trunk-only
50 # --exclude, --force-tag, --force-branch
51 # --batch
52 # --loopcheck
53
54 # -o, --output
55 # --dry-run
56 # --symbol-transform RE:XX
57
@@ -82,11 +81,10 @@
82 --force-tag { project::sym forcetag [Value arguments] }
83 --force-branch { project::sym forcebranch [Value arguments] }
84 --batch { log noprogress }
85 --dots { cyclebreaker dotsto [Value arguments] }
86 --watch { cyclebreaker watch [Value arguments] }
87 --loopcheck { integrity loopcheckon }
88 default {
89 Usage $badoption$option\n$gethelp
90 }
91 }
92 }
@@ -149,12 +147,10 @@
149 trouble info ""
150 trouble info " --dots PATH Write the changeset graphs before, after,"
151 trouble info " and during breaking the of cycles to the"
152 trouble info " direcotry PATH, using GraphViz's dot format"
153 trouble info ""
154 trouble info " --loopcheck Activate the expensive search for change-"
155 trouble info " with loops, i.e. depending on themselves."
156
157 # --project, --cache
158 # ...
159 return
160 }
161
--- tools/cvs2fossil/lib/c2f_option.tcl
+++ tools/cvs2fossil/lib/c2f_option.tcl
@@ -47,11 +47,10 @@
47 # -q, --quiet
48 # --state (conversion status, ala config.cache)
49 # --trunk-only
50 # --exclude, --force-tag, --force-branch
51 # --batch
 
52
53 # -o, --output
54 # --dry-run
55 # --symbol-transform RE:XX
56
@@ -82,11 +81,10 @@
81 --force-tag { project::sym forcetag [Value arguments] }
82 --force-branch { project::sym forcebranch [Value arguments] }
83 --batch { log noprogress }
84 --dots { cyclebreaker dotsto [Value arguments] }
85 --watch { cyclebreaker watch [Value arguments] }
 
86 default {
87 Usage $badoption$option\n$gethelp
88 }
89 }
90 }
@@ -149,12 +147,10 @@
147 trouble info ""
148 trouble info " --dots PATH Write the changeset graphs before, after,"
149 trouble info " and during breaking the of cycles to the"
150 trouble info " direcotry PATH, using GraphViz's dot format"
151 trouble info ""
 
 
152
153 # --project, --cache
154 # ...
155 return
156 }
157
--- tools/cvs2fossil/lib/c2f_patopsort.tcl
+++ tools/cvs2fossil/lib/c2f_patopsort.tcl
@@ -8,11 +8,11 @@
88
# This software consists of voluntary contributions made by many
99
# individuals. For exact contribution history, see the revision
1010
# history and logs, available at http://fossil-scm.hwaci.com/fossil
1111
# # ## ### ##### ######## ############# #####################
1212
13
-## Pass X. This pass goes over all changesets and sorts them
13
+## Pass XI. This pass goes over all changesets and sorts them
1414
## topologically. It assumes that there are no cycles which could
1515
## impede it, any remaining having been broken by the previous two
1616
## passes, and aborts if that condition doesn't hold.
1717
1818
# # ## ### ##### ######## ############# #####################
1919
--- tools/cvs2fossil/lib/c2f_patopsort.tcl
+++ tools/cvs2fossil/lib/c2f_patopsort.tcl
@@ -8,11 +8,11 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass X. This pass goes over all changesets and sorts them
14 ## topologically. It assumes that there are no cycles which could
15 ## impede it, any remaining having been broken by the previous two
16 ## passes, and aborts if that condition doesn't hold.
17
18 # # ## ### ##### ######## ############# #####################
19
--- tools/cvs2fossil/lib/c2f_patopsort.tcl
+++ tools/cvs2fossil/lib/c2f_patopsort.tcl
@@ -8,11 +8,11 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass XI. This pass goes over all changesets and sorts them
14 ## topologically. It assumes that there are no cycles which could
15 ## impede it, any remaining having been broken by the previous two
16 ## passes, and aborts if that condition doesn't hold.
17
18 # # ## ### ##### ######## ############# #####################
19
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -8,12 +8,12 @@
88
# This software consists of voluntary contributions made by many
99
# individuals. For exact contribution history, see the revision
1010
# history and logs, available at http://fossil-scm.hwaci.com/fossil
1111
# # ## ### ##### ######## ############# #####################
1212
13
-## Pass IX. This is the final pass for breaking changeset dependency
14
-## cycles. The previous breaker passes (6 and 8) broke cycles covering
13
+## Pass X. This is the final pass for breaking changeset dependency
14
+## cycles. The previous breaker passes (7 and 9) broke cycles covering
1515
## revision and symbol changesets, respectively. This pass now breaks
1616
## any remaining cycles, each of which has to contain at least one
1717
## revision and at least one symbol changeset.
1818
1919
# # ## ### ##### ######## ############# #####################
@@ -80,11 +80,11 @@
8080
LoadCommitOrder
8181
cyclebreaker run break-all [myproc Changesets]
8282
}
8383
8484
repository printcsetstatistics
85
- integrity changesets [project::rev all]
85
+ integrity changesets
8686
return
8787
}
8888
8989
typemethod discard {} {
9090
# Pass manager interface. Executed for all passes after the
@@ -94,11 +94,14 @@
9494
}
9595
9696
# # ## ### ##### ######## #############
9797
## Internal methods
9898
99
- proc Changesets {} { project::rev all }
99
+ proc Changesets {} {
100
+ log write 2 breakrcycle {Selecting all changesets}
101
+ return [project::rev all]
102
+ }
100103
101104
proc LoadCommitOrder {} {
102105
::variable mycset
103106
::variable myrevisionchangesets
104107
105108
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -8,12 +8,12 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass IX. This is the final pass for breaking changeset dependency
14 ## cycles. The previous breaker passes (6 and 8) broke cycles covering
15 ## revision and symbol changesets, respectively. This pass now breaks
16 ## any remaining cycles, each of which has to contain at least one
17 ## revision and at least one symbol changeset.
18
19 # # ## ### ##### ######## ############# #####################
@@ -80,11 +80,11 @@
80 LoadCommitOrder
81 cyclebreaker run break-all [myproc Changesets]
82 }
83
84 repository printcsetstatistics
85 integrity changesets [project::rev all]
86 return
87 }
88
89 typemethod discard {} {
90 # Pass manager interface. Executed for all passes after the
@@ -94,11 +94,14 @@
94 }
95
96 # # ## ### ##### ######## #############
97 ## Internal methods
98
99 proc Changesets {} { project::rev all }
 
 
 
100
101 proc LoadCommitOrder {} {
102 ::variable mycset
103 ::variable myrevisionchangesets
104
105
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -8,12 +8,12 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass X. This is the final pass for breaking changeset dependency
14 ## cycles. The previous breaker passes (7 and 9) broke cycles covering
15 ## revision and symbol changesets, respectively. This pass now breaks
16 ## any remaining cycles, each of which has to contain at least one
17 ## revision and at least one symbol changeset.
18
19 # # ## ### ##### ######## ############# #####################
@@ -80,11 +80,11 @@
80 LoadCommitOrder
81 cyclebreaker run break-all [myproc Changesets]
82 }
83
84 repository printcsetstatistics
85 integrity changesets
86 return
87 }
88
89 typemethod discard {} {
90 # Pass manager interface. Executed for all passes after the
@@ -94,11 +94,14 @@
94 }
95
96 # # ## ### ##### ######## #############
97 ## Internal methods
98
99 proc Changesets {} {
100 log write 2 breakrcycle {Selecting all changesets}
101 return [project::rev all]
102 }
103
104 proc LoadCommitOrder {} {
105 ::variable mycset
106 ::variable myrevisionchangesets
107
108
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -8,13 +8,13 @@
88
# This software consists of voluntary contributions made by many
99
# individuals. For exact contribution history, see the revision
1010
# history and logs, available at http://fossil-scm.hwaci.com/fossil
1111
# # ## ### ##### ######## ############# #####################
1212
13
-## Pass VI. This pass goes over the set of revision based changesets
13
+## Pass VII. This pass goes over the set of revision based changesets
1414
## and breaks all dependency cycles they may be in. We need a
15
-## dependency tree. Identical to pass VII, except for the selection of
15
+## dependency tree. Identical to pass IX, except for the selection of
1616
## the changesets.
1717
1818
# # ## ### ##### ######## ############# #####################
1919
## Requirements
2020
@@ -69,11 +69,11 @@
6969
state transaction {
7070
cyclebreaker run break-rev [myproc Changesets]
7171
}
7272
7373
repository printcsetstatistics
74
- integrity changesets [project::rev all]
74
+ integrity changesets
7575
return
7676
}
7777
7878
typemethod discard {} {
7979
# Pass manager interface. Executed for all passes after the
@@ -84,15 +84,14 @@
8484
8585
# # ## ### ##### ######## #############
8686
## Internal methods
8787
8888
proc Changesets {} {
89
- return [struct::list filter [project::rev all] [myproc IsByRevision]]
89
+ log write 2 breakrcycle {Selecting the revision changesets}
90
+ return [project::rev rev]
9091
}
9192
92
- proc IsByRevision {cset} { $cset byrevision }
93
-
9493
# # ## ### ##### ######## #############
9594
## Configuration
9695
9796
pragma -hasinstances no ; # singleton
9897
pragma -hastypeinfo no ; # no introspection
9998
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -8,13 +8,13 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass VI. This pass goes over the set of revision based changesets
14 ## and breaks all dependency cycles they may be in. We need a
15 ## dependency tree. Identical to pass VII, except for the selection of
16 ## the changesets.
17
18 # # ## ### ##### ######## ############# #####################
19 ## Requirements
20
@@ -69,11 +69,11 @@
69 state transaction {
70 cyclebreaker run break-rev [myproc Changesets]
71 }
72
73 repository printcsetstatistics
74 integrity changesets [project::rev all]
75 return
76 }
77
78 typemethod discard {} {
79 # Pass manager interface. Executed for all passes after the
@@ -84,15 +84,14 @@
84
85 # # ## ### ##### ######## #############
86 ## Internal methods
87
88 proc Changesets {} {
89 return [struct::list filter [project::rev all] [myproc IsByRevision]]
 
90 }
91
92 proc IsByRevision {cset} { $cset byrevision }
93
94 # # ## ### ##### ######## #############
95 ## Configuration
96
97 pragma -hasinstances no ; # singleton
98 pragma -hastypeinfo no ; # no introspection
99
--- tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl
@@ -8,13 +8,13 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass VII. This pass goes over the set of revision based changesets
14 ## and breaks all dependency cycles they may be in. We need a
15 ## dependency tree. Identical to pass IX, except for the selection of
16 ## the changesets.
17
18 # # ## ### ##### ######## ############# #####################
19 ## Requirements
20
@@ -69,11 +69,11 @@
69 state transaction {
70 cyclebreaker run break-rev [myproc Changesets]
71 }
72
73 repository printcsetstatistics
74 integrity changesets
75 return
76 }
77
78 typemethod discard {} {
79 # Pass manager interface. Executed for all passes after the
@@ -84,15 +84,14 @@
84
85 # # ## ### ##### ######## #############
86 ## Internal methods
87
88 proc Changesets {} {
89 log write 2 breakrcycle {Selecting the revision changesets}
90 return [project::rev rev]
91 }
92
 
 
93 # # ## ### ##### ######## #############
94 ## Configuration
95
96 pragma -hasinstances no ; # singleton
97 pragma -hastypeinfo no ; # no introspection
98
--- tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
@@ -8,21 +8,22 @@
88
# This software consists of voluntary contributions made by many
99
# individuals. For exact contribution history, see the revision
1010
# history and logs, available at http://fossil-scm.hwaci.com/fossil
1111
# # ## ### ##### ######## ############# #####################
1212
13
-## Pass VIII. This pass goes over the set of symbol based changesets
14
-## and breaks all dependency cycles they may be in. We need a
15
-## dependency tree. Identical to pass VI, except for the selection of
16
-## the changesets.
13
+## Pass IX. This pass goes over the set of symbol based changesets and
14
+## breaks all dependency cycles they may be in. We need a dependency
15
+## tree. Identical to pass VII, except for the selection of the
16
+## changesets.
1717
1818
# # ## ### ##### ######## ############# #####################
1919
## Requirements
2020
2121
package require Tcl 8.4 ; # Required runtime.
2222
package require snit ; # OO system.
2323
package require struct::list ; # Higher order list operations.
24
+package require vc::tools::log ; # User feedback.
2425
package require vc::fossil::import::cvs::cyclebreaker ; # Breaking dependency cycles.
2526
package require vc::fossil::import::cvs::repository ; # Repository management.
2627
package require vc::fossil::import::cvs::state ; # State storage.
2728
package require vc::fossil::import::cvs::integrity ; # State integrity checks.
2829
package require vc::fossil::import::cvs::project::rev ; # Project level changesets
@@ -68,11 +69,11 @@
6869
state transaction {
6970
cyclebreaker run break-sym [myproc Changesets]
7071
}
7172
7273
repository printcsetstatistics
73
- integrity changesets [project::rev all]
74
+ integrity changesets
7475
return
7576
}
7677
7778
typemethod discard {} {
7879
# Pass manager interface. Executed for all passes after the
@@ -83,15 +84,14 @@
8384
8485
# # ## ### ##### ######## #############
8586
## Internal methods
8687
8788
proc Changesets {} {
88
- return [struct::list filter [project::rev all] [myproc IsBySymbol]]
89
+ log write 2 breakscycle {Selecting the symbol changesets}
90
+ return [project::rev sym]
8991
}
9092
91
- proc IsBySymbol {cset} { $cset bysymbol }
92
-
9393
# # ## ### ##### ######## #############
9494
## Configuration
9595
9696
pragma -hasinstances no ; # singleton
9797
pragma -hastypeinfo no ; # no introspection
@@ -108,13 +108,15 @@
108108
namespace import ::vc::fossil::import::cvs::state
109109
namespace import ::vc::fossil::import::cvs::integrity
110110
namespace eval project {
111111
namespace import ::vc::fossil::import::cvs::project::rev
112112
}
113
+ namespace import ::vc::tools::log
114
+ log register breakscycle
113115
}
114116
}
115117
116118
# # ## ### ##### ######## ############# #####################
117119
## Ready
118120
119121
package provide vc::fossil::import::cvs::pass::breakscycle 1.0
120122
return
121123
--- tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
@@ -8,21 +8,22 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass VIII. This pass goes over the set of symbol based changesets
14 ## and breaks all dependency cycles they may be in. We need a
15 ## dependency tree. Identical to pass VI, except for the selection of
16 ## the changesets.
17
18 # # ## ### ##### ######## ############# #####################
19 ## Requirements
20
21 package require Tcl 8.4 ; # Required runtime.
22 package require snit ; # OO system.
23 package require struct::list ; # Higher order list operations.
 
24 package require vc::fossil::import::cvs::cyclebreaker ; # Breaking dependency cycles.
25 package require vc::fossil::import::cvs::repository ; # Repository management.
26 package require vc::fossil::import::cvs::state ; # State storage.
27 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
28 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
@@ -68,11 +69,11 @@
68 state transaction {
69 cyclebreaker run break-sym [myproc Changesets]
70 }
71
72 repository printcsetstatistics
73 integrity changesets [project::rev all]
74 return
75 }
76
77 typemethod discard {} {
78 # Pass manager interface. Executed for all passes after the
@@ -83,15 +84,14 @@
83
84 # # ## ### ##### ######## #############
85 ## Internal methods
86
87 proc Changesets {} {
88 return [struct::list filter [project::rev all] [myproc IsBySymbol]]
 
89 }
90
91 proc IsBySymbol {cset} { $cset bysymbol }
92
93 # # ## ### ##### ######## #############
94 ## Configuration
95
96 pragma -hasinstances no ; # singleton
97 pragma -hastypeinfo no ; # no introspection
@@ -108,13 +108,15 @@
108 namespace import ::vc::fossil::import::cvs::state
109 namespace import ::vc::fossil::import::cvs::integrity
110 namespace eval project {
111 namespace import ::vc::fossil::import::cvs::project::rev
112 }
 
 
113 }
114 }
115
116 # # ## ### ##### ######## ############# #####################
117 ## Ready
118
119 package provide vc::fossil::import::cvs::pass::breakscycle 1.0
120 return
121
--- tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakscycle.tcl
@@ -8,21 +8,22 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass IX. This pass goes over the set of symbol based changesets and
14 ## breaks all dependency cycles they may be in. We need a dependency
15 ## tree. Identical to pass VII, except for the selection of the
16 ## changesets.
17
18 # # ## ### ##### ######## ############# #####################
19 ## Requirements
20
21 package require Tcl 8.4 ; # Required runtime.
22 package require snit ; # OO system.
23 package require struct::list ; # Higher order list operations.
24 package require vc::tools::log ; # User feedback.
25 package require vc::fossil::import::cvs::cyclebreaker ; # Breaking dependency cycles.
26 package require vc::fossil::import::cvs::repository ; # Repository management.
27 package require vc::fossil::import::cvs::state ; # State storage.
28 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
29 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
@@ -68,11 +69,11 @@
69 state transaction {
70 cyclebreaker run break-sym [myproc Changesets]
71 }
72
73 repository printcsetstatistics
74 integrity changesets
75 return
76 }
77
78 typemethod discard {} {
79 # Pass manager interface. Executed for all passes after the
@@ -83,15 +84,14 @@
84
85 # # ## ### ##### ######## #############
86 ## Internal methods
87
88 proc Changesets {} {
89 log write 2 breakscycle {Selecting the symbol changesets}
90 return [project::rev sym]
91 }
92
 
 
93 # # ## ### ##### ######## #############
94 ## Configuration
95
96 pragma -hasinstances no ; # singleton
97 pragma -hastypeinfo no ; # no introspection
@@ -108,13 +108,15 @@
108 namespace import ::vc::fossil::import::cvs::state
109 namespace import ::vc::fossil::import::cvs::integrity
110 namespace eval project {
111 namespace import ::vc::fossil::import::cvs::project::rev
112 }
113 namespace import ::vc::tools::log
114 log register breakscycle
115 }
116 }
117
118 # # ## ### ##### ######## ############# #####################
119 ## Ready
120
121 package provide vc::fossil::import::cvs::pass::breakscycle 1.0
122 return
123
--- tools/cvs2fossil/lib/c2f_pinitcsets.tcl
+++ tools/cvs2fossil/lib/c2f_pinitcsets.tcl
@@ -22,11 +22,10 @@
2222
package require vc::tools::misc ; # Text formatting.
2323
package require vc::tools::log ; # User feedback.
2424
package require vc::fossil::import::cvs::repository ; # Repository management.
2525
package require vc::fossil::import::cvs::state ; # State storage.
2626
package require vc::fossil::import::cvs::integrity ; # State integrity checks.
27
-package require vc::fossil::import::cvs::project::sym ; # Project level symbols
2827
package require vc::fossil::import::cvs::project::rev ; # Project level changesets
2928
3029
# # ## ### ##### ######## ############# #####################
3130
## Register the pass with the management
3231
@@ -113,22 +112,27 @@
113112
114113
# Need the types first, the constructor in the loop below uses
115114
# them to assert the correctness of type names.
116115
project::rev getcstypes
117116
117
+ # TODO: Move to project::rev
118
+ set n 0
119
+ log write 2 initcsets {Loading the changesets}
118120
foreach {id pid cstype srcid} [state run {
119121
SELECT C.cid, C.pid, CS.name, C.src
120122
FROM changeset C, cstype CS
121123
WHERE C.type = CS.tid
122124
ORDER BY C.cid
123125
}] {
126
+ log progress 2 initcsets $n {}
124127
set r [project::rev %AUTO% [repository projectof $pid] $cstype $srcid [state run {
125128
SELECT C.iid
126129
FROM csitem C
127130
WHERE C.cid = $id
128131
ORDER BY C.pos
129132
}] $id]
133
+ incr n
130134
}
131135
132136
project::rev loadcounter
133137
return
134138
}
@@ -143,11 +147,11 @@
143147
CreateSymbolChangesets ; # Create csets for tags and branches.
144148
PersistTheChangesets
145149
}
146150
147151
repository printcsetstatistics
148
- integrity changesets [project::rev all]
152
+ integrity changesets
149153
return
150154
}
151155
152156
typemethod discard {} {
153157
# Pass manager interface. Executed for all passes after the
154158
--- tools/cvs2fossil/lib/c2f_pinitcsets.tcl
+++ tools/cvs2fossil/lib/c2f_pinitcsets.tcl
@@ -22,11 +22,10 @@
22 package require vc::tools::misc ; # Text formatting.
23 package require vc::tools::log ; # User feedback.
24 package require vc::fossil::import::cvs::repository ; # Repository management.
25 package require vc::fossil::import::cvs::state ; # State storage.
26 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
27 package require vc::fossil::import::cvs::project::sym ; # Project level symbols
28 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
29
30 # # ## ### ##### ######## ############# #####################
31 ## Register the pass with the management
32
@@ -113,22 +112,27 @@
113
114 # Need the types first, the constructor in the loop below uses
115 # them to assert the correctness of type names.
116 project::rev getcstypes
117
 
 
 
118 foreach {id pid cstype srcid} [state run {
119 SELECT C.cid, C.pid, CS.name, C.src
120 FROM changeset C, cstype CS
121 WHERE C.type = CS.tid
122 ORDER BY C.cid
123 }] {
 
124 set r [project::rev %AUTO% [repository projectof $pid] $cstype $srcid [state run {
125 SELECT C.iid
126 FROM csitem C
127 WHERE C.cid = $id
128 ORDER BY C.pos
129 }] $id]
 
130 }
131
132 project::rev loadcounter
133 return
134 }
@@ -143,11 +147,11 @@
143 CreateSymbolChangesets ; # Create csets for tags and branches.
144 PersistTheChangesets
145 }
146
147 repository printcsetstatistics
148 integrity changesets [project::rev all]
149 return
150 }
151
152 typemethod discard {} {
153 # Pass manager interface. Executed for all passes after the
154
--- tools/cvs2fossil/lib/c2f_pinitcsets.tcl
+++ tools/cvs2fossil/lib/c2f_pinitcsets.tcl
@@ -22,11 +22,10 @@
22 package require vc::tools::misc ; # Text formatting.
23 package require vc::tools::log ; # User feedback.
24 package require vc::fossil::import::cvs::repository ; # Repository management.
25 package require vc::fossil::import::cvs::state ; # State storage.
26 package require vc::fossil::import::cvs::integrity ; # State integrity checks.
 
27 package require vc::fossil::import::cvs::project::rev ; # Project level changesets
28
29 # # ## ### ##### ######## ############# #####################
30 ## Register the pass with the management
31
@@ -113,22 +112,27 @@
112
113 # Need the types first, the constructor in the loop below uses
114 # them to assert the correctness of type names.
115 project::rev getcstypes
116
117 # TODO: Move to project::rev
118 set n 0
119 log write 2 initcsets {Loading the changesets}
120 foreach {id pid cstype srcid} [state run {
121 SELECT C.cid, C.pid, CS.name, C.src
122 FROM changeset C, cstype CS
123 WHERE C.type = CS.tid
124 ORDER BY C.cid
125 }] {
126 log progress 2 initcsets $n {}
127 set r [project::rev %AUTO% [repository projectof $pid] $cstype $srcid [state run {
128 SELECT C.iid
129 FROM csitem C
130 WHERE C.cid = $id
131 ORDER BY C.pos
132 }] $id]
133 incr n
134 }
135
136 project::rev loadcounter
137 return
138 }
@@ -143,11 +147,11 @@
147 CreateSymbolChangesets ; # Create csets for tags and branches.
148 PersistTheChangesets
149 }
150
151 repository printcsetstatistics
152 integrity changesets
153 return
154 }
155
156 typemethod discard {} {
157 # Pass manager interface. Executed for all passes after the
158
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -51,10 +51,11 @@
5151
set mypos {} ; # Commit location is not known yet.
5252
5353
# Keep track of the generated changesets and of the inverse
5454
# mapping from items to them.
5555
lappend mychangesets $self
56
+ lappend mytchangesets($cstype) $self
5657
set myidmap($myid) $self
5758
foreach iid $items {
5859
set key [list $cstype $iid]
5960
set myitemmap($key) $self
6061
lappend mytitems $key
@@ -86,16 +87,43 @@
8687
delegate method isbranch to mytypeobj
8788
delegate method istag to mytypeobj
8889
8990
method setpos {p} { set mypos $p ; return }
9091
method pos {} { return $mypos }
92
+
93
+ method determinesuccessors {} {
94
+ # Pass 6 operation. Compute project-level dependencies from
95
+ # the file-level data and save it back to the state. This may
96
+ # be called during the cycle breaker passes as well, to adjust
97
+ # the successor information of changesets which are the
98
+ # predecessors of dropped changesets. For them we have to
99
+ # remove their existing information first before inserting the
100
+ # new data.
101
+ state run {
102
+ DELETE FROM cssuccessor WHERE cid = $myid;
103
+ }
104
+ set loop 0
105
+ foreach nid [$mytypeobj cs_successors $myitems] {
106
+ state run {
107
+ INSERT INTO cssuccessor (cid, nid)
108
+ VALUES ($myid,$nid)
109
+ }
110
+ if {$nid == $myid} { set loop 1 }
111
+ }
112
+ # Report after the complete structure has been saved.
113
+ if {$loop} { $self reportloop }
114
+ return
115
+ }
91116
92117
# result = list (changeset)
93118
method successors {} {
94
- return [struct::list map \
95
- [$mytypeobj cs_successors $myitems] \
96
- [mytypemethod of]]
119
+ # Use the data saved by pass 6.
120
+ return [struct::list map [state run {
121
+ SELECT S.nid
122
+ FROM cssuccessor S
123
+ WHERE S.cid = $myid
124
+ }] [mytypemethod of]]
97125
}
98126
99127
# result = dict (item -> list (changeset))
100128
method successormap {} {
101129
# NOTE / FUTURE: Definitive bottleneck (can be millions of pairs).
@@ -172,11 +200,11 @@
172200
# one. The previous algorithm, adapted from cvs2svn, computed
173201
# a lot of state which was thrown away and then computed again
174202
# for each of the fragments. It should be easier to update and
175203
# reuse that state.
176204
177
- # The code checks only sucessor dependencies, as this
205
+ # The code checks only successor dependencies, as this
178206
# automatically covers the predecessor dependencies as well (A
179207
# successor dependency a -> b is also a predecessor dependency
180208
# b -> a).
181209
182210
# Array of dependencies (parent -> child). This is pulled from
@@ -356,52 +384,56 @@
356384
method drop {} {
357385
log write 8 csets {Dropping $self = [$self str]}
358386
359387
state transaction {
360388
state run {
361
- DELETE FROM changeset WHERE cid = $myid;
362
- DELETE FROM csitem WHERE cid = $myid;
389
+ DELETE FROM changeset WHERE cid = $myid;
390
+ DELETE FROM csitem WHERE cid = $myid;
391
+ DELETE FROM cssuccessor WHERE cid = $myid;
363392
}
364393
}
365394
foreach iid $myitems {
366395
set key [list $mytype $iid]
367396
unset myitemmap($key)
368397
log write 8 csets {MAP- item <$key> $self = [$self str]}
369398
}
370399
set pos [lsearch -exact $mychangesets $self]
371400
set mychangesets [lreplace $mychangesets $pos $pos]
372
- return
373
- }
374
-
375
- method loopcheck {} {
376
- log write 7 csets {Checking [$self str] for loops /[llength $myitems]}
377
-
378
- if {![struct::set contains [$self successors] $self]} {
379
- return 0
380
- }
381
- if {[log verbosity?] < 8} { return 1 }
382
-
383
- # Print the detailed successor structure of the self-
384
- # referential changeset, if the verbosity of the log is dialed
385
- # high enough.
386
-
387
- log write 8 csets [set hdr {Self-referential changeset [$self str] __________________}]
388
- array set nmap [$self nextmap]
389
- foreach item [lsort -dict [array names nmap]] {
390
- foreach succitem $nmap($item) {
391
- set succcs $myitemmap($succitem)
392
- set hint [expr {($succcs eq $self)
393
- ? "LOOP"
394
- : " "}]
395
- set i "<$item [$type itemstr $item]>"
396
- set s "<$succitem [$type itemstr $succitem]>"
397
- set scs [$succcs str]
398
- log write 8 csets {$hint * $i --> $s --> cs $scs}
399
- }
400
- }
401
- log write 8 csets [regsub -all {[^ ]} $hdr {_}]
402
- return 1
401
+ set pos [lsearch -exact $mytchangesets($mytype) $self]
402
+ set mytchangesets($mytype) [lreplace $mytchangesets($mytype) $pos $pos]
403
+
404
+ # Return the list of predecessors so that they can be adjusted.
405
+ return [struct::list map [state run {
406
+ SELECT cid
407
+ FROM cssuccessor
408
+ WHERE nid = $myid
409
+ }] [mytypemethod of]]
410
+ }
411
+
412
+ method reportloop {{kill 1}} {
413
+ # We print the items which are producing the loop, and how.
414
+
415
+ set hdr "Self-referential changeset [$self str] __________________"
416
+ set ftr [regsub -all {[^ ]} $hdr {_}]
417
+
418
+ log write 0 csets $hdr
419
+ foreach {item nextitem} [$mytypeobj loops $myitems] {
420
+ # Create tagged items from the id and our type.
421
+ set item [list $mytype $item]
422
+ set nextitem [list $mytype $nextitem]
423
+ # Printable labels.
424
+ set i "<[$type itemstr $item]>"
425
+ set n "<[$type itemstr $nextitem]>"
426
+ set ncs $myitemmap($nextitem)
427
+ # Print
428
+ log write 0 csets {* $i --> $n --> cs [$ncs str]}
429
+ }
430
+ log write 0 csets $ftr
431
+
432
+ if {!$kill} return
433
+ trouble internal "[$self str] depends on itself"
434
+ return
403435
}
404436
405437
typemethod split {cset args} {
406438
# As part of the creation of the new changesets specified in
407439
# ARGS as sets of items, all subsets of CSET's item set, CSET
@@ -417,28 +449,32 @@
417449
418450
# All checks pass, actually perform the split.
419451
420452
struct::list assign [$cset data] project cstype cssrc
421453
422
- $cset drop
454
+ set predecessors [$cset drop]
423455
$cset destroy
424456
425457
set newcsets {}
426458
foreach fragmentitems $args {
427459
log write 8 csets {MAKE: [lsort $fragmentitems]}
428460
429461
set fragment [$type %AUTO% $project $cstype $cssrc \
430462
[Untag $fragmentitems $cstype]]
431463
lappend newcsets $fragment
464
+
432465
$fragment persist
466
+ $fragment determinesuccessors
467
+ }
433468
434
- if {[$fragment loopcheck]} {
435
- trouble fatal "[$fragment str] depends on itself"
436
- }
469
+ # The predecessors have to recompute their successors, i.e.
470
+ # remove the dropped changeset and put one of the fragments
471
+ # into its place.
472
+ foreach p $predecessors {
473
+ $p determinesuccessors
437474
}
438475
439
- trouble abort?
440476
return $newcsets
441477
}
442478
443479
typemethod itemstr {item} {
444480
struct::list assign $item itype iid
@@ -560,10 +596,11 @@
560596
return
561597
}
562598
563599
typemethod loadcounter {} {
564600
# Initialize the counter from the state
601
+ log write 2 initcsets {Loading changeset counter}
565602
set mycounter [state one { SELECT MAX(cid) FROM changeset }]
566603
return
567604
}
568605
569606
typemethod num {} { return $mycounter }
@@ -778,22 +815,30 @@
778815
return
779816
}
780817
781818
# # ## ### ##### ######## #############
782819
783
- typevariable mychangesets {} ; # List of all known changesets.
784
- typevariable myitemmap -array {} ; # Map from items (tagged) to
785
- # the list of changesets
786
- # containing it. Each item can
787
- # be used by only one
788
- # changeset.
820
+ typevariable mychangesets {} ; # List of all known
821
+ # changesets.
822
+ typevariable mytchangesets -array {} ; # List of all known
823
+ # changesets of a type.
824
+ typevariable myitemmap -array {} ; # Map from items (tagged)
825
+ # to the list of changesets
826
+ # containing it. Each item
827
+ # can be used by only one
828
+ # changeset.
789829
typevariable myidmap -array {} ; # Map from changeset id to
790830
# changeset.
791831
792832
typemethod all {} { return $mychangesets }
793833
typemethod of {cid} { return $myidmap($cid) }
794834
typemethod ofitem {iid} { return $myitemmap($iid) }
835
+
836
+ typemethod rev {} { return $mytchangesets(rev) }
837
+ typemethod sym {} { return [concat \
838
+ ${mytchangesets(sym::branch)} \
839
+ ${mytchangesets(sym::tag)}] }
795840
796841
# # ## ### ##### ######## #############
797842
## Configuration
798843
799844
pragma -hastypeinfo no ; # no type introspection
@@ -924,10 +969,46 @@
924969
}
925970
}
926971
}
927972
return
928973
}
974
+
975
+ # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
976
+ typemethod loops {revisions} {
977
+ # Note: Tags and branches cannot cause the loop. Their id's,
978
+ # bein of a fundamentally different type than the revisions
979
+ # coming in cannot be in the set.
980
+
981
+ set theset ('[join $revisions {','}]')
982
+ return [state run [subst -nocommands -nobackslashes {
983
+ -- (1) Primary child
984
+ SELECT R.rid, R.child
985
+ FROM revision R
986
+ WHERE R.rid IN $theset -- Restrict to revisions of interest
987
+ AND R.child IS NOT NULL -- Has primary child
988
+ AND R.child IN $theset -- Loop
989
+ --
990
+ UNION
991
+ -- (2) Secondary (branch) children
992
+ SELECT R.rid, B.brid
993
+ FROM revision R, revisionbranchchildren B
994
+ WHERE R.rid IN $theset -- Restrict to revisions of interest
995
+ AND R.rid = B.rid -- Select subset of branch children
996
+ AND B.rid IN $theset -- Loop
997
+ --
998
+ UNION
999
+ -- (4) Child of trunk root successor of last NTDB on trunk.
1000
+ SELECT R.rid, RA.child
1001
+ FROM revision R, revision RA
1002
+ WHERE R.rid IN $theset -- Restrict to revisions of interest
1003
+ AND R.isdefault -- Restrict to NTDB
1004
+ AND R.dbchild IS NOT NULL -- and last NTDB belonging to trunk
1005
+ AND RA.rid = R.dbchild -- Go directly to trunk root
1006
+ AND RA.child IS NOT NULL -- Has primary child.
1007
+ AND RA.child IN $theset -- Loop
1008
+ }]]
1009
+ }
9291010
9301011
# var(dv) = dict (item -> list (item)), item = list (type id)
9311012
typemethod successors {dv revisions} {
9321013
upvar 1 $dv dependencies
9331014
set theset ('[join $revisions {','}]')
@@ -986,19 +1067,19 @@
9861067
lappend dependencies([list rev $rid]) [list rev $child]
9871068
}
9881069
foreach {rid child} [state run "
9891070
SELECT R.rid, T.tid
9901071
FROM revision R, tag T
991
- WHERE R.rid in $theset
1072
+ WHERE R.rid IN $theset
9921073
AND T.rev = R.rid
9931074
"] {
9941075
lappend dependencies([list rev $rid]) [list sym::tag $child]
9951076
}
9961077
foreach {rid child} [state run "
9971078
SELECT R.rid, B.bid
9981079
FROM revision R, branch B
999
- WHERE R.rid in $theset
1080
+ WHERE R.rid IN $theset
10001081
AND B.root = R.rid
10011082
"] {
10021083
lappend dependencies([list rev $rid]) [list sym::branch $child]
10031084
}
10041085
return
@@ -1159,10 +1240,16 @@
11591240
# var(dv) = dict (item -> list (item)), item = list (type id)
11601241
typemethod successors {dv tags} {
11611242
# Tags have no successors.
11621243
return
11631244
}
1245
+
1246
+ # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
1247
+ typemethod loops {tags} {
1248
+ # Tags have no successors, therefore cannot cause loops
1249
+ return {}
1250
+ }
11641251
11651252
# var(dv) = dict (item -> list (item)), item = list (type id)
11661253
typemethod predecessors {dv tags} {
11671254
upvar 1 $dv dependencies
11681255
# The predecessors of a tag are all the revisions the tags are
@@ -1244,10 +1331,27 @@
12441331
FROM branch B, revision R
12451332
WHERE B.bid IN $theset
12461333
AND R.rid = B.root
12471334
"]
12481335
}
1336
+
1337
+ # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
1338
+ typemethod loops {branches} {
1339
+ # Note: Revisions and tags cannot cause the loop. Being of a
1340
+ # fundamentally different type they cannot be in the incoming
1341
+ # set of ids.
1342
+
1343
+ set theset ('[join $branches {','}]')
1344
+ return [state run [subst -nocommands -nobackslashes {
1345
+ SELECT B.bid, BX.bid
1346
+ FROM branch B, preferedparent P, branch BX
1347
+ WHERE B.bid IN $theset
1348
+ AND B.sid = P.pid
1349
+ AND BX.sid = P.sid
1350
+ AND BX.bid IN $theset
1351
+ }]]
1352
+ }
12491353
12501354
# var(dv) = dict (item -> list (item)), item = list (type id)
12511355
typemethod successors {dv branches} {
12521356
upvar 1 $dv dependencies
12531357
# The first revision committed on a branch, and all branches
@@ -1259,29 +1363,29 @@
12591363
SELECT B.bid, R.rid
12601364
FROM branch B, revision R
12611365
WHERE B.bid IN $theset
12621366
AND B.first = R.rid
12631367
"] {
1264
- lappend dependencies([list sym::tag $bid]) [list rev $child]
1368
+ lappend dependencies([list sym::branch $bid]) [list rev $child]
12651369
}
12661370
foreach {bid child} [state run "
12671371
SELECT B.bid, BX.bid
12681372
FROM branch B, preferedparent P, branch BX
12691373
WHERE B.bid IN $theset
12701374
AND B.sid = P.pid
12711375
AND BX.sid = P.sid
12721376
"] {
1273
- lappend dependencies([list sym::tag $bid]) [list sym::branch $child]
1377
+ lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
12741378
}
12751379
foreach {bid child} [state run "
12761380
SELECT B.bid, T.tid
12771381
FROM branch B, preferedparent P, tag T
12781382
WHERE B.bid IN $theset
12791383
AND B.sid = P.pid
12801384
AND T.sid = P.sid
12811385
"] {
1282
- lappend dependencies([list sym::tag $bid]) [list sym::tag $child]
1386
+ lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
12831387
}
12841388
return
12851389
}
12861390
12871391
# var(dv) = dict (item -> list (item)), item = list (type id)
12881392
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -51,10 +51,11 @@
51 set mypos {} ; # Commit location is not known yet.
52
53 # Keep track of the generated changesets and of the inverse
54 # mapping from items to them.
55 lappend mychangesets $self
 
56 set myidmap($myid) $self
57 foreach iid $items {
58 set key [list $cstype $iid]
59 set myitemmap($key) $self
60 lappend mytitems $key
@@ -86,16 +87,43 @@
86 delegate method isbranch to mytypeobj
87 delegate method istag to mytypeobj
88
89 method setpos {p} { set mypos $p ; return }
90 method pos {} { return $mypos }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
92 # result = list (changeset)
93 method successors {} {
94 return [struct::list map \
95 [$mytypeobj cs_successors $myitems] \
96 [mytypemethod of]]
 
 
 
97 }
98
99 # result = dict (item -> list (changeset))
100 method successormap {} {
101 # NOTE / FUTURE: Definitive bottleneck (can be millions of pairs).
@@ -172,11 +200,11 @@
172 # one. The previous algorithm, adapted from cvs2svn, computed
173 # a lot of state which was thrown away and then computed again
174 # for each of the fragments. It should be easier to update and
175 # reuse that state.
176
177 # The code checks only sucessor dependencies, as this
178 # automatically covers the predecessor dependencies as well (A
179 # successor dependency a -> b is also a predecessor dependency
180 # b -> a).
181
182 # Array of dependencies (parent -> child). This is pulled from
@@ -356,52 +384,56 @@
356 method drop {} {
357 log write 8 csets {Dropping $self = [$self str]}
358
359 state transaction {
360 state run {
361 DELETE FROM changeset WHERE cid = $myid;
362 DELETE FROM csitem WHERE cid = $myid;
 
363 }
364 }
365 foreach iid $myitems {
366 set key [list $mytype $iid]
367 unset myitemmap($key)
368 log write 8 csets {MAP- item <$key> $self = [$self str]}
369 }
370 set pos [lsearch -exact $mychangesets $self]
371 set mychangesets [lreplace $mychangesets $pos $pos]
372 return
373 }
374
375 method loopcheck {} {
376 log write 7 csets {Checking [$self str] for loops /[llength $myitems]}
377
378 if {![struct::set contains [$self successors] $self]} {
379 return 0
380 }
381 if {[log verbosity?] < 8} { return 1 }
382
383 # Print the detailed successor structure of the self-
384 # referential changeset, if the verbosity of the log is dialed
385 # high enough.
386
387 log write 8 csets [set hdr {Self-referential changeset [$self str] __________________}]
388 array set nmap [$self nextmap]
389 foreach item [lsort -dict [array names nmap]] {
390 foreach succitem $nmap($item) {
391 set succcs $myitemmap($succitem)
392 set hint [expr {($succcs eq $self)
393 ? "LOOP"
394 : " "}]
395 set i "<$item [$type itemstr $item]>"
396 set s "<$succitem [$type itemstr $succitem]>"
397 set scs [$succcs str]
398 log write 8 csets {$hint * $i --> $s --> cs $scs}
399 }
400 }
401 log write 8 csets [regsub -all {[^ ]} $hdr {_}]
402 return 1
 
 
 
403 }
404
405 typemethod split {cset args} {
406 # As part of the creation of the new changesets specified in
407 # ARGS as sets of items, all subsets of CSET's item set, CSET
@@ -417,28 +449,32 @@
417
418 # All checks pass, actually perform the split.
419
420 struct::list assign [$cset data] project cstype cssrc
421
422 $cset drop
423 $cset destroy
424
425 set newcsets {}
426 foreach fragmentitems $args {
427 log write 8 csets {MAKE: [lsort $fragmentitems]}
428
429 set fragment [$type %AUTO% $project $cstype $cssrc \
430 [Untag $fragmentitems $cstype]]
431 lappend newcsets $fragment
 
432 $fragment persist
 
 
433
434 if {[$fragment loopcheck]} {
435 trouble fatal "[$fragment str] depends on itself"
436 }
 
 
437 }
438
439 trouble abort?
440 return $newcsets
441 }
442
443 typemethod itemstr {item} {
444 struct::list assign $item itype iid
@@ -560,10 +596,11 @@
560 return
561 }
562
563 typemethod loadcounter {} {
564 # Initialize the counter from the state
 
565 set mycounter [state one { SELECT MAX(cid) FROM changeset }]
566 return
567 }
568
569 typemethod num {} { return $mycounter }
@@ -778,22 +815,30 @@
778 return
779 }
780
781 # # ## ### ##### ######## #############
782
783 typevariable mychangesets {} ; # List of all known changesets.
784 typevariable myitemmap -array {} ; # Map from items (tagged) to
785 # the list of changesets
786 # containing it. Each item can
787 # be used by only one
788 # changeset.
 
 
 
789 typevariable myidmap -array {} ; # Map from changeset id to
790 # changeset.
791
792 typemethod all {} { return $mychangesets }
793 typemethod of {cid} { return $myidmap($cid) }
794 typemethod ofitem {iid} { return $myitemmap($iid) }
 
 
 
 
 
795
796 # # ## ### ##### ######## #############
797 ## Configuration
798
799 pragma -hastypeinfo no ; # no type introspection
@@ -924,10 +969,46 @@
924 }
925 }
926 }
927 return
928 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
930 # var(dv) = dict (item -> list (item)), item = list (type id)
931 typemethod successors {dv revisions} {
932 upvar 1 $dv dependencies
933 set theset ('[join $revisions {','}]')
@@ -986,19 +1067,19 @@
986 lappend dependencies([list rev $rid]) [list rev $child]
987 }
988 foreach {rid child} [state run "
989 SELECT R.rid, T.tid
990 FROM revision R, tag T
991 WHERE R.rid in $theset
992 AND T.rev = R.rid
993 "] {
994 lappend dependencies([list rev $rid]) [list sym::tag $child]
995 }
996 foreach {rid child} [state run "
997 SELECT R.rid, B.bid
998 FROM revision R, branch B
999 WHERE R.rid in $theset
1000 AND B.root = R.rid
1001 "] {
1002 lappend dependencies([list rev $rid]) [list sym::branch $child]
1003 }
1004 return
@@ -1159,10 +1240,16 @@
1159 # var(dv) = dict (item -> list (item)), item = list (type id)
1160 typemethod successors {dv tags} {
1161 # Tags have no successors.
1162 return
1163 }
 
 
 
 
 
 
1164
1165 # var(dv) = dict (item -> list (item)), item = list (type id)
1166 typemethod predecessors {dv tags} {
1167 upvar 1 $dv dependencies
1168 # The predecessors of a tag are all the revisions the tags are
@@ -1244,10 +1331,27 @@
1244 FROM branch B, revision R
1245 WHERE B.bid IN $theset
1246 AND R.rid = B.root
1247 "]
1248 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1249
1250 # var(dv) = dict (item -> list (item)), item = list (type id)
1251 typemethod successors {dv branches} {
1252 upvar 1 $dv dependencies
1253 # The first revision committed on a branch, and all branches
@@ -1259,29 +1363,29 @@
1259 SELECT B.bid, R.rid
1260 FROM branch B, revision R
1261 WHERE B.bid IN $theset
1262 AND B.first = R.rid
1263 "] {
1264 lappend dependencies([list sym::tag $bid]) [list rev $child]
1265 }
1266 foreach {bid child} [state run "
1267 SELECT B.bid, BX.bid
1268 FROM branch B, preferedparent P, branch BX
1269 WHERE B.bid IN $theset
1270 AND B.sid = P.pid
1271 AND BX.sid = P.sid
1272 "] {
1273 lappend dependencies([list sym::tag $bid]) [list sym::branch $child]
1274 }
1275 foreach {bid child} [state run "
1276 SELECT B.bid, T.tid
1277 FROM branch B, preferedparent P, tag T
1278 WHERE B.bid IN $theset
1279 AND B.sid = P.pid
1280 AND T.sid = P.sid
1281 "] {
1282 lappend dependencies([list sym::tag $bid]) [list sym::tag $child]
1283 }
1284 return
1285 }
1286
1287 # var(dv) = dict (item -> list (item)), item = list (type id)
1288
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -51,10 +51,11 @@
51 set mypos {} ; # Commit location is not known yet.
52
53 # Keep track of the generated changesets and of the inverse
54 # mapping from items to them.
55 lappend mychangesets $self
56 lappend mytchangesets($cstype) $self
57 set myidmap($myid) $self
58 foreach iid $items {
59 set key [list $cstype $iid]
60 set myitemmap($key) $self
61 lappend mytitems $key
@@ -86,16 +87,43 @@
87 delegate method isbranch to mytypeobj
88 delegate method istag to mytypeobj
89
90 method setpos {p} { set mypos $p ; return }
91 method pos {} { return $mypos }
92
93 method determinesuccessors {} {
94 # Pass 6 operation. Compute project-level dependencies from
95 # the file-level data and save it back to the state. This may
96 # be called during the cycle breaker passes as well, to adjust
97 # the successor information of changesets which are the
98 # predecessors of dropped changesets. For them we have to
99 # remove their existing information first before inserting the
100 # new data.
101 state run {
102 DELETE FROM cssuccessor WHERE cid = $myid;
103 }
104 set loop 0
105 foreach nid [$mytypeobj cs_successors $myitems] {
106 state run {
107 INSERT INTO cssuccessor (cid, nid)
108 VALUES ($myid,$nid)
109 }
110 if {$nid == $myid} { set loop 1 }
111 }
112 # Report after the complete structure has been saved.
113 if {$loop} { $self reportloop }
114 return
115 }
116
117 # result = list (changeset)
118 method successors {} {
119 # Use the data saved by pass 6.
120 return [struct::list map [state run {
121 SELECT S.nid
122 FROM cssuccessor S
123 WHERE S.cid = $myid
124 }] [mytypemethod of]]
125 }
126
127 # result = dict (item -> list (changeset))
128 method successormap {} {
129 # NOTE / FUTURE: Definitive bottleneck (can be millions of pairs).
@@ -172,11 +200,11 @@
200 # one. The previous algorithm, adapted from cvs2svn, computed
201 # a lot of state which was thrown away and then computed again
202 # for each of the fragments. It should be easier to update and
203 # reuse that state.
204
205 # The code checks only successor dependencies, as this
206 # automatically covers the predecessor dependencies as well (A
207 # successor dependency a -> b is also a predecessor dependency
208 # b -> a).
209
210 # Array of dependencies (parent -> child). This is pulled from
@@ -356,52 +384,56 @@
384 method drop {} {
385 log write 8 csets {Dropping $self = [$self str]}
386
387 state transaction {
388 state run {
389 DELETE FROM changeset WHERE cid = $myid;
390 DELETE FROM csitem WHERE cid = $myid;
391 DELETE FROM cssuccessor WHERE cid = $myid;
392 }
393 }
394 foreach iid $myitems {
395 set key [list $mytype $iid]
396 unset myitemmap($key)
397 log write 8 csets {MAP- item <$key> $self = [$self str]}
398 }
399 set pos [lsearch -exact $mychangesets $self]
400 set mychangesets [lreplace $mychangesets $pos $pos]
401 set pos [lsearch -exact $mytchangesets($mytype) $self]
402 set mytchangesets($mytype) [lreplace $mytchangesets($mytype) $pos $pos]
403
404 # Return the list of predecessors so that they can be adjusted.
405 return [struct::list map [state run {
406 SELECT cid
407 FROM cssuccessor
408 WHERE nid = $myid
409 }] [mytypemethod of]]
410 }
411
412 method reportloop {{kill 1}} {
413 # We print the items which are producing the loop, and how.
414
415 set hdr "Self-referential changeset [$self str] __________________"
416 set ftr [regsub -all {[^ ]} $hdr {_}]
417
418 log write 0 csets $hdr
419 foreach {item nextitem} [$mytypeobj loops $myitems] {
420 # Create tagged items from the id and our type.
421 set item [list $mytype $item]
422 set nextitem [list $mytype $nextitem]
423 # Printable labels.
424 set i "<[$type itemstr $item]>"
425 set n "<[$type itemstr $nextitem]>"
426 set ncs $myitemmap($nextitem)
427 # Print
428 log write 0 csets {* $i --> $n --> cs [$ncs str]}
429 }
430 log write 0 csets $ftr
431
432 if {!$kill} return
433 trouble internal "[$self str] depends on itself"
434 return
435 }
436
437 typemethod split {cset args} {
438 # As part of the creation of the new changesets specified in
439 # ARGS as sets of items, all subsets of CSET's item set, CSET
@@ -417,28 +449,32 @@
449
450 # All checks pass, actually perform the split.
451
452 struct::list assign [$cset data] project cstype cssrc
453
454 set predecessors [$cset drop]
455 $cset destroy
456
457 set newcsets {}
458 foreach fragmentitems $args {
459 log write 8 csets {MAKE: [lsort $fragmentitems]}
460
461 set fragment [$type %AUTO% $project $cstype $cssrc \
462 [Untag $fragmentitems $cstype]]
463 lappend newcsets $fragment
464
465 $fragment persist
466 $fragment determinesuccessors
467 }
468
469 # The predecessors have to recompute their successors, i.e.
470 # remove the dropped changeset and put one of the fragments
471 # into its place.
472 foreach p $predecessors {
473 $p determinesuccessors
474 }
475
 
476 return $newcsets
477 }
478
479 typemethod itemstr {item} {
480 struct::list assign $item itype iid
@@ -560,10 +596,11 @@
596 return
597 }
598
599 typemethod loadcounter {} {
600 # Initialize the counter from the state
601 log write 2 initcsets {Loading changeset counter}
602 set mycounter [state one { SELECT MAX(cid) FROM changeset }]
603 return
604 }
605
606 typemethod num {} { return $mycounter }
@@ -778,22 +815,30 @@
815 return
816 }
817
818 # # ## ### ##### ######## #############
819
820 typevariable mychangesets {} ; # List of all known
821 # changesets.
822 typevariable mytchangesets -array {} ; # List of all known
823 # changesets of a type.
824 typevariable myitemmap -array {} ; # Map from items (tagged)
825 # to the list of changesets
826 # containing it. Each item
827 # can be used by only one
828 # changeset.
829 typevariable myidmap -array {} ; # Map from changeset id to
830 # changeset.
831
832 typemethod all {} { return $mychangesets }
833 typemethod of {cid} { return $myidmap($cid) }
834 typemethod ofitem {iid} { return $myitemmap($iid) }
835
836 typemethod rev {} { return $mytchangesets(rev) }
837 typemethod sym {} { return [concat \
838 ${mytchangesets(sym::branch)} \
839 ${mytchangesets(sym::tag)}] }
840
841 # # ## ### ##### ######## #############
842 ## Configuration
843
844 pragma -hastypeinfo no ; # no type introspection
@@ -924,10 +969,46 @@
969 }
970 }
971 }
972 return
973 }
974
975 # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
976 typemethod loops {revisions} {
977 # Note: Tags and branches cannot cause the loop. Their id's,
978 # bein of a fundamentally different type than the revisions
979 # coming in cannot be in the set.
980
981 set theset ('[join $revisions {','}]')
982 return [state run [subst -nocommands -nobackslashes {
983 -- (1) Primary child
984 SELECT R.rid, R.child
985 FROM revision R
986 WHERE R.rid IN $theset -- Restrict to revisions of interest
987 AND R.child IS NOT NULL -- Has primary child
988 AND R.child IN $theset -- Loop
989 --
990 UNION
991 -- (2) Secondary (branch) children
992 SELECT R.rid, B.brid
993 FROM revision R, revisionbranchchildren B
994 WHERE R.rid IN $theset -- Restrict to revisions of interest
995 AND R.rid = B.rid -- Select subset of branch children
996 AND B.rid IN $theset -- Loop
997 --
998 UNION
999 -- (4) Child of trunk root successor of last NTDB on trunk.
1000 SELECT R.rid, RA.child
1001 FROM revision R, revision RA
1002 WHERE R.rid IN $theset -- Restrict to revisions of interest
1003 AND R.isdefault -- Restrict to NTDB
1004 AND R.dbchild IS NOT NULL -- and last NTDB belonging to trunk
1005 AND RA.rid = R.dbchild -- Go directly to trunk root
1006 AND RA.child IS NOT NULL -- Has primary child.
1007 AND RA.child IN $theset -- Loop
1008 }]]
1009 }
1010
1011 # var(dv) = dict (item -> list (item)), item = list (type id)
1012 typemethod successors {dv revisions} {
1013 upvar 1 $dv dependencies
1014 set theset ('[join $revisions {','}]')
@@ -986,19 +1067,19 @@
1067 lappend dependencies([list rev $rid]) [list rev $child]
1068 }
1069 foreach {rid child} [state run "
1070 SELECT R.rid, T.tid
1071 FROM revision R, tag T
1072 WHERE R.rid IN $theset
1073 AND T.rev = R.rid
1074 "] {
1075 lappend dependencies([list rev $rid]) [list sym::tag $child]
1076 }
1077 foreach {rid child} [state run "
1078 SELECT R.rid, B.bid
1079 FROM revision R, branch B
1080 WHERE R.rid IN $theset
1081 AND B.root = R.rid
1082 "] {
1083 lappend dependencies([list rev $rid]) [list sym::branch $child]
1084 }
1085 return
@@ -1159,10 +1240,16 @@
1240 # var(dv) = dict (item -> list (item)), item = list (type id)
1241 typemethod successors {dv tags} {
1242 # Tags have no successors.
1243 return
1244 }
1245
1246 # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
1247 typemethod loops {tags} {
1248 # Tags have no successors, therefore cannot cause loops
1249 return {}
1250 }
1251
1252 # var(dv) = dict (item -> list (item)), item = list (type id)
1253 typemethod predecessors {dv tags} {
1254 upvar 1 $dv dependencies
1255 # The predecessors of a tag are all the revisions the tags are
@@ -1244,10 +1331,27 @@
1331 FROM branch B, revision R
1332 WHERE B.bid IN $theset
1333 AND R.rid = B.root
1334 "]
1335 }
1336
1337 # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
1338 typemethod loops {branches} {
1339 # Note: Revisions and tags cannot cause the loop. Being of a
1340 # fundamentally different type they cannot be in the incoming
1341 # set of ids.
1342
1343 set theset ('[join $branches {','}]')
1344 return [state run [subst -nocommands -nobackslashes {
1345 SELECT B.bid, BX.bid
1346 FROM branch B, preferedparent P, branch BX
1347 WHERE B.bid IN $theset
1348 AND B.sid = P.pid
1349 AND BX.sid = P.sid
1350 AND BX.bid IN $theset
1351 }]]
1352 }
1353
1354 # var(dv) = dict (item -> list (item)), item = list (type id)
1355 typemethod successors {dv branches} {
1356 upvar 1 $dv dependencies
1357 # The first revision committed on a branch, and all branches
@@ -1259,29 +1363,29 @@
1363 SELECT B.bid, R.rid
1364 FROM branch B, revision R
1365 WHERE B.bid IN $theset
1366 AND B.first = R.rid
1367 "] {
1368 lappend dependencies([list sym::branch $bid]) [list rev $child]
1369 }
1370 foreach {bid child} [state run "
1371 SELECT B.bid, BX.bid
1372 FROM branch B, preferedparent P, branch BX
1373 WHERE B.bid IN $theset
1374 AND B.sid = P.pid
1375 AND BX.sid = P.sid
1376 "] {
1377 lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
1378 }
1379 foreach {bid child} [state run "
1380 SELECT B.bid, T.tid
1381 FROM branch B, preferedparent P, tag T
1382 WHERE B.bid IN $theset
1383 AND B.sid = P.pid
1384 AND T.sid = P.sid
1385 "] {
1386 lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
1387 }
1388 return
1389 }
1390
1391 # var(dv) = dict (item -> list (item)), item = list (type id)
1392
--- tools/cvs2fossil/lib/c2f_prtopsort.tcl
+++ tools/cvs2fossil/lib/c2f_prtopsort.tcl
@@ -8,11 +8,11 @@
88
# This software consists of voluntary contributions made by many
99
# individuals. For exact contribution history, see the revision
1010
# history and logs, available at http://fossil-scm.hwaci.com/fossil
1111
# # ## ### ##### ######## ############# #####################
1212
13
-## Pass VII. This pass goes over the set of revision based changesets
13
+## Pass VIII. This pass goes over the set of revision based changesets
1414
## and sorts them topologically. It assumes that there are no cycles
1515
## which could impede it, any having been broken by the previous pass,
1616
## and aborts if that condition doesn't hold.
1717
1818
# # ## ### ##### ######## ############# #####################
@@ -99,15 +99,14 @@
9999
100100
# # ## ### ##### ######## #############
101101
## Internal methods
102102
103103
proc Changesets {} {
104
- return [struct::list filter [project::rev all] [myproc IsByRevision]]
104
+ log write 2 breakscycle {Selecting the revision changesets}
105
+ return [project::rev rev]
105106
}
106107
107
- proc IsByRevision {cset} { $cset byrevision }
108
-
109108
proc SaveOrder {graph at cset} {
110109
::variable myatfmt
111110
::variable mycsfmt
112111
113112
set cid [$cset id]
114113
--- tools/cvs2fossil/lib/c2f_prtopsort.tcl
+++ tools/cvs2fossil/lib/c2f_prtopsort.tcl
@@ -8,11 +8,11 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass VII. This pass goes over the set of revision based changesets
14 ## and sorts them topologically. It assumes that there are no cycles
15 ## which could impede it, any having been broken by the previous pass,
16 ## and aborts if that condition doesn't hold.
17
18 # # ## ### ##### ######## ############# #####################
@@ -99,15 +99,14 @@
99
100 # # ## ### ##### ######## #############
101 ## Internal methods
102
103 proc Changesets {} {
104 return [struct::list filter [project::rev all] [myproc IsByRevision]]
 
105 }
106
107 proc IsByRevision {cset} { $cset byrevision }
108
109 proc SaveOrder {graph at cset} {
110 ::variable myatfmt
111 ::variable mycsfmt
112
113 set cid [$cset id]
114
--- tools/cvs2fossil/lib/c2f_prtopsort.tcl
+++ tools/cvs2fossil/lib/c2f_prtopsort.tcl
@@ -8,11 +8,11 @@
8 # This software consists of voluntary contributions made by many
9 # individuals. For exact contribution history, see the revision
10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
11 # # ## ### ##### ######## ############# #####################
12
13 ## Pass VIII. This pass goes over the set of revision based changesets
14 ## and sorts them topologically. It assumes that there are no cycles
15 ## which could impede it, any having been broken by the previous pass,
16 ## and aborts if that condition doesn't hold.
17
18 # # ## ### ##### ######## ############# #####################
@@ -99,15 +99,14 @@
99
100 # # ## ### ##### ######## #############
101 ## Internal methods
102
103 proc Changesets {} {
104 log write 2 breakscycle {Selecting the revision changesets}
105 return [project::rev rev]
106 }
107
 
 
108 proc SaveOrder {graph at cset} {
109 ::variable myatfmt
110 ::variable mycsfmt
111
112 set cid [$cset id]
113
--- tools/cvs2fossil/lib/cvs2fossil.tcl
+++ tools/cvs2fossil/lib/cvs2fossil.tcl
@@ -33,10 +33,11 @@
3333
# are not implemented by us. They are irrelevant due to our use
3434
# of a relational database proper for the persistent state,
3535
# allowing us to sort the data on the fly as we need it.
3636
3737
package require vc::fossil::import::cvs::pass::initcsets ; # Init'ialize C'hange'Sets
38
+package require vc::fossil::import::cvs::pass::csetdeps ; # C'hange'Set Dep'endencies
3839
package require vc::fossil::import::cvs::pass::breakrcycle ; # Break' R'evision Cycle's
3940
package require vc::fossil::import::cvs::pass::rtopsort ; # R'evision Top'ological Sort'
4041
package require vc::fossil::import::cvs::pass::breakscycle ; # Break' S'ymbol Cycle's
4142
package require vc::fossil::import::cvs::pass::breakacycle ; # Break' A'll Cycle's
4243
package require vc::fossil::import::cvs::pass::atopsort ; # A'll Top'ological Sort'
4344
--- tools/cvs2fossil/lib/cvs2fossil.tcl
+++ tools/cvs2fossil/lib/cvs2fossil.tcl
@@ -33,10 +33,11 @@
33 # are not implemented by us. They are irrelevant due to our use
34 # of a relational database proper for the persistent state,
35 # allowing us to sort the data on the fly as we need it.
36
37 package require vc::fossil::import::cvs::pass::initcsets ; # Init'ialize C'hange'Sets
 
38 package require vc::fossil::import::cvs::pass::breakrcycle ; # Break' R'evision Cycle's
39 package require vc::fossil::import::cvs::pass::rtopsort ; # R'evision Top'ological Sort'
40 package require vc::fossil::import::cvs::pass::breakscycle ; # Break' S'ymbol Cycle's
41 package require vc::fossil::import::cvs::pass::breakacycle ; # Break' A'll Cycle's
42 package require vc::fossil::import::cvs::pass::atopsort ; # A'll Top'ological Sort'
43
--- tools/cvs2fossil/lib/cvs2fossil.tcl
+++ tools/cvs2fossil/lib/cvs2fossil.tcl
@@ -33,10 +33,11 @@
33 # are not implemented by us. They are irrelevant due to our use
34 # of a relational database proper for the persistent state,
35 # allowing us to sort the data on the fly as we need it.
36
37 package require vc::fossil::import::cvs::pass::initcsets ; # Init'ialize C'hange'Sets
38 package require vc::fossil::import::cvs::pass::csetdeps ; # C'hange'Set Dep'endencies
39 package require vc::fossil::import::cvs::pass::breakrcycle ; # Break' R'evision Cycle's
40 package require vc::fossil::import::cvs::pass::rtopsort ; # R'evision Top'ological Sort'
41 package require vc::fossil::import::cvs::pass::breakscycle ; # Break' S'ymbol Cycle's
42 package require vc::fossil::import::cvs::pass::breakacycle ; # Break' A'll Cycle's
43 package require vc::fossil::import::cvs::pass::atopsort ; # A'll Top'ological Sort'
44
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -15,10 +15,11 @@
1515
package ifneeded vc::fossil::import::cvs::pass::collar 1.0 [list source [file join $dir c2f_pcollar.tcl]]
1616
package ifneeded vc::fossil::import::cvs::pass::collrev 1.0 [list source [file join $dir c2f_pcollrev.tcl]]
1717
package ifneeded vc::fossil::import::cvs::pass::collsym 1.0 [list source [file join $dir c2f_pcollsym.tcl]]
1818
package ifneeded vc::fossil::import::cvs::pass::filtersym 1.0 [list source [file join $dir c2f_pfiltersym.tcl]]
1919
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::csetdeps 1.0 [list source [file join $dir c2f_pcsetdeps.tcl]]
2021
package ifneeded vc::fossil::import::cvs::pass::breakrcycle 1.0 [list source [file join $dir c2f_pbreakrcycle.tcl]]
2122
package ifneeded vc::fossil::import::cvs::pass::rtopsort 1.0 [list source [file join $dir c2f_prtopsort.tcl]]
2223
package ifneeded vc::fossil::import::cvs::pass::breakscycle 1.0 [list source [file join $dir c2f_pbreakscycle.tcl]]
2324
package ifneeded vc::fossil::import::cvs::pass::breakacycle 1.0 [list source [file join $dir c2f_pbreakacycle.tcl]]
2425
package ifneeded vc::fossil::import::cvs::pass::atopsort 1.0 [list source [file join $dir c2f_patopsort.tcl]]
2526
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -15,10 +15,11 @@
15 package ifneeded vc::fossil::import::cvs::pass::collar 1.0 [list source [file join $dir c2f_pcollar.tcl]]
16 package ifneeded vc::fossil::import::cvs::pass::collrev 1.0 [list source [file join $dir c2f_pcollrev.tcl]]
17 package ifneeded vc::fossil::import::cvs::pass::collsym 1.0 [list source [file join $dir c2f_pcollsym.tcl]]
18 package ifneeded vc::fossil::import::cvs::pass::filtersym 1.0 [list source [file join $dir c2f_pfiltersym.tcl]]
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::pass::rtopsort 1.0 [list source [file join $dir c2f_prtopsort.tcl]]
22 package ifneeded vc::fossil::import::cvs::pass::breakscycle 1.0 [list source [file join $dir c2f_pbreakscycle.tcl]]
23 package ifneeded vc::fossil::import::cvs::pass::breakacycle 1.0 [list source [file join $dir c2f_pbreakacycle.tcl]]
24 package ifneeded vc::fossil::import::cvs::pass::atopsort 1.0 [list source [file join $dir c2f_patopsort.tcl]]
25
--- tools/cvs2fossil/lib/pkgIndex.tcl
+++ tools/cvs2fossil/lib/pkgIndex.tcl
@@ -15,10 +15,11 @@
15 package ifneeded vc::fossil::import::cvs::pass::collar 1.0 [list source [file join $dir c2f_pcollar.tcl]]
16 package ifneeded vc::fossil::import::cvs::pass::collrev 1.0 [list source [file join $dir c2f_pcollrev.tcl]]
17 package ifneeded vc::fossil::import::cvs::pass::collsym 1.0 [list source [file join $dir c2f_pcollsym.tcl]]
18 package ifneeded vc::fossil::import::cvs::pass::filtersym 1.0 [list source [file join $dir c2f_pfiltersym.tcl]]
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::csetdeps 1.0 [list source [file join $dir c2f_pcsetdeps.tcl]]
21 package ifneeded vc::fossil::import::cvs::pass::breakrcycle 1.0 [list source [file join $dir c2f_pbreakrcycle.tcl]]
22 package ifneeded vc::fossil::import::cvs::pass::rtopsort 1.0 [list source [file join $dir c2f_prtopsort.tcl]]
23 package ifneeded vc::fossil::import::cvs::pass::breakscycle 1.0 [list source [file join $dir c2f_pbreakscycle.tcl]]
24 package ifneeded vc::fossil::import::cvs::pass::breakacycle 1.0 [list source [file join $dir c2f_pbreakacycle.tcl]]
25 package ifneeded vc::fossil::import::cvs::pass::atopsort 1.0 [list source [file join $dir c2f_patopsort.tcl]]
26

Keyboard Shortcuts

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