Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/daemon/controller/workertaskdetail/PhabricatorWorkerTaskDetailController.php b/src/applications/daemon/controller/workertaskdetail/PhabricatorWorkerTaskDetailController.php
index 03cbfdcadc..d4acf74840 100644
--- a/src/applications/daemon/controller/workertaskdetail/PhabricatorWorkerTaskDetailController.php
+++ b/src/applications/daemon/controller/workertaskdetail/PhabricatorWorkerTaskDetailController.php
@@ -1,95 +1,133 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorWorkerTaskDetailController
extends PhabricatorDaemonController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$task = id(new PhabricatorWorkerTask())->load($this->id);
if (!$task) {
$error_view = new AphrontErrorView();
$error_view->setTitle('No Such Task');
$error_view->appendChild(
'<p>This task may have recently completed.</p>');
$error_view->setSeverity(AphrontErrorView::SEVERITY_WARNING);
return $this->buildStandardPageResponse(
$error_view,
array(
'title' => 'Task Does Not Exist',
));
}
$data = id(new PhabricatorWorkerTaskData())->loadOneWhere(
'id = %d',
$task->getDataID());
+
+ $extra = null;
+ switch ($task->getTaskClass()) {
+ case 'PhabricatorRepositorySvnCommitChangeParserWorker':
+ case 'PhabricatorRepositoryGitCommitChangeParserWorker':
+ $commit_id = idx($data->getData(), 'commitID');
+ if ($commit_id) {
+ $commit = id(new PhabricatorRepositoryCommit())->load($commit_id);
+ if ($commit) {
+ $repository = id(new PhabricatorRepository())->load(
+ $commit->getRepositoryID());
+ if ($repository) {
+ $extra =
+ "<strong>NOTE:</strong> ".
+ "You can manually retry this task by running this script:".
+ "<pre>".
+ "phabricator/\$ ./scripts/repository/parse_one_commit.php ".
+ "r".
+ phutil_escape_html($repository->getCallsign()).
+ phutil_escape_html($commit->getCommitIdentifier()).
+ "</pre>";
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
if ($data) {
$data = json_encode($data->getData());
}
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('ID')
->setValue($task->getID()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Type')
->setValue($task->getTaskClass()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Lease Owner')
->setValue($task->getLeaseOwner()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Lease Expires')
->setValue($task->getLeaseExpires() - time()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Failure Count')
->setValue($task->getFailureCount()))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Data')
- ->setValue($data))
+ ->setValue($data));
+
+ if ($extra) {
+ $form->appendChild(
+ id(new AphrontFormMarkupControl())
+ ->setLabel('More')
+ ->setValue($extra));
+ }
+
+ $form
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/daemon/'));
$panel = new AphrontPanelView();
$panel->setHeader('Task Detail');
- $panel->setWidth(AphrontPanelView::WIDTH_FORM);
+ $panel->setWidth(AphrontPanelView::WIDTH_WIDE);
$panel->appendChild($form);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'Task',
));
}
}
diff --git a/src/applications/daemon/controller/workertaskdetail/__init__.php b/src/applications/daemon/controller/workertaskdetail/__init__.php
index 13e9017739..66839c4cf7 100644
--- a/src/applications/daemon/controller/workertaskdetail/__init__.php
+++ b/src/applications/daemon/controller/workertaskdetail/__init__.php
@@ -1,22 +1,26 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/daemon/controller/base');
+phutil_require_module('phabricator', 'applications/repository/storage/commit');
+phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/taskdata');
phutil_require_module('phabricator', 'view/form/base');
+phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorWorkerTaskDetailController.php');
diff --git a/src/applications/diffusion/controller/browse/DiffusionBrowseController.php b/src/applications/diffusion/controller/browse/DiffusionBrowseController.php
index f69d18da9e..f67b9cfaf2 100644
--- a/src/applications/diffusion/controller/browse/DiffusionBrowseController.php
+++ b/src/applications/diffusion/controller/browse/DiffusionBrowseController.php
@@ -1,125 +1,135 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DiffusionBrowseController extends DiffusionController {
public function processRequest() {
$drequest = $this->diffusionRequest;
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
$results = $browse_query->loadPaths();
$content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
if (!$results) {
// TODO: Format all these commits into nice VCS-agnostic links, and
// below.
$commit = $drequest->getCommit();
$callsign = $drequest->getRepository()->getCallsign();
if ($commit) {
$commit = "r{$callsign}{$commit}";
} else {
$commit = 'HEAD';
}
switch ($browse_query->getReasonForEmptyResultSet()) {
case DiffusionBrowseQuery::REASON_IS_NONEXISTENT:
$title = 'Path Does Not Exist';
// TODO: Under git, this error message should be more specific. It
// may exist on some other branch.
$body = "This path does not exist anywhere.";
$severity = AphrontErrorView::SEVERITY_ERROR;
break;
case DiffusionBrowseQuery::REASON_IS_EMPTY:
$title = 'Empty Directory';
$body = "This path was an empty directory at {$commit}.\n";
$severity = AphrontErrorView::SEVERITY_NOTICE;
break;
case DiffusionBrowseQuery::REASON_IS_DELETED:
$deleted = $browse_query->getDeletedAtCommit();
$existed = $browse_query->getExistedAtCommit();
$deleted = "r{$callsign}{$deleted}";
$existed = "r{$callsign}{$existed}";
$title = 'Path Was Deleted';
$body = "This path does not exist at {$commit}. It was deleted in ".
"{$deleted} and last existed at {$existed}.";
$severity = AphrontErrorView::SEVERITY_WARNING;
break;
case DiffusionBrowseQuery::REASON_IS_FILE:
$controller = new DiffusionBrowseFileController($this->getRequest());
$controller->setDiffusionRequest($drequest);
return $this->delegateToController($controller);
break;
+ case DiffusionBrowseQuery::REASON_IS_UNTRACKED_PARENT:
+ $subdir = $drequest->getRepository()->getDetail('svn-subpath');
+ $title = 'Directory Not Tracked';
+ $body =
+ "This repository is configured to track only one subdirectory ".
+ "of the entire repository ('".phutil_escape_html($subdir)."'), ".
+ "but you aren't looking at something in that subdirectory, so no ".
+ "information is available.";
+ $severity = AphrontErrorView::SEVERITY_WARNING;
+ break;
default:
throw new Exception("Unknown failure reason!");
}
$error_view = new AphrontErrorView();
$error_view->setSeverity($severity);
$error_view->setTitle($title);
$error_view->appendChild('<p>'.$body.'</p>');
$content[] = $error_view;
} else {
$phids = array();
foreach ($results as $result) {
$data = $result->getLastCommitData();
if ($data) {
if ($data->getCommitDetail('authorPHID')) {
$phids[$data->getCommitDetail('authorPHID')] = true;
}
}
}
$phids = array_keys($phids);
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$browse_table = new DiffusionBrowseTableView();
$browse_table->setDiffusionRequest($drequest);
$browse_table->setHandles($handles);
$browse_table->setPaths($results);
$browse_panel = new AphrontPanelView();
$browse_panel->appendChild($browse_table);
$content[] = $browse_panel;
}
$nav = $this->buildSideNav('browse', false);
$nav->appendChild($content);
return $this->buildStandardPageResponse(
$nav,
array(
'title' => basename($drequest->getPath()),
));
}
}
diff --git a/src/applications/diffusion/controller/browse/__init__.php b/src/applications/diffusion/controller/browse/__init__.php
index 20a7e93855..2c07414577 100644
--- a/src/applications/diffusion/controller/browse/__init__.php
+++ b/src/applications/diffusion/controller/browse/__init__.php
@@ -1,20 +1,21 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/controller/file');
phutil_require_module('phabricator', 'applications/diffusion/query/browse/base');
phutil_require_module('phabricator', 'applications/diffusion/view/browsetable');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionBrowseController.php');
diff --git a/src/applications/diffusion/controller/commit/DiffusionCommitController.php b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
index 4b7e80178c..1d8566656d 100644
--- a/src/applications/diffusion/controller/commit/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
@@ -1,255 +1,280 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100;
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
$user = $request->getUser();
$callsign = $drequest->getRepository()->getCallsign();
$content = array();
$content[] = $this->buildCrumbs(array(
'commit' => true,
));
$detail_panel = new AphrontPanelView();
$repository = $drequest->getRepository();
$commit = $drequest->loadCommit();
if (!$commit) {
// TODO: Make more user-friendly.
throw new Exception('This commit has not parsed yet.');
}
$commit_data = $drequest->loadCommitData();
- $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
-
- require_celerity_resource('diffusion-commit-view-css');
- require_celerity_resource('phabricator-remarkup-css');
-
- $property_table = $this->renderPropertyTable($commit, $commit_data);
-
- $detail_panel->appendChild(
- '<div class="diffusion-commit-view">'.
- '<div class="diffusion-commit-dateline">'.
- 'r'.$callsign.$commit->getCommitIdentifier().
- ' &middot; '.
- phabricator_datetime($commit->getEpoch(), $user).
- '</div>'.
- '<h1>Revision Detail</h1>'.
- '<div class="diffusion-commit-details">'.
- $property_table.
- '<hr />'.
- '<div class="diffusion-commit-message phabricator-remarkup">'.
- $engine->markupText($commit_data->getCommitMessage()).
+ $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
+ if ($is_foreign) {
+ $subpath = $commit_data->getCommitDetail('svn-subpath');
+
+ $error_panel = new AphrontErrorView();
+ $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
+ $error_panel->setTitle('Commit Not Tracked');
+ $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
+ $error_panel->appendChild(
+ "This Diffusion repository is configured to track only one ".
+ "subdirectory of the entire Subversion repository, and this commit ".
+ "didn't affect the tracked subdirectory ('".
+ phutil_escape_html($subpath)."'), so no information is available.");
+ $content[] = $error_panel;
+ } else {
+ $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
+
+ require_celerity_resource('diffusion-commit-view-css');
+ require_celerity_resource('phabricator-remarkup-css');
+
+ $property_table = $this->renderPropertyTable($commit, $commit_data);
+
+ $detail_panel->appendChild(
+ '<div class="diffusion-commit-view">'.
+ '<div class="diffusion-commit-dateline">'.
+ 'r'.$callsign.$commit->getCommitIdentifier().
+ ' &middot; '.
+ phabricator_datetime($commit->getEpoch(), $user).
+ '</div>'.
+ '<h1>Revision Detail</h1>'.
+ '<div class="diffusion-commit-details">'.
+ $property_table.
+ '<hr />'.
+ '<div class="diffusion-commit-message phabricator-remarkup">'.
+ $engine->markupText($commit_data->getCommitMessage()).
+ '</div>'.
'</div>'.
- '</div>'.
- '</div>');
+ '</div>');
- $content[] = $detail_panel;
+ $content[] = $detail_panel;
+ }
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$changes = $change_query->loadChanges();
$original_changes_count = count($changes);
if ($request->getStr('show_all') !== 'true' &&
$original_changes_count > self::CHANGES_LIMIT) {
$changes = array_slice($changes, 0, self::CHANGES_LIMIT);
}
$change_table = new DiffusionCommitChangeTableView();
$change_table->setDiffusionRequest($drequest);
$change_table->setPathChanges($changes);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
'r'.$callsign.$commit->getCommitIdentifier());
}
if ($bad_commit) {
$error_panel = new AphrontErrorView();
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
$error_panel->setTitle('Bad Commit');
$error_panel->appendChild(
phutil_escape_html($bad_commit['description']));
$content[] = $error_panel;
+ } else if ($is_foreign) {
+ // Don't render anything else.
+ } else if (!count($changes)) {
+ $no_changes = new AphrontErrorView();
+ $no_changes->setWidth(AphrontErrorView::WIDTH_WIDE);
+ $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
+ $no_changes->setTitle('Not Yet Parsed');
+ // TODO: This can also happen with weird SVN changes that don't do
+ // anything (or only alter properties?), although the real no-changes case
+ // is extremely rare and might be impossible to produce organically. We
+ // should probably write some kind of "Nothing Happened!" change into the
+ // DB once we parse these changes so we can distinguish between
+ // "not parsed yet" and "no changes".
+ $no_changes->appendChild(
+ "This commit hasn't been fully parsed yet (or doesn't affect any ".
+ "paths).");
+ $content[] = $no_changes;
} else {
$change_panel = new AphrontPanelView();
$change_panel->setHeader("Changes (".number_format($count).")");
if ($count !== $original_changes_count) {
$show_all_button = phutil_render_tag(
'a',
array(
'class' => 'button green',
'href' => '?show_all=true',
),
phutil_escape_html('Show All Changes'));
$warning_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
->setTitle(sprintf(
"Showing only the first %d changes out of %s!",
self::CHANGES_LIMIT,
number_format($original_changes_count)));
$change_panel->appendChild($warning_view);
$change_panel->addButton($show_all_button);
}
$change_panel->appendChild($change_table);
$content[] = $change_panel;
- if ($changes) {
- $changesets = DiffusionPathChange::convertToDifferentialChangesets(
- $changes);
-
- $vcs = $repository->getVersionControlSystem();
- switch ($vcs) {
- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- $vcs_supports_directory_changes = true;
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- $vcs_supports_directory_changes = false;
- break;
- default:
- throw new Exception("Unknown VCS.");
- }
+ $changesets = DiffusionPathChange::convertToDifferentialChangesets(
+ $changes);
+
+ $vcs = $repository->getVersionControlSystem();
+ switch ($vcs) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
+ $vcs_supports_directory_changes = true;
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ $vcs_supports_directory_changes = false;
+ break;
+ default:
+ throw new Exception("Unknown VCS.");
+ }
- $references = array();
- foreach ($changesets as $key => $changeset) {
- $file_type = $changeset->getFileType();
- if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
- if (!$vcs_supports_directory_changes) {
- unset($changesets[$key]);
- continue;
- }
+ $references = array();
+ foreach ($changesets as $key => $changeset) {
+ $file_type = $changeset->getFileType();
+ if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
+ if (!$vcs_supports_directory_changes) {
+ unset($changesets[$key]);
+ continue;
}
-
- $branch = $drequest->getBranchURIComponent(
- $drequest->getBranch());
- $filename = $changeset->getFilename();
- $commit = $drequest->getCommit();
- $reference = "{$branch}{$filename};{$commit}";
- $references[$key] = $reference;
}
- $change_list = new DifferentialChangesetListView();
- $change_list->setChangesets($changesets);
- $change_list->setRenderingReferences($references);
- $change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
-
- // TODO: This is pretty awkward, unify the CSS between Diffusion and
- // Differential better.
- require_celerity_resource('differential-core-view-css');
- $change_list =
- '<div class="differential-primary-pane">'.
- $change_list->render().
- '</div>';
- } else {
- $change_list =
- '<div style="margin: 2em; color: #666; padding: 1em;
- background: #eee;">'.
- '(no changes blah blah)'.
- '</div>';
+ $branch = $drequest->getBranchURIComponent(
+ $drequest->getBranch());
+ $filename = $changeset->getFilename();
+ $commit = $drequest->getCommit();
+ $reference = "{$branch}{$filename};{$commit}";
+ $references[$key] = $reference;
}
+ $change_list = new DifferentialChangesetListView();
+ $change_list->setChangesets($changesets);
+ $change_list->setRenderingReferences($references);
+ $change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
+
+ // TODO: This is pretty awkward, unify the CSS between Diffusion and
+ // Differential better.
+ require_celerity_resource('differential-core-view-css');
+ $change_list =
+ '<div class="differential-primary-pane">'.
+ $change_list->render().
+ '</div>';
+
$content[] = $change_list;
}
return $this->buildStandardPageResponse(
$content,
array(
'title' => 'Diffusion',
));
}
private function renderPropertyTable(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
$phids = array();
if ($data->getCommitDetail('authorPHID')) {
$phids[] = $data->getCommitDetail('authorPHID');
}
if ($data->getCommitDetail('reviewerPHID')) {
$phids[] = $data->getCommitDetail('reviewerPHID');
}
if ($data->getCommitDetail('differential.revisionPHID')) {
$phids[] = $data->getCommitDetail('differential.revisionPHID');
}
$handles = array();
if ($phids) {
$handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles();
}
$props = array();
$author_phid = $data->getCommitDetail('authorPHID');
if ($data->getCommitDetail('authorPHID')) {
$props['Author'] = $handles[$author_phid]->renderLink();
} else {
$props['Author'] = phutil_escape_html($data->getAuthorName());
}
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
$reviewer_name = $data->getCommitDetail('reviewerName');
if ($reviewer_phid) {
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
} else if ($reviewer_name) {
$props['Reviewer'] = phutil_escape_html($reviewer_name);
}
$revision_phid = $data->getCommitDetail('differential.revisionPHID');
if ($revision_phid) {
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
}
$rows = array();
foreach ($props as $key => $value) {
$rows[] =
'<tr>'.
'<th>'.$key.':</th>'.
'<td>'.$value.'</td>'.
'</tr>';
}
return
'<table class="diffusion-commit-properties">'.
implode("\n", $rows).
'</table>';
}
}
diff --git a/src/applications/diffusion/query/browse/base/DiffusionBrowseQuery.php b/src/applications/diffusion/query/browse/base/DiffusionBrowseQuery.php
index 02c3283a87..cba77ec2b5 100644
--- a/src/applications/diffusion/query/browse/base/DiffusionBrowseQuery.php
+++ b/src/applications/diffusion/query/browse/base/DiffusionBrowseQuery.php
@@ -1,93 +1,94 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class DiffusionBrowseQuery {
private $request;
protected $reason;
protected $existedAtCommit;
protected $deletedAtCommit;
protected $validityOnly;
- const REASON_IS_FILE = 'is-file';
- const REASON_IS_DELETED = 'is-deleted';
- const REASON_IS_NONEXISTENT = 'nonexistent';
- const REASON_BAD_COMMIT = 'bad-commit';
- const REASON_IS_EMPTY = 'empty';
+ const REASON_IS_FILE = 'is-file';
+ const REASON_IS_DELETED = 'is-deleted';
+ const REASON_IS_NONEXISTENT = 'nonexistent';
+ const REASON_BAD_COMMIT = 'bad-commit';
+ const REASON_IS_EMPTY = 'empty';
+ const REASON_IS_UNTRACKED_PARENT = 'untracked-parent';
final private function __construct() {
// <private>
}
final public static function newFromDiffusionRequest(
DiffusionRequest $request) {
$repository = $request->getRepository();
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
// TODO: Verify local-path?
$class = 'DiffusionGitBrowseQuery';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$class = 'DiffusionSvnBrowseQuery';
break;
default:
throw new Exception("Unsupported VCS!");
}
PhutilSymbolLoader::loadClass($class);
$query = new $class();
$query->request = $request;
return $query;
}
final protected function getRequest() {
return $this->request;
}
final public function getReasonForEmptyResultSet() {
return $this->reason;
}
final public function getExistedAtCommit() {
return $this->existedAtCommit;
}
final public function getDeletedAtCommit() {
return $this->deletedAtCommit;
}
final public function loadPaths() {
return $this->executeQuery();
}
final public function shouldOnlyTestValidity() {
return $this->validityOnly;
}
final public function needValidityOnly($need_validity_only) {
$this->validityOnly = $need_validity_only;
return $this;
}
abstract protected function executeQuery();
}
diff --git a/src/applications/diffusion/query/browse/svn/DiffusionSvnBrowseQuery.php b/src/applications/diffusion/query/browse/svn/DiffusionSvnBrowseQuery.php
index c47952118a..b513b50763 100644
--- a/src/applications/diffusion/query/browse/svn/DiffusionSvnBrowseQuery.php
+++ b/src/applications/diffusion/query/browse/svn/DiffusionSvnBrowseQuery.php
@@ -1,189 +1,198 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionSvnBrowseQuery extends DiffusionBrowseQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
+ $subpath = $repository->getDetail('svn-subpath');
+ if ($subpath && strncmp($subpath, $path, strlen($subpath))) {
+ // If we have a subpath and the path isn't a child of it, it (almost
+ // certainly) won't exist since we don't track commits which affect
+ // it. (Even if it exists, return a consistent result.)
+ $this->reason = self::REASON_IS_UNTRACKED_PARENT;
+ return array();
+ }
+
$conn_r = $repository->establishConnection('r');
$parent_path = dirname($path);
$path_query = new DiffusionGitPathIDQuery(
array(
$path,
$parent_path,
));
$path_map = $path_query->loadPathIDs();
$path_id = $path_map[$path];
$parent_path_id = $path_map[$parent_path];
if (empty($path_id)) {
$this->reason = self::REASON_IS_NONEXISTENT;
return array();
}
if ($commit) {
$slice_clause = 'AND svnCommit <= '.(int)$commit;
} else {
$slice_clause = '';
}
$index = queryfx_all(
$conn_r,
'SELECT pathID, max(svnCommit) maxCommit FROM %T WHERE
repositoryID = %d AND parentID = %d
%Q GROUP BY pathID',
PhabricatorRepository::TABLE_FILESYSTEM,
$repository->getID(),
$path_id,
$slice_clause);
if (!$index) {
if ($path == '/') {
$this->reason = self::REASON_IS_EMPTY;
} else {
// NOTE: The parent path ID is included so this query can take
// advantage of the table's primary key; it is uniquely determined by
// the pathID but if we don't do the lookup ourselves MySQL doesn't have
// the information it needs to avoid a table scan.
$reasons = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE repositoryID = %d
AND parentID = %d
AND pathID = %d
%Q ORDER BY svnCommit DESC LIMIT 2',
PhabricatorRepository::TABLE_FILESYSTEM,
$repository->getID(),
$parent_path_id,
$path_id,
$slice_clause);
$reason = reset($reasons);
if (!$reason) {
$this->reason = self::REASON_IS_NONEXISTENT;
} else {
$file_type = $reason['fileType'];
if (empty($reason['existed'])) {
$this->reason = self::REASON_IS_DELETED;
$this->deletedAtCommit = $reason['svnCommit'];
if (!empty($reasons[1])) {
$this->existedAtCommit = $reasons[1]['svnCommit'];
}
} else if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
$this->reason = self::REASON_IS_EMPTY;
} else {
$this->reason = self::REASON_IS_FILE;
}
}
}
return array();
}
if ($this->shouldOnlyTestValidity()) {
return true;
}
$sql = array();
foreach ($index as $row) {
$sql[] = '('.(int)$row['pathID'].', '.(int)$row['maxCommit'].')';
}
$browse = queryfx_all(
$conn_r,
'SELECT *, p.path pathName
FROM %T f JOIN %T p ON f.pathID = p.id
WHERE repositoryID = %d
AND parentID = %d
AND existed = 1
AND (pathID, svnCommit) in (%Q)
ORDER BY pathName',
PhabricatorRepository::TABLE_FILESYSTEM,
PhabricatorRepository::TABLE_PATH,
$repository->getID(),
$path_id,
implode(', ', $sql));
$loadable_commits = array();
foreach ($browse as $key => $file) {
// We need to strip out directories because we don't store last-modified
// in the filesystem table.
if ($file['fileType'] != DifferentialChangeType::FILE_DIRECTORY) {
$loadable_commits[] = $file['svnCommit'];
$browse[$key]['hasCommit'] = true;
}
}
$commits = array();
$commit_data = array();
if ($loadable_commits) {
// NOTE: Even though these are integers, use '%Ls' because MySQL doesn't
// use the second part of the key otherwise!
$commits = id(new PhabricatorRepositoryCommit())->loadAllWhere(
'repositoryID = %d AND commitIdentifier IN (%Ls)',
$repository->getID(),
$loadable_commits);
$commits = mpull($commits, null, 'getCommitIdentifier');
$commit_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID in (%Ld)',
mpull($commits, 'getID'));
$commit_data = mpull($commit_data, null, 'getCommitID');
}
$path_normal = DiffusionGitPathIDQuery::normalizePath($path);
$results = array();
foreach ($browse as $file) {
$file_path = $file['pathName'];
$file_path = ltrim(substr($file_path, strlen($path_normal)), '/');
$result = new DiffusionRepositoryPath();
$result->setPath($file_path);
// $result->setHash($hash);
$result->setFileType($file['fileType']);
// $result->setFileSize($size);
if (!empty($file['hasCommit'])) {
$commit = idx($commits, $file['svnCommit']);
if ($commit) {
$data = idx($commit_data, $commit->getID());
$result->setLastModifiedCommit($commit);
$result->setLastCommitData($data);
}
}
$results[] = $result;
}
if (empty($results)) {
$this->reason = self::REASON_IS_EMPTY;
}
return $results;
}
}
diff --git a/src/applications/diffusion/request/svn/DiffusionSvnRequest.php b/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
index 577e36c64e..81c9c68bd1 100644
--- a/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
+++ b/src/applications/diffusion/request/svn/DiffusionSvnRequest.php
@@ -1,59 +1,67 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DiffusionSvnRequest extends DiffusionRequest {
protected function initializeFromAphrontRequestDictionary(array $data) {
parent::initializeFromAphrontRequestDictionary($data);
+
+ if ($this->path === null) {
+ $subpath = $this->repository->getDetail('svn-subpath');
+ if ($subpath) {
+ $this->path = $subpath;
+ }
+ }
+
if (!strncmp($this->path, ':', 1)) {
$this->path = substr($this->path, 1);
$this->path = ltrim($this->path, '/');
}
}
public function getStableCommitName() {
if ($this->commit) {
return $this->commit;
}
if ($this->stableCommitName === null) {
$commit = id(new PhabricatorRepositoryCommit())
->loadOneWhere(
'repositoryID = %d ORDER BY epoch DESC LIMIT 1',
$this->getRepository()->getID());
if ($commit) {
$this->stableCommitName = $commit->getCommitIdentifier();
} else {
// For new repositories, we may not have parsed any commits yet. Call
// the stable commit "1" and avoid fataling.
$this->stableCommitName = 1;
}
}
return $this->stableCommitName;
}
public function getCommit() {
if ($this->commit) {
return $this->commit;
}
return $this->getStableCommitName();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Dec 3, 1:29 PM (8 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
433503
Default Alt Text
(36 KB)

Event Timeline