#!/usr/bin/env nu # Install - Install binaries from source or bundle # # Usage: # nu scripts/provisioning/install.nu --source ./bin --prefix ~/.local # nu scripts/provisioning/install.nu --source ./bin # use common/platform.nu * use common/validate.nu * def show-help [] { let help_text = " syntaxis Install - Install binaries to system USAGE: nu scripts/provisioning/install.nu [OPTIONS] OPTIONS: --source Source directory containing binaries (required) --prefix Installation prefix Default: /usr/local --force Overwrite existing binaries --backup Backup existing binaries before overwriting --help Show this help message EXAMPLES: # Install binaries to default location nu scripts/provisioning/install.nu --source ./bin # Install to custom prefix nu scripts/provisioning/install.nu --source ./bin --prefix ~/.local # Install with backup nu scripts/provisioning/install.nu --source ./bin --backup " print $help_text } def detect-binaries [source_dir: path] { if (not (($source_dir | path exists))) { let msg = "Source directory not found: " + ($source_dir | into string) error make {msg: $msg} } let files = (glob ($source_dir | path join "*")) let binaries = ( $files | where {|f| (($f | path type) == "file")} | each {|f| {path: $f, name: ($f | path basename)}} ) if (($binaries | length) == 0) { let msg = "No binaries found in: " + ($source_dir | into string) error make {msg: $msg} } $binaries } def ensure-bin-directory [bin_dir: path] { if (not (($bin_dir | path exists))) { print ("📁 Creating directory: " + ($bin_dir | into string)) ^mkdir -p $bin_dir } let perm_check = (validate-permissions $bin_dir --write true) if (not ($perm_check.valid)) { let msg = "Cannot write to directory: " + ($bin_dir | into string) error make {msg: $msg} } } def backup-existing [bin_dir: path, binary_name: string] { let binary_path = ($bin_dir | path join $binary_name) if (($binary_path | path exists)) { let timestamp = (date now | format date "%Y%m%d-%H%M%S") let backup_path = ($bin_dir | path join ($binary_name + ".backup-" + $timestamp)) ^cp $binary_path $backup_path print (" 📦 Backed up to: " + ($backup_path | path basename)) } } def install-binary [source_path: path, bin_dir: path, binary_name: string, force: bool, backup: bool] { let dest_path = ($bin_dir | path join $binary_name) if (($dest_path | path exists)) { if $backup { backup-existing $bin_dir $binary_name } else if (not $force) { print (" ⚠️ " + $binary_name + " already exists (use --force to overwrite)") return false } } print (" 📋 Installing: " + $binary_name) ^cp $source_path $dest_path ^chmod +x $dest_path print (" ✓ Installed to: " + ($dest_path | into string)) true } def create-manifest [bin_dir: path, installed_binaries: list] { let manifest_dir = ($env.HOME | path join ".syntaxis") ^mkdir -p $manifest_dir let manifest = { installation: { installed_at: (date now | format date "%Y-%m-%dT%H:%M:%SZ") prefix: ($bin_dir | into string) binaries: $installed_binaries } } let manifest_file = ($manifest_dir | path join "manifest.toml") let content = $manifest | to toml $content | ^tee $manifest_file print ("✅ Manifest saved: " + ($manifest_file | into string)) } def show-installation-summary [bin_dir: path, installed_binaries: list] { print "" print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" print "✅ Installation Summary" print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" print ("Installed to: " + ($bin_dir | into string)) print ("Binaries: " + (($installed_binaries | length) | into string)) $installed_binaries | each { |bin| print (" ✓ " + $bin) } print "" print "Next steps:" print " 1. Add to PATH: export PATH=\"" + ($bin_dir | into string) + ":$PATH\"" print " 2. Verify: " + (($installed_binaries.0) | into string) + " --help" print "" } # Main entry point def main [--source: path = "", --prefix: path = "", --force = false, --backup = false, --help = false] { if $help { show-help return } if ($source == "") { error make {msg: "Source directory must be specified with --source"} } # Determine installation prefix let install_prefix = if ($prefix == "") { default-prefix (current-target) } else { $prefix } let bin_dir = ($install_prefix | path join "bin") print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" print "📦 syntaxis Install" print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" print ("Source: " + ($source | into string)) print ("Destination: " + ($bin_dir | into string)) print ("Force: " + ($force | into string)) print ("Backup: " + ($backup | into string)) print "" # Ensure destination directory is writable ensure-bin-directory $bin_dir # Detect binaries in source print "🔍 Detecting binaries..." let binaries = (detect-binaries $source) print (" Found " + (($binaries | length) | into string) + " binaries") print "" # Install each binary print "📥 Installing binaries..." let installed_binaries = ( $binaries | each { |bin| let success = (install-binary $bin.path $bin_dir $bin.name $force $backup) if $success { $bin.name } else { null } } | where { |item| (not ($item == null)) } ) if (($installed_binaries | length) > 0) { create-manifest $bin_dir $installed_binaries show-installation-summary $bin_dir $installed_binaries } else { print "❌ No binaries were installed" } }