Page MenuHomePhabricator

D21682.id51640.diff
No OneTemporary

D21682.id51640.diff

diff --git a/src/land/engine/ArcanistGitLandEngine.php b/src/land/engine/ArcanistGitLandEngine.php
--- a/src/land/engine/ArcanistGitLandEngine.php
+++ b/src/land/engine/ArcanistGitLandEngine.php
@@ -885,7 +885,7 @@
);
}
- protected function didHoldChanges($into_commit) {
+ protected function didHoldChanges($into_commit, $branches_pruned) {
$log = $this->getLogEngine();
$local_state = $this->getLocalState();
@@ -916,6 +916,12 @@
pht('To push changes manually, run this command:'),
$push_command);
+ if ($branches_pruned) {
+ // No restore is possible if the user decided to prune the merged
+ // branches when using `--hold`.
+ return;
+ }
+
$restore_commands = $local_state->getRestoreCommandsForDisplay();
if ($restore_commands) {
echo tsprintf(
diff --git a/src/land/engine/ArcanistLandEngine.php b/src/land/engine/ArcanistLandEngine.php
--- a/src/land/engine/ArcanistLandEngine.php
+++ b/src/land/engine/ArcanistLandEngine.php
@@ -1225,6 +1225,16 @@
$is_hold = $this->getShouldHold();
$is_keep = $this->getShouldKeep();
+ $should_prune_after_hold = false;
+ if ($is_hold && !$is_keep) {
+ $query = pht('Prune merged branches after holding?');
+ $should_prune_after_hold = $this->getWorkflow()
+ ->getPrompt('arc.land.prune-after-hold')
+ ->setQuery($query)
+ ->setAbortsWorkflow(false)
+ ->execute();
+ }
+
$local_state = $api->newLocalState()
->setWorkflow($workflow)
->saveLocalState();
@@ -1238,6 +1248,8 @@
$need_cascade = array();
$need_prune = array();
+ $branches_pruned = false;
+
foreach ($sets as $set_key => $set) {
// Add these first, so we don't add them multiple times if we need
// to retry a push.
@@ -1248,13 +1260,16 @@
$into_commit = $this->executeMerge($set, $into_commit);
$this->setHasUnpushedChanges(true);
+ $is_last = ($set_key === $last_key);
if ($is_hold) {
$should_push = false;
+ $should_cascade_and_prune = $should_prune_after_hold && $is_last;
} else if ($is_incremental) {
$should_push = true;
+ $should_cascade_and_prune = true;
} else {
- $is_last = ($set_key === $last_key);
$should_push = $is_last;
+ $should_cascade_and_prune = $should_push;
}
if ($should_push) {
@@ -1285,7 +1300,9 @@
throw new PhutilArgumentUsageException(
$ex->getMessage());
}
+ }
+ if ($should_cascade_and_prune) {
if ($need_cascade) {
// NOTE: We cascade each set we've pushed, but we're going to
@@ -1303,6 +1320,7 @@
if (!$is_keep) {
$this->pruneBranches($need_prune);
$need_prune = array();
+ $branches_pruned = true;
}
}
@@ -1311,8 +1329,13 @@
}
if ($is_hold) {
- $this->didHoldChanges($into_commit);
- $local_state->discardLocalState();
+ if ($branches_pruned) {
+ $this->reconcileLocalState($into_commit, $local_state);
+ } else {
+ $local_state->discardLocalState();
+ }
+
+ $this->didHoldChanges($into_commit, $branches_pruned);
} else {
// TODO: Restore this.
// $this->getWorkflow()->askForRepositoryUpdate();
@@ -1407,6 +1430,21 @@
ArcanistLandCommitSet $set,
$into_commit);
abstract protected function pushChange($into_commit);
+
+ /**
+ * Update all local refs that depend on refs selected-and-modified during the
+ * land. E.g. with branches named change1 -> change2 -> change3 and using
+ * `arc land change2`, in the general case the local change3 should be
+ * rebased onto the landed version of change2 so that it no longer has
+ * out-of-date ancestors.
+ *
+ * When multiple revisions are landed at once this will be called in a loop
+ * for each set, in order of max to min, where max is the latest descendant
+ * and min is the earliest ancestor. This is done so that non-landing commits
+ * that are descendants of the latest revision will only be rebased once.
+ *
+ * @param ArcanistLandCommitSet The current commit set to cascade.
+ */
abstract protected function cascadeState(
ArcanistLandCommitSet $set,
$into_commit);
@@ -1415,13 +1453,38 @@
return ($this->getStrategy() === 'squash');
}
+ /**
+ * Prunes the given sets of commits. This should be called after the sets
+ * have been merged.
+ *
+ * @param array The list of ArcanistLandCommitSet to prune, in order of
+ * min to max commit set, where min is the earliest ancestor and max
+ * is the latest descendant.
+ */
abstract protected function pruneBranches(array $sets);
+ /**
+ * Restore the local repository to an expected state after landing. This
+ * should only be called after all changes have been merged, pruned, and
+ * pushed.
+ *
+ * @param string The commit hash that was landed into.
+ * @param ArcanistRepositoryLocalState The local state that was captured
+ * at the beginning of the land process. This may include stashed changes.
+ */
abstract protected function reconcileLocalState(
$into_commit,
ArcanistRepositoryLocalState $state);
- abstract protected function didHoldChanges($into_commit);
+ /**
+ * Display information to the user about how to proceed since the land
+ * process was not fully completed. The merged branch has not been pushed
+ * and the original branch may have been pruned.
+ *
+ * @param string The commit hash that was landed into.
+ * @param bool Whether the source branches that were merged were pruned.
+ */
+ abstract protected function didHoldChanges($into_commit, $branches_pruned);
private function selectMergeStrategy() {
$log = $this->getLogEngine();
diff --git a/src/land/engine/ArcanistMercurialLandEngine.php b/src/land/engine/ArcanistMercurialLandEngine.php
--- a/src/land/engine/ArcanistMercurialLandEngine.php
+++ b/src/land/engine/ArcanistMercurialLandEngine.php
@@ -1222,7 +1222,7 @@
$state->discardLocalState();
}
- protected function didHoldChanges($into_commit) {
+ protected function didHoldChanges($into_commit, $branches_pruned) {
$log = $this->getLogEngine();
$local_state = $this->getLocalState();
@@ -1249,6 +1249,12 @@
echo tsprintf("\n");
+ if ($branches_pruned) {
+ // No restore is possible if the user decided to prune the merged
+ // branches when using `--hold`.
+ return;
+ }
+
$restore_commands = $local_state->getRestoreCommandsForDisplay();
if ($restore_commands) {
echo tsprintf(
diff --git a/src/toolset/ArcanistPrompt.php b/src/toolset/ArcanistPrompt.php
--- a/src/toolset/ArcanistPrompt.php
+++ b/src/toolset/ArcanistPrompt.php
@@ -7,6 +7,7 @@
private $workflow;
private $description;
private $query;
+ private $abortsWorkflow;
public function setKey($key) {
$this->key = $key;
@@ -44,6 +45,15 @@
return $this->query;
}
+ public function setAbortsWorkflow($aborts_workflow) {
+ $this->abortsWorkflow = $aborts_workflow;
+ return $this;
+ }
+
+ public function getAbortsWorkflow() {
+ return $this->abortsWorkflow;
+ }
+
public function execute() {
$workflow = $this->getWorkflow();
if ($workflow) {
@@ -248,9 +258,11 @@
$this->getKey()));
}
- if (!$result) {
+ $allow_abort = $this->abortsWorkflow === null || $this->abortsWorkflow;
+ if ($allow_abort && !$result) {
throw new ArcanistUserAbortException();
}
+ return $result;
}
private function getSavedResponse() {
diff --git a/src/workflow/ArcanistLandWorkflow.php b/src/workflow/ArcanistLandWorkflow.php
--- a/src/workflow/ArcanistLandWorkflow.php
+++ b/src/workflow/ArcanistLandWorkflow.php
@@ -285,6 +285,11 @@
pht(
'Confirms that new branches or bookmarks should be created '.
'in the remote.')),
+ $this->newPrompt('arc.land.prune-after-hold')
+ ->setDescription(
+ pht(
+ 'Confirms that branches or bookmarks should be pruned after they '.
+ 'are merged when using `--hold`.')),
);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 21, 4:29 PM (4 d, 18 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7707308
Default Alt Text
D21682.id51640.diff (8 KB)

Event Timeline