Fossil

Check-in [97b4405e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Extended cycle breaker with debug facility allowing the user to watch the neighbourhood of specific changesets during the traversal. Extended label information, highlighting of the nodes of interest. Tweaked log output a bit.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 97b4405ecf7ef61e838044ffa5ea5a6754a3d20e
User & Date: aku 2007-11-25 07:35:30
Context
2007-11-25
07:37
Fixed log output for pass 10, and added missing command. check-in: 63052cb6 user: aku tags: trunk
07:35
Extended cycle breaker with debug facility allowing the user to watch the neighbourhood of specific changesets during the traversal. Extended label information, highlighting of the nodes of interest. Tweaked log output a bit. check-in: 97b4405e user: aku tags: trunk
07:32
State log output, moved to slightly higher verbosity level to allow them to be suppressed. check-in: 00e041dd user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to tools/cvs2fossil/lib/c2f_cyclebreaker.tcl.

51
52
53
54
55
56
57





58
59
60
61
62
63
64
..
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
...
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
189
190
191
...
207
208
209
210
211
212
213




214
215
216
217
218

219

220
221
222
223
224
225
226
...
393
394
395
396
397
398
399

400
401
402
403



404
405
406
407
408
409
410
...
473
474
475
476
477
478
479

























480
481
482
483
484
485
486
...
489
490
491
492
493
494
495


496
497
498
499
500
501
502

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

    typemethod dotsto {path} {
	::variable mydotdestination $path
	return
    }






    typemethod dot {label changesets} {
	::variable mydotprefix $label
	::variable mydotid     0

	set dg [Setup $changesets 0]
	Mark $dg
................................................................................
	#    and work on breaking it.

	log write 3 cyclebreaker {Traverse changesets}

	InitializeCandidates $dg
	while {1} {
	    while {[WithoutPredecessor $dg n]} {

		ProcessedHook $dg $n $myat
		$dg node delete $n
		incr myat
		ShowPendingNodes
	    }

	    if {![llength [dg nodes]]} break

	    BreakCycleHook       $dg
	    InitializeCandidates $dg

	}

	$dg destroy

	log write 3 cyclebreaker Done.
	ClearHooks

................................................................................
    }

    # # ## ### ##### ######## #############
    ## Internal methods

    proc Setup {changesets {log 1}} {
	if {$log} {
	    log write 3 cyclebreaker "Create changeset graph, [nsp [llength $changesets] node]"
	}

	set dg [struct::graph dg]

	foreach cset $changesets {

	    $dg node insert $cset
	    $dg node set    $cset timerange [$cset timerange]
	    $dg node set    $cset label     [$cset str]
	    $dg node set    $cset __id__    [$cset id]







	}

	# 2. Find for all relevant changeset their revisions and their
	#    dependencies. Map the latter back to changesets and
	#    construct the corresponding arcs.

	if {$log} {
	    log write 3 cyclebreaker {Setting up node dependencies}
	}

	foreach cset $changesets {
	    foreach succ [$cset successors] {
		# Changesets may have dependencies outside of the
		# chosen set. These are ignored
		if {![$dg node exists $succ]} continue
		$dg arc insert $cset $succ

................................................................................
			    log write 2 cyclebreaker \
				"LOOP * rev <$r> --> rev <$succrev> --> cs [project::rev strlist [project::rev ofrev $succrev]]"
			}
		    }
		}
	    }
	}





	# Run the user hook to manipulate the graph before
	# consummation.

	if {$log} { Mark $dg -start }

	PreHook $dg


	# This kills the application if loops (see above) were found.
	trouble abort?
	return  $dg
    }

    # Instead of searching the whole graph for the degree-0 nodes in
