2011-03-13 01:17:34 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-01-05 23:41:11 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-03-13 01:17:34 +01:00
|
|
|
*
|
|
|
|
* 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();
|
|
|
|
|
Improve several Diffusion UI error states
Summary:
Give users better errors and UI:
- For subpath SVN repositories, default the path to the subdirectory, not to
"/". This makes the home screen useful and things generally less confusing.
- For unparsed commits, show a more descriptive error message without the
"blah blah" silliness.
- For paths outside of the subpath parse tree, short circuit into an
appropriate error message.
- For foreign SVN stub commits (see D892), show an explicit message.
Test Plan: Looked at unparsed commits, subpath repositories, foreign stub
commits, and paths outside of the subpath parse tree. Received sensible error
messages.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: jungejason
CC: aran, jungejason
Differential Revision: 894
2011-09-04 23:39:52 +02:00
|
|
|
$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();
|
|
|
|
}
|
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
$conn_r = $repository->establishConnection('r');
|
|
|
|
|
2011-09-14 20:23:39 +02:00
|
|
|
$parent_path = DiffusionPathIDQuery::getParentPath($path);
|
2011-09-14 19:59:52 +02:00
|
|
|
$path_query = new DiffusionPathIDQuery(
|
2011-03-21 01:46:02 +01:00
|
|
|
array(
|
|
|
|
$path,
|
|
|
|
$parent_path,
|
|
|
|
));
|
|
|
|
$path_map = $path_query->loadPathIDs();
|
|
|
|
|
|
|
|
$path_id = $path_map[$path];
|
|
|
|
$parent_path_id = $path_map[$parent_path];
|
2011-03-14 06:03:30 +01:00
|
|
|
|
|
|
|
if (empty($path_id)) {
|
|
|
|
$this->reason = self::REASON_IS_NONEXISTENT;
|
|
|
|
return array();
|
|
|
|
}
|
2011-03-13 01:17:34 +01:00
|
|
|
|
2011-03-13 07:51:40 +01:00
|
|
|
if ($commit) {
|
|
|
|
$slice_clause = 'AND svnCommit <= '.(int)$commit;
|
|
|
|
} else {
|
|
|
|
$slice_clause = '';
|
|
|
|
}
|
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
$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,
|
2011-03-13 07:51:40 +01:00
|
|
|
$slice_clause);
|
2011-03-13 01:17:34 +01:00
|
|
|
|
|
|
|
if (!$index) {
|
2011-03-14 15:43:13 +01:00
|
|
|
if ($path == '/') {
|
2011-03-14 06:03:30 +01:00
|
|
|
$this->reason = self::REASON_IS_EMPTY;
|
|
|
|
} else {
|
2011-03-21 01:46:02 +01:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
2011-03-14 06:03:30 +01:00
|
|
|
$reasons = queryfx_all(
|
|
|
|
$conn_r,
|
2011-03-21 01:46:02 +01:00
|
|
|
'SELECT * FROM %T WHERE repositoryID = %d
|
|
|
|
AND parentID = %d
|
|
|
|
AND pathID = %d
|
2011-03-14 06:03:30 +01:00
|
|
|
%Q ORDER BY svnCommit DESC LIMIT 2',
|
|
|
|
PhabricatorRepository::TABLE_FILESYSTEM,
|
|
|
|
$repository->getID(),
|
2011-03-21 01:46:02 +01:00
|
|
|
$parent_path_id,
|
2011-03-14 06:03:30 +01:00
|
|
|
$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();
|
2011-03-13 01:17:34 +01:00
|
|
|
}
|
|
|
|
|
2011-04-04 04:20:47 +02:00
|
|
|
if ($this->shouldOnlyTestValidity()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
$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));
|
|
|
|
|
2011-03-31 07:41:31 +02:00
|
|
|
$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');
|
2012-01-05 23:41:11 +01:00
|
|
|
if ($commits) {
|
|
|
|
$commit_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
|
|
|
|
'commitID in (%Ld)',
|
|
|
|
mpull($commits, 'getID'));
|
|
|
|
$commit_data = mpull($commit_data, null, 'getCommitID');
|
|
|
|
} else {
|
|
|
|
$commit_data = array();
|
|
|
|
}
|
2011-03-31 07:41:31 +02:00
|
|
|
}
|
|
|
|
|
2011-09-14 19:59:52 +02:00
|
|
|
$path_normal = DiffusionPathIDQuery::normalizePath($path);
|
2011-03-21 01:46:02 +01:00
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
$results = array();
|
|
|
|
foreach ($browse as $file) {
|
|
|
|
|
2012-03-29 05:43:48 +02:00
|
|
|
$full_path = $file['pathName'];
|
|
|
|
$file_path = ltrim(substr($full_path, strlen($path_normal)), '/');
|
|
|
|
$full_path = ltrim($full_path, '/');
|
2011-03-13 01:17:34 +01:00
|
|
|
|
|
|
|
$result = new DiffusionRepositoryPath();
|
|
|
|
$result->setPath($file_path);
|
2012-03-29 05:43:48 +02:00
|
|
|
$result->setFullPath($full_path);
|
2011-03-13 01:17:34 +01:00
|
|
|
// $result->setHash($hash);
|
|
|
|
$result->setFileType($file['fileType']);
|
|
|
|
// $result->setFileSize($size);
|
|
|
|
|
2011-03-31 07:41:31 +02:00
|
|
|
if (!empty($file['hasCommit'])) {
|
|
|
|
$commit = idx($commits, $file['svnCommit']);
|
|
|
|
if ($commit) {
|
|
|
|
$data = idx($commit_data, $commit->getID());
|
|
|
|
$result->setLastModifiedCommit($commit);
|
|
|
|
$result->setLastCommitData($data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
$results[] = $result;
|
|
|
|
}
|
|
|
|
|
2011-08-22 22:33:48 +02:00
|
|
|
if (empty($results)) {
|
|
|
|
$this->reason = self::REASON_IS_EMPTY;
|
|
|
|
}
|
|
|
|
|
2011-03-13 01:17:34 +01:00
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|