Fossil

Diff
Login

Differences From Artifact [7e073778fc]:

To Artifact [4af9517982]:


105
106
107
108
109
110
111



112
113

114
115
116
117

118
119
120
121
122
123
124
	return [project::rev all]
    }

    proc LoadCommitOrder {} {
	::variable mycset
	::variable myrevisionchangesets




	state transaction {
	    foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {

		set cset [project::rev of $cid]
		$cset setpos $pos
		set mycset($pos) $cset
		lappend myrevisionchangesets $cset

	    }
	}
	return
    }

    # # ## ### ##### ######## #############








>
>
>


>




>







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	return [project::rev all]
    }

    proc LoadCommitOrder {} {
	::variable mycset
	::variable myrevisionchangesets

	log write 2 breakacycle {Loading revision commit order}

	set n 0
	state transaction {
	    foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
		log progress 2 breakacycle $n
		set cset [project::rev of $cid]
		$cset setpos $pos
		set mycset($pos) $cset
		lappend myrevisionchangesets $cset
		incr n
	    }
	}
	return
    }

    # # ## ### ##### ######## #############

147
148
149
150
151
152
153
154
155
156
157
158



159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	    # look at the individual branches in the changeset and
	    # determine which of them are responsible for the
	    # overlap. This allows us to split them into two sets, one
	    # of non-overlapping branches, and of overlapping
	    # ones. Each set induces a new changeset, and the second
	    # one may still be backward and in need of further
	    # splitting. Hence the looping.
	    #
	    # The border used for the split is the minimal commit
	    # position among the minimal sucessor commit positions for
	    # the branches in the changeset.




	    # Note that individual branches may not have changesets
	    # which are their predecessors and/or successors, leaving
	    # the limits partially or completely undefined.


	    # limits : dict (revision -> list (max predecessor commit, min sucessor commit))

	    ComputeLimits $cset limits border

	    log write 5 breakacycle "Breaking backward changeset [$cset str] with commit position $border as border"

	    # Secondly we sort the file level items based on there
	    # they sit relative to the border into before and after
	    # the border.

	    SplitItems $limits $border normalitems backwarditems

	    set replacements [project::rev split $cset $normalitems $backwarditems]
	    cyclebreaker replace $graph $cset $replacements

	    # At last check that the normal frament is indeed not
	    # backward, and iterate over the possibly still backward
	    # second fragment.

	    struct::list assign $replacements normal backward
	    integrity assert {
		![IsBackward $graph $normal]
	    } {The normal fragment is unexpectedly backward}







|


|
|
>
>
>
|
<
<
>





|
<
<
<
<






|







152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167


168
169
170
171
172
173
174




175
176
177
178
179
180
181
182
183
184
185
186
187
188
	    # look at the individual branches in the changeset and
	    # determine which of them are responsible for the
	    # overlap. This allows us to split them into two sets, one
	    # of non-overlapping branches, and of overlapping
	    # ones. Each set induces a new changeset, and the second
	    # one may still be backward and in need of further
	    # splitting. Hence the looping.

	    # The border used for the split is the minimal commit
	    # position among the minimal sucessor commit positions for
	    # the branches in the changeset.  We sort the file level
	    # items based on there they sit relative to the border
	    # into before and after the border. As the branches cannot
	    # be backward at file level thos before the border cannot
	    # generate a backward symbol changeset, however the
	    # branches after may constitute another backward branch


	    # with a new border.

	    # limits : dict (revision -> list (max predecessor commit, min sucessor commit))

	    ComputeLimits $cset limits border

	    log write 5 breakacycle "Breaking backward changeset [$cset str] using commit position $border as border"





	    SplitItems $limits $border normalitems backwarditems

	    set replacements [project::rev split $cset $normalitems $backwarditems]
	    cyclebreaker replace $graph $cset $replacements

	    # At last we check that the normal frament is indeed not
	    # backward, and iterate over the possibly still backward
	    # second fragment.

	    struct::list assign $replacements normal backward
	    integrity assert {
		![IsBackward $graph $normal]
	    } {The normal fragment is unexpectedly backward}
231
232
233
234
235
236
237



238

239
240

241
242

243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

267

