@@ -17,11 +17,15 @@
17 17 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# # ## ### ##### ######## ############# #####################
18 18 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
## Requirements
19 19 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
20 20 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
package require Tcl 8.4 ; # Required runtime.
21 21 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
package require snit ; # OO system.
22 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ package require struct::graph ; # Graph handling.
23 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ package require struct::list ; # Higher order list operations.
22 24 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
package require vc::tools::log ; # User feedback.
25 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ package require vc::fossil::import::cvs::state ; # State storage.
26 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ package require vc::fossil::import::cvs::project::rev ; # Project level changesets
23 27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
24 28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# # ## ### ##### ######## ############# #####################
25 29 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
## Register the pass with the management
26 30 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
27 31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
vc::fossil::import::cvs::pass define \
@@ -37,10 +41,19 @@
37 41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
## Public API
38 42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
39 43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
typemethod setup {} {
40 44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# Define the names and structure of the persistent state of
41 45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# this pass.
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state writing csorder {
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ -- Commit order of changesets based on their dependencies
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cid INTEGER NOT NULL REFERENCES changeset,
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pos INTEGER NOT NULL,
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ UNIQUE (cid),
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ UNIQUE (pos)
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
42 55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return
43 56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
44 57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
45 58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
typemethod load {} {
46 59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# Pass manager interface. Executed to load data computed by
@@ -50,23 +63,187 @@
50 63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
51 64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
52 65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
typemethod run {} {
53 66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# Pass manager interface. Executed to perform the
54 67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# functionality of the pass.
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state reading revision
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # We create a graph of the revision changesets, using the file
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # level dependencies to construct a first approximation of
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # them at the project level. Then look for cycles in that
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # graph and break them.
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # 1. Create nodes for all relevant changesets and a mapping
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # from the revisions to their changesets/nodes.
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ log write 3 brkrcycle {Creating changeset graph, filling with nodes}
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set dg [struct::graph dg]
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state transaction {
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ foreach cset [project::rev all] {
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {[$cset bysymbol]} continue
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dg node insert $cset
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dg node set $cset timerange [$cset timerange]
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # 2. Find for all relevant changeset their revisions and their
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # dependencies. Map the latter back to changesets and
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # construct the corresponding arcs.
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ log write 3 brkrcycle {Setting up node dependencies}
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state transaction {
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ foreach cset [project::rev all] {
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {[$cset bysymbol]} continue
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ foreach succ [$cset successors] {
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ dg arc insert $cset $succ
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # 3. Lastly we iterate the graph topologically. We mark off
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # the nodes which have no predecessors, in order from
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # oldest to youngest, saving and removing dependencies. If
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # we find no nodes without predecessors we have a cycle,
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # and work on breaking it.
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ log write 3 brkrcycle {Computing changeset order, breaking cycles}
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ InitializeCandidates $dg
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state transaction {
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while {1} {
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while {[WithoutPredecessor $dg n]} {
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ SaveAndRemove $dg $n
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {![llength [dg nodes]]} break
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set cycle [FindCycle $dg]
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ BreakCycle $dg $cycle
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
55 126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return
56 127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
57 128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
58 129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
typemethod discard {} {
59 130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# Pass manager interface. Executed for all passes after the
60 131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# run passes, to remove all data of this pass from the state,
61 132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# as being out of date.
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state discard csorder
62 135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return
63 136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
64 137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
65 138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# # ## ### ##### ######## #############
66 139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
## Internal methods
67 140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Instead of searching the whole graph for the degree-0 nodes in
142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # each iteration we compute the list once to start, and then only
143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # update it incrementally based on the outgoing neighbours of the
144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # node chosen for commit.
145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ proc InitializeCandidates {dg} {
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # bottom = list (list (node, range min, range max))
148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ::variable bottom
149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ foreach n [$dg nodes] {
150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {[$dg node degree -in $n]} continue
151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ lappend bottom [linsert [$dg node get $n timerange] 0 $n]
152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set bottom [lsort -index 1 -integer [lsort -index 2 -integer $bottom]]
154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ proc WithoutPredecessor {dg nv} {
158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ::variable bottom
159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ upvar 1 $nv n
161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {![llength $bottom]} { return 0 }
162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set n [lindex [lindex $bottom 0] 0]
164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set bottom [lrange $bottom 1 end]
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set changed 0
166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Update list of nodes without predecessor, based on the
168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # outgoing neighbours of the chosen node. This should be
169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # faster than iterating of the whole set of nodes, finding all
170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # without predecessors, sorting them by time, etc. pp.
171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ foreach out [$dg nodes -out $n] {
172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {[$dg node degree -in $out] > 1} continue
173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Degree-1 neighbour, will have no predecessors after the
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # removal of n. Put on the list.
175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ lappend bottom [linsert [$dg node get $out timerange] 0 $out]
176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set changed 1
177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {$changed} {
179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set bottom [lsort -index 1 -integer [lsort -index 2 -integer $bottom]]
180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # We do not delete the node immediately, to allow the Save
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # procedure to save the dependencies as well (encoded in the
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # arcs).
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return 1
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ proc SaveAndRemove {dg n} {
189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ::variable at
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set cid [$n id]
191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ log write 4 breakrcycle "Comitting @ $at: <$cid>"
193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ state run {
194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ INSERT INTO csorder (cid, pos)
195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ VALUES ($cid, $at)
196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # TODO: Write the project level changeset dependencies as well.
198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ incr at
199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ $dg node delete $n
200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ proc FindCycle {dg} {
204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # This procedure is run if and only the graph is not empty and
205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # all nodes have predecessors. This means that each node is
206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # either part of a cycle or (indirectly) depending on a node
207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # in a cycle. We can start at an arbitrary node, follow its
208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # incoming edges to its predecessors until we see a node a
209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # second time. That node closes the cycle and the beginning is
210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # its first occurence. Note that we can choose an arbitrary
211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # predecessor of each node as well, we do not have to search.
212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # We record for each node the index of the first appearance in
214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # the path, making it easy at the end to cut the cycle from
215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # it.
216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Choose arbitrary node to start our search at.
218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set start [lindex [$dg nodes] 0]
219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Initialize state, path of seen nodes, and when seen.
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set path {}
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ array set seen {}
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while {1} {
225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Stop searching when we have seen the current node
226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # already, the circle has been closed.
227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if {[info exists seen($start)]} break
228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ lappend path $start
229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set seen($start) [llength $path]
230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ # Choose arbitrary predecessor
231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ set start [lindex [$dg nodes -in $start] 0]
232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return [struct::list reverse [lrange $path $seen($start) end]]
235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
237 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ proc BreakCycle {dg cycle} {
238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ trouble internal "Break cycle <$cycle>"
239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ typevariable at 0 ; # Counter for commit ids for the changesets.
243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ typevariable bottom {} ; # List of candidate nodes for committing.
244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
68 245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# # ## ### ##### ######## #############
69 246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
## Configuration
70 247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
71 248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pragma -hasinstances no ; # singleton
72 249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pragma -hastypeinfo no ; # no introspection
@@ -74,12 +251,16 @@
74 251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
75 252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
# # ## ### ##### ######## #############
76 253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
77 254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
78 255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
namespace eval ::vc::fossil::import::cvs::pass {
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- namespace export initcsets
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- namespace eval initcsets {
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespace export breakrcycle
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespace eval breakrcycle {
258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespace import ::vc::fossil::import::cvs::state
259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespace eval project {
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ namespace import ::vc::fossil::import::cvs::project::rev
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
81 262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
namespace import ::vc::tools::log
82 263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
log register brkrcycle
83 264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
84 265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
85 266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
86 267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!