Page MenuHomePhabricator

D21336.diff
No OneTemporary

D21336.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -225,6 +225,7 @@
'ArcanistGitRawCommitTestCase' => 'repository/raw/__tests__/ArcanistGitRawCommitTestCase.php',
'ArcanistGitRepositoryMarkerQuery' => 'repository/marker/ArcanistGitRepositoryMarkerQuery.php',
'ArcanistGitUpstreamPath' => 'repository/api/ArcanistGitUpstreamPath.php',
+ 'ArcanistGitWorkEngine' => 'work/ArcanistGitWorkEngine.php',
'ArcanistGitWorkingCopy' => 'workingcopy/ArcanistGitWorkingCopy.php',
'ArcanistGitWorkingCopyRevisionHardpointQuery' => 'query/ArcanistGitWorkingCopyRevisionHardpointQuery.php',
'ArcanistGlobalVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistGlobalVariableXHPASTLinterRule.php',
@@ -336,6 +337,7 @@
'ArcanistMercurialParser' => 'repository/parser/ArcanistMercurialParser.php',
'ArcanistMercurialParserTestCase' => 'repository/parser/__tests__/ArcanistMercurialParserTestCase.php',
'ArcanistMercurialRepositoryMarkerQuery' => 'repository/marker/ArcanistMercurialRepositoryMarkerQuery.php',
+ 'ArcanistMercurialWorkEngine' => 'work/ArcanistMercurialWorkEngine.php',
'ArcanistMercurialWorkingCopy' => 'workingcopy/ArcanistMercurialWorkingCopy.php',
'ArcanistMercurialWorkingCopyRevisionHardpointQuery' => 'query/ArcanistMercurialWorkingCopyRevisionHardpointQuery.php',
'ArcanistMergeConflictLinter' => 'lint/linter/ArcanistMergeConflictLinter.php',
@@ -538,8 +540,11 @@
'ArcanistWeldWorkflow' => 'workflow/ArcanistWeldWorkflow.php',
'ArcanistWhichWorkflow' => 'workflow/ArcanistWhichWorkflow.php',
'ArcanistWildConfigOption' => 'config/option/ArcanistWildConfigOption.php',
+ 'ArcanistWorkEngine' => 'work/ArcanistWorkEngine.php',
+ 'ArcanistWorkWorkflow' => 'workflow/ArcanistWorkWorkflow.php',
'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php',
'ArcanistWorkflowArgument' => 'toolset/ArcanistWorkflowArgument.php',
+ 'ArcanistWorkflowEngine' => 'engine/ArcanistWorkflowEngine.php',
'ArcanistWorkflowGitHardpointQuery' => 'query/ArcanistWorkflowGitHardpointQuery.php',
'ArcanistWorkflowInformation' => 'toolset/ArcanistWorkflowInformation.php',
'ArcanistWorkflowMercurialHardpointQuery' => 'query/ArcanistWorkflowMercurialHardpointQuery.php',
@@ -1253,6 +1258,7 @@
'ArcanistGitRawCommitTestCase' => 'PhutilTestCase',
'ArcanistGitRepositoryMarkerQuery' => 'ArcanistRepositoryMarkerQuery',
'ArcanistGitUpstreamPath' => 'Phobject',
+ 'ArcanistGitWorkEngine' => 'ArcanistWorkEngine',
'ArcanistGitWorkingCopy' => 'ArcanistWorkingCopy',
'ArcanistGitWorkingCopyRevisionHardpointQuery' => 'ArcanistWorkflowGitHardpointQuery',
'ArcanistGlobalVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@@ -1322,7 +1328,7 @@
'ArcanistLambdaFuncFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistLandCommit' => 'Phobject',
'ArcanistLandCommitSet' => 'Phobject',
- 'ArcanistLandEngine' => 'Phobject',
+ 'ArcanistLandEngine' => 'ArcanistWorkflowEngine',
'ArcanistLandSymbol' => 'Phobject',
'ArcanistLandTarget' => 'Phobject',
'ArcanistLandWorkflow' => 'ArcanistArcWorkflow',
@@ -1355,7 +1361,10 @@
'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistLowercaseFunctionsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
- 'ArcanistMarkerRef' => 'ArcanistRef',
+ 'ArcanistMarkerRef' => array(
+ 'ArcanistRef',
+ 'ArcanistDisplayRefInterface',
+ ),
'ArcanistMarkersWorkflow' => 'ArcanistArcWorkflow',
'ArcanistMercurialAPI' => 'ArcanistRepositoryAPI',
'ArcanistMercurialCommitMessageHardpointQuery' => 'ArcanistWorkflowMercurialHardpointQuery',
@@ -1364,6 +1373,7 @@
'ArcanistMercurialParser' => 'Phobject',
'ArcanistMercurialParserTestCase' => 'PhutilTestCase',
'ArcanistMercurialRepositoryMarkerQuery' => 'ArcanistRepositoryMarkerQuery',
+ 'ArcanistMercurialWorkEngine' => 'ArcanistWorkEngine',
'ArcanistMercurialWorkingCopy' => 'ArcanistWorkingCopy',
'ArcanistMercurialWorkingCopyRevisionHardpointQuery' => 'ArcanistWorkflowMercurialHardpointQuery',
'ArcanistMergeConflictLinter' => 'ArcanistLinter',
@@ -1576,8 +1586,11 @@
'ArcanistWeldWorkflow' => 'ArcanistArcWorkflow',
'ArcanistWhichWorkflow' => 'ArcanistWorkflow',
'ArcanistWildConfigOption' => 'ArcanistConfigOption',
+ 'ArcanistWorkEngine' => 'ArcanistWorkflowEngine',
+ 'ArcanistWorkWorkflow' => 'ArcanistArcWorkflow',
'ArcanistWorkflow' => 'Phobject',
'ArcanistWorkflowArgument' => 'Phobject',
+ 'ArcanistWorkflowEngine' => 'Phobject',
'ArcanistWorkflowGitHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistWorkflowInformation' => 'Phobject',
'ArcanistWorkflowMercurialHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
diff --git a/src/engine/ArcanistWorkflowEngine.php b/src/engine/ArcanistWorkflowEngine.php
new file mode 100644
--- /dev/null
+++ b/src/engine/ArcanistWorkflowEngine.php
@@ -0,0 +1,48 @@
+<?php
+
+abstract class ArcanistWorkflowEngine
+ extends Phobject {
+
+ private $workflow;
+ private $viewer;
+ private $logEngine;
+ private $repositoryAPI;
+
+ final public function setViewer($viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ final public function getViewer() {
+ return $this->viewer;
+ }
+
+ final public function setWorkflow(ArcanistWorkflow $workflow) {
+ $this->workflow = $workflow;
+ return $this;
+ }
+
+ final public function getWorkflow() {
+ return $this->workflow;
+ }
+
+ final public function setRepositoryAPI(
+ ArcanistRepositoryAPI $repository_api) {
+ $this->repositoryAPI = $repository_api;
+ return $this;
+ }
+
+ final public function getRepositoryAPI() {
+ return $this->repositoryAPI;
+ }
+
+ final public function setLogEngine(ArcanistLogEngine $log_engine) {
+ $this->logEngine = $log_engine;
+ return $this;
+ }
+
+ final public function getLogEngine() {
+ return $this->logEngine;
+ }
+
+}
diff --git a/src/hardpoint/ArcanistHardpointObject.php b/src/hardpoint/ArcanistHardpointObject.php
--- a/src/hardpoint/ArcanistHardpointObject.php
+++ b/src/hardpoint/ArcanistHardpointObject.php
@@ -5,6 +5,12 @@
private $hardpointList;
+ public function __clone() {
+ if ($this->hardpointList) {
+ $this->hardpointList = clone $this->hardpointList;
+ }
+ }
+
final public function getHardpoint($hardpoint) {
return $this->getHardpointList()->getHardpoint(
$this,
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
@@ -1,11 +1,7 @@
<?php
-abstract class ArcanistLandEngine extends Phobject {
-
- private $workflow;
- private $viewer;
- private $logEngine;
- private $repositoryAPI;
+abstract class ArcanistLandEngine
+ extends ArcanistWorkflowEngine {
private $sourceRefs;
private $shouldHold;
@@ -33,15 +29,6 @@
private $localState;
- final public function setViewer($viewer) {
- $this->viewer = $viewer;
- return $this;
- }
-
- final public function getViewer() {
- return $this->viewer;
- }
-
final public function setOntoRemote($onto_remote) {
$this->ontoRemote = $onto_remote;
return $this;
@@ -96,34 +83,6 @@
return $this->intoLocal;
}
- final public function setWorkflow($workflow) {
- $this->workflow = $workflow;
- return $this;
- }
-
- final public function getWorkflow() {
- return $this->workflow;
- }
-
- final public function setRepositoryAPI(
- ArcanistRepositoryAPI $repository_api) {
- $this->repositoryAPI = $repository_api;
- return $this;
- }
-
- final public function getRepositoryAPI() {
- return $this->repositoryAPI;
- }
-
- final public function setLogEngine(ArcanistLogEngine $log_engine) {
- $this->logEngine = $log_engine;
- return $this;
- }
-
- final public function getLogEngine() {
- return $this->logEngine;
- }
-
final public function setShouldHold($should_hold) {
$this->shouldHold = $should_hold;
return $this;
diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php
--- a/src/repository/api/ArcanistGitAPI.php
+++ b/src/repository/api/ArcanistGitAPI.php
@@ -1746,6 +1746,10 @@
return new ArcanistGitLandEngine();
}
+ protected function newWorkEngine() {
+ return new ArcanistGitWorkEngine();
+ }
+
public function newLocalState() {
return id(new ArcanistGitLocalState())
->setRepositoryAPI($this);
diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php
--- a/src/repository/api/ArcanistMercurialAPI.php
+++ b/src/repository/api/ArcanistMercurialAPI.php
@@ -1134,6 +1134,10 @@
return new ArcanistMercurialLandEngine();
}
+ protected function newWorkEngine() {
+ return new ArcanistMercurialWorkEngine();
+ }
+
public function newLocalState() {
return id(new ArcanistMercurialLocalState())
->setRepositoryAPI($this);
diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php
--- a/src/repository/api/ArcanistRepositoryAPI.php
+++ b/src/repository/api/ArcanistRepositoryAPI.php
@@ -763,6 +763,20 @@
return null;
}
+ final public function getWorkEngine() {
+ $engine = $this->newWorkEngine();
+
+ if ($engine) {
+ $engine->setRepositoryAPI($this);
+ }
+
+ return $engine;
+ }
+
+ protected function newWorkEngine() {
+ return null;
+ }
+
final public function getSupportedMarkerTypes() {
return $this->newSupportedMarkerTypes();
}
@@ -780,4 +794,8 @@
throw new PhutilMethodNotImplementedException();
}
+ final public function getDisplayHash($hash) {
+ return substr($hash, 0, 12);
+ }
+
}
diff --git a/src/repository/marker/ArcanistMarkerRef.php b/src/repository/marker/ArcanistMarkerRef.php
--- a/src/repository/marker/ArcanistMarkerRef.php
+++ b/src/repository/marker/ArcanistMarkerRef.php
@@ -1,9 +1,12 @@
<?php
final class ArcanistMarkerRef
- extends ArcanistRef {
+ extends ArcanistRef
+ implements
+ ArcanistDisplayRefInterface {
- const HARDPOINT_COMMITREF = 'commitRef';
+ const HARDPOINT_COMMITREF = 'arc.marker.commitRef';
+ const HARDPOINT_WORKINGCOPYSTATEREF = 'arc.marker.workingCopyStateRef';
const TYPE_BRANCH = 'branch';
const TYPE_BOOKMARK = 'bookmark';
@@ -13,18 +16,38 @@
private $epoch;
private $markerHash;
private $commitHash;
+ private $displayHash;
private $treeHash;
private $summary;
private $message;
private $isActive = false;
public function getRefDisplayName() {
- return pht('Marker %s', $this->getName());
+ return $this->getDisplayRefObjectName();
+ }
+
+ public function getDisplayRefObjectName() {
+ switch ($this->getMarkerType()) {
+ case self::TYPE_BRANCH:
+ return pht('Branch "%s"', $this->getName());
+ case self::TYPE_BOOKMARK:
+ return pht('Bookmark "%s"', $this->getName());
+ default:
+ return pht('Marker "%s"', $this->getName());
+ }
+ }
+
+ public function getDisplayRefTitle() {
+ return pht(
+ '%s %s',
+ $this->getDisplayHash(),
+ $this->getSummary());
}
protected function newHardpoints() {
return array(
$this->newHardpoint(self::HARDPOINT_COMMITREF),
+ $this->newHardpoint(self::HARDPOINT_WORKINGCOPYSTATEREF),
);
}
@@ -64,6 +87,17 @@
return $this->markerHash;
}
+ public function setDisplayHash($display_hash) {
+ $this->displayHash = $display_hash;
+ return $this;
+ }
+
+ public function getDisplayHash() {
+ return $this->displayHash;
+ }
+
+
+
public function setCommitHash($commit_hash) {
$this->commitHash = $commit_hash;
return $this;
@@ -125,4 +159,12 @@
return $this->getHardpoint(self::HARDPOINT_COMMITREF);
}
+ public function attachWorkingCopyStateRef(ArcanistWorkingCopyStateRef $ref) {
+ return $this->attachHardpoint(self::HARDPOINT_WORKINGCOPYSTATEREF, $ref);
+ }
+
+ public function getWorkingCopyStateRef() {
+ return $this->getHardpoint(self::HARDPOINT_WORKINGCOPYSTATEREF);
+ }
+
}
diff --git a/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php b/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
--- a/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
+++ b/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
@@ -100,6 +100,7 @@
}
$message = $fields[4];
+ $message_lines = phutil_split_lines($message, false);
$commit_ref = $api->newCommitRef()
->setCommitHash($node)
@@ -107,6 +108,7 @@
$template = id(new ArcanistMarkerRef())
->setCommitHash($node)
+ ->setSummary(head($message_lines))
->attachCommitRef($commit_ref);
if ($is_bookmarks) {
diff --git a/src/repository/marker/ArcanistRepositoryMarkerQuery.php b/src/repository/marker/ArcanistRepositoryMarkerQuery.php
--- a/src/repository/marker/ArcanistRepositoryMarkerQuery.php
+++ b/src/repository/marker/ArcanistRepositoryMarkerQuery.php
@@ -6,6 +6,7 @@
private $repositoryAPI;
private $isActive;
private $markerTypes;
+ private $names;
private $commitHashes;
private $ancestorCommitHashes;
@@ -23,14 +24,47 @@
return $this;
}
+ final public function withNames(array $names) {
+ $this->names = array_fuse($names);
+ return $this;
+ }
+
final public function withIsActive($active) {
$this->isActive = $active;
return $this;
}
+ final public function executeOne() {
+ $markers = $this->execute();
+
+ if (!$markers) {
+ return null;
+ }
+
+ if (count($markers) > 1) {
+ throw new Exception(
+ pht(
+ 'Query matched multiple markers, expected zero or one.'));
+ }
+
+ return head($markers);
+ }
+
final public function execute() {
$markers = $this->newRefMarkers();
+ $api = $this->getRepositoryAPI();
+ foreach ($markers as $marker) {
+ $state_ref = id(new ArcanistWorkingCopyStateRef())
+ ->setCommitRef($marker->getCommitRef());
+
+ $marker->attachWorkingCopyStateRef($state_ref);
+
+ $hash = $marker->getCommitHash();
+ $hash = $api->getDisplayHash($hash);
+ $marker->setDisplayHash($hash);
+ }
+
$types = $this->markerTypes;
if ($types !== null) {
foreach ($markers as $key => $marker) {
@@ -40,6 +74,15 @@
}
}
+ $names = $this->names;
+ if ($names !== null) {
+ foreach ($markers as $key => $marker) {
+ if (!isset($names[$marker->getName()])) {
+ unset($markers[$key]);
+ }
+ }
+ }
+
if ($this->isActive !== null) {
foreach ($markers as $key => $marker) {
if ($marker->getIsActive() !== $this->isActive) {
@@ -48,6 +91,7 @@
}
}
+
return $this->sortMarkers($markers);
}
diff --git a/src/repository/state/ArcanistGitLocalState.php b/src/repository/state/ArcanistGitLocalState.php
--- a/src/repository/state/ArcanistGitLocalState.php
+++ b/src/repository/state/ArcanistGitLocalState.php
@@ -42,7 +42,7 @@
}
$log = $this->getWorkflow()->getLogEngine();
- $log->writeStatus(pht('SAVE STATE'), $where);
+ $log->writeTrace(pht('SAVE STATE'), $where);
}
protected function executeRestoreLocalState() {
diff --git a/src/work/ArcanistGitWorkEngine.php b/src/work/ArcanistGitWorkEngine.php
new file mode 100644
--- /dev/null
+++ b/src/work/ArcanistGitWorkEngine.php
@@ -0,0 +1,57 @@
+<?php
+
+final class ArcanistGitWorkEngine
+ extends ArcanistWorkEngine {
+
+ protected function getDefaultStartSymbol() {
+ $api = $this->getRepositoryAPI();
+
+ // NOTE: In Git, we're trying to find the current branch name because the
+ // behavior of "--track" depends on the symbol we pass.
+
+ $marker = $api->newMarkerRefQuery()
+ ->withIsActive(true)
+ ->withMarkerTypes(array(ArcanistMarkerRef::TYPE_BRANCH))
+ ->executeOne();
+ if ($marker) {
+ return $marker->getName();
+ }
+
+ return $api->getWorkingCopyRevision();
+ }
+
+ protected function newMarker($symbol, $start) {
+ $api = $this->getRepositoryAPI();
+ $log = $this->getLogEngine();
+
+ $log->writeStatus(
+ pht('NEW BRANCH'),
+ pht(
+ 'Creating new branch "%s" from "%s".',
+ $symbol,
+ $start));
+
+ $future = $api->newFuture(
+ 'checkout --track -b %s %s --',
+ $symbol,
+ $start);
+ $future->resolve();
+ }
+
+ protected function moveToMarker(ArcanistMarkerRef $marker) {
+ $api = $this->getRepositoryAPI();
+ $log = $this->getLogEngine();
+
+ $log->writeStatus(
+ pht('BRANCH'),
+ pht(
+ 'Checking out branch "%s".',
+ $marker->getName()));
+
+ $future = $api->newFuture(
+ 'checkout %s --',
+ $marker->getName());
+ $future->resolve();
+ }
+
+}
diff --git a/src/work/ArcanistMercurialWorkEngine.php b/src/work/ArcanistMercurialWorkEngine.php
new file mode 100644
--- /dev/null
+++ b/src/work/ArcanistMercurialWorkEngine.php
@@ -0,0 +1,56 @@
+<?php
+
+final class ArcanistMercurialWorkEngine
+ extends ArcanistWorkEngine {
+
+ protected function getDefaultStartSymbol() {
+ $api = $this->getRepositoryAPI();
+ return $api->getWorkingCopyRevision();
+ }
+
+ protected function newMarker($symbol, $start) {
+ $api = $this->getRepositoryAPI();
+ $log = $this->getLogEngine();
+
+ $log->writeStatus(
+ pht('NEW BOOKMARK'),
+ pht(
+ 'Creating new bookmark "%s" from "%s".',
+ $symbol,
+ $start));
+
+ if ($start !== $this->getDefaultStartSymbol()) {
+ $future = $api->newFuture('update -- %s', $start);
+ $future->resolve();
+ }
+
+ $future = $api->newFuture('bookmark %s --', $symbol);
+ $future->resolve();
+ }
+
+ protected function moveToMarker(ArcanistMarkerRef $marker) {
+ $api = $this->getRepositoryAPI();
+ $log = $this->getLogEngine();
+
+ if ($marker->isBookmark()) {
+ $log->writeStatus(
+ pht('BOOKMARK'),
+ pht(
+ 'Checking out bookmark "%s".',
+ $marker->getName()));
+ } else {
+ $log->writeStatus(
+ pht('BRANCH'),
+ pht(
+ 'Checking out branch "%s".',
+ $marker->getName()));
+ }
+
+ $future = $api->newFuture(
+ 'checkout %s --',
+ $marker->getName());
+
+ $future->resolve();
+ }
+
+}
diff --git a/src/work/ArcanistWorkEngine.php b/src/work/ArcanistWorkEngine.php
new file mode 100644
--- /dev/null
+++ b/src/work/ArcanistWorkEngine.php
@@ -0,0 +1,215 @@
+<?php
+
+abstract class ArcanistWorkEngine
+ extends ArcanistWorkflowEngine {
+
+ private $symbolArgument;
+ private $startArgument;
+
+ final public function setSymbolArgument($symbol_argument) {
+ $this->symbolArgument = $symbol_argument;
+ return $this;
+ }
+
+ final public function getSymbolArgument() {
+ return $this->symbolArgument;
+ }
+
+ final public function setStartArgument($start_argument) {
+ $this->startArgument = $start_argument;
+ return $this;
+ }
+
+ final public function getStartArgument() {
+ return $this->startArgument;
+ }
+
+ final public function execute() {
+ $workflow = $this->getWorkflow();
+ $api = $this->getRepositoryAPI();
+
+ $local_state = $api->newLocalState()
+ ->setWorkflow($workflow)
+ ->saveLocalState();
+
+ $symbol = $this->getSymbolArgument();
+
+ $markers = $api->newMarkerRefQuery()
+ ->withNames(array($symbol))
+ ->execute();
+
+ if ($markers) {
+ if (count($markers) > 1) {
+
+ // TODO: This almost certainly means the symbol is a Mercurial branch
+ // with multiple heads. We can pick some head.
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Symbol "%s" is ambiguous.',
+ $symbol));
+ }
+
+ $target = head($markers);
+ $this->moveToMarker($target);
+ $local_state->discardLocalState();
+ return;
+ }
+
+ $revision_marker = $this->workOnRevision($symbol);
+ if ($revision_marker) {
+ $this->moveToMarker($revision_marker);
+ $local_state->discardLocalState();
+ return;
+ }
+
+ $task_marker = $this->workOnTask($symbol);
+ if ($task_marker) {
+ $this->moveToMarker($task_marker);
+ $local_state->discardLocalState();
+ return;
+ }
+
+ // NOTE: We're resolving this symbol so we can raise an error message if
+ // it's bogus, but we're using the symbol (not the resolved version) to
+ // actually create the new marker. This matters in Git because it impacts
+ // the behavior of "--track" when we pass a branch name.
+
+ $start = $this->getStartArgument();
+ if ($start !== null) {
+ $start_commit = $api->getCanonicalRevisionName($start);
+ if (!$start_commit) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Unable to resolve startpoint "%s".',
+ $start));
+ }
+ } else {
+ $start = $this->getDefaultStartSymbol();
+ }
+
+ $this->newMarker($symbol, $start);
+ $local_state->discardLocalState();
+ }
+
+ abstract protected function newMarker($symbol, $start);
+ abstract protected function moveToMarker(ArcanistMarkerRef $marker);
+ abstract protected function getDefaultStartSymbol();
+
+ private function workOnRevision($symbol) {
+ $workflow = $this->getWorkflow();
+ $api = $this->getRepositoryAPI();
+ $log = $this->getLogEngine();
+
+ try {
+ $revision_symbol = id(new ArcanistRevisionSymbolRef())
+ ->setSymbol($symbol);
+ } catch (Exception $ex) {
+ return;
+ }
+
+ $workflow->loadHardpoints(
+ $revision_symbol,
+ ArcanistSymbolRef::HARDPOINT_OBJECT);
+
+ $revision_ref = $revision_symbol->getObject();
+ if (!$revision_ref) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'No revision "%s" exists, or you do not have permission to '.
+ 'view it.',
+ $symbol));
+ }
+
+ $markers = $api->newMarkerRefQuery()
+ ->execute();
+
+ $state_refs = mpull($markers, 'getWorkingCopyStateRef');
+
+ $workflow->loadHardpoints(
+ $state_refs,
+ ArcanistWorkingCopyStateRef::HARDPOINT_REVISIONREFS);
+
+ $selected = array();
+ foreach ($markers as $marker) {
+ $state_ref = $marker->getWorkingCopyStateRef();
+ $revision_refs = $state_ref->getRevisionRefs();
+ $revision_refs = mpull($revision_refs, null, 'getPHID');
+
+ if (isset($revision_refs[$revision_ref->getPHID()])) {
+ $selected[] = $marker;
+ }
+ }
+
+ if (!$selected) {
+
+ // TODO: We could patch/load here.
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Revision "%s" was not found anywhere in this working copy.',
+ $revision_ref->getMonogram()));
+ }
+
+ if (count($selected) > 1) {
+ $selected = msort($selected, 'getEpoch');
+
+ echo tsprintf(
+ "\n%!\n%W\n\n",
+ pht('AMBIGUOUS MARKER'),
+ pht(
+ 'More than one marker in the local working copy is associated '.
+ 'with the revision "%s", using the most recent one.',
+ $revision_ref->getMonogram()));
+
+ foreach ($selected as $marker) {
+ echo tsprintf('%s', $marker->newDisplayRef());
+ }
+
+ echo tsprintf("\n");
+
+ $target = last($selected);
+ } else {
+ $target = head($selected);
+ }
+
+ $log->writeStatus(
+ pht('REVISION'),
+ pht('Resuming work on revision:'));
+
+ echo tsprintf('%s', $revision_ref->newDisplayRef());
+ echo tsprintf("\n");
+
+ return $target;
+ }
+
+ private function workOnTask($symbol) {
+ $workflow = $this->getWorkflow();
+
+ try {
+ $task_symbol = id(new ArcanistTaskSymbolRef())
+ ->setSymbol($symbol);
+ } catch (Exception $ex) {
+ return;
+ }
+
+ $workflow->loadHardpoints(
+ $task_symbol,
+ ArcanistSymbolRef::HARDPOINT_OBJECT);
+
+ $task_ref = $task_symbol->getObject();
+ if (!$task_ref) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'No task "%s" exists, or you do not have permission to view it.',
+ $symbol));
+ }
+
+ throw new Exception(pht('TODO: Implement this workflow.'));
+
+ $this->loadHardpoints(
+ $task_ref,
+ ArcanistTaskRef::HARDPOINT_REVISIONREFS);
+ }
+
+}
diff --git a/src/workflow/ArcanistWorkWorkflow.php b/src/workflow/ArcanistWorkWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/workflow/ArcanistWorkWorkflow.php
@@ -0,0 +1,95 @@
+<?php
+
+final class ArcanistWorkWorkflow
+ extends ArcanistArcWorkflow {
+
+ public function getWorkflowName() {
+ return 'work';
+ }
+
+ public function getWorkflowArguments() {
+ return array(
+ $this->newWorkflowArgument('start')
+ ->setParameter('symbol')
+ ->setHelp(
+ pht(
+ 'When creating a new branch or bookmark, use this as the '.
+ 'branch point.')),
+ $this->newWorkflowArgument('symbol')
+ ->setWildcard(true),
+ );
+ }
+
+ public function getWorkflowInformation() {
+ $help = pht(<<<EOHELP
+Begin or resume work on a branch, bookmark, task, or revision.
+
+The __symbol__ may be a branch or bookmark name, a revision name (like "D123"),
+a task name (like "T123"), or a new symbol.
+
+If you provide a symbol which currently does not identify any ongoing work,
+Arcanist will create a new branch or bookmark with the name you provide.
+
+If you provide the name of an existing branch or bookmark, Arcanist will switch
+to that branch or bookmark.
+
+If you provide the name of a revision or task, Arcanist will look for a related
+branch or bookmark that exists in the working copy. If it finds one, it will
+switch to it. If it does not find one, it will attempt to create a new branch
+or bookmark.
+
+When "arc work" creates a branch or bookmark, it will use "--start" as the
+branchpoint if it is provided. Otherwise, the current working copy state will
+serve as the starting point.
+EOHELP
+ );
+
+ return $this->newWorkflowInformation()
+ ->setSynopsis(pht('Begin or resume work.'))
+ ->addExample(pht('**work** [--start __start__] __symbol__'))
+ ->setHelp($help);
+ }
+
+ public function runWorkflow() {
+ $api = $this->getRepositoryAPI();
+
+ $work_engine = $api->getWorkEngine();
+ if (!$work_engine) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ '"arc work" must be run in a Git or Mercurial working copy.'));
+ }
+
+ $argv = $this->getArgument('symbol');
+ if (count($argv) === 0) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Provide a branch, bookmark, task, or revision name to begin '.
+ 'or resume work on.'));
+ } else if (count($argv) === 1) {
+ $symbol_argument = $argv[0];
+ if (!strlen($symbol_argument)) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Provide a nonempty symbol to begin or resume work on.'));
+ }
+ } else {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Too many arguments: provide exactly one argument.'));
+ }
+
+ $start_argument = $this->getArgument('start');
+
+ $work_engine
+ ->setViewer($this->getViewer())
+ ->setWorkflow($this)
+ ->setLogEngine($this->getLogEngine())
+ ->setSymbolArgument($symbol_argument)
+ ->setStartArgument($start_argument)
+ ->execute();
+
+ return 0;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
May 16 2024, 12:15 AM (4 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6274695
Default Alt Text
D21336.diff (27 KB)

Event Timeline