1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-21 22:32:41 +01:00

Load and map repository objects for remote URIs

Summary:
Ref T13546. Query and associate known Phabricator repositories to working copy remotes by normalizing and comparing URIs.

This primarily gives us access to "permanentRefRules" so we can tell which branches have published changes.

Test Plan: Ran "arc look remotes" in Git and Mercurial working copies, saw repositories map properly.

Maniphest Tasks: T13546

Differential Revision: https://secure.phabricator.com/D21377
This commit is contained in:
epriestley 2020-06-30 13:03:20 -07:00
parent 6bf7a40358
commit 50f7a853b5
9 changed files with 232 additions and 3 deletions

View file

@ -422,6 +422,7 @@ phutil_register_library_map(array(
'ArcanistRefView' => 'ref/ArcanistRefView.php', 'ArcanistRefView' => 'ref/ArcanistRefView.php',
'ArcanistRemoteRef' => 'repository/remote/ArcanistRemoteRef.php', 'ArcanistRemoteRef' => 'repository/remote/ArcanistRemoteRef.php',
'ArcanistRemoteRefInspector' => 'repository/remote/ArcanistRemoteRefInspector.php', 'ArcanistRemoteRefInspector' => 'repository/remote/ArcanistRemoteRefInspector.php',
'ArcanistRemoteRepositoryRefsHardpointQuery' => 'repository/remote/ArcanistRemoteRepositoryRefsHardpointQuery.php',
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php', 'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
'ArcanistRepositoryAPIMiscTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIMiscTestCase.php', 'ArcanistRepositoryAPIMiscTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIMiscTestCase.php',
'ArcanistRepositoryAPIStateTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php', 'ArcanistRepositoryAPIStateTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php',
@ -1455,6 +1456,7 @@ phutil_register_library_map(array(
), ),
'ArcanistRemoteRef' => 'ArcanistRef', 'ArcanistRemoteRef' => 'ArcanistRef',
'ArcanistRemoteRefInspector' => 'ArcanistRefInspector', 'ArcanistRemoteRefInspector' => 'ArcanistRefInspector',
'ArcanistRemoteRepositoryRefsHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistRepositoryAPI' => 'Phobject', 'ArcanistRepositoryAPI' => 'Phobject',
'ArcanistRepositoryAPIMiscTestCase' => 'PhutilTestCase', 'ArcanistRepositoryAPIMiscTestCase' => 'PhutilTestCase',
'ArcanistRepositoryAPIStateTestCase' => 'PhutilTestCase', 'ArcanistRepositoryAPIStateTestCase' => 'PhutilTestCase',

View file

@ -3,6 +3,7 @@
final class ArcanistRepositoryRef final class ArcanistRepositoryRef
extends ArcanistRef { extends ArcanistRef {
private $parameters = array();
private $phid; private $phid;
private $browseURI; private $browseURI;
@ -24,6 +25,37 @@ final class ArcanistRepositoryRef
return $this; return $this;
} }
public static function newFromConduit(array $map) {
$ref = new self();
$ref->parameters = $map;
$ref->phid = $map['phid'];
return $ref;
}
public function getURIs() {
$uris = idxv($this->parameters, array('attachments', 'uris', 'uris'));
if (!$uris) {
return array();
}
$results = array();
foreach ($uris as $uri) {
$effective_uri = idxv($uri, array('fields', 'uri', 'effective'));
if ($effective_uri !== null) {
$results[] = $effective_uri;
}
}
return $results;
}
public function getDisplayName() {
return idxv($this->parameters, array('fields', 'name'));
}
public function newBrowseURI(array $params) { public function newBrowseURI(array $params) {
PhutilTypeSpec::checkMap( PhutilTypeSpec::checkMap(
$params, $params,
@ -67,9 +99,13 @@ final class ArcanistRepositoryRef
} }
public function getDefaultBranch() { public function getDefaultBranch() {
// TODO: This should read from the remote, and is not correct for $branch = idxv($this->parameters, array('fields', 'defaultBranch'));
// Mercurial anyway, as "default" would be a better default branch.
return 'master'; if ($branch === null) {
return 'master';
}
return $branch;
} }
} }

View file

@ -1767,4 +1767,10 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
return new ArcanistGitRepositoryRemoteQuery(); return new ArcanistGitRepositoryRemoteQuery();
} }
protected function newNormalizedURI($uri) {
return new ArcanistRepositoryURINormalizer(
ArcanistRepositoryURINormalizer::TYPE_GIT,
$uri);
}
} }

