1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Add "Clone As" to repositories and generate full clone commands in UI

Summary:
Ref T4175.

  - Add a configurable name for the clone-as directory, so you can have "Bits & Pieces" clone as "bits~n~pieces/" or simliar.
  - By default, use "reasonable" heruistics to choose such a name.
  - Generate a copy/pasteable clone commmand with this directory name.

Test Plan: Looked at some repositories.

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T4175

Differential Revision: https://secure.phabricator.com/D8097
This commit is contained in:
epriestley 2014-01-30 11:42:10 -08:00
parent 96dd530c44
commit ffeee37810
7 changed files with 124 additions and 10 deletions

View file

@ -176,38 +176,50 @@ final class DiffusionRepositoryController extends DiffusionController {
if ($repository->isHosted()) {
$ssh_uri = $repository->getSSHCloneURIObject();
if ($ssh_uri) {
$clone_uri = $this->renderCloneURI(
$clone_uri = $this->renderCloneCommand(
$repository,
$ssh_uri,
$repository->getServeOverSSH(),
'/settings/panel/ssh/');
$view->addProperty(pht('Clone URI (SSH)'), $clone_uri);
$view->addProperty(
$repository->isSVN()
? pht('Checkout (SSH)')
: pht('Clone (SSH)'),
$clone_uri);
}
$http_uri = $repository->getHTTPCloneURIObject();
if ($http_uri) {
$clone_uri = $this->renderCloneURI(
$clone_uri = $this->renderCloneCommand(
$repository,
$http_uri,
$repository->getServeOverHTTP(),
PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')
? '/settings/panel/vcspassword/'
: null);
$view->addProperty(pht('Clone URI (HTTP)'), $clone_uri);
$view->addProperty(
$repository->isSVN()
? pht('Checkout (HTTP)')
: pht('Clone (HTTP)'),
$clone_uri);
}
} else {
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$view->addProperty(
pht('Clone URI'),
$this->renderCloneURI(
pht('Clone'),
$this->renderCloneCommand(
$repository,
$repository->getPublicCloneURI()));
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$view->addProperty(
pht('Repository Root'),
$this->renderCloneURI(
pht('Checkout'),
$this->renderCloneCommand(
$repository,
$repository->getPublicCloneURI()));
break;
}
@ -526,7 +538,8 @@ final class DiffusionRepositoryController extends DiffusionController {
return $browse_panel;
}
private function renderCloneURI(
private function renderCloneCommand(
PhabricatorRepository $repository,
$uri,
$serve_mode = null,
$manage_uri = null) {
@ -535,11 +548,32 @@ final class DiffusionRepositoryController extends DiffusionController {
Javelin::initBehavior('select-on-click');
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$command = csprintf(
'git clone %s %s',
$uri,
$repository->getCloneName());
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$command = csprintf(
'hg clone %s %s',
$uri,
$repository->getCloneName());
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$command = csprintf(
'svn checkout %s %s',
$uri,
$repository->getCloneName());
break;
}
$input = javelin_tag(
'input',
array(
'type' => 'text',
'value' => (string)$uri,
'value' => (string)$command,
'class' => 'diffusion-clone-uri',
'sigil' => 'select-on-click',
'readonly' => 'true',

View file

@ -28,6 +28,7 @@ final class DiffusionRepositoryEditBasicController
$v_name = $repository->getName();
$v_desc = $repository->getDetail('description');
$v_clone_name = $repository->getDetail('clone-name');
$e_name = true;
$errors = array();
@ -35,6 +36,7 @@ final class DiffusionRepositoryEditBasicController
$v_name = $request->getStr('name');
$v_desc = $request->getStr('description');
$v_projects = $request->getArr('projectPHIDs');
$v_clone_name = $request->getStr('cloneName');
if (!strlen($v_name)) {
$e_name = pht('Required');
@ -50,6 +52,7 @@ final class DiffusionRepositoryEditBasicController
$type_name = PhabricatorRepositoryTransaction::TYPE_NAME;
$type_desc = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION;
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$type_clone_name = PhabricatorRepositoryTransaction::TYPE_CLONE_NAME;
$xactions[] = id(clone $template)
->setTransactionType($type_name)
@ -59,6 +62,10 @@ final class DiffusionRepositoryEditBasicController
->setTransactionType($type_desc)
->setNewValue($v_desc);
$xactions[] = id(clone $template)
->setTransactionType($type_clone_name)
->setNewValue($v_clone_name);
$xactions[] = id(clone $template)
->setTransactionType($type_edge)
->setMetadataValue(
@ -93,6 +100,15 @@ final class DiffusionRepositoryEditBasicController
->setLabel(pht('Name'))
->setValue($v_name)
->setError($e_name))
->appendChild(
id(new AphrontFormTextControl())
->setName('cloneName')
->setLabel(pht('Clone/Checkout As'))
->setValue($v_clone_name)
->setCaption(
pht(
'Optional directory name to use when cloning or checking out '.
'this repository.')))
->appendChild(
id(new PhabricatorRemarkupControl())
->setName('description')

View file

@ -253,6 +253,15 @@ final class DiffusionRepositoryEditMainController
$view->addProperty(pht('Type'), $type);
$view->addProperty(pht('Callsign'), $repository->getCallsign());
$clone_name = $repository->getDetail('clone-name');
$view->addProperty(
pht('Clone/Checkout As'),
$clone_name
? $clone_name.'/'
: phutil_tag('em', array(), $repository->getCloneName().'/'));
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$repository->getPHID(),
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT);

View file

@ -31,6 +31,7 @@ final class PhabricatorRepositoryEditor
$types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
$types[] = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
$types[] = PhabricatorRepositoryTransaction::TYPE_DANGEROUS;
$types[] = PhabricatorRepositoryTransaction::TYPE_CLONE_NAME;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
@ -84,6 +85,8 @@ final class PhabricatorRepositoryEditor
return $object->getCredentialPHID();
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
return $object->shouldAllowDangerousChanges();
case PhabricatorRepositoryTransaction::TYPE_CLONE_NAME:
return $object->getDetail('clone-name');
}
}
@ -115,6 +118,7 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
case PhabricatorRepositoryTransaction::TYPE_CLONE_NAME:
return $xaction->getNewValue();
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
@ -183,6 +187,9 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
$object->setDetail('allow-dangerous-changes', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_CLONE_NAME:
$object->setDetail('clone-name', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't type
@ -294,6 +301,7 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
case PhabricatorRepositoryTransaction::TYPE_CLONE_NAME:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,

View file

@ -212,6 +212,34 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
}
/**
* Get the name of the directory this repository should clone or checkout
* into. For example, if the repository name is "Example Repository", a
* reasonable name might be "example-repository". This is used to help users
* get reasonable results when cloning repositories, since they generally do
* not want to clone into directories called "X/" or "Example Repository/".
*
* @return string
*/
public function getCloneName() {
$name = $this->getDetail('clone-name');
// Make some reasonable effort to produce reasonable default directory
// names from repository names.
if (!strlen($name)) {
$name = $this->getName();
$name = phutil_utf8_strtolower($name);
$name = preg_replace('@[/ -:]+@', '-', $name);
$name = trim($name, '-');
if (!strlen($name)) {
$name = $this->getCallsign();
}
}
return $name;
}
/* -( Remote Command Execution )------------------------------------------- */

View file

@ -23,6 +23,7 @@ final class PhabricatorRepositoryTransaction
const TYPE_PUSH_POLICY = 'repo:push-policy';
const TYPE_CREDENTIAL = 'repo:credential';
const TYPE_DANGEROUS = 'repo:dangerous';
const TYPE_CLONE_NAME = 'repo:clone-name';
// TODO: Clean up these legacy transaction types.
const TYPE_SSH_LOGIN = 'repo:ssh-login';
@ -349,6 +350,23 @@ final class PhabricatorRepositoryTransaction
'%s enabled protection against dangerous changes.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_CLONE_NAME:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the clone name of this repository.',
$this->renderHandleLink($author_phid));
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the clone name of this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the clone name of this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
}
return parent::getTitle();

View file

@ -228,6 +228,7 @@ abstract class PhabricatorApplicationTransactionEditor
private function applyInternalEffects(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());