1
0
Fork 0
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:
epriestley 2013-10-30 16:04:19 -07:00
parent edd8bea85b
commit 3a39b01233
7 changed files with 215 additions and 36 deletions

View 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;

View file

@ -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',

View file

@ -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())

View file

@ -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 )----------------------------------------- */

View file

@ -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 )----------------------------------------- */

View file

@ -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);
}
}

View file

@ -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'),
),
);
}
}