Implement stow config file and folder unwrapping
Move includes to their own folder, config.php will otherwise be included and cleans up nicely
This commit is contained in:
118
php/includes/stow.php
Normal file
118
php/includes/stow.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
readonly class stow
|
||||
{
|
||||
public const ACTION_STOW = 'stow';
|
||||
public const ACTION_UNSTOW = 'unstow';
|
||||
|
||||
public function __construct(
|
||||
private string $action = self::ACTION_STOW,
|
||||
private bool $backup = false,
|
||||
private bool $force = false,
|
||||
private bool $unwrap = false,
|
||||
) {}
|
||||
|
||||
private function getNoStow(string $path): array
|
||||
{
|
||||
if (file_exists(path($path, '.nostow'))) {
|
||||
$noStow = file_get_contents(path($path, '.nostow'));
|
||||
if ($noStow === false) {
|
||||
return [];
|
||||
}
|
||||
return array_values(array_filter(array_map('trim', explode(PHP_EOL, $noStow))));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function run(string $sourcePath, string $targetPath): void
|
||||
{
|
||||
$noStow = $this->getNoStow($sourcePath);
|
||||
$sourceFiles = array_diff(scandir($sourcePath), ['..', '.', 'config.php', '.nostow', ...$noStow]);
|
||||
|
||||
foreach ($sourceFiles as $sourceFile) {
|
||||
$targetFile = path($targetPath, $sourceFile);
|
||||
$stowFile = path($sourcePath, $sourceFile);
|
||||
|
||||
switch ($this->action) {
|
||||
case self::ACTION_STOW:
|
||||
$this->stow($stowFile, $targetFile);
|
||||
break;
|
||||
case self::ACTION_UNSTOW:
|
||||
$this->unstow($stowFile, $targetFile);
|
||||
break;
|
||||
default:
|
||||
line("Unknown action: {$this->action}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function stow(string $stowFile, string $targetFile): void
|
||||
{
|
||||
if (is_link($targetFile)) {
|
||||
$targetLink = readlink($targetFile);
|
||||
if ($targetLink === $stowFile) {
|
||||
line("File $targetFile is already stowed from $stowFile");
|
||||
} else {
|
||||
if ($this->unwrap) {
|
||||
line("Unwrapping $targetFile from $targetLink");
|
||||
unlink($targetFile);
|
||||
mkdir($targetFile);
|
||||
$this->run($targetLink, $targetFile);
|
||||
$this->run($stowFile, $targetFile);
|
||||
} else {
|
||||
line("File $targetFile is linked from $targetLink, ignoring, add -w to unwrap");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (is_dir($targetFile)) {
|
||||
if (is_dir($stowFile)) {
|
||||
line("File $targetFile and $stowFile are folders, recurse into existing folders");
|
||||
$this->run($stowFile, $targetFile);
|
||||
} else {
|
||||
line("File $targetFile is a folder, but stow file $stowFile is not a folder");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (is_file($targetFile)) {
|
||||
if ($this->backup) {
|
||||
$backFile = $targetFile . '.bak';
|
||||
if (is_file($backFile)) {
|
||||
line("Backup file $backFile already exists");
|
||||
return;
|
||||
}
|
||||
rename($targetFile, $backFile);
|
||||
line("Backup file $targetFile to $backFile");
|
||||
} elseif ($this->force) {
|
||||
line("Todo: delete file $targetFile");
|
||||
return;
|
||||
} else {
|
||||
line("File $targetFile already exists");
|
||||
return;
|
||||
}
|
||||
}
|
||||
line("Stow $targetFile from $stowFile");
|
||||
symlink($stowFile, $targetFile);
|
||||
}
|
||||
|
||||
public function unstow(string $stowFile, string $targetFile): void
|
||||
{
|
||||
if (is_link($targetFile) && readlink($targetFile) === $stowFile) {
|
||||
line("Unstow $targetFile from $stowFile");
|
||||
unlink($targetFile);
|
||||
return;
|
||||
}
|
||||
if (is_dir($targetFile)) {
|
||||
if (is_dir($stowFile)) {
|
||||
line("File $targetFile and $stowFile are folders, recurse into existing folders");
|
||||
$this->run($stowFile, $targetFile);
|
||||
return;
|
||||
} else {
|
||||
line("File $targetFile is a folder, but stow file $stowFile is not a folder");
|
||||
}
|
||||
}
|
||||
line("File $targetFile is not stowed from $stowFile");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user