mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-15 17:21:10 +01:00
Add "RepositoryStatusMessage" and detailed information about initilization
Summary: `RepositoryStatusMessage` is basically a key/value table associated with a repository that I'm using to let the daemons store the most recent event of a given type, so we can easily show it on the status dashboard. I think this will be a lot easier for users to figure out than digging through logfiles. I'm also going to write the "this needs a pull" status here eventually, for reducing the time lapse between pushes and discovery. - Add storage for these messages. - Have the pull engine populate the INIT phase. I'll do the FETCH phase next. - Update the status readout to show all the various states. Test Plan: See screenshots. Reviewers: btrahan Reviewed By: btrahan CC: aran Differential Revision: https://secure.phabricator.com/D7461
This commit is contained in:
parent
edd8bea85b
commit
3a39b01233
7 changed files with 215 additions and 36 deletions
10
resources/sql/patches/20131030.repostatusmessage.sql
Normal file
10
resources/sql/patches/20131030.repostatusmessage.sql
Normal file
|
@ -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;
|
||||
|
|
@ -1665,6 +1665,7 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
|
||||
'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO',
|
||||
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
|
||||
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
|
||||
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
|
||||
|
|
|
@ -565,6 +565,10 @@ final class DiffusionRepositoryEditMainController
|
|||
|
||||
$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 @@ final class DiffusionRepositoryEditMainController
|
|||
|
||||
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())
|
||||
|
|
|
@ -27,7 +27,7 @@ final class PhabricatorRepositoryPullEngine
|
|||
$callsign = $repository->getCallsign();
|
||||
|
||||
if ($repository->isHosted()) {
|
||||
$this->log(
|
||||
$this->skipPull(
|
||||
pht(
|
||||
'Repository "%s" is hosted, so Phabricator does not pull updates '.
|
||||
'for it.',
|
||||
|
@ -38,10 +38,11 @@ final class PhabricatorRepositoryPullEngine
|
|||
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;
|
||||
|
@ -50,44 +51,91 @@ final class PhabricatorRepositoryPullEngine
|
|||
$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}'.");
|
||||
$this->abortPull(
|
||||
pht(
|
||||
"No local path is configured for repository '%s'.",
|
||||
$callsign));
|
||||
}
|
||||
|
||||
$dirname = dirname($local_path);
|
||||
if (!Filesystem::pathExists($dirname)) {
|
||||
Filesystem::createDirectory($dirname, 0755, $recursive = true);
|
||||
try {
|
||||
$dirname = dirname($local_path);
|
||||
if (!Filesystem::pathExists($dirname)) {
|
||||
Filesystem::createDirectory($dirname, 0755, $recursive = true);
|
||||
}
|
||||
|
||||
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->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);
|
||||
}
|
||||
|
||||
if (!Filesystem::pathExists($local_path)) {
|
||||
$this->log(
|
||||
"Creating a new working copy for repository '%s'.",
|
||||
$callsign);
|
||||
if ($is_git) {
|
||||
$this->executeGitCreate();
|
||||
} else {
|
||||
$this->executeMercurialCreate();
|
||||
}
|
||||
} else {
|
||||
$this->log(
|
||||
"Updating the working copy for repository '%s'.",
|
||||
$callsign);
|
||||
if ($is_git) {
|
||||
$this->executeGitUpdate();
|
||||
} else {
|
||||
$this->executeMercurialUpdate();
|
||||
}
|
||||
}
|
||||
$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 )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -815,6 +815,43 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
|||
}
|
||||
}
|
||||
|
||||
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 )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1712,6 +1712,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131026.commitstatus.sql'),
|
||||
),
|
||||
'20131030.repostatusmessage.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131030.repostatusmessage.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue