Skip to main content
Glama

CTX: Context as Code (CaC) tool

by context-hub
MIT License
235
  • Apple
  • Linux
UnixUpdateStrategy.php4.95 kB
<?php declare(strict_types=1); namespace Butschster\ContextGenerator\Lib\BinaryUpdater\Strategy; use Psr\Log\LoggerInterface; use Spiral\Files\FilesInterface; /** * Unix-specific strategy for updating binary files. * Creates a bash script that runs in the background after the current process exits. */ final readonly class UnixUpdateStrategy implements UpdateStrategyInterface { public function __construct( private FilesInterface $files, private ?LoggerInterface $logger = null, ) {} public function update(string $sourcePath, string $targetPath): bool { $this->logger?->info("Using Unix update strategy for binary: {$targetPath}"); // Create the update script $this->logger?->info("Creating Unix update script..."); $scriptPath = $this->createUpdateScript($sourcePath, $targetPath); if ($scriptPath === null) { $this->logger?->error("Failed to create Unix update script"); return false; } $this->logger?->info("Created update script at: {$scriptPath}"); // Make the script executable $this->logger?->info("Setting executable permissions on script"); if (!\chmod($scriptPath, 0755)) { $this->logger?->error("Failed to set executable permissions on script"); return false; } // Run the script in the background and continue after PHP exits $command = \sprintf( 'nohup %s > /dev/null 2>&1 & echo $!', \escapeshellarg($scriptPath), ); $this->logger?->info("Executing update script in background with command: {$command}"); // Execute the command and capture the process ID $output = []; $resultCode = 0; \exec($command, $output, $resultCode); // If we got a process ID and the command executed successfully, consider it a success $success = $resultCode === 0 && !empty($output[0]) && \is_numeric($output[0]); if ($success) { $this->logger?->info("Successfully started background update process with PID: {$output[0]}"); } else { $this->logger?->error("Failed to start background update process, exit code: {$resultCode}"); } return $success; } /** * Create a temporary bash script that will perform the update. * * @return string|null Path to the created script, or null if creation failed */ private function createUpdateScript(string $sourcePath, string $targetPath): ?string { try { $scriptPath = $this->files->tempFilename('.sh'); $this->logger?->info("Generated temporary script path: {$scriptPath}"); $scriptContent = <<<BASH #!/bin/bash # Wait for the parent process to exit sleep 1 # Define paths SOURCE="{$sourcePath}" TARGET="{$targetPath}" TARGET_DIR="\$(dirname "\$TARGET")" # Set up retry logic MAX_ATTEMPTS=10 ATTEMPT=1 SUCCESS=0 echo "Starting update process for \$TARGET" # Create the target directory if it doesn't exist mkdir -p "\$TARGET_DIR" # Try to update the file with multiple attempts while [ \$ATTEMPT -le \$MAX_ATTEMPTS ] && [ \$SUCCESS -eq 0 ]; do echo "Attempt \$ATTEMPT: Trying to update \$TARGET" # Try to copy the file if cp "\$SOURCE" "\$TARGET" 2>/dev/null; then # Make the file executable chmod 755 "\$TARGET" echo "Update successful!" SUCCESS=1 else echo "Binary busy or permission denied, waiting 2 seconds..." sleep 2 ATTEMPT=\$((ATTEMPT+1)) fi done # Clean up the temporary source file rm -f "\$SOURCE" rm -f "$scriptPath" # Exit with the appropriate status if [ \$SUCCESS -eq 0 ]; then echo "Update failed after \$MAX_ATTEMPTS attempts." exit 1 fi exit 0 BASH; $this->logger?->debug("Writing bash script content to temporary file"); $this->files->write($scriptPath, $scriptContent); return $scriptPath; } catch (\Throwable $e) { $this->logger?->error("Error creating update script: {$e->getMessage()}"); return null; } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/context-hub/generator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server