................................................................................
	# circles, leaving them in, unbroken.

	set pre [$dg nodes -in $n]

        $dg node delete $n

	foreach cset $replacements {

	    $dg node insert $cset
	    $dg node set    $cset timerange [$cset timerange]
	    $dg node set    $cset label     [$cset str]
	    $dg node set    $cset __id__    [$cset id]



	}

	foreach cset $replacements {
	    foreach succ [$cset successors] {
		# The new changesets may have dependencies outside of
		# the chosen set. These are ignored
		if {![$dg node exists $succ]} continue
................................................................................
	::variable myprecmd   {}
	::variable mysavecmd  {}
	::variable mybreakcmd {}
	return
    }

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


























    typevariable myat      0 ; # Counter for commit ids for the
			       # changesets.
    typevariable mybottom {} ; # List of the candidate nodes for
			       # committing.

    typevariable myprecmd   {} ; # Callback, change graph before walk.
................................................................................

    typevariable mydotdestination {} ; # Destination directory for the
				       # generated .dot files.
    typevariable mydotprefix      {} ; # Prefix for dot files when
				       # exporting the graphs.
    typevariable mydotid           0 ; # Counter for dot file name
				       # generation.



    # # ## ### ##### ######## #############
    ## Configuration

    pragma -hasinstances   no ; # singleton
    pragma -hastypeinfo    no ; # no introspection
    pragma -hastypedestroy no ; # immortal







>
>
>
>
>







 







>










>







 







|





>

|
|

>
>
>
>
>
>
>






<
<
<
<







 







>
>
>
>





>
|
>







 







>

|
|

>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195




196
197
198
199
200
201
202
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550

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

    typemethod dotsto {path} {
	::variable mydotdestination $path
	return
    }

    typemethod watch {id} {
	::variable mywatchids
	lappend mywatchids $id
    }

    typemethod dot {label changesets} {
	::variable mydotprefix $label
	::variable mydotid     0

	set dg [Setup $changesets 0]
	Mark $dg
................................................................................
	#    and work on breaking it.

	log write 3 cyclebreaker {Traverse changesets}

	InitializeCandidates $dg
	while {1} {
	    while {[WithoutPredecessor $dg n]} {
		MarkWatch $dg
		ProcessedHook $dg $n $myat
		$dg node delete $n
		incr myat
		ShowPendingNodes
	    }

	    if {![llength [dg nodes]]} break

	    BreakCycleHook       $dg
	    InitializeCandidates $dg
	    MarkWatch            $dg
	}

	$dg destroy

	log write 3 cyclebreaker Done.
	ClearHooks

................................................................................
    }

    # # ## ### ##### ######## #############
    ## Internal methods

    proc Setup {changesets {log 1}} {
	if {$log} {
	    log write 3 cyclebreaker "Creating graph of changesets"
	}

	set dg [struct::graph dg]

	foreach cset $changesets {
	    set tr [$cset timerange]
	    $dg node insert $cset
	    $dg node set    $cset timerange $tr
	    $dg node set    $cset label     "[$cset str]\\n[join [struct::list map $tr {::clock format}] "\\n"]"
	    $dg node set    $cset __id__    [$cset id]
	    $dg node set    $cset shape     [expr {[$cset bysymbol]
						   ? "ellipse"
						   : "box"}]
	}

	if {$log} {
	    log write 3 cyclebreaker "Has [nsp [llength $changesets] changeset]"
	}

	# 2. Find for all relevant changeset their revisions and their
	#    dependencies. Map the latter back to changesets and
	#    construct the corresponding arcs.





	foreach cset $changesets {
	    foreach succ [$cset successors] {
		# Changesets may have dependencies outside of the
		# chosen set. These are ignored
		if {![$dg node exists $succ]} continue
		$dg arc insert $cset $succ

................................................................................
			    log write 2 cyclebreaker \
				"LOOP * rev <$r> --> rev <$succrev> --> cs [project::rev strlist [project::rev ofrev $succrev]]"
			}
		    }
		}
	    }
	}

	if {$log} {
	    log write 3 cyclebreaker "Has [nsp [llength [$dg arcs]] dependency dependencies]"
	}

	# Run the user hook to manipulate the graph before
	# consummation.

	if {$log} { Mark $dg -start }
	MarkWatch $dg
	PreHook   $dg
	MarkWatch $dg

	# This kills the application if loops (see above) were found.
	trouble abort?
	return  $dg
    }

    # Instead of searching the whole graph for the degree-0 nodes in
