Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/updater.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGit'Fellow <carlos@reendex.com>2022-06-30 11:53:42 +0300
committerGitHub <noreply@github.com>2022-06-30 11:53:42 +0300
commitdab7606ae895f2dc7903124aafe6d1f6b0d183b5 (patch)
tree7e51a274b6f420a3fd9c8dff6a977269c8e91f9c
parentbd6a4114864faec390044e8bb4f4505db73bfbce (diff)
Introduce Update Directory
Allow to specify a specific directory as updater working directory
-rw-r--r--lib/Updater.php181
1 files changed, 89 insertions, 92 deletions
diff --git a/lib/Updater.php b/lib/Updater.php
index b527e8d..7ede201 100644
--- a/lib/Updater.php
+++ b/lib/Updater.php
@@ -47,7 +47,7 @@ class Updater {
public function __construct($baseDir) {
$this->baseDir = $baseDir;
- if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
+ if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@@ -66,8 +66,8 @@ class Updater {
return;
}
- $dataDir = $this->getDataDirectoryLocation();
- if(empty($dataDir) || !is_string($dataDir)) {
+ $dataDir = $this->getUpdateDirectoryLocation();
+ if (empty($dataDir) || !is_string($dataDir)) {
throw new \Exception('Could not read data directory from config.php.');
}
@@ -84,16 +84,13 @@ class Updater {
$buildTime = $OC_Build;
}
- if($version === null) {
- return;
- }
- if($buildTime === null) {
+ if ($version === null || $buildTime === null) {
return;
}
// normalize version to 3 digits
$splittedVersion = explode('.', $version);
- if(sizeof($splittedVersion) >= 3) {
+ if (sizeof($splittedVersion) >= 3) {
$splittedVersion = array_slice($splittedVersion, 0, 3);
}
@@ -188,8 +185,8 @@ class Updater {
*
* @return string
*/
- private function getDataDirectoryLocation() {
- return $this->configValues['datadirectory'];
+ private function getUpdateDirectoryLocation() {
+ return $this->configValues['updatedirectory'] ?? $this->configValues['datadirectory'];
}
/**
@@ -250,11 +247,11 @@ class Updater {
*/
private function getAppDirectories() {
$expected = [];
- if($appsPaths = $this->getConfigOption('apps_paths')) {
+ if ($appsPaths = $this->getConfigOption('apps_paths')) {
foreach ($appsPaths as $appsPath) {
$parentDir = realpath($this->baseDir . '/../');
$appDir = basename($appsPath['path']);
- if(strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
+ if (strpos($appsPath['path'], $parentDir) === 0 && $appDir !== 'apps') {
$expected[] = $appDir;
}
}
@@ -287,7 +284,7 @@ class Updater {
$expectedElements = $this->getExpectedElementsList();
$unexpectedElements = [];
foreach (new \DirectoryIterator($this->baseDir . '/../') as $fileInfo) {
- if(array_search($fileInfo->getFilename(), $expectedElements) === false) {
+ if (array_search($fileInfo->getFilename(), $expectedElements) === false) {
$unexpectedElements[] = $fileInfo->getFilename();
}
}
@@ -310,11 +307,11 @@ class Updater {
$it = new \RecursiveIteratorIterator($filter);
foreach ($it as $path => $dir) {
- if(!is_writable($path)) {
+ if (!is_writable($path)) {
$notWritablePaths[] = $path;
}
}
- if(count($notWritablePaths) > 0) {
+ if (count($notWritablePaths) > 0) {
throw new UpdateException($notWritablePaths);
}
@@ -330,7 +327,7 @@ class Updater {
public function setMaintenanceMode($state) {
$this->silentLog('[info] setMaintenanceMode("' . ($state ? 'true' : 'false') . '")');
- if($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
+ if ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
$configFileName = rtrim($dir, '/') . '/config.php';
} else {
$configFileName = $this->baseDir . '/../config/config.php';
@@ -370,11 +367,11 @@ class Updater {
];
// Create new folder for the backup
- $backupFolderLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
+ $backupFolderLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid').'/backups/nextcloud-'.$this->getConfigOption('version') . '-' . time() . '/';
$this->silentLog('[info] backup folder location: ' . $backupFolderLocation);
$state = mkdir($backupFolderLocation, 0750, true);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not create backup folder location');
}
@@ -390,35 +387,35 @@ class Updater {
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
- if(isset($folderStructure[0])) {
- if(array_search($folderStructure[0], $excludedElements) !== false) {
+ if (isset($folderStructure[0])) {
+ if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
- if(array_search($fileName, $excludedElements) !== false) {
+ if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
// Create folder if it doesn't exist
- if(!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
+ if (!file_exists($backupFolderLocation . '/' . dirname($fileName))) {
$state = mkdir($backupFolderLocation . '/' . dirname($fileName), 0750, true);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not create folder: '.$backupFolderLocation.'/'.dirname($fileName));
}
}
// If it is a file copy it
- if($fileInfo->isFile()) {
+ if ($fileInfo->isFile()) {
$state = copy($fileInfo->getRealPath(), $backupFolderLocation . $fileName);
- if($state === false) {
+ if ($state === false) {
$message = sprintf(
'Could not copy "%s" to "%s"',
$fileInfo->getRealPath(),
$backupFolderLocation . $fileName
);
- if(is_readable($fileInfo->getRealPath()) === false) {
+ if (is_readable($fileInfo->getRealPath()) === false) {
$message = sprintf(
'%s. Source %s is not readable',
$message,
@@ -426,7 +423,7 @@ class Updater {
);
}
- if(is_writable($backupFolderLocation . $fileName) === false) {
+ if (is_writable($backupFolderLocation . $fileName) === false) {
$message = sprintf(
'%s. Destination %s is not writable',
$message,
@@ -456,7 +453,7 @@ class Updater {
$this->silentLog('[info] getUpdateServerResponse()');
$updaterServer = $this->getConfigOption('updater.server.url');
- if($updaterServer === null) {
+ if ($updaterServer === null) {
// FIXME: used deployed URL
$updaterServer = 'https://updates.nextcloud.com/updater_server/';
}
@@ -486,26 +483,26 @@ class Updater {
}
$response = curl_exec($curl);
- if($response === false) {
+ if ($response === false) {
throw new \Exception('Could not do request to updater server: '.curl_error($curl));
}
curl_close($curl);
// Response can be empty when no update is available
- if($response === '') {
+ if ($response === '') {
return [];
}
$xml = simplexml_load_string($response);
- if($xml === false) {
+ if ($xml === false) {
throw new \Exception('Could not parse updater server XML response');
}
$json = json_encode($xml);
- if($json === false) {
+ if ($json === false) {
throw new \Exception('Could not JSON encode updater server response');
}
$response = json_decode($json, true);
- if($response === null) {
+ if ($response === null) {
throw new \Exception('Could not JSON decode updater server response.');
}
$this->silentLog('[info] getUpdateServerResponse response: ' . print_r($response, true));
@@ -521,13 +518,13 @@ class Updater {
$this->silentLog('[info] downloadUpdate()');
$response = $this->getUpdateServerResponse();
- $storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
- if(file_exists($storageLocation)) {
+ $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
+ if (file_exists($storageLocation)) {
$this->silentLog('[info] storage location exists');
$this->recursiveDelete($storageLocation);
}
$state = mkdir($storageLocation, 0750, true);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not mkdir storage location');
}
@@ -546,11 +543,11 @@ class Updater {
]);
}
- if(curl_exec($ch) === false) {
+ if (curl_exec($ch) === false) {
throw new \Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- if($httpCode !== 200) {
+ if ($httpCode !== 200) {
$statusCodes = [
400 => 'Bad request',
401 => 'Unauthorized',
@@ -563,14 +560,14 @@ class Updater {
];
$message = 'Download failed';
- if(isset($statusCodes[$httpCode])) {
+ if (isset($statusCodes[$httpCode])) {
$message .= ' - ' . $statusCodes[$httpCode] . ' (HTTP ' . $httpCode . ')';
} else {
$message .= ' - HTTP status code: ' . $httpCode;
}
$curlErrorMessage = curl_error($ch);
- if(!empty($curlErrorMessage)) {
+ if (!empty($curlErrorMessage)) {
$message .= ' - curl error message: ' . $curlErrorMessage;
}
@@ -589,7 +586,7 @@ class Updater {
* @throws \Exception
*/
private function getDownloadedFilePath() {
- $storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
+ $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$filesInStorageLocation = scandir($storageLocation);
@@ -597,7 +594,7 @@ class Updater {
return $path !== '.' && $path !== '..';
}));
// only the downloaded archive
- if(count($files) !== 1) {
+ if (count($files) !== 1) {
throw new \Exception('There are more files than the downloaded archive in the downloads/ folder.');
}
return $storageLocation . '/' . $files[0];
@@ -611,13 +608,13 @@ class Updater {
public function verifyIntegrity() {
$this->silentLog('[info] verifyIntegrity()');
- if($this->getCurrentReleaseChannel() === 'daily') {
+ if ($this->getCurrentReleaseChannel() === 'daily') {
$this->silentLog('[info] current channel is "daily" which is not signed. Skipping verification.');
return;
}
$response = $this->getUpdateServerResponse();
- if(!isset($response['signature'])) {
+ if (!isset($response['signature'])) {
throw new \Exception('No signature specified for defined update');
}
@@ -658,7 +655,7 @@ EOF;
OPENSSL_ALGO_SHA512
);
- if($validSignature === false) {
+ if ($validSignature === false) {
throw new \Exception('Signature of update is not valid');
}
@@ -675,7 +672,7 @@ EOF;
private function getVersionByVersionFile($versionFile) {
require $versionFile;
- if(isset($OC_Version)) {
+ if (isset($OC_Version)) {
/** @var array $OC_Version */
return implode('.', $OC_Version);
}
@@ -696,12 +693,12 @@ EOF;
$zipState = $zip->open($downloadedFilePath);
if ($zipState === true) {
$extraction = $zip->extractTo(dirname($downloadedFilePath));
- if($extraction === false) {
+ if ($extraction === false) {
throw new \Exception('Error during unpacking zipfile: '.($zip->getStatusString()));
}
$zip->close();
$state = unlink($downloadedFilePath);
- if($state === false) {
+ if ($state === false) {
throw new \Exception("Can't unlink ". $downloadedFilePath);
}
} else {
@@ -711,7 +708,7 @@ EOF;
// Ensure that the downloaded version is not lower
$downloadedVersion = $this->getVersionByVersionFile(dirname($downloadedFilePath) . '/nextcloud/version.php');
$currentVersion = $this->getVersionByVersionFile($this->baseDir . '/../version.php');
- if(version_compare($downloadedVersion, $currentVersion, '<')) {
+ if (version_compare($downloadedVersion, $currentVersion, '<')) {
throw new \Exception('Downloaded version is lower than installed version');
}
@@ -739,14 +736,14 @@ EOF;
foreach($filesToReplace as $file) {
$this->silentLog('[info] replace ' . $file);
$parentDir = dirname($this->baseDir . '/../' . $file);
- if(!file_exists($parentDir)) {
+ if (!file_exists($parentDir)) {
$r = mkdir($parentDir);
- if($r !== true) {
+ if ($r !== true) {
throw new \Exception('Can\'t create parent directory for entry point: ' . $file);
}
}
$state = file_put_contents($this->baseDir . '/../' . $file, $content);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Can\'t replace entry point: '.$file);
}
}
@@ -761,7 +758,7 @@ EOF;
* @throws \Exception
*/
private function recursiveDelete($folder) {
- if(!file_exists($folder)) {
+ if (!file_exists($folder)) {
return;
}
$iterator = new \RecursiveIteratorIterator(
@@ -791,7 +788,7 @@ EOF;
}
$state = rmdir($folder);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not rmdir ' . $folder);
}
}
@@ -805,12 +802,12 @@ EOF;
$this->silentLog('[info] deleteOldFiles()');
$shippedAppsFile = $this->baseDir . '/../core/shipped.json';
- if(!file_exists($shippedAppsFile)) {
+ if (!file_exists($shippedAppsFile)) {
throw new \Exception('core/shipped.json is not available');
}
- $newShippedAppsFile = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
- if(!file_exists($newShippedAppsFile)) {
+ $newShippedAppsFile = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/core/shipped.json';
+ if (!file_exists($newShippedAppsFile)) {
throw new \Exception('core/shipped.json is not available in the new release');
}
@@ -824,7 +821,7 @@ EOF;
}
$configSampleFile = $this->baseDir . '/../config/config.sample.php';
- if(file_exists($configSampleFile)) {
+ if (file_exists($configSampleFile)) {
$this->silentLog('[info] config sample exists');
// Delete example config
@@ -835,7 +832,7 @@ EOF;
}
$themesReadme = $this->baseDir . '/../themes/README';
- if(file_exists($themesReadme)) {
+ if (file_exists($themesReadme)) {
$this->silentLog('[info] themes README exists');
// Delete themes
@@ -871,23 +868,23 @@ EOF;
$fileName = explode($currentDir, $path)[1];
$folderStructure = explode('/', $fileName, -1);
// Exclude the exclusions
- if(isset($folderStructure[0])) {
- if(array_search($folderStructure[0], $excludedElements) !== false) {
+ if (isset($folderStructure[0])) {
+ if (array_search($folderStructure[0], $excludedElements) !== false) {
continue;
}
} else {
- if(array_search($fileName, $excludedElements) !== false) {
+ if (array_search($fileName, $excludedElements) !== false) {
continue;
}
}
- if($fileInfo->isFile() || $fileInfo->isLink()) {
+ if ($fileInfo->isFile() || $fileInfo->isLink()) {
$state = unlink($path);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not unlink: '.$path);
}
- } elseif($fileInfo->isDir()) {
+ } elseif ($fileInfo->isDir()) {
$state = rmdir($path);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not rmdir: '.$path);
}
}
@@ -922,15 +919,15 @@ EOF;
}
}
- if($fileInfo->isFile()) {
- if(!file_exists($this->baseDir . '/../' . dirname($fileName))) {
+ if ($fileInfo->isFile()) {
+ if (!file_exists($this->baseDir . '/../' . dirname($fileName))) {
$state = mkdir($this->baseDir . '/../' . dirname($fileName), 0755, true);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not mkdir ' . $this->baseDir . '/../' . dirname($fileName));
}
}
$state = rename($path, $this->baseDir . '/../' . $fileName);
- if($state === false) {
+ if ($state === false) {
throw new \Exception(
sprintf(
'Could not rename %s to %s',
@@ -940,9 +937,9 @@ EOF;
);
}
}
- if($fileInfo->isDir()) {
+ if ($fileInfo->isDir()) {
$state = rmdir($path);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not rmdir ' . $path);
}
}
@@ -967,7 +964,7 @@ EOF;
'ocs/v1.php',
'ocs/v2.php',
];
- $storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
+ $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, $excludedElements);
@@ -983,15 +980,15 @@ EOF;
public function finalize() {
$this->silentLog('[info] finalize()');
- $storageLocation = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
+ $storageLocation = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/downloads/nextcloud/';
$this->silentLog('[info] storage location: ' . $storageLocation);
$this->moveWithExclusions($storageLocation, []);
$state = rmdir($storageLocation);
- if($state === false) {
+ if ($state === false) {
throw new \Exception('Could not rmdir $storagelocation');
}
- $state = unlink($this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
- if($state === false) {
+ $state = unlink($this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid') . '/.step');
+ if ($state === false) {
throw new \Exception('Could not rmdir .step');
}
@@ -1009,22 +1006,22 @@ EOF;
* @throws \Exception
*/
private function writeStep($state, $step) {
- $updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
- if(!file_exists($updaterDir . '/.step')) {
- if(!file_exists($updaterDir)) {
+ $updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
+ if (!file_exists($updaterDir . '/.step')) {
+ if (!file_exists($updaterDir)) {
$result = mkdir($updaterDir);
if ($result === false) {
throw new \Exception('Could not create $updaterDir');
}
}
$result = touch($updaterDir . '/.step');
- if($result === false) {
+ if ($result === false) {
throw new \Exception('Could not create .step');
}
}
$result = file_put_contents($updaterDir . '/.step', json_encode(['state' => $state, 'step' => $step]));
- if($result === false) {
+ if ($result === false) {
throw new \Exception('Could not write to .step');
}
}
@@ -1054,9 +1051,9 @@ EOF;
public function currentStep() {
$this->silentLog('[info] currentStep()');
- $updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
+ $updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
$jsonData = [];
- if(file_exists($updaterDir. '/.step')) {
+ if (file_exists($updaterDir. '/.step')) {
$state = file_get_contents($updaterDir . '/.step');
if ($state === false) {
throw new \Exception('Could not read from .step');
@@ -1079,8 +1076,8 @@ EOF;
public function rollbackChanges($step) {
$this->silentLog('[info] rollbackChanges("' . $step . '")');
- $updaterDir = $this->getDataDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
- if(file_exists($updaterDir . '/.step')) {
+ $updaterDir = $this->getUpdateDirectoryLocation() . '/updater-'.$this->getConfigOption('instanceid');
+ if (file_exists($updaterDir . '/.step')) {
$this->silentLog('[info] unlink .step');
$state = unlink($updaterDir . '/.step');
if ($state === false) {
@@ -1088,7 +1085,7 @@ EOF;
}
}
- if($step >= 7) {
+ if ($step >= 7) {
$this->silentLog('[info] rollbackChanges - step >= 7');
// TODO: If it fails after step 7: Rollback
}
@@ -1110,7 +1107,7 @@ EOF;
$message .= 'Trace:' . PHP_EOL . $e->getTraceAsString() . PHP_EOL;
$message .= 'File:' . $e->getFile() . PHP_EOL;
$message .= 'Line:' . $e->getLine() . PHP_EOL;
- if($e instanceof UpdateException) {
+ if ($e instanceof UpdateException) {
$message .= 'Data:' . PHP_EOL . print_r($e->getData(), true) . PHP_EOL;
}
$this->log($message);
@@ -1123,14 +1120,14 @@ EOF;
* @throws LogException
*/
public function log($message) {
- $updaterLogPath = $this->getDataDirectoryLocation() . '/updater.log';
+ $updaterLogPath = $this->getUpdateDirectoryLocation() . '/updater.log';
$fh = fopen($updaterLogPath, 'a');
- if($fh === false) {
+ if ($fh === false) {
throw new LogException('Could not open updater.log');
}
- if($this->requestID === null) {
+ if ($this->requestID === null) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
@@ -1143,7 +1140,7 @@ EOF;
$logLine = date(\DateTime::ISO8601) . ' ' . $this->requestID . ' ' . $message . PHP_EOL;
$result = fwrite($fh, $logLine);
- if($result === false) {
+ if ($result === false) {
throw new LogException('Could not write to updater.log');
}