getNoStow($sourcePath); $sourceFiles = array_diff(scandir($sourcePath), ['..', '.', '.nostow', ...$noStow]); foreach ($sourceFiles as $sourceFile) { $targetFile = path($targetPath, $sourceFile); $stowFile = path($sourcePath, $sourceFile); switch ($this->action) { case self::ACTION_STOW: $this->stow($targetFile, $stowFile); break; case self::ACTION_UNSTOW: $this->unstow($targetFile, $stowFile); break; default: line("Unknown action: {$this->action}"); return; } } } public function stow(string $targetFile, string $stowFile): void { if (is_link($targetFile)) { $targetLink = readlink($targetFile); if ($targetLink === $stowFile) { line("File $targetFile is already stowed from $stowFile"); } else { line("File $targetFile is linked from $targetLink"); } 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 $targetFile, string $stowFile): 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"); } }