................................................................................
	# circles, leaving them in, unbroken.

	set pre [$dg nodes -in $n]

        $dg node delete $n

	foreach cset $replacements {
	    set tr [$cset timerange]
	    $dg node insert $cset
	    $dg node set    $cset timerange $tr
	    $dg node set    $cset label     "[$cset str]\\n[join [struct::list map $tr {::clock format}] "\\n"]"
	    $dg node set    $cset __id__    [$cset id]
	    $dg node set    $cset shape     [expr {[$cset bysymbol]
						   ? "ellipse"
						   : "box"}]
	}

	foreach cset $replacements {
	    foreach succ [$cset successors] {
		# The new changesets may have dependencies outside of
		# the chosen set. These are ignored
		if {![$dg node exists $succ]} continue
................................................................................
	::variable myprecmd   {}
	::variable mysavecmd  {}
	::variable mybreakcmd {}
	return
    }

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

    proc MarkWatch {graph} {
	::variable mywatchids
	set watched [Watched $graph $mywatchids]
	if {![llength $watched]} return
	set neighbours [eval [linsert $watched 0 $graph nodes -adj]]
	#foreach n $neighbours { log write 6 cyclebreaker "Neighbor [$n id] => $n" }
	Mark $graph watched [concat $watched $neighbours]
	return
    }

    proc Watched {graph watchids} {
	set res {}
	foreach id $watchids {
	    set nl [$graph nodes -key __id__ -value $id]
	    if {![llength $nl]} continue
	    lappend res $nl
	    #log write 6 breakrcycle "Watching $id => $nl"
	    $graph node set $nl fontcolor red
	}
	return $res
    }

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


    typevariable myat      0 ; # Counter for commit ids for the
			       # changesets.
    typevariable mybottom {} ; # List of the candidate nodes for
			       # committing.

    typevariable myprecmd   {} ; # Callback, change graph before walk.
................................................................................

    typevariable mydotdestination {} ; # Destination directory for the
				       # generated .dot files.
    typevariable mydotprefix      {} ; # Prefix for dot files when
				       # exporting the graphs.
    typevariable mydotid           0 ; # Counter for dot file name
				       # generation.
    typevariable mywatchids       {} ; # Changesets to watch the
				       # neighbourhood of.

    # # ## ### ##### ######## #############
    ## Configuration

    pragma -hasinstances   no ; # singleton
    pragma -hastypeinfo    no ; # no introspection
    pragma -hastypedestroy no ; # immortal

Changes to tools/cvs2fossil/lib/c2f_option.tcl.

77
78
79
80
81
82
83

84
85
86
87
88
89
90
		--state                     { state use [Value arguments] }
		--trunk-only                { repository trunkonly! }
		--exclude                   { project::sym exclude     [Value arguments] }
		--force-tag                 { project::sym forcetag    [Value arguments] }
		--force-branch              { project::sym forcebranch [Value arguments] }
		--batch                     { log noprogress }
		--dots                      { cyclebreaker dotsto [Value arguments] }

		default {
		    Usage $badoption$option\n$gethelp
		}
	    }
	}

	if {[llength $arguments] > 1} Usage







>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
		--state                     { state use [Value arguments] }
		--trunk-only                { repository trunkonly! }
		--exclude                   { project::sym exclude     [Value arguments] }
		--force-tag                 { project::sym forcetag    [Value arguments] }
		--force-branch              { project::sym forcebranch [Value arguments] }
		--batch                     { log noprogress }
		--dots                      { cyclebreaker dotsto [Value arguments] }
		--watch                     { cyclebreaker watch  [Value arguments] }
		default {
		    Usage $badoption$option\n$gethelp
		}
	    }
	}

	if {[llength $arguments] > 1} Usage