Page MenuHomePhabricator

D21378.id50886.diff
No OneTemporary

D21378.id50886.diff

diff --git a/src/ref/ArcanistRepositoryRef.php b/src/ref/ArcanistRepositoryRef.php
--- a/src/ref/ArcanistRepositoryRef.php
+++ b/src/ref/ArcanistRepositoryRef.php
@@ -108,4 +108,39 @@
return $branch;
}
+ public function isPermanentRef(ArcanistMarkerRef $ref) {
+ $rules = idxv(
+ $this->parameters,
+ array('fields', 'refRules', 'permanentRefRules'));
+
+ if ($rules === null) {
+ return false;
+ }
+
+ // If the rules exist but there are no specified rules, treat every ref
+ // as permanent.
+ if (!$rules) {
+ return true;
+ }
+
+ // TODO: It would be nice to unify evaluation of permanent ref rules
+ // across Arcanist and Phabricator.
+
+ $ref_name = $ref->getName();
+ foreach ($rules as $rule) {
+ $matches = null;
+ if (preg_match('(^regexp\\((.*)\\)\z)', $rule, $matches)) {
+ if (preg_match($matches[1], $ref_name)) {
+ return true;
+ }
+ } else {
+ if ($rule === $ref_name) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
}
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
@@ -1773,4 +1773,47 @@
$uri);
}
+ protected function newPublishedCommitHashes() {
+ $remotes = $this->newRemoteRefQuery()
+ ->execute();
+ if (!$remotes) {
+ return array();
+ }
+
+ $markers = $this->newMarkerRefQuery()
+ ->withIsRemoteCache(true)
+ ->execute();
+
+ if (!$markers) {
+ return array();
+ }
+
+ $runtime = $this->getRuntime();
+ $workflow = $runtime->getCurrentWorkflow();
+
+ $workflow->loadHardpoints(
+ $remotes,
+ ArcanistRemoteRef::HARDPOINT_REPOSITORYREFS);
+
+ $remotes = mpull($remotes, null, 'getRemoteName');
+
+ $hashes = array();
+
+ foreach ($markers as $marker) {
+ $remote_name = $marker->getRemoteName();
+ $remote = idx($remotes, $remote_name);
+ if (!$remote) {
+ continue;
+ }
+
+ if (!$remote->isPermanentRef($marker)) {
+ continue;
+ }
+
+ $hashes[] = $marker->getCommitHash();
+ }
+
+ return $hashes;
+ }
+
}
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
@@ -807,4 +807,12 @@
return $uri;
}
+ final public function getPublishedCommitHashes() {
+ return $this->newPublishedCommitHashes();
+ }
+
+ protected function newPublishedCommitHashes() {
+ return array();
+ }
+
}
diff --git a/src/repository/marker/ArcanistGitRepositoryMarkerQuery.php b/src/repository/marker/ArcanistGitRepositoryMarkerQuery.php
--- a/src/repository/marker/ArcanistGitRepositoryMarkerQuery.php
+++ b/src/repository/marker/ArcanistGitRepositoryMarkerQuery.php
@@ -23,11 +23,11 @@
$branch_prefix = 'refs/heads/';
$branch_length = strlen($branch_prefix);
- // NOTE: Since we only return branches today, we restrict this operation
- // to branches.
+ $remote_prefix = 'refs/remotes/';
+ $remote_length = strlen($remote_prefix);
list($stdout) = $api->newFuture(
- 'for-each-ref --format %s -- refs/heads/',
+ 'for-each-ref --format %s -- refs/',
implode('%01', $field_list))->resolve();
$markers = array();
@@ -53,9 +53,20 @@
list($ref, $hash, $epoch, $tree, $dst_hash, $summary, $text) = $fields;
+ $remote_name = null;
+
if (!strncmp($ref, $branch_prefix, $branch_length)) {
$type = ArcanistMarkerRef::TYPE_BRANCH;
$name = substr($ref, $branch_length);
+ } else if (!strncmp($ref, $remote_prefix, $remote_length)) {
+ // This isn't entirely correct: the ref may be a tag, etc.
+ $type = ArcanistMarkerRef::TYPE_BRANCH;
+
+ $label = substr($ref, $remote_length);
+ $parts = explode('/', $label, 2);
+
+ $remote_name = $parts[0];
+ $name = $parts[1];
} else {
// For now, discard other refs.
continue;
@@ -70,6 +81,10 @@
->setSummary($summary)
->setMessage($text);
+ if ($remote_name !== null) {
+ $marker->setRemoteName($remote_name);
+ }
+
if (strlen($dst_hash)) {
$commit_hash = $dst_hash;
} else {
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
@@ -20,6 +20,7 @@
private $summary;
private $message;
private $isActive = false;
+ private $remoteName;
public function getRefDisplayName() {
switch ($this->getMarkerType()) {
@@ -130,6 +131,15 @@
return $this->isActive;
}
+ public function setRemoteName($remote_name) {
+ $this->remoteName = $remote_name;
+ return $this;
+ }
+
+ public function getRemoteName() {
+ return $this->remoteName;
+ }
+
public function isBookmark() {
return ($this->getMarkerType() === self::TYPE_BOOKMARK);
}
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
@@ -9,6 +9,7 @@
private $commitHashes;
private $ancestorCommitHashes;
private $remotes;
+ private $isRemoteCache = false;
final public function withMarkerTypes(array $types) {
$this->markerTypes = array_fuse($types);
@@ -26,6 +27,11 @@
return $this;
}
+ final public function withIsRemoteCache($is_cache) {
+ $this->isRemoteCache = $is_cache;
+ return $this;
+ }
+
final public function withIsActive($active) {
$this->isActive = $active;
return $this;
@@ -88,6 +94,16 @@
}
}
+ if ($this->isRemoteCache !== null) {
+ $want_cache = $this->isRemoteCache;
+ foreach ($markers as $key => $marker) {
+ $is_cache = ($marker->getRemoteName() !== null);
+ if ($is_cache !== $want_cache) {
+ unset($markers[$key]);
+ }
+ }
+ }
+
return $this->sortMarkers($markers);
}
diff --git a/src/repository/remote/ArcanistRemoteRef.php b/src/repository/remote/ArcanistRemoteRef.php
--- a/src/repository/remote/ArcanistRemoteRef.php
+++ b/src/repository/remote/ArcanistRemoteRef.php
@@ -89,4 +89,13 @@
return null;
}
+ public function isPermanentRef(ArcanistMarkerRef $ref) {
+ $repository_ref = $this->getPushRepositoryRef();
+ if (!$repository_ref) {
+ return false;
+ }
+
+ return $repository_ref->isPermanentRef($ref);
+ }
+
}
diff --git a/src/workflow/ArcanistLookWorkflow.php b/src/workflow/ArcanistLookWorkflow.php
--- a/src/workflow/ArcanistLookWorkflow.php
+++ b/src/workflow/ArcanistLookWorkflow.php
@@ -41,6 +41,10 @@
return $this->lookRemotes();
}
+ if ($argv === array('published')) {
+ return $this->lookPublished();
+ }
+
echo tsprintf(
"%s\n",
pht(
@@ -195,6 +199,48 @@
echo tsprintf('%s', $view);
}
+
+ echo tsprintf("\n");
+ echo tsprintf(
+ pht(
+ "Across the grove, a stream flows north toward ".
+ "**published** commits.\n"));
+ }
+
+ private function lookPublished() {
+ echo tsprintf(
+ "%W\n\n",
+ pht(
+ 'You walk along the narrow bank of the stream as it winds lazily '.
+ 'downhill and turns east, gradually widening into a river.'));
+
+ $api = $this->getRepositoryAPI();
+
+ $published = $api->getPublishedCommitHashes();
+
+ if ($published) {
+ echo tsprintf(
+ "%W\n\n",
+ pht(
+ 'Floating on the water, you see published commits:'));
+
+ foreach ($published as $hash) {
+ echo tsprintf(
+ "%s\n",
+ $hash);
+ }
+
+ echo tsprintf(
+ "\n%W\n",
+ pht(
+ 'They river bubbles peacefully.'));
+ } else {
+ echo tsprintf(
+ "%W\n",
+ pht(
+ 'The river bubbles quietly, but you do not see any published '.
+ 'commits anywhere.'));
+ }
}
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 9, 6:03 AM (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7386958
Default Alt Text
D21378.id50886.diff (8 KB)

Event Timeline