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 @@ -30,6 +30,7 @@ 'ArcanistCheckstyleXMLLintRenderer' => 'lint/renderer/ArcanistCheckstyleXMLLintRenderer.php', 'ArcanistChmodLinter' => 'lint/linter/ArcanistChmodLinter.php', 'ArcanistChmodLinterTestCase' => 'lint/linter/__tests__/ArcanistChmodLinterTestCase.php', + 'ArcanistClaimWorkflow' => 'workflow/ArcanistClaimWorkflow.php', 'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php', 'ArcanistCloseWorkflow' => 'workflow/ArcanistCloseWorkflow.php', 'ArcanistClosureLinter' => 'lint/linter/ArcanistClosureLinter.php', @@ -230,6 +231,7 @@ 'ArcanistCheckstyleXMLLintRenderer' => 'ArcanistLintRenderer', 'ArcanistChmodLinter' => 'ArcanistLinter', 'ArcanistChmodLinterTestCase' => 'ArcanistLinterTestCase', + 'ArcanistClaimWorkflow' => 'ArcanistWorkflow', 'ArcanistCloseRevisionWorkflow' => 'ArcanistWorkflow', 'ArcanistCloseWorkflow' => 'ArcanistWorkflow', 'ArcanistClosureLinter' => 'ArcanistExternalLinter', diff --git a/src/workflow/ArcanistClaimWorkflow.php b/src/workflow/ArcanistClaimWorkflow.php new file mode 100644 --- /dev/null +++ b/src/workflow/ArcanistClaimWorkflow.php @@ -0,0 +1,118 @@ + 'task_id', + /* 'release' => array( + 'help' => 'Place the task back up for grabs' + )*/ + ); + } + + public function run() { + $ids = $this->getArgument('task_id'); + $release = $this->getArgument('release'); + + foreach ($ids as $id) { + if (!preg_match('/^T?\d+$/', $id)) { + echo "Invalid Task ID: {$id}.\n"; + return 1; + } + $id = ltrim($id, 'T'); + + if ($release) { + $result = $this->releaseTask($id); + + if ($result) { + echo "T{$id} is up for grabs.\n"; + } else { + echo "T{$id} is not assigned to you.\n"; + } + } else { + $result = $this->claimTask($id); + + if ($result) { + echo "T{$id} is now assigned to you.\n"; + } else { + echo "T{$id} is already assigned to you.\n"; + } + } + + } + return 0; + } + + // FIXME: maniphest.update does not accept a single null value + private function releaseTask($task_id) { + $conduit = $this->getConduit(); + $info = $conduit->callMethodSynchronous( + 'maniphest.info', + array( + 'task_id' => $task_id, + )); + if ($info['ownerPHID'] != $this->getUserPHID()) { + return false; + } + return $conduit->callMethodSynchronous( + 'maniphest.update', + array( + 'id' => $task_id, + 'ownerPHID' => null, + )); + } + + private function claimTask($task_id) { + $conduit = $this->getConduit(); + $info = $conduit->callMethodSynchronous( + 'maniphest.info', + array( + 'task_id' => $task_id, + )); + if ($info['ownerPHID'] == $this->getUserPHID()) { + return false; + } + return $conduit->callMethodSynchronous( + 'maniphest.update', + array( + 'id' => $task_id, + 'ownerPHID' => $this->getUserPHID(), + )); + } + +} diff --git a/src/workflow/ArcanistFeatureWorkflow.php b/src/workflow/ArcanistFeatureWorkflow.php --- a/src/workflow/ArcanistFeatureWorkflow.php +++ b/src/workflow/ArcanistFeatureWorkflow.php @@ -31,7 +31,8 @@ With __name__, it creates or checks out a branch. If the branch __name__ doesn't exist and is in format D123 then the branch of - revision D123 is checked out. Use __start__ to specify where the new + revision D123 is checked out. If the format is T123 the corresponding + task will be assigned to you. Use __start__ to specify where the new branch will start. Use 'arc.feature.start.default' to set the default feature start location. EOTEXT @@ -47,7 +48,12 @@ } public function requiresAuthentication() { - return !$this->getArgument('branch'); + // We need authentication if the branch specifies a revision or a task + $branch = $this->getArgument('branch'); + if (!isset($branch[0]) || preg_match('/^[DT](\d+)$/', $branch[0])) { + return true; + } + return false; } public function getArguments() { @@ -140,6 +146,41 @@ $name); } } catch (ConduitClientException $ex) {} + } else if (preg_match('/^T(\d+)$/', $name, $match)) { + // The specified branch looks like a task - Try to assign it to me + try { + $info = $this->getConduit()->callMethodSynchronous( + 'maniphest.info', + array( + 'task_id' => $match[1], + )); + + if ($info['ownerPHID'] != $this->getUserPHID()) { + if ($info['ownerPHID'] != null) { + $owner = $this->getConduit()->callMethodSynchronous( + 'user.query', + array( + 'phids' => array($info['ownerPHID']), + )); + + if (isset($owner[0])) { + echo "Task is already assigned to ".$owner[0]['userName'].".\n"; + } else { + echo "Task is already assigned to someone else.\n"; + } + } else { + $result = $this->getConduit()->callMethodSynchronous( + 'maniphest.update', + array( + 'id' => $match[1], + 'ownerPHID' => $this->getUserPHID(), + )); + if ($result) { + echo "T{$match[1]} is now assigned to you.\n"; + } + } + } + } catch (ConduitClientException $ex) {} } }