diff --git a/scripts/Commands/InitCommand.php b/scripts/Commands/InitCommand.php
index 720dcd119..26ab54c9e 100644
--- a/scripts/Commands/InitCommand.php
+++ b/scripts/Commands/InitCommand.php
@@ -105,10 +105,11 @@ class InitCommand extends Command
*/
protected function cloneBookStackViaGit(string $installDir): void
{
- $errors = (new ProgramRunner('git', '/usr/bin/git'))
+ $git = (new ProgramRunner('git', '/usr/bin/git'))
->withTimeout(240)
- ->withIdleTimeout(15)
- ->runCapturingStdErr([
+ ->withIdleTimeout(15);
+
+ $errors = $git->runCapturingStdErr([
'clone', '-q',
'--branch', 'release',
'--single-branch',
@@ -119,6 +120,12 @@ class InitCommand extends Command
if ($errors) {
throw new CommandError("Failed git clone with errors:\n" . $errors);
}
+
+ // Disable file permission tracking for git repo
+ $git->runCapturingStdErr([
+ '-C', $installDir,
+ 'config', 'core.fileMode', 'false'
+ ]);
}
/**
diff --git a/scripts/Commands/RestoreCommand.php b/scripts/Commands/RestoreCommand.php
index 6c2b7deb5..a7c8ac5ff 100644
--- a/scripts/Commands/RestoreCommand.php
+++ b/scripts/Commands/RestoreCommand.php
@@ -48,7 +48,6 @@ class RestoreCommand extends Command
$zipPath = realpath($input->getArgument('backup-zip'));
$zip = new BackupZip($zipPath);
- // TODO - Fix folders not being picked up here:
$contents = $zip->getContentsOverview();
$output->writeln("\nContents found in the backup ZIP:");
@@ -79,9 +78,10 @@ class RestoreCommand extends Command
}
$zip->extractInto($extractDir);
+ $envChanges = [];
if ($contents['env']['exists']) {
$output->writeln("Restoring and merging .env file...");
- $this->restoreEnv($extractDir, $appDir);
+ $envChanges = $this->restoreEnv($extractDir, $appDir, $output, $interactions);
}
$folderLocations = ['themes', 'public/uploads', 'storage/uploads'];
@@ -92,18 +92,22 @@ class RestoreCommand extends Command
}
}
+ $artisan = (new ArtisanRunner($appDir));
if ($contents['db']['exists']) {
$output->writeln("Restoring database from SQL dump...");
$this->restoreDatabase($appDir, $extractDir);
$output->writeln("Running database migrations...");
- $artisan = (new ArtisanRunner($appDir));
$artisan->run(['migrate', '--force']);
}
- // TODO - Handle change of URL?
- // TODO - Update system URL (via BookStack artisan command) if
- // there's been a change from old backup env
+ if ($envChanges && $envChanges['old_url'] !== $envChanges['new_url']) {
+ $output->writeln("App URL change made, Updating database with URL change...");
+ $artisan->run([
+ 'bookstack:update-url',
+ $envChanges['old_url'], $envChanges['new_url'],
+ ]);
+ }
$output->writeln("Clearing app caches...");
$artisan->run(['cache:clear']);
@@ -118,7 +122,7 @@ class RestoreCommand extends Command
return Command::SUCCESS;
}
- protected function restoreEnv(string $extractDir, string $appDir)
+ protected function restoreEnv(string $extractDir, string $appDir, OutputInterface $output, InteractiveConsole $interactions): array
{
$oldEnv = EnvironmentLoader::load($extractDir);
$currentEnv = EnvironmentLoader::load($appDir);
@@ -149,7 +153,23 @@ class RestoreCommand extends Command
copy($appEnvPath, $appEnvPath . '.backup');
}
+ $oldUrl = $oldEnv['APP_URL'] ?? '';
+ $newUrl = $currentEnv['APP_URL'] ?? '';
+ $returnData = [
+ 'old_url' => $oldUrl,
+ 'new_url' => $oldUrl,
+ ];
+
+ if ($oldUrl !== $newUrl) {
+ $output->writeln("Found different APP_URL values:");
+ $changedUrl = $interactions->choice('Which would you like to use?', array_filter([$oldUrl, $newUrl]));
+ $envContents = preg_replace('/^APP_URL=.*?$/', 'APP_URL="' . $changedUrl . '"', $envContents);
+ $returnData['new_url'] = $changedUrl;
+ }
+
file_put_contents($appDir . DIRECTORY_SEPARATOR . '.env', $envContents);
+
+ return $returnData;
}
protected function restoreFolder(string $folderSubPath, string $appDir, string $extractDir): void
diff --git a/scripts/Services/BackupZip.php b/scripts/Services/BackupZip.php
index 798e24477..cb3ca280a 100644
--- a/scripts/Services/BackupZip.php
+++ b/scripts/Services/BackupZip.php
@@ -30,15 +30,15 @@ class BackupZip
],
'themes' => [
'desc' => 'Themes Folder',
- 'exists' => $this->zip->locateName('/themes/') !== false,
+ 'exists' => $this->hasFolder('themes/'),
],
'public/uploads' => [
'desc' => 'Public File Uploads',
- 'exists' => $this->zip->locateName('/public/uploads/') !== false,
+ 'exists' => $this->hasFolder('public/uploads/'),
],
'storage/uploads' => [
'desc' => 'Private File Uploads',
- 'exists' => $this->zip->locateName('/storage/uploads/') !== false,
+ 'exists' => $this->hasFolder('storage/uploads/'),
],
'db' => [
'desc' => 'Database Dump',
@@ -54,4 +54,15 @@ class BackupZip
throw new \Exception("Failed extraction of ZIP into [{$directoryPath}].");
}
}
+
+ protected function hasFolder($folderPath): bool
+ {
+ for ($i = 0; $i < $this->zip->numFiles; $i++) {
+ $filePath = $this->zip->getNameIndex($i);
+ if (str_starts_with($filePath, $folderPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/scripts/Services/InteractiveConsole.php b/scripts/Services/InteractiveConsole.php
index 8d8f92626..0fdabe052 100644
--- a/scripts/Services/InteractiveConsole.php
+++ b/scripts/Services/InteractiveConsole.php
@@ -2,6 +2,7 @@
namespace Cli\Services;
+use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -9,14 +10,11 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
class InteractiveConsole
{
-
-
public function __construct(
protected QuestionHelper $helper,
protected InputInterface $input,
protected OutputInterface $output,
- )
- {
+ ) {
}
public function confirm(string $text): bool
@@ -24,4 +22,10 @@ class InteractiveConsole
$question = new ConfirmationQuestion($text . " (y/n)\n", false);
return $this->helper->ask($this->input, $this->output, $question);
}
-}
\ No newline at end of file
+
+ public function choice(string $question, array $answers)
+ {
+ $question = new ChoiceQuestion($question, $answers, $answers[0]);
+ return $this->helper->ask($this->input, $this->output, $question);
+ }
+}
diff --git a/scripts/Services/MySqlRunner.php b/scripts/Services/MySqlRunner.php
index 1b1091c77..40b1d98fd 100644
--- a/scripts/Services/MySqlRunner.php
+++ b/scripts/Services/MySqlRunner.php
@@ -39,7 +39,7 @@ class MySqlRunner
'-u', $this->user,
'-p' . $this->password,
$this->database,
- '-e' . "'show tables;'"
+ '-e', "show tables;"
]);
return !$output;