Page MenuHomePhabricator

D7461.diff

diff --git a/resources/sql/patches/20131030.repostatusmessage.sql b/resources/sql/patches/20131030.repostatusmessage.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/patches/20131030.repostatusmessage.sql
@@ -0,0 +1,10 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_statusmessage (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ repositoryID INT UNSIGNED NOT NULL,
+ statusType VARCHAR(32) NOT NULL COLLATE utf8_bin,
+ statusCode VARCHAR(32) NOT NULL COLLATE utf8_bin,
+ parameters LONGTEXT NOT NULL,
+ epoch INT UNSIGNED NOT NULL,
+ UNIQUE KEY (repositoryID, statusType)
+) ENGINE=InnoDB, CHARSET utf8;
+
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1665,6 +1665,7 @@
'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php',
'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php',
'PhabricatorRepositoryShortcut' => 'applications/repository/storage/PhabricatorRepositoryShortcut.php',
+ 'PhabricatorRepositoryStatusMessage' => 'applications/repository/storage/PhabricatorRepositoryStatusMessage.php',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php',
'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php',
@@ -4005,6 +4006,7 @@
'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
+ 'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
--- a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
@@ -565,6 +565,10 @@
$view = new PHUIStatusListView();
+ $messages = id(new PhabricatorRepositoryStatusMessage())
+ ->loadAllWhere('repositoryID = %d', $repository->getID());
+ $messages = mpull($messages, null, 'getStatusType');
+
if ($repository->isTracked()) {
$view->addItem(
id(new PHUIStatusItemView())
@@ -655,12 +659,53 @@
if ($repository->usesLocalWorkingCopy()) {
$local_path = $repository->getLocalPath();
- if (Filesystem::pathExists($local_path)) {
- $view->addItem(
- id(new PHUIStatusItemView())
- ->setIcon('accept-green')
- ->setTarget(pht('Working Copy OK'))
- ->setNote(phutil_tag('tt', array(), $local_path)));
+ $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT);
+ if ($message) {
+ switch ($message->getStatusCode()) {
+ case PhabricatorRepositoryStatusMessage::CODE_ERROR:
+ $view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon('warning-red')
+ ->setTarget(pht('Initialization Error'))
+ ->setNote($message->getParameter('message')));
+ return $view;
+ case PhabricatorRepositoryStatusMessage::CODE_OKAY:
+ if (Filesystem::pathExists($local_path)) {
+ $view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon('accept-green')
+ ->setTarget(pht('Working Copy OK'))
+ ->setNote(phutil_tag('tt', array(), $local_path)));
+ } else {
+ $view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon('warning-red')
+ ->setTarget(pht('Working Copy Error'))
+ ->setNote(
+ pht(
+ 'Working copy %s has been deleted, or is not '.
+ 'readable by the webserver. Make this directory '.
+ 'readable. If it has been deleted, the daemons should '.
+ 'restore it automatically.',
+ phutil_tag('tt', array(), $local_path))));
+ return $view;
+ }
+ break;
+ case PhabricatorRepositoryStatusMessage::CODE_WORKING:
+ $view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon('time-green')
+ ->setTarget(pht('Initializing Working Copy'))
+ ->setNote(pht('Daemons are initilizing the working copy.')));
+ return $view;
+ default:
+ $view->addItem(
+ id(new PHUIStatusItemView())
+ ->setIcon('warning-red')
+ ->setTarget(pht('Unknown Init Status'))
+ ->setNote($message->getStatusCode()));
+ return $view;
+ }
} else {
$view->addItem(
id(new PHUIStatusItemView())
diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
--- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
@@ -27,7 +27,7 @@
$callsign = $repository->getCallsign();
if ($repository->isHosted()) {
- $this->log(
+ $this->skipPull(
pht(
'Repository "%s" is hosted, so Phabricator does not pull updates '.
'for it.',
@@ -38,56 +38,104 @@
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
// We never pull a local copy of Subversion repositories.
- $this->log(
- "Repository '%s' is a Subversion repository, which does not require ".
- "a local working copy to be pulled.",
- $callsign);
+ $this->skipPull(
+ pht(
+ "Repository '%s' is a Subversion repository, which does not ".
+ "require a local working copy to be pulled.",
+ $callsign));
return;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$is_git = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$is_hg = true;
break;
default:
- throw new Exception("Unsupported VCS '{$vcs}'!");
+ $this->abortPull(pht('Unknown VCS "%s"!', $vcs));
}
$callsign = $repository->getCallsign();
$local_path = $repository->getLocalPath();
if ($local_path === null) {
- throw new Exception(
- "No local path is configured for repository '{$callsign}'.");
- }
-
- $dirname = dirname($local_path);
- if (!Filesystem::pathExists($dirname)) {
- Filesystem::createDirectory($dirname, 0755, $recursive = true);
+ $this->abortPull(
+ pht(
+ "No local path is configured for repository '%s'.",
+ $callsign));
}
- if (!Filesystem::pathExists($local_path)) {
- $this->log(
- "Creating a new working copy for repository '%s'.",
- $callsign);
- if ($is_git) {
- $this->executeGitCreate();
- } else {
- $this->executeMercurialCreate();
+ try {
+ $dirname = dirname($local_path);
+ if (!Filesystem::pathExists($dirname)) {
+ Filesystem::createDirectory($dirname, 0755, $recursive = true);
}
- } else {
- $this->log(
- "Updating the working copy for repository '%s'.",
- $callsign);
- if ($is_git) {
- $this->executeGitUpdate();
+
+ if (!Filesystem::pathExists($local_path)) {
+ $this->logPull(
+ pht(
+ "Creating a new working copy for repository '%s'.",
+ $callsign));
+ if ($is_git) {
+ $this->executeGitCreate();
+ } else {
+ $this->executeMercurialCreate();
+ }
} else {
- $this->executeMercurialUpdate();
+ $this->logPull(
+ pht(
+ "Updating the working copy for repository '%s'.",
+ $callsign));
+ if ($is_git) {
+ $this->executeGitUpdate();
+ } else {
+ $this->executeMercurialUpdate();
+ }
}
+ } catch (Exception $ex) {
+ $this->abortPull(
+ pht('Pull of "%s" failed: %s', $callsign, $ex->getMessage()),
+ $ex);
}
+ $this->donePull();
+
return $this;
}
+ private function skipPull($message) {
+ $this->updateRepositoryInitStatus(null);
+ $this->log('%s', $message);
+ }
+
+ private function abortPull($message, Exception $ex = null) {
+ $code_error = PhabricatorRepositoryStatusMessage::CODE_ERROR;
+ $this->updateRepositoryInitStatus($code_error, $message);
+ if ($ex) {
+ throw $ex;
+ } else {
+ throw new Exception($message);
+ }
+ }
+
+ private function logPull($message) {
+ $code_working = PhabricatorRepositoryStatusMessage::CODE_WORKING;
+ $this->updateRepositoryInitStatus($code_working, $message);
+ $this->log('%s', $message);
+ }
+
+ private function donePull() {
+ $code_okay = PhabricatorRepositoryStatusMessage::CODE_OKAY;
+ $this->updateRepositoryInitStatus($code_okay);
+ }
+
+ private function updateRepositoryInitStatus($code, $message = null) {
+ $this->getRepository()->writeStatusMessage(
+ PhabricatorRepositoryStatusMessage::TYPE_INIT,
+ $code,
+ array(
+ 'message' => $message
+ ));
+ }
+
/* -( Pulling Git Working Copies )----------------------------------------- */
diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php
--- a/src/applications/repository/storage/PhabricatorRepository.php
+++ b/src/applications/repository/storage/PhabricatorRepository.php
@@ -815,6 +815,43 @@
}
}
+ public function writeStatusMessage(
+ $status_type,
+ $status_code,
+ array $parameters = array()) {
+
+ $table = new PhabricatorRepositoryStatusMessage();
+ $conn_w = $table->establishConnection('w');
+ $table_name = $table->getTableName();
+
+ if ($status_code === null) {
+ queryfx(
+ $conn_w,
+ 'DELETE FROM %T WHERE repositoryID = %d AND statusType = %s',
+ $table_name,
+ $this->getID(),
+ $status_type);
+ } else {
+ queryfx(
+ $conn_w,
+ 'INSERT INTO %T
+ (repositoryID, statusType, statusCode, parameters, epoch)
+ VALUES (%d, %s, %s, %s, %d)
+ ON DUPLICATE KEY UPDATE
+ statusCode = VALUES(statusCode),
+ parameters = VALUES(parameters),
+ epoch = VALUES(epoch)',
+ $table_name,
+ $this->getID(),
+ $status_type,
+ $status_code,
+ json_encode($parameters),
+ time());
+ }
+
+ return $this;
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php b/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositoryStatusMessage.php
@@ -0,0 +1,33 @@
+<?php
+
+final class PhabricatorRepositoryStatusMessage
+ extends PhabricatorRepositoryDAO {
+
+ const TYPE_INIT = 'init';
+ const TYPE_FETCH = 'fetch';
+ const TYPE_NEEDS_UPDATE = 'needs-update';
+
+ const CODE_ERROR = 'error';
+ const CODE_WORKING = 'working';
+ const CODE_OKAY = 'okay';
+
+ protected $repositoryID;
+ protected $statusType;
+ protected $statusCode;
+ protected $parameters = array();
+ protected $epoch;
+
+ public function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_SERIALIZATION => array(
+ 'parameters' => self::SERIALIZATION_JSON,
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getParameter($key, $default = null) {
+ return idx($this->parameters, $key, $default);
+ }
+
+}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1712,6 +1712,10 @@
'type' => 'sql',
'name' => $this->getPatchPath('20131026.commitstatus.sql'),
),
+ '20131030.repostatusmessage.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20131030.repostatusmessage.sql'),
+ ),
);
}
}

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/3m/bz/xessnj6wwmzg33yx
Default Alt Text
D7461.diff (13 KB)

Event Timeline