Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Created convenience methods to create the human readable repesentation of a changeset and lists of such, and made liberal use of them. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | 87cf60902113c7564a2ae43de7ede9e8 |
User & Date: | aku 2007-11-24 05:31:30 |
Context
2007-11-25
| ||
02:51 | Tweaks of the log output, and reworked internals to expose not only breaking of cycles, but of paths as well. check-in: 54e9b0a1 user: aku tags: trunk | |
2007-11-24
| ||
05:31 | Created convenience methods to create the human readable repesentation of a changeset and lists of such, and made liberal use of them. check-in: 87cf6090 user: aku tags: trunk | |
04:40 | Bugfix in changeset class. Documented and fixed the SQL statements pulling the successor and predecessor information out of the state. It mishandled the Trunk <-> NTDB transitions. check-in: 184c5632 user: aku tags: trunk | |
Changes
Changes to tools/cvs2fossil/lib/c2f_cyclebreaker.tcl.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 ... 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 ... 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 ... 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 ... 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 ... 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
} set dg [struct::graph dg] foreach cset $changesets { $dg node insert $cset $dg node set $cset timerange [$cset timerange] $dg node set $cset label [ID $cset] $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. ................................................................................ # to be not possible, as pass 5 (InitCsets) takes care # to transform internal into external dependencies by # breaking the relevant changesets apart. So having # one indicates big trouble in pass 5. We report them # and dump internal structures to make it easier to # trace the links causing the problem. if {$succ eq $cset} { trouble fatal "Self-referencing changeset <[$cset id]>" log write 2 cyclebreaker "LOOP changeset <[$cset id]> __________________" array set nmap [$cset nextmap] foreach r [lsort -dict [array names nmap]] { foreach succrev $nmap($r) { log write 2 cyclebreaker \ "LOOP * rev <$r> --> rev <$succrev> --> cs [join [struct::list map [project::rev ofrev $succrev] [myproc ID]] { }]" } } } } } # Run the user hook to manipulate the graph before ................................................................................ if {[log verbosity?] < 10} return ::variable mybottom log write 10 cyclebreaker \ "Pending: [struct::list map $mybottom [myproc FormatPendingItem]]" return } proc FormatPendingItem {item} { lreplace $item 0 0 <[[lindex $item 0] id]> } proc FindCycle {dg} { # This procedure is run if and only the graph is not empty and # all nodes have predecessors. This means that each node is # either part of a cycle or (indirectly) depending on a node # in a cycle. We can start at an arbitrary node, follow its # incoming edges to its predecessors until we see a node a ................................................................................ # Choose arbitrary predecessor set start [lindex [$dg nodes -in $start] 0] } return [struct::list reverse [lrange $path $seen($start) end]] } proc ID {cset} { return "<[$cset id]>" } proc BreakCycle {dg cycle} { # The cycle we have gotten is broken by breaking apart one or # more of the changesets in the cycle. This causes us to # create one or more changesets which are to be committed, # added to the graph, etc. pp. # NOTE/TODO. Move this map operation to project::rev, as typemethod. set cprint [join [struct::list map $cycle [myproc ID]] { }] lappend cycle [lindex $cycle 0] [lindex $cycle 1] set bestlink {} set bestnode {} foreach \ prev [lrange $cycle 0 end-2] \ ................................................................................ set bestlink $link set bestnode $cset } else { $link destroy } } log write 5 cyclebreaker "Breaking cycle ($cprint) by splitting changeset <[$bestnode id]>" set ID [$bestnode id] Mark $dg -${ID}-before set newcsets [$bestlink break] $bestlink destroy # At this point the old changeset (BESTNODE) is gone ................................................................................ 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 [ID $cset] $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 $dg arc insert $cset $succ if {$succ eq $cset} { trouble internal "Self-referencing changeset <[$cset id]>" } } } foreach cset $pre { foreach succ [$cset successors] { # Note that the arc may already exist in the graph. If # so ignore it. The new changesets may have |
| | | | | < < | | | | |
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 ... 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 ... 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 ... 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 ... 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 ... 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
} 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. ................................................................................ # to be not possible, as pass 5 (InitCsets) takes care # to transform internal into external dependencies by # breaking the relevant changesets apart. So having # one indicates big trouble in pass 5. We report them # and dump internal structures to make it easier to # trace the links causing the problem. if {$succ eq $cset} { trouble fatal "Self-referencing changeset [$cset str]" log write 2 cyclebreaker "LOOP changeset [$cset str] __________________" array set nmap [$cset nextmap] foreach r [lsort -dict [array names nmap]] { foreach succrev $nmap($r) { 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 ................................................................................ if {[log verbosity?] < 10} return ::variable mybottom log write 10 cyclebreaker \ "Pending: [struct::list map $mybottom [myproc FormatPendingItem]]" return } proc FormatPendingItem {item} { lreplace $item 0 0 [[lindex $item 0] str] } proc FindCycle {dg} { # This procedure is run if and only the graph is not empty and # all nodes have predecessors. This means that each node is # either part of a cycle or (indirectly) depending on a node # in a cycle. We can start at an arbitrary node, follow its # incoming edges to its predecessors until we see a node a ................................................................................ # Choose arbitrary predecessor set start [lindex [$dg nodes -in $start] 0] } return [struct::list reverse [lrange $path $seen($start) end]] } proc BreakCycle {dg cycle} { # The cycle we have gotten is broken by breaking apart one or # more of the changesets in the cycle. This causes us to # create one or more changesets which are to be committed, # added to the graph, etc. pp. # NOTE/TODO. Move this map operation to project::rev, as typemethod. set cprint [project::rev strlist $cycle] lappend cycle [lindex $cycle 0] [lindex $cycle 1] set bestlink {} set bestnode {} foreach \ prev [lrange $cycle 0 end-2] \ ................................................................................ set bestlink $link set bestnode $cset } else { $link destroy } } log write 5 cyclebreaker "Breaking cycle ($cprint) by splitting changeset [$bestnode str]" set ID [$bestnode id] Mark $dg -${ID}-before set newcsets [$bestlink break] $bestlink destroy # At this point the old changeset (BESTNODE) is gone ................................................................................ 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 $dg arc insert $cset $succ if {$succ eq $cset} { trouble internal "Self-referencing changeset [$cset str]" } } } foreach cset $pre { foreach succ [$cset successors] { # Note that the arc may already exist in the graph. If # so ignore it. The new changesets may have |
Changes to tools/cvs2fossil/lib/c2f_pbreakacycle.tcl.
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
|
CheckAndBreakBackwardBranch $graph $cset } return } proc CheckAndBreakBackwardBranch {graph cset} { while {[IsABackwardBranch $graph $cset]} { log write 5 breakacycle "Breaking backward branch changeset <[$cset id]>" # Knowing that the branch is backward we now look at the # individual revisions 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 revisions, and of overlapping ones. Each # induces a new changeset, and the second may still be ................................................................................ if {![llength $backwardrevisions]} { trouble internal "Set of backward revisions is empty" } return } # # ## ### ##### ######## ############# proc SaveOrder {graph cset pos} { } # # ## ### ##### ######## ############# proc BreakCycle {graph} { cyclebreaker break $graph } |
|
|
>
>
>
>
>
>
>
>
>
|
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
CheckAndBreakBackwardBranch $graph $cset } return } proc CheckAndBreakBackwardBranch {graph cset} { while {[IsABackwardBranch $graph $cset]} { log write 5 breakacycle "Breaking backward branch changeset [$cset str]" # Knowing that the branch is backward we now look at the # individual revisions 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 revisions, and of overlapping ones. Each # induces a new changeset, and the second may still be ................................................................................ if {![llength $backwardrevisions]} { trouble internal "Set of backward revisions is empty" } return } # # ## ### ##### ######## ############# proc SaveOrder {graph at cset} { set cid [$cset id] log write 4 breakacycle "Comitting @ $at: [$cset str]" state run { INSERT INTO csorder (cid, pos) VALUES ($cid, $at) } # MAYBE TODO: Write the project level changeset dependencies as well. return } # # ## ### ##### ######## ############# proc BreakCycle {graph} { cyclebreaker break $graph } |
Changes to tools/cvs2fossil/lib/c2f_pbreakrcycle.tcl.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
}
proc IsByRevision {cset} { $cset byrevision }
proc SaveOrder {graph at cset} {
set cid [$cset id]
log write 4 breakrcycle "Comitting @ $at: <$cid>"
state run {
INSERT INTO csorder (cid, pos)
VALUES ($cid, $at)
}
# TODO: Write the project level changeset dependencies as well.
return
}
# # ## ### ##### ######## #############
## Configuration
pragma -hasinstances no ; # singleton
|
| | |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
} proc IsByRevision {cset} { $cset byrevision } proc SaveOrder {graph at cset} { set cid [$cset id] log write 4 breakrcycle "Comitting @ $at: [$cset str]" state run { INSERT INTO csorder (cid, pos) VALUES ($cid, $at) } # MAYBE TODO: Write the project level changeset dependencies as well. return } # # ## ### ##### ######## ############# ## Configuration pragma -hasinstances no ; # singleton |
Changes to tools/cvs2fossil/lib/c2f_prev.tcl.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 ... 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 ... 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 ... 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# mapping from revisions to them. lappend mychangesets $self set myidmap($myid) $self foreach r $revisions { lappend myrevmap($r) $self } return } method id {} { return $myid } method revisions {} { return $myrevisions } method data {} { return [list $myproject $mytype $mysrcid] } method bysymbol {} { return [expr {$mytype eq "sym"}] } method byrevision {} { return [expr {$mytype eq "rev"}] } ................................................................................ # Array of dependencies (parent -> child). This is pulled from # the state, and limited to successors within the changeset. array set dependencies {} PullInternalSuccessorRevisions dependencies $myrevisions if {![array size dependencies]} {return 0} ; # Nothing to break. log write 6 csets ...<$myid>....................................................... # We have internal dependencies to break. We now iterate over # all positions in the list (which is chronological, at least # as far as the timestamps are correct and unique) and # determine the best position for the break, by trying to # break as many dependencies as possible in one go. When a # break was found this is redone for the fragments coming and ................................................................................ Border $fragment s e if {$laste != ($s - 1)} { trouble internal "Bad fragment border <$laste | $s>, gap or overlap" } set new [$type %AUTO% $myproject $mytype $mysrcid [lrange $myrevisions $s $e]] log write 4 csets "Breaking <$myid> @ $laste, new <[$new id]>, cutting $breaks($laste)" set laste $e } if {$laste != ([llength $myrevisions]-1)} { trouble internal "Bad fragment end @ $laste, gap, or beyond end of the range" } ................................................................................ } lappend newcsets [$type %AUTO% $project $cstype $cssrc $fragmentrevisions] } foreach c $newcsets { $c persist } return $newcsets } # # ## ### ##### ######## ############# ## State variable myid {} ; # Id of the cset for the persistent # state. variable myproject {} ; # Reference of the project object the |
> > | | > > > > > > |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ... 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 ... 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 ... 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
# mapping from revisions to them. lappend mychangesets $self set myidmap($myid) $self foreach r $revisions { lappend myrevmap($r) $self } return } method str {} { return "<${myid}>" } method id {} { return $myid } method revisions {} { return $myrevisions } method data {} { return [list $myproject $mytype $mysrcid] } method bysymbol {} { return [expr {$mytype eq "sym"}] } method byrevision {} { return [expr {$mytype eq "rev"}] } ................................................................................ # Array of dependencies (parent -> child). This is pulled from # the state, and limited to successors within the changeset. array set dependencies {} PullInternalSuccessorRevisions dependencies $myrevisions if {![array size dependencies]} {return 0} ; # Nothing to break. log write 6 csets ...[$self str]....................................................... # We have internal dependencies to break. We now iterate over # all positions in the list (which is chronological, at least # as far as the timestamps are correct and unique) and # determine the best position for the break, by trying to # break as many dependencies as possible in one go. When a # break was found this is redone for the fragments coming and ................................................................................ Border $fragment s e if {$laste != ($s - 1)} { trouble internal "Bad fragment border <$laste | $s>, gap or overlap" } set new [$type %AUTO% $myproject $mytype $mysrcid [lrange $myrevisions $s $e]] log write 4 csets "Breaking [$self str ] @ $laste, new [$new str], cutting $breaks($laste)" set laste $e } if {$laste != ([llength $myrevisions]-1)} { trouble internal "Bad fragment end @ $laste, gap, or beyond end of the range" } ................................................................................ } lappend newcsets [$type %AUTO% $project $cstype $cssrc $fragmentrevisions] } foreach c $newcsets { $c persist } return $newcsets } typemethod strlist {changesets} { return [join [struct::list map $changesets [myproc ID]]] } proc ID {cset} { $cset str } # # ## ### ##### ######## ############# ## State variable myid {} ; # Id of the cset for the persistent # state. variable myproject {} ; # Reference of the project object the |
Changes to tools/cvs2fossil/lib/c2f_prevlink.tcl.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
if {$smove < $omove} { return 1 } ; # self is better. return 0 ; # Self is worse or equal, i.e. not better. } method break {} { if {![$self breakable]} { trouble internal "Changeset <[$mycset id]> is not breakable." } # One thing to choose when splitting CSET is where the # revision in categories 1 and 2 (none and passthrough # respectively) are moved to. This is done using the counters. if {!$mycount(prev)} { |
| |
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
if {$smove < $omove} { return 1 } ; # self is better.
return 0 ; # Self is worse or equal, i.e. not better.
}
method break {} {
if {![$self breakable]} {
trouble internal "Changeset [$mycset str] is not breakable."
}
# One thing to choose when splitting CSET is where the
# revision in categories 1 and 2 (none and passthrough
# respectively) are moved to. This is done using the counters.
if {!$mycount(prev)} {
|