diff --git a/resources/sql/autopatches/20151114.diffusion.callsign.sql b/resources/sql/autopatches/20151114.diffusion.callsign.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20151114.diffusion.callsign.sql @@ -0,0 +1,3 @@ +ALTER TABLE {$NAMESPACE}_repository.repository + CHANGE callsign callsign VARCHAR(32) + CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL; diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -65,7 +65,7 @@ '(?:query/(?P[^/]+)/)?' => 'DiffusionPushLogListController', 'view/(?P\d+)/' => 'DiffusionPushEventViewController', ), - '(?P[A-Z]+)/' => array( + '((?P[A-Z]+)|(?P[1-9][0-9]*))/' => array( '' => 'DiffusionRepositoryController', 'repository/(?P.*)' => 'DiffusionRepositoryController', @@ -78,6 +78,8 @@ 'branches/(?P.*)' => 'DiffusionBranchTableController', 'refs/(?P.*)' => 'DiffusionRefTableController', 'lint/(?P.*)' => 'DiffusionLintController', + 'commit/(?P[a-z0-9]+)' + => 'DiffusionCommitController', 'commit/(?P[a-z0-9]+)/branches/' => 'DiffusionCommitBranchesController', 'commit/(?P[a-z0-9]+)/tags/' diff --git a/src/applications/diffusion/controller/DiffusionController.php b/src/applications/diffusion/controller/DiffusionController.php --- a/src/applications/diffusion/controller/DiffusionController.php +++ b/src/applications/diffusion/controller/DiffusionController.php @@ -36,12 +36,12 @@ } final public function handleRequest(AphrontRequest $request) { - if ($request->getURIData('callsign') && + if (($request->getURIData('callsign') || $request->getURIData('id')) && $this->shouldLoadDiffusionRequest()) { try { - $drequest = DiffusionRequest::newFromAphrontRequestDictionary( - $request->getURIMap(), - $request); + $drequest = DiffusionRequest::newFromAphrontRequestDictionary( + $request->getURIMap(), + $request); } catch (Exception $ex) { return id(new Aphront404Response()) ->setRequest($request); diff --git a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php --- a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php @@ -174,16 +174,6 @@ ->setTransactionType($type_service) ->setNewValue($service->getPHID()); } - - $default_local_path = PhabricatorEnv::getEnvConfig( - 'repository.default-local-path'); - - $default_local_path = rtrim($default_local_path, '/'); - $default_local_path = $default_local_path.'/'.$callsign.'/'; - - $xactions[] = id(clone $template) - ->setTransactionType($type_local_path) - ->setNewValue($default_local_path); } if ($is_init) { @@ -418,31 +408,29 @@ $c_call = $page->getControl('callsign'); $v_call = $c_call->getValue(); - if (!strlen($v_call)) { - $c_call->setError(pht('Required')); - $page->addPageError( - pht('You must choose a callsign for this repository.')); - } else if (!preg_match('/^[A-Z]+\z/', $v_call)) { - $c_call->setError(pht('Invalid')); - $page->addPageError( - pht('The callsign must contain only UPPERCASE letters.')); - } else { - $exists = false; - try { - $repo = id(new PhabricatorRepositoryQuery()) - ->setViewer($this->getRequest()->getUser()) - ->withCallsigns(array($v_call)) - ->executeOne(); - $exists = (bool)$repo; - } catch (PhabricatorPolicyException $ex) { - $exists = true; - } - if ($exists) { - $c_call->setError(pht('Not Unique')); + if (strlen($v_call)) { + if (!preg_match('/^[A-Z]+\z/', $v_call)) { + $c_call->setError(pht('Invalid')); $page->addPageError( - pht( - 'Another repository already uses that callsign. You must choose '. - 'a unique callsign.')); + pht('The callsign must contain only UPPERCASE letters.')); + } else { + $exists = false; + try { + $repo = id(new PhabricatorRepositoryQuery()) + ->setViewer($this->getRequest()->getUser()) + ->withCallsigns(array($v_call)) + ->executeOne(); + $exists = (bool)$repo; + } catch (PhabricatorPolicyException $ex) { + $exists = true; + } + if ($exists) { + $c_call->setError(pht('Not Unique')); + $page->addPageError( + pht( + 'Another repository already uses that callsign. You must choose '. + 'a unique callsign.')); + } } } diff --git a/src/applications/diffusion/request/DiffusionRequest.php b/src/applications/diffusion/request/DiffusionRequest.php --- a/src/applications/diffusion/request/DiffusionRequest.php +++ b/src/applications/diffusion/request/DiffusionRequest.php @@ -60,6 +60,17 @@ * @task new */ final public static function newFromDictionary(array $data) { + if (isset($data['callsign']) && !strlen($data['callsign'])) { + unset($data['callsign']); + } + + if (isset($data['id'])) { + $data['repository'] = id(new PhabricatorRepositoryQuery()) + ->setViewer($data['user']) + ->withIDs(array($data['id'])) + ->executeOne(); + } + if (isset($data['repository']) && isset($data['callsign'])) { throw new Exception( pht( @@ -105,8 +116,12 @@ array $data, AphrontRequest $request) { - $callsign = phutil_unescape_uri_path_component(idx($data, 'callsign')); - $object = self::newFromCallsign($callsign, $request->getUser()); + if (isset($data['id']) && $data['id']) { + $object = self::newFromId($data['id'], $request->getUser()); + } else { + $callsign = phutil_unescape_uri_path_component(idx($data, 'callsign')); + $object = self::newFromCallsign($callsign, $request->getUser()); + } $use_branches = $object->supportsBranches(); @@ -141,6 +156,27 @@ /** * Internal. Use @{method:newFromDictionary}, not this method. * + * @param id Repository ID. + * @param PhabricatorUser Viewing user. + * @return DiffusionRequest New request object. + * @task new + */ + final private static function newFromId($id, PhabricatorUser $viewer) { + $repository = id(new PhabricatorRepositoryQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + + if (!$repository) { + throw new Exception(pht('No such repository with ID %d.', $id)); + } + + return self::newFromRepository($repository); + } + + /** + * Internal. Use @{method:newFromDictionary}, not this method. + * * @param string Repository callsign. * @param PhabricatorUser Viewing user. * @return DiffusionRequest New request object. @@ -522,40 +558,14 @@ $req_commit = false; switch ($action) { - case 'history': - case 'browse': - case 'change': - case 'lastmodified': - case 'tags': - case 'branches': - case 'lint': - case 'refs': - $req_callsign = true; - break; case 'branch': - $req_callsign = true; $req_branch = true; break; case 'commit': - $req_callsign = true; $req_commit = true; break; } - if ($req_callsign && !strlen($callsign)) { - throw new Exception( - pht( - "Diffusion URI action '%s' requires callsign!", - $action)); - } - - if ($req_commit && !strlen($commit)) { - throw new Exception( - pht( - "Diffusion URI action '%s' requires commit!", - $action)); - } - switch ($action) { case 'change': case 'history': diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -92,7 +92,7 @@ ), self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'sort255', - 'callsign' => 'sort32', + 'callsign' => 'sort32?', 'versionControlSystem' => 'text32', 'uuid' => 'text64?', 'pushPolicy' => 'policy', @@ -215,7 +215,20 @@ } public function getLocalPath() { - return $this->getDetail('local-path'); + $local_path = $this->getDetail('local-path'); + + if (!$local_path) { + $default_local_path = PhabricatorEnv::getEnvConfig( + 'repository.default-local-path'); + + $default_local_path = rtrim($default_local_path, '/'); + + $default_local_path = implode('/', array( + $default_local_path, + coalesce($this->getCallsign(), $this->getId()), + '', + )); + } } public function getSubversionBaseURI($commit = null) {