268
269
270
271
272
273
274
275
276







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

    proc ToPosition    {cset} { $cset pos }
    proc ValidPosition {pos}  { expr {$pos ne ""} }

    proc ComputeLimits {cset lv bv} {
	upvar 1 $lv thelimits $bv border




	# Initialize the boundaries for all items.


	array set limits {}

	foreach revision [$cset items] {
	    set limits($revision) {0 {}}

	}

	# Compute and store the maximal predecessors per item (branch)

	foreach {item csets} [$cset predecessormap] {

	    set s [Positions $csets]
	    if {![llength $s]} continue
	    set limits($item) [lreplace $limits($item) 0 0 [max $s]]
	}

	# Compute and store the minimal successors per item (branch)

	foreach {item csets} [$cset successormap] {
	    set s [Positions $csets]
	    if {![llength $s]} continue
	    set limits($item) [lreplace $limits($item) 1 1 [min $s]]
	}

	# Check that the ordering at the file level is correct. We
	# cannot have backward ordering per branch, or something is
	# wrong.

	foreach item [array names limits] {
	    struct::list assign $limits($item) maxp mins

	    # Handle min successor position "" as representing infinity

	    integrity assert {
		($mins eq "") || ($maxp < $mins) 
	    } {Item <$item> is backward at file level ($maxp >= $mins)}
	}

	# Save the limits for the splitter, and compute the border at
	# which to split as the minimum of all minimal successor
	# positions.








	set thelimits [array get limits]
	set border [min [struct::list filter [struct::list map [Values $thelimits] \
						  [myproc MinSuccessorPosition]] \
			     [myproc ValidPosition]]]
	return
    }

    proc Values {dict} {
	set res {}
	foreach {k v} $dict { lappend res $v }
	return $res
    }

    proc MinSuccessorPosition {item} { lindex $item 1 }

    proc SplitItems {limits border nv bv} {
	upvar 1 $nv normalitems $bv backwarditems

	set normalitems   {}
	set backwarditems {}

	foreach {rev v} $limits {
	    struct::list assign $v maxp mins
	    if {$maxp >= $border} {
		lappend backwarditems  $rev
	    } else {
		lappend normalitems $rev
	    }
	}

	integrity assert {[llength $normalitems]}   {Set of normal items is empty}
	integrity assert {[llength $backwarditems]} {Set of backward items is empty}
	return
    }


    # # ## ### ##### ######## #############

    proc KeepOrder {graph at cset} {
	::variable myatfmt
	::variable mycsfmt








>
>
>
|
>

|
>
|
|
>


<
|
<
>
|
<
<
|
|
<

|
|
<
<
|
<





|
>
|
>









>
>
>
>
>
>
>
|
<
<
<









<
<






|
<

|

|







<







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254

255
256


257
258

259
260
261


262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288



289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322

    proc ToPosition    {cset} { $cset pos }
    proc ValidPosition {pos}  { expr {$pos ne ""} }

    proc ComputeLimits {cset lv bv} {
	upvar 1 $lv thelimits $bv border

	# Individual branches may not have revision changesets which
	# are their predecessors and/or successors, leaving the limits
	# partially or completely undefined. To overcome this
	# initialize boundaries for all items with proper defaults (-1
	# for max, {} for min, representing +infinity).

	array set maxpa {}
	array set minsa {}
	foreach item [$cset items] {
	    set maxpa($item) -1
	    set minsa($item) {}
	}


	# Get the limits from the database, for the items which

	# actually have such, and merge the information with the
	# defaults.



	struct::list assign [$cset limits] maxpdict minsdict


	array set maxpa $maxpdict
	array set minsa $minsdict




	# Check that the ordering at the file level is correct. We
	# cannot have backward ordering per branch, or something is
	# wrong.

	foreach item [array names limits] {
	    set mins $minsa($item)
	    set maxp $maxp($item)
	    # Note that for the min successor position "" represents
	    # +infinity
	    integrity assert {
		($mins eq "") || ($maxp < $mins) 
	    } {Item <$item> is backward at file level ($maxp >= $mins)}
	}

	# Save the limits for the splitter, and compute the border at
	# which to split as the minimum of all minimal successor
	# positions.

	# Compute the border at which to split as the minimum of all
	# minimal successor positions. By using the database info we
	# automatically/implicitly filter out anything without a min
	# successor. Further the data going into the comparison with
	# the border is put together.

	set border    [min [Values $minsdict]]
	set thelimits [array get maxpa]



	return
    }

    proc Values {dict} {
	set res {}
	foreach {k v} $dict { lappend res $v }
	return $res
    }



    proc SplitItems {limits border nv bv} {
	upvar 1 $nv normalitems $bv backwarditems

	set normalitems   {}
	set backwarditems {}

	foreach {item maxp} $limits {

	    if {$maxp >= $border} {
		lappend backwarditems $item
	    } else {
		lappend normalitems   $item
	    }
	}

	integrity assert {[llength $normalitems]}   {Set of normal items is empty}
	integrity assert {[llength $backwarditems]} {Set of backward items is empty}
	return
    }


    # # ## ### ##### ######## #############

    proc KeepOrder {graph at cset} {
	::variable myatfmt
	::variable mycsfmt