| | @@ -56,10 +56,11 @@ |
| 56 | 56 | struct GraphRow { |
| 57 | 57 | int rid; /* The rid for the check-in */ |
| 58 | 58 | i8 nParent; /* Number of parents. */ |
| 59 | 59 | i8 nCherrypick; /* Subset of aParent that are cherrypicks */ |
| 60 | 60 | i8 nNonCherrypick; /* Number of non-cherrypick parents */ |
| 61 | + u8 nMergeChild; /* Number of merge children */ |
| 61 | 62 | int *aParent; /* Array of parents. 0 element is primary .*/ |
| 62 | 63 | char *zBranch; /* Branch name */ |
| 63 | 64 | char *zBgClr; /* Background Color */ |
| 64 | 65 | char zUuid[HNAME_MAX+1]; /* Check-in for file ID */ |
| 65 | 66 | |
| | @@ -472,11 +473,12 @@ |
| 472 | 473 | ** the aParent[] array. |
| 473 | 474 | */ |
| 474 | 475 | if( (tmFlags & (TIMELINE_DISJOINT|TIMELINE_XMERGE))!=0 ){ |
| 475 | 476 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 476 | 477 | for(i=1; i<pRow->nParent; i++){ |
| 477 | | - if( hashFind(p, pRow->aParent[i])==0 ){ |
| 478 | + GraphRow *pParent = hashFind(p, pRow->aParent[i]); |
| 479 | + if( pParent==0 ){ |
| 478 | 480 | memmove(pRow->aParent+i, pRow->aParent+i+1, |
| 479 | 481 | sizeof(pRow->aParent[0])*(pRow->nParent-i-1)); |
| 480 | 482 | pRow->nParent--; |
| 481 | 483 | if( i<pRow->nNonCherrypick ){ |
| 482 | 484 | pRow->nNonCherrypick--; |
| | @@ -486,10 +488,62 @@ |
| 486 | 488 | i--; |
| 487 | 489 | } |
| 488 | 490 | } |
| 489 | 491 | } |
| 490 | 492 | } |
| 493 | + |
| 494 | + /* Put the deepest (earliest) merge parent first in the list. |
| 495 | + ** An off-screen merge parent is considered deepest. |
| 496 | + */ |
| 497 | + for(pRow=p->pFirst; pRow; pRow=pRow->pNext ){ |
| 498 | + if( pRow->nParent<=1 ) continue; |
| 499 | + for(i=1; i<pRow->nParent; i++){ |
| 500 | + GraphRow *pParent = hashFind(p, pRow->aParent[i]); |
| 501 | + if( pParent ) pParent->nMergeChild++; |
| 502 | + } |
| 503 | + if( pRow->nCherrypick>1 ){ |
| 504 | + int iBest = -1; |
| 505 | + int iDeepest = -1; |
| 506 | + for(i=pRow->nNonCherrypick; i<pRow->nParent; i++){ |
| 507 | + GraphRow *pParent = hashFind(p, pRow->aParent[i]); |
| 508 | + if( pParent==0 ){ |
| 509 | + iBest = i; |
| 510 | + break; |
| 511 | + } |
| 512 | + if( pParent->idx>iDeepest ){ |
| 513 | + iDeepest = pParent->idx; |
| 514 | + iBest = i; |
| 515 | + } |
| 516 | + } |
| 517 | + i = pRow->nNonCherrypick; |
| 518 | + if( iBest>i ){ |
| 519 | + int x = pRow->aParent[i]; |
| 520 | + pRow->aParent[i] = pRow->aParent[iBest]; |
| 521 | + pRow->aParent[iBest] = x; |
| 522 | + } |
| 523 | + } |
| 524 | + if( pRow->nNonCherrypick>2 ){ |
| 525 | + int iBest = -1; |
| 526 | + int iDeepest = -1; |
| 527 | + for(i=1; i<pRow->nNonCherrypick; i++){ |
| 528 | + GraphRow *pParent = hashFind(p, pRow->aParent[i]); |
| 529 | + if( pParent==0 ){ |
| 530 | + iBest = i; |
| 531 | + break; |
| 532 | + } |
| 533 | + if( pParent->idx>iDeepest ){ |
| 534 | + iDeepest = pParent->idx; |
| 535 | + iBest = i; |
| 536 | + } |
| 537 | + } |
| 538 | + if( iBest>1 ){ |
| 539 | + int x = pRow->aParent[1]; |
| 540 | + pRow->aParent[1] = pRow->aParent[iBest]; |
| 541 | + pRow->aParent[iBest] = x; |
| 542 | + } |
| 543 | + } |
| 544 | + } |
| 491 | 545 | |
| 492 | 546 | /* If the primary parent is in a different branch, but there are |
| 493 | 547 | ** other parents in the same branch, reorder the parents to make |
| 494 | 548 | ** the parent from the same branch the primary parent. |
| 495 | 549 | */ |
| | @@ -668,15 +722,26 @@ |
| 668 | 722 | |
| 669 | 723 | /* |
| 670 | 724 | ** Insert merge rails and merge arrows |
| 671 | 725 | */ |
| 672 | 726 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 727 | + int iReuseIdx = -1; |
| 728 | + int iReuseRail = -1; |
| 729 | + int isCherrypick = 0; |
| 673 | 730 | for(i=1; i<pRow->nParent; i++){ |
| 674 | 731 | int parentRid = pRow->aParent[i]; |
| 732 | + if( i==pRow->nNonCherrypick ){ |
| 733 | + iReuseIdx = -1; |
| 734 | + iReuseRail = -1; |
| 735 | + isCherrypick = 1; |
| 736 | + } |
| 675 | 737 | pDesc = hashFind(p, parentRid); |
| 676 | 738 | if( pDesc==0 ){ |
| 677 | 739 | /* Merge from a node that is off-screen */ |
| 740 | + if( iReuseIdx>=p->nRow+1 ){ |
| 741 | + continue; /* Suppress multiple off-screen merges */ |
| 742 | + } |
| 678 | 743 | int iMrail = -1; |
| 679 | 744 | for(j=0; j<GR_MAX_RAIL; j++){ |
| 680 | 745 | if( mergeRiserFrom[j]==parentRid ){ |
| 681 | 746 | iMrail = j; |
| 682 | 747 | break; |
| | @@ -685,10 +750,12 @@ |
| 685 | 750 | if( iMrail==-1 ){ |
| 686 | 751 | iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0); |
| 687 | 752 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 688 | 753 | mergeRiserFrom[iMrail] = parentRid; |
| 689 | 754 | } |
| 755 | + iReuseIdx = p->nRow+1; |
| 756 | + iReuseRail = iMrail; |
| 690 | 757 | mask = BIT(iMrail); |
| 691 | 758 | if( i>=pRow->nNonCherrypick ){ |
| 692 | 759 | pRow->mergeIn[iMrail] = 2; |
| 693 | 760 | pRow->cherrypickDown |= mask; |
| 694 | 761 | }else{ |
| | @@ -697,13 +764,31 @@ |
| 697 | 764 | } |
| 698 | 765 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 699 | 766 | pLoop->railInUse |= mask; |
| 700 | 767 | } |
| 701 | 768 | }else{ |
| 702 | | - /* Merge from an on-screen node */ |
| 703 | | - createMergeRiser(p, pDesc, pRow, i>=pRow->nNonCherrypick); |
| 704 | | - if( p->mxRail>=GR_MAX_RAIL ) return; |
| 769 | + /* The merge parent node does exist on this graph */ |
| 770 | + if( iReuseIdx>pDesc->idx |
| 771 | + && pDesc->nMergeChild==1 |
| 772 | + ){ |
| 773 | + /* Reuse an existing merge riser */ |
| 774 | + pDesc->mergeOut = iReuseRail; |
| 775 | + if( isCherrypick ){ |
| 776 | + pDesc->cherrypickUpto = pDesc->idx; |
| 777 | + }else{ |
| 778 | + pDesc->hasNormalOutMerge = 1; |
| 779 | + pDesc->mergeUpto = pDesc->idx; |
| 780 | + } |
| 781 | + }else{ |
| 782 | + /* Create a new merge for an on-screen node */ |
| 783 | + createMergeRiser(p, pDesc, pRow, isCherrypick); |
| 784 | + if( p->mxRail>=GR_MAX_RAIL ) return; |
| 785 | + if( iReuseIdx<0 && pDesc->nMergeChild==1 ){ |
| 786 | + iReuseIdx = pDesc->idx; |
| 787 | + iReuseRail = pDesc->mergeOut; |
| 788 | + } |
| 789 | + } |
| 705 | 790 | } |
| 706 | 791 | } |
| 707 | 792 | } |
| 708 | 793 | |
| 709 | 794 | /* |
| 710 | 795 | |