mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-27 00:16:21 +00:00
141 lines
3.4 KiB
PHP
141 lines
3.4 KiB
PHP
<?php
|
|
|
|
class Upgrader {
|
|
public static function upgraderRoot() {
|
|
return UOJContext::documentRoot() . '/app/upgrade';
|
|
}
|
|
|
|
public static function runSQL($filename) {
|
|
passthru('mysql ' . escapeshellarg(UOJConfig::$data['database']['database'])
|
|
. ' -u ' . escapeshellarg(UOJConfig::$data['database']['username'])
|
|
. ' --password=' . escapeshellarg(UOJConfig::$data['database']['password'])
|
|
. ' -h ' . escapeshellarg(UOJConfig::$data['database']['host'])
|
|
. ' -P ' . escapeshellarg(UOJConfig::$data['database']['port'])
|
|
. '<' . escapeshellarg($filename), $ret);
|
|
if ($ret !== 0) {
|
|
die("run sql failed: " . HTML::escape($filename) . "\n");
|
|
}
|
|
}
|
|
public static function runShell($cmd) {
|
|
passthru("$cmd", $ret);
|
|
if ($ret !== 0) {
|
|
die("run shell failed: " . HTML::escape($cmd) . "\n");
|
|
}
|
|
}
|
|
|
|
public static function transaction($fun) {
|
|
if (!DB::checkTableExists('upgrades')) {
|
|
echo "error: table upgrades does NOT exist!\n";
|
|
}
|
|
|
|
DB::lock(['upgrades' => DB::WLOCK], $fun);
|
|
}
|
|
|
|
public static function getStatus($name) {
|
|
$u = DB::selectFirst([
|
|
"select * from upgrades",
|
|
"where", ["name" => $name]
|
|
]);
|
|
if ($u) {
|
|
return $u['status'];
|
|
} else {
|
|
return 'down';
|
|
}
|
|
}
|
|
|
|
public static function upgrade($name, $type) {
|
|
if ($type != 'up' && $type != 'down') {
|
|
die("invalid upgrade type\n");
|
|
}
|
|
|
|
echo $type . ' ' . HTML::escape($name) . ': ';
|
|
|
|
$dir = self::upgraderRoot() . '/' . $name;
|
|
|
|
if (!is_dir($dir)) {
|
|
die("invalid upgrade name\n");
|
|
}
|
|
|
|
if (self::getStatus($name) == $type) {
|
|
echo "OK\n";
|
|
return;
|
|
}
|
|
|
|
if (is_file($dir . '/upgrade.php')) {
|
|
$fun = include $dir . '/upgrade.php';
|
|
$fun($type);
|
|
}
|
|
if (is_file($dir . '/' . $type . '.sql')) {
|
|
self::runSQL($dir . '/' . $type . '.sql');
|
|
}
|
|
if (is_file($dir . '/upgrade.php')) {
|
|
$fun = include $dir . '/upgrade.php';
|
|
$fun("{$type}_after_sql");
|
|
}
|
|
if (is_file($dir . '/upgrade.sh')) {
|
|
self::runShell('/bin/bash' . ' ' . escapeshellarg($dir . '/upgrade.sh') . ' ' . $type);
|
|
}
|
|
|
|
DB::insert([
|
|
"insert into upgrades",
|
|
"(name, status, updated_at)",
|
|
"values", DB::tuple([$name, $type, DB::now()]),
|
|
"on duplicate key update", ["status" => $type, "updated_at" => DB::now()]
|
|
]);
|
|
|
|
echo "DONE\n";
|
|
}
|
|
public static function up($name) {
|
|
self::upgrade($name, 'up');
|
|
}
|
|
public static function down($name) {
|
|
self::upgrade($name, 'down');
|
|
}
|
|
public static function refresh($name) {
|
|
self::upgrade($name, 'down');
|
|
self::upgrade($name, 'up');
|
|
}
|
|
public static function remove($name) {
|
|
self::upgrade($name, 'down');
|
|
DB::delete([
|
|
"delete from upgrades",
|
|
"where", ["name" => $name]
|
|
]);
|
|
}
|
|
public static function removeAll() {
|
|
$names = [];
|
|
foreach (DB::selectAll("select * from upgrades") as $u) {
|
|
$names[] = $u['name'];
|
|
}
|
|
natsort($names);
|
|
foreach (array_reverse($names) as $name) {
|
|
self::upgrade($name, 'down');
|
|
}
|
|
DB::delete("delete from upgrades");
|
|
}
|
|
|
|
public static function upgradeToLatest() {
|
|
$names = array_filter(scandir(self::upgraderRoot()), function ($name) {
|
|
return is_dir(self::upgraderRoot() . '/' . $name) && preg_match('/^\d+_[0-9a-zA-Z\._]+$/', $name);
|
|
});
|
|
|
|
natsort($names);
|
|
|
|
$names_table = [];
|
|
foreach ($names as $name) {
|
|
$names_table[$name] = true;
|
|
}
|
|
|
|
$dres = DB::selectAll("select * from upgrades");
|
|
foreach ($dres as $u) {
|
|
if (!isset($names_table[$u['name']])) {
|
|
die('missing: ' . HTML::escape($name) . "\n");
|
|
}
|
|
}
|
|
|
|
foreach ($names as $name) {
|
|
self::up($name);
|
|
}
|
|
}
|
|
}
|