View file

@ -1025,4 +1025,10 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
); );
} }
protected function newNormalizedURI($uri) {
return new ArcanistRepositoryURINormalizer(
ArcanistRepositoryURINormalizer::TYPE_MERCURIAL,
$uri);
}
} }

View file

@ -798,4 +798,13 @@ abstract class ArcanistRepositoryAPI extends Phobject {
return substr($hash, 0, 12); return substr($hash, 0, 12);
} }
final public function getNormalizedURI($uri) {
$normalized_uri = $this->newNormalizedURI($uri);
return $normalized_uri->getNormalizedURI();
}
protected function newNormalizedURI($uri) {
return $uri;
}
} }

View file

@ -3,14 +3,26 @@
final class ArcanistRemoteRef final class ArcanistRemoteRef
extends ArcanistRef { extends ArcanistRef {
private $repositoryAPI;
private $remoteName; private $remoteName;
private $fetchURI; private $fetchURI;
private $pushURI; private $pushURI;
const HARDPOINT_REPOSITORYREFS = 'arc.remote.repositoryRefs';
public function getRefDisplayName() { public function getRefDisplayName() {
return pht('Remote "%s"', $this->getRemoteName()); return pht('Remote "%s"', $this->getRemoteName());
} }
public function setRepositoryAPI(ArcanistRepositoryAPI $repository_api) {
$this->repositoryAPI = $repository_api;
return $this;
}
public function getRepositoryAPI() {
return $this->repositoryAPI;
}
public function setRemoteName($remote_name) { public function setRemoteName($remote_name) {
$this->remoteName = $remote_name; $this->remoteName = $remote_name;
return $this; return $this;
@ -42,4 +54,39 @@ final class ArcanistRemoteRef
$view->setObjectName($this->getRemoteName()); $view->setObjectName($this->getRemoteName());
} }
protected function newHardpoints() {
$object_list = new ArcanistObjectListHardpoint();
return array(
$this->newTemplateHardpoint(self::HARDPOINT_REPOSITORYREFS, $object_list),
);
}
private function getRepositoryRefs() {
return $this->getHardpoint(self::HARDPOINT_REPOSITORYREFS);
}
public function getPushRepositoryRef() {
return $this->getRepositoryRefByURI($this->getPushURI());
}
public function getFetchRepositoryRef() {
return $this->getRepositoryRefByURI($this->getFetchURI());
}
private function getRepositoryRefByURI($uri) {
$api = $this->getRepositoryAPI();
$uri = $api->getNormalizedURI($uri);
foreach ($this->getRepositoryRefs() as $repository_ref) {
foreach ($repository_ref->getURIs() as $repository_uri) {
$repository_uri = $api->getNormalizedURI($repository_uri);
if ($repository_uri === $uri) {
return $repository_ref;
}
}
}
return null;
}
} }

View file

