Page MenuHomePhabricator

D17103.diff
No OneTemporary

D17103.diff

diff --git a/src/applications/config/controller/PhabricatorConfigVersionController.php b/src/applications/config/controller/PhabricatorConfigVersionController.php
--- a/src/applications/config/controller/PhabricatorConfigVersionController.php
+++ b/src/applications/config/controller/PhabricatorConfigVersionController.php
@@ -39,8 +39,20 @@
$versions = $this->loadVersions($viewer);
$version_property_list = id(new PHUIPropertyListView());
- foreach ($versions as $name => $version) {
- $version_property_list->addProperty($name, $version);
+ foreach ($versions as $name => $info) {
+ $version = $info['version'];
+
+ if ($info['branchpoint']) {
+ $display = pht(
+ '%s (branched from %s on %s)',
+ $version,
+ $info['branchpoint'],
+ $info['upstream']);
+ } else {
+ $display = $version;
+ }
+
+ $version_property_list->addProperty($name, $display);
}
$phabricator_root = dirname(phutil_get_library_root('phabricator'));
@@ -67,16 +79,109 @@
$other_libraries = array_diff($all_libraries, $specs);
$specs = array_merge($specs, $other_libraries);
- $futures = array();
+ $log_futures = array();
+ $remote_futures = array();
+
foreach ($specs as $lib) {
$root = dirname(phutil_get_library_root($lib));
- $futures[$lib] =
- id(new ExecFuture('git log --format=%s -n 1 --', '%H %ct'))
+
+ $log_command = csprintf(
+ 'git log --format=%s -n 1 --',
+ '%H %ct');
+
+ $remote_command = csprintf(
+ 'git remote -v');
+
+ $log_futures[$lib] = id(new ExecFuture('%C', $log_command))
+ ->setCWD($root);
+
+ $remote_futures[$lib] = id(new ExecFuture('%C', $remote_command))
->setCWD($root);
}
+ $all_futures = array_merge($log_futures, $remote_futures);
+
+ id(new FutureIterator($all_futures))
+ ->resolveAll();
+
+ // A repository may have a bunch of remotes, but we're only going to look
+ // for remotes we host to try to figure out where this repository branched.
+ $upstream_pattern = '(github\.com/phacility/|secure\.phabricator\.com/)';
+
+ $upstream_futures = array();
+ $lib_upstreams = array();
+ foreach ($specs as $lib) {
+ $remote_future = $remote_futures[$lib];
+
+ list($err, $stdout) = $remote_future->resolve();
+ if ($err) {
+ // If this fails for whatever reason, just move on.
+ continue;
+ }
+
+ // These look like this, with a tab separating the first two fields:
+ // remote-name http://remote.uri/ (push)
+
+ $upstreams = array();
+
+ $remotes = phutil_split_lines($stdout, false);
+ foreach ($remotes as $remote) {
+ $remote_pattern = '/^([^\t]+)\t([^ ]+) \(([^)]+)\)\z/';
+ $matches = null;
+ if (!preg_match($remote_pattern, $remote, $matches)) {
+ continue;
+ }
+
+ // Remote URIs are either "push" or "fetch": we only care about "fetch"
+ // URIs.
+ $type = $matches[3];
+ if ($type != 'fetch') {
+ continue;
+ }
+
+ $uri = $matches[2];
+ $is_upstream = preg_match($upstream_pattern, $uri);
+ if (!$is_upstream) {
+ continue;
+ }
+
+ $name = $matches[1];
+ $upstreams[$name] = $name;
+ }
+
+ // If we have several suitable upstreams, try to pick the one named
+ // "origin", if it exists. Otherwise, just pick the first one.
+ if (isset($upstreams['origin'])) {
+ $upstream = $upstreams['origin'];
+ } else if ($upstreams) {
+ $upstream = head($upstreams);
+ } else {
+ $upstream = null;
+ }
+
+ if (!$upstream) {
+ continue;
+ }
+
+ $lib_upstreams[$lib] = $upstream;
+
+ $merge_base_command = csprintf(
+ 'git merge-base HEAD %s/master --',
+ $upstream);
+
+ $root = dirname(phutil_get_library_root($lib));
+
+ $upstream_futures[$lib] = id(new ExecFuture('%C', $merge_base_command))
+ ->setCWD($root);
+ }
+
+ if ($upstream_futures) {
+ id(new FutureIterator($upstream_futures))
+ ->resolveAll();
+ }
+
$results = array();
- foreach ($futures as $key => $future) {
+ foreach ($log_futures as $lib => $future) {
list($err, $stdout) = $future->resolve();
if (!$err) {
list($hash, $epoch) = explode(' ', $stdout);
@@ -84,7 +189,29 @@
} else {
$version = pht('Unknown');
}
- $results[$key] = $version;
+
+ $result = array(
+ 'version' => $version,
+ 'upstream' => null,
+ 'branchpoint' => null,
+ );
+
+ $upstream_future = idx($upstream_futures, $lib);
+ if ($upstream_future) {
+ list($err, $stdout) = $upstream_future->resolve();
+ if (!$err) {
+ $branchpoint = trim($stdout);
+ if (strlen($branchpoint)) {
+ // We only list a branchpoint if it differs from HEAD.
+ if ($branchpoint != $hash) {
+ $result['upstream'] = $lib_upstreams[$lib];
+ $result['branchpoint'] = trim($stdout);
+ }
+ }
+ }
+ }
+
+ $results[$lib] = $result;
}
return $results;
diff --git a/src/docs/contributor/version.diviner b/src/docs/contributor/version.diviner
--- a/src/docs/contributor/version.diviner
+++ b/src/docs/contributor/version.diviner
@@ -49,6 +49,29 @@
prevents you from reaching the version reporting screen.
+Running a Fork?
+===============
+
+If you've forked Phabricator and have local commits, please make sure you are
+reporting upstream commit hashes, not local commit hashes. The UI will attempt
+to figure out where you branched from, but it may not be able to in all cases.
+
+If you report local commit hashes instead of upstream commit hashes we can not
+go look up the commit hashes to figure out which changes they correspond to, so
+we can not use that information to determine out how old your install is or
+which patches you are missing.
+
+In most cases, you can find the upstream commit you've branched from like this:
+
+```
+$ git merge-base HEAD origin/master
+````
+
+Note that if you report a bug and have local commits, we will almost always ask
+you to reproduce the issue against a clean copy of Phabricator before we
+continue. You can get help faster by doing this //before// reporting an issue.
+
+
Next Steps
==========

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 4, 2:26 PM (3 d, 22 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7709213
Default Alt Text
D17103.diff (6 KB)

Event Timeline