Fossil SCM
Reworked the code determining the parent of the currently committed changeset. It should now handle the transition from vendor branch to trunk correctly.
Commit
e8efbc317a008a6c94465099784ac1213a5174eb
Parent
e5ae612c8d41412…
1 file changed
+97
-48
+97
-48
| --- tools/cvs2fossil/lib/c2f_prev.tcl | ||
| +++ tools/cvs2fossil/lib/c2f_prev.tcl | ||
| @@ -400,20 +400,21 @@ | ||
| 400 | 400 | # - Commit message (-- mysrcid -> repository meta) |
| 401 | 401 | # - User doing the commit (s.a.) |
| 402 | 402 | # |
| 403 | 403 | # - Timestamp of when committed (command argument) |
| 404 | 404 | # |
| 405 | - # - The parent changeset, if any. If there is no parent use | |
| 406 | - # the empty base revision as parent. | |
| 405 | + # - The parent changeset, if any. If there is no parent fossil | |
| 406 | + # will use the empty base revision as parent. | |
| 407 | 407 | # |
| 408 | 408 | # - List of the file revisions in the changeset. |
| 409 | 409 | |
| 410 | 410 | struct::list assign [$myproject getmeta $mysrcid] __ branch user message |
| 411 | 411 | struct::list assign $branch __ lodname |
| 412 | 412 | |
| 413 | - # Perform the import. As part of that convert the list of | |
| 414 | - # items in the changeset into uuids and printable data. | |
| 413 | + # Perform the import. As part of that we determine the parent | |
| 414 | + # we need, and convert the list of items in the changeset into | |
| 415 | + # uuids and printable data. | |
| 415 | 416 | |
| 416 | 417 | set uuid [Updatestate state $lodname \ |
| 417 | 418 | [$repository importrevision [$self str] \ |
| 418 | 419 | $user $message $date \ |
| 419 | 420 | [Getparent state $lodname $myproject] \ |
| @@ -444,54 +445,102 @@ | ||
| 444 | 445 | } |
| 445 | 446 | |
| 446 | 447 | proc Getparent {sv lodname project} { |
| 447 | 448 | upvar 1 $sv state |
| 448 | 449 | |
| 449 | - # The parent is determined via the line-of-development (LOD) | |
| 450 | - # information of each changeset, and the history of | |
| 451 | - # imports. The last changeset committed to the same LOD is | |
| 452 | - # taken as the parent of the current changeset. If the | |
| 453 | - # changeset is the first on that LOD it can be either spawned | |
| 454 | - # from another LOD, or detached. For the first case we | |
| 455 | - # retrieve the parent LOD of the current LOD symbol (*) and | |
| 456 | - # recheck for a committed changeset. The second case is taken | |
| 457 | - # if that lookup fails as well. | |
| 458 | - # | |
| 459 | - # (*) And this parent was found in previous passes when | |
| 460 | - # determining the prefered parents of all the symbols. | |
| 461 | - | |
| 462 | - # NOTE: The above is incomplete and buggy. Vendor-branches and | |
| 463 | - # the various possibilities of its interaction with the | |
| 464 | - # trunk are not fully handled. | |
| 465 | - | |
| 466 | - if {[info exists state($lodname)]} { | |
| 467 | - # LOD exists and has already been committed to. | |
| 468 | - return $state($lodname) | |
| 469 | - } | |
| 470 | - | |
| 471 | - # LOD has not been committed to before, this is the first | |
| 472 | - # time. Determine the name of the parent LOD. | |
| 473 | - | |
| 474 | - set lodname [[[$project getsymbol $lodname] parent] name] | |
| 475 | - | |
| 476 | - if {[info exists state($lodname)]} { | |
| 477 | - # The parental LOD has been committed to, take that last | |
| 478 | - # changeset as the spawnpoint for the new LOD. | |
| 479 | - return $state($lodname) | |
| 480 | - } | |
| 481 | - | |
| 482 | - # The parental LOD is not defined (yet). This LOD is | |
| 483 | - # detached. We choose as our parent the automatic empty root | |
| 484 | - # baseline of the target repository. | |
| 485 | - return {} | |
| 486 | - } | |
| 487 | - | |
| 488 | - proc Updatestate {sv lodname uuid} { | |
| 489 | - # Remember the imported changeset in the state, under our LOD. | |
| 490 | - | |
| 491 | - upvar 1 $sv state | |
| 492 | - set state($lodname) $uuid | |
| 450 | + struct::list assign [Getisdefault $myitems] isdefault lastdefaultontrunk | |
| 451 | + | |
| 452 | + # See (a) below, we have to remember if the changeset is last | |
| 453 | + # on vendor branch also belonging to trunk even if we find a | |
| 454 | + # parent in the state. The caller will later (after import) | |
| 455 | + # make us the first trunk changeset in the state (See (**)). | |
| 456 | + | |
| 457 | + if {$lastdefaultontrunk} { | |
| 458 | + set state(:vendor:last:) . | |
| 459 | + } | |
| 460 | + | |
| 461 | + # The state array holds for each line-of-development (LOD) the | |
| 462 | + # last committed changeset belonging to that LOD. | |
| 463 | + | |
| 464 | + # (*) Standard handling if in-LOD changesets. If the LOD of | |
| 465 | + # the current changeset exists in the state (= has been | |
| 466 | + # committed to) then the stored changeset is the parent we | |
| 467 | + # are looking for. | |
| 468 | + | |
| 469 | + if {[info exists state($lodname)]} { | |
| 470 | + return $state($lodname) | |
| 471 | + } | |
| 472 | + | |
| 473 | + # If the LOD is not yet known the current changeset can either | |
| 474 | + # be | |
| 475 | + # (a) the root of a vendor branch, | |
| 476 | + # (b) the root of the trunk LOD, or | |
| 477 | + # (c) the first changeset in a new LOD which was spawned from | |
| 478 | + # an existing LOD. | |
| 479 | + | |
| 480 | + if {$isdefault} { | |
| 481 | + # In case of (a) the changeset has no parent, signaled by | |
| 482 | + # the empty string. We do remember if the changeset is | |
| 483 | + # last on the vendor branch still belonging to trunk, for | |
| 484 | + # the trunk root. | |
| 485 | + return {} | |
| 486 | + } | |
| 487 | + | |
| 488 | + if {$lodname eq ":trunk:"} { | |
| 489 | + # This is case (b), and we also can be sure that there is | |
| 490 | + # no vendor branch changeset which could be our | |
| 491 | + # parent. That was already dealt with through the | |
| 492 | + # :vendor:last: signal and code in the caller (setting | |
| 493 | + # such a changeset up as parent in the state, causing the | |
| 494 | + # standard LOD handler at (*) to kick in. So, no parent | |
| 495 | + # here at all. | |
| 496 | + return {} | |
| 497 | + } | |
| 498 | + | |
| 499 | + # Case (c). We find the parent LOD of our LOD and take the | |
| 500 | + # last changeset committed to that as our parent. If that | |
| 501 | + # doesn't exist we have an error on our hands. | |
| 502 | + | |
| 503 | + set lodname [[[$project getsymbol $lodname] parent] name] | |
| 504 | + if {[info exists state($lodname)]} { | |
| 505 | + return $state($lodname) | |
| 506 | + } | |
| 507 | + | |
| 508 | + trouble internal {Unable to determine changeset parent} | |
| 509 | + return | |
| 510 | + } | |
| 511 | + | |
| 512 | + proc Getisdefault {revisions} { | |
| 513 | + set theset ('[join $revisions {','}]') | |
| 514 | + | |
| 515 | + struct::list assign [state run [subst -nocommands -nobackslashes { | |
| 516 | + SELECT R.isdefault, R.dbchild | |
| 517 | + FROM revision R | |
| 518 | + WHERE R.rid IN $theset -- All specified revisions | |
| 519 | + LIMIT 1 | |
| 520 | + }]] def last | |
| 521 | + | |
| 522 | + # TODO/CHECK: look for changesets where isdefault/dbchild is | |
| 523 | + # ambigous. | |
| 524 | + | |
| 525 | + return [list $def [expr {$last ne ""}]] | |
| 526 | + } | |
| 527 | + | |
| 528 | + proc Updatestate {sv lodname uuid} { | |
| 529 | + upvar 1 $sv state | |
| 530 | + | |
| 531 | + # Remember the imported changeset in the state, under our | |
| 532 | + # LOD. (**) And if the :vendor:last: signal is present then | |
| 533 | + # the revision is also the actual root of the :trunk:, so | |
| 534 | + # remember it as such. | |
| 535 | + | |
| 536 | + set state($lodname) $uuid | |
| 537 | + if {[info exists state(:vendor:last:)]} { | |
| 538 | + unset state(:vendor:last:) | |
| 539 | + set state(:trunk:) $uuid | |
| 540 | + } | |
| 541 | + | |
| 493 | 542 | return $uuid |
| 494 | 543 | } |
| 495 | 544 | |
| 496 | 545 | typemethod split {cset args} { |
| 497 | 546 | # As part of the creation of the new changesets specified in |
| 498 | 547 |
| --- tools/cvs2fossil/lib/c2f_prev.tcl | |
| +++ tools/cvs2fossil/lib/c2f_prev.tcl | |
| @@ -400,20 +400,21 @@ | |
| 400 | # - Commit message (-- mysrcid -> repository meta) |
| 401 | # - User doing the commit (s.a.) |
| 402 | # |
| 403 | # - Timestamp of when committed (command argument) |
| 404 | # |
| 405 | # - The parent changeset, if any. If there is no parent use |
| 406 | # the empty base revision as parent. |
| 407 | # |
| 408 | # - List of the file revisions in the changeset. |
| 409 | |
| 410 | struct::list assign [$myproject getmeta $mysrcid] __ branch user message |
| 411 | struct::list assign $branch __ lodname |
| 412 | |
| 413 | # Perform the import. As part of that convert the list of |
| 414 | # items in the changeset into uuids and printable data. |
| 415 | |
| 416 | set uuid [Updatestate state $lodname \ |
| 417 | [$repository importrevision [$self str] \ |
| 418 | $user $message $date \ |
| 419 | [Getparent state $lodname $myproject] \ |
| @@ -444,54 +445,102 @@ | |
| 444 | } |
| 445 | |
| 446 | proc Getparent {sv lodname project} { |
| 447 | upvar 1 $sv state |
| 448 | |
| 449 | # The parent is determined via the line-of-development (LOD) |
| 450 | # information of each changeset, and the history of |
| 451 | # imports. The last changeset committed to the same LOD is |
| 452 | # taken as the parent of the current changeset. If the |
| 453 | # changeset is the first on that LOD it can be either spawned |
| 454 | # from another LOD, or detached. For the first case we |
| 455 | # retrieve the parent LOD of the current LOD symbol (*) and |
| 456 | # recheck for a committed changeset. The second case is taken |
| 457 | # if that lookup fails as well. |
| 458 | # |
| 459 | # (*) And this parent was found in previous passes when |
| 460 | # determining the prefered parents of all the symbols. |
| 461 | |
| 462 | # NOTE: The above is incomplete and buggy. Vendor-branches and |
| 463 | # the various possibilities of its interaction with the |
| 464 | # trunk are not fully handled. |
| 465 | |
| 466 | if {[info exists state($lodname)]} { |
| 467 | # LOD exists and has already been committed to. |
| 468 | return $state($lodname) |
| 469 | } |
| 470 | |
| 471 | # LOD has not been committed to before, this is the first |
| 472 | # time. Determine the name of the parent LOD. |
| 473 | |
| 474 | set lodname [[[$project getsymbol $lodname] parent] name] |
| 475 | |
| 476 | if {[info exists state($lodname)]} { |
| 477 | # The parental LOD has been committed to, take that last |
| 478 | # changeset as the spawnpoint for the new LOD. |
| 479 | return $state($lodname) |
| 480 | } |
| 481 | |
| 482 | # The parental LOD is not defined (yet). This LOD is |
| 483 | # detached. We choose as our parent the automatic empty root |
| 484 | # baseline of the target repository. |
| 485 | return {} |
| 486 | } |
| 487 | |
| 488 | proc Updatestate {sv lodname uuid} { |
| 489 | # Remember the imported changeset in the state, under our LOD. |
| 490 | |
| 491 | upvar 1 $sv state |
| 492 | set state($lodname) $uuid |
| 493 | return $uuid |
| 494 | } |
| 495 | |
| 496 | typemethod split {cset args} { |
| 497 | # As part of the creation of the new changesets specified in |
| 498 |
| --- tools/cvs2fossil/lib/c2f_prev.tcl | |
| +++ tools/cvs2fossil/lib/c2f_prev.tcl | |
| @@ -400,20 +400,21 @@ | |
| 400 | # - Commit message (-- mysrcid -> repository meta) |
| 401 | # - User doing the commit (s.a.) |
| 402 | # |
| 403 | # - Timestamp of when committed (command argument) |
| 404 | # |
| 405 | # - The parent changeset, if any. If there is no parent fossil |
| 406 | # will use the empty base revision as parent. |
| 407 | # |
| 408 | # - List of the file revisions in the changeset. |
| 409 | |
| 410 | struct::list assign [$myproject getmeta $mysrcid] __ branch user message |
| 411 | struct::list assign $branch __ lodname |
| 412 | |
| 413 | # Perform the import. As part of that we determine the parent |
| 414 | # we need, and convert the list of items in the changeset into |
| 415 | # uuids and printable data. |
| 416 | |
| 417 | set uuid [Updatestate state $lodname \ |
| 418 | [$repository importrevision [$self str] \ |
| 419 | $user $message $date \ |
| 420 | [Getparent state $lodname $myproject] \ |
| @@ -444,54 +445,102 @@ | |
| 445 | } |
| 446 | |
| 447 | proc Getparent {sv lodname project} { |
| 448 | upvar 1 $sv state |
| 449 | |
| 450 | struct::list assign [Getisdefault $myitems] isdefault lastdefaultontrunk |
| 451 | |
| 452 | # See (a) below, we have to remember if the changeset is last |
| 453 | # on vendor branch also belonging to trunk even if we find a |
| 454 | # parent in the state. The caller will later (after import) |
| 455 | # make us the first trunk changeset in the state (See (**)). |
| 456 | |
| 457 | if {$lastdefaultontrunk} { |
| 458 | set state(:vendor:last:) . |
| 459 | } |
| 460 | |
| 461 | # The state array holds for each line-of-development (LOD) the |
| 462 | # last committed changeset belonging to that LOD. |
| 463 | |
| 464 | # (*) Standard handling if in-LOD changesets. If the LOD of |
| 465 | # the current changeset exists in the state (= has been |
| 466 | # committed to) then the stored changeset is the parent we |
| 467 | # are looking for. |
| 468 | |
| 469 | if {[info exists state($lodname)]} { |
| 470 | return $state($lodname) |
| 471 | } |
| 472 | |
| 473 | # If the LOD is not yet known the current changeset can either |
| 474 | # be |
| 475 | # (a) the root of a vendor branch, |
| 476 | # (b) the root of the trunk LOD, or |
| 477 | # (c) the first changeset in a new LOD which was spawned from |
| 478 | # an existing LOD. |
| 479 | |
| 480 | if {$isdefault} { |
| 481 | # In case of (a) the changeset has no parent, signaled by |
| 482 | # the empty string. We do remember if the changeset is |
| 483 | # last on the vendor branch still belonging to trunk, for |
| 484 | # the trunk root. |
| 485 | return {} |
| 486 | } |
| 487 | |
| 488 | if {$lodname eq ":trunk:"} { |
| 489 | # This is case (b), and we also can be sure that there is |
| 490 | # no vendor branch changeset which could be our |
| 491 | # parent. That was already dealt with through the |
| 492 | # :vendor:last: signal and code in the caller (setting |
| 493 | # such a changeset up as parent in the state, causing the |
| 494 | # standard LOD handler at (*) to kick in. So, no parent |
| 495 | # here at all. |
| 496 | return {} |
| 497 | } |
| 498 | |
| 499 | # Case (c). We find the parent LOD of our LOD and take the |
| 500 | # last changeset committed to that as our parent. If that |
| 501 | # doesn't exist we have an error on our hands. |
| 502 | |
| 503 | set lodname [[[$project getsymbol $lodname] parent] name] |
| 504 | if {[info exists state($lodname)]} { |
| 505 | return $state($lodname) |
| 506 | } |
| 507 | |
| 508 | trouble internal {Unable to determine changeset parent} |
| 509 | return |
| 510 | } |
| 511 | |
| 512 | proc Getisdefault {revisions} { |
| 513 | set theset ('[join $revisions {','}]') |
| 514 | |
| 515 | struct::list assign [state run [subst -nocommands -nobackslashes { |
| 516 | SELECT R.isdefault, R.dbchild |
| 517 | FROM revision R |
| 518 | WHERE R.rid IN $theset -- All specified revisions |
| 519 | LIMIT 1 |
| 520 | }]] def last |
| 521 | |
| 522 | # TODO/CHECK: look for changesets where isdefault/dbchild is |
| 523 | # ambigous. |
| 524 | |
| 525 | return [list $def [expr {$last ne ""}]] |
| 526 | } |
| 527 | |
| 528 | proc Updatestate {sv lodname uuid} { |
| 529 | upvar 1 $sv state |
| 530 | |
| 531 | # Remember the imported changeset in the state, under our |
| 532 | # LOD. (**) And if the :vendor:last: signal is present then |
| 533 | # the revision is also the actual root of the :trunk:, so |
| 534 | # remember it as such. |
| 535 | |
| 536 | set state($lodname) $uuid |
| 537 | if {[info exists state(:vendor:last:)]} { |
| 538 | unset state(:vendor:last:) |
| 539 | set state(:trunk:) $uuid |
| 540 | } |
| 541 | |
| 542 | return $uuid |
| 543 | } |
| 544 | |
| 545 | typemethod split {cset args} { |
| 546 | # As part of the creation of the new changesets specified in |
| 547 |