@ -0,0 +1,89 @@
<?php
final class ArcanistRemoteRepositoryRefsHardpointQuery
extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
ArcanistRemoteRef::HARDPOINT_REPOSITORYREFS,
);
}
protected function canLoadRef(ArcanistRef $ref) {
return ($ref instanceof ArcanistRemoteRef);
}
public function loadHardpoint(array $refs, $hardpoint) {
$api = $this->getRepositoryAPI();
$uris = array();
foreach ($refs as $remote) {
$fetch_uri = $remote->getFetchURI();
if ($fetch_uri !== null) {
$uris[] = $fetch_uri;
}
$push_uri = $remote->getPushURI();
if ($push_uri !== null) {
$uris[] = $push_uri;
}
}
if (!$uris) {
yield $this->yieldValue($refs, array());
}
$uris = array_fuse($uris);
$uris = array_values($uris);
$search_future = $this->newConduitSearch(
'diffusion.repository.search',
array(
'uris' => $uris,
),
array(
'uris' => true,
));
$repository_info = (yield $this->yieldFuture($search_future));
$repository_refs = array();
foreach ($repository_info as $raw_result) {
$repository_refs[] = ArcanistRepositoryRef::newFromConduit($raw_result);
}
$uri_map = array();
foreach ($repository_refs as $repository_ref) {
foreach ($repository_ref->getURIs() as $repository_uri) {
$repository_uri = $api->getNormalizedURI($repository_uri);
$uri_map[$repository_uri] = $repository_ref;
}
}
$results = array();
foreach ($refs as $key => $remote) {
$result = array();
$fetch_uri = $remote->getFetchURI();
if ($fetch_uri !== null) {
$fetch_uri = $api->getNormalizedURI($fetch_uri);
if (isset($uri_map[$fetch_uri])) {
$result[] = $uri_map[$fetch_uri];
}
}
$push_uri = $remote->getPushURI();
if ($push_uri !== null) {
$push_uri = $api->getNormalizedURI($push_uri);
if (isset($uri_map[$push_uri])) {
$result[] = $uri_map[$push_uri];
}
}
$results[$key] = $result;
}
yield $this->yieldMap($results);
}
}

View file

@ -11,8 +11,13 @@ abstract class ArcanistRepositoryRemoteQuery
} }
final public function execute() { final public function execute() {
$api = $this->getRepositoryAPI();
$refs = $this->newRemoteRefs(); $refs = $this->newRemoteRefs();
foreach ($refs as $ref) {
$ref->setRepositoryAPI($api);
}
$names = $this->names; $names = $this->names;
if ($names !== null) { if ($names !== null) {
$names = array_fuse($names); $names = array_fuse($names);

View file

@ -140,6 +140,11 @@ EOTEXT
$remotes = $api->newRemoteRefQuery() $remotes = $api->newRemoteRefQuery()
->execute(); ->execute();
$this->loadHardpoints(
$remotes,
ArcanistRemoteRef::HARDPOINT_REPOSITORYREFS);
foreach ($remotes as $remote) { foreach ($remotes as $remote) {
$view = $remote->newRefView(); $view = $remote->newRefView();
@ -154,6 +159,18 @@ EOTEXT
'Push URI: %s', 'Push URI: %s',
$push_uri)); $push_uri));
$push_repository = $remote->getPushRepositoryRef();
if ($push_repository) {
$push_display = $push_repository->getDisplayName();
} else {
$push_display = '-';
}
$view->appendLine(
pht(
'Push Repository: %s',
$push_display));
$fetch_uri = $remote->getFetchURI(); $fetch_uri = $remote->getFetchURI();
if ($fetch_uri === null) { if ($fetch_uri === null) {
$fetch_uri = '-'; $fetch_uri = '-';
@ -164,6 +181,18 @@ EOTEXT
'Fetch URI: %s', 'Fetch URI: %s',
$fetch_uri)); $fetch_uri));
$fetch_repository = $remote->getFetchRepositoryRef();
if ($fetch_repository) {
$fetch_display = $fetch_repository->getDisplayName();
} else {
$fetch_display = '-';
}
$view->appendLine(
pht(
'Fetch Repository: %s',
$fetch_display));
echo tsprintf('%s', $view); echo tsprintf('%s', $view);
} }
} }