@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow branch deletions to be pushed in Mercurial

Summary: Fixes T5050. This might not be 100% right in all edge cases, but it worked on everything I tried.

Test Plan:
- Pushed a branch deletion.
- Pushed a branch creation.
- Pushed a brnach creation + deletion.
- Pushed a brnach deletion + creation.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5050

Differential Revision: https://secure.phabricator.com/D9122

+49 -24
+49 -24
src/applications/diffusion/engine/DiffusionCommitHookEngine.php
··· 730 730 sort($old_heads); 731 731 sort($new_heads); 732 732 733 + if (!$old_heads && !$new_heads) { 734 + // This should never be possible, as it makes no sense. Explode. 735 + throw new Exception( 736 + pht( 737 + 'Mercurial repository has no new or old heads for branch "%s" '. 738 + 'after push. This makes no sense; rejecting change.', 739 + $ref)); 740 + } 741 + 733 742 if ($old_heads === $new_heads) { 734 743 // No changes to this branch, so skip it. 735 744 continue; 736 745 } 737 746 738 - if (!$new_heads) { 739 - if ($old_heads) { 740 - // TODO: This comment is wrong, and branches can be deleted with 741 - // --close-branch. Fix it soon: see T5050. 742 - // It looks like this push deletes a branch, but that isn't possible 743 - // in Mercurial, so something is going wrong here. Bail out. 744 - throw new Exception( 745 - pht( 746 - 'Mercurial repository has no new head for branch "%s" after '. 747 - 'push. This is unexpected; rejecting change.', 748 - $ref)); 749 - } else { 750 - // Obviously, this should never be possible either, as it makes 751 - // no sense. Explode. 752 - throw new Exception( 753 - pht( 754 - 'Mercurial repository has no new or old heads for branch "%s" '. 755 - 'after push. This makes no sense; rejecting change.', 756 - $ref)); 757 - } 758 - } 747 + $stray_heads = array(); 759 748 760 - $stray_heads = array(); 761 - if (count($old_heads) > 1) { 749 + if ($old_heads && !$new_heads) { 750 + // This is a branch deletion with "--close-branch". 751 + $head_map = array(); 752 + foreach ($old_heads as $old_head) { 753 + $head_map[$old_head] = array(self::EMPTY_HASH); 754 + } 755 + } else if (count($old_heads) > 1) { 762 756 // HORRIBLE: In Mercurial, branches can have multiple heads. If the 763 757 // old branch had multiple heads, we need to figure out which new 764 758 // heads descend from which old heads, so we can tell whether you're ··· 777 771 $head_map = array(); 778 772 foreach (Futures($dfutures) as $future_head => $dfuture) { 779 773 list($stdout) = $dfuture->resolvex(); 780 - $head_map[$future_head] = array_filter(explode("\1", $stdout)); 774 + $descendant_heads = array_filter(explode("\1", $stdout)); 775 + if ($descendant_heads) { 776 + // This old head has at least one descendant in the push. 777 + $head_map[$future_head] = $descendant_heads; 778 + } else { 779 + // This old head has no descendants, so it is being deleted. 780 + $head_map[$future_head] = array(self::EMPTY_HASH); 781 + } 781 782 } 782 783 783 784 // Now, find all the new stray heads this push creates, if any. These 784 785 // are new heads which do not descend from the old heads. 785 786 $seen = array_fuse(array_mergev($head_map)); 786 787 foreach ($new_heads as $new_head) { 788 + if ($new_head === self::EMPTY_HASH) { 789 + // If a branch head is being deleted, don't insert it as an add. 790 + continue; 791 + } 787 792 if (empty($seen[$new_head])) { 788 793 $head_map[self::EMPTY_HASH][] = $new_head; 789 794 } ··· 808 813 $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_APPEND; 809 814 } 810 815 816 + 817 + $deletes_existing_head = ($new_head == self::EMPTY_HASH); 811 818 $splits_existing_head = (count($child_heads) > 1); 812 819 $creates_duplicate_head = ($old_head == self::EMPTY_HASH) && 813 820 (count($head_map) > 1); ··· 842 849 $ref, 843 850 implode(', ', $readable_child_heads)); 844 851 } 852 + } 853 + 854 + if ($deletes_existing_head) { 855 + // TODO: Somewhere in here we should be setting CHANGEFLAG_REWRITE 856 + // if we are also creating at least one other head to replace 857 + // this one. 858 + 859 + // NOTE: In Git, this is a dangerous change, but it is not dangerous 860 + // in Mercurial. Mercurial branches are version controlled, and 861 + // Mercurial does not prompt you for any special flags when pushing 862 + // a `--close-branch` commit by default. 863 + 864 + $ref_flags |= PhabricatorRepositoryPushLog::CHANGEFLAG_DELETE; 845 865 } 846 866 847 867 $ref_update = $this->newPushLog() ··· 1082 1102 'The raw text of this change is enormous (larger than %d '. 1083 1103 'bytes). Herald can not process it.', 1084 1104 $byte_limit)); 1105 + } 1106 + 1107 + if (!strlen($raw_diff)) { 1108 + // If the commit is actually empty, just return no changesets. 1109 + return array(); 1085 1110 } 1086 1111 1087 1112 $parser = new ArcanistDiffParser();