// Functions related to OS and installing software import chalk from 'chalk' import { execSync } from 'child_process' // Detects the operating system we are running on let distro export function detectOS() { if(distro) { return distro } try { execSync('[ -f "/etc/debian_version" ]') distro = 'debian' console.log(`${greenChalk('Debian')}, Ubuntu, or Raspbian OS detected.`) } catch(err) {} try { execSync('[ -f "/etc/arch-release" ]') distro = 'arch' console.log(`${greenChalk('Arch or Manjaro-based')} OS detected.`) } catch(err) {} try { execSync('[ -f "/etc/fedora-release" ]') distro = 'fedora' console.log(`${greenChalk('Fedora')} OS detected.`) } catch(err) {} try { execSync('[ $(uname | grep -c "Darwin") -eq 1 ]') distro = 'mac' console.log(`${greenChalk('MacOS')} detected.`) } catch(err) {} if(!distro) { console.log("Your OS was not recognized, sorry.") process.exit(1) } return distro } // Runs the correct command to update all your software for any recognized OS export function updateSoftware() { detectOS() if(!distro) { console.log("Your OS was not recognized, so nothing was updated, sorry.") return false } console.log('Updating your software from repositories...') console.log(`(You may need to input your ${chalk.blue.bold("'sudo' password")} here)`) switch(distro) { case 'debian': execSync('sudo apt update -yqqq && sudo apt autoremove -yqqq && sudo apt upgrade -yqqq') break case 'arch': execSync('sudo pacman -Syu --noconfirm') // for Manjaro, also do pamac upgrade -a && pamac update --aur --devel to do normal then build all AUR packages (check https://forum.manjaro.org/c/announcements/11 first) break case 'fedora': execSync('sudo dnf update -yqqq 2>/dev/null && && sudo dnf autoremove -yqqq && sudo dnf upgrade -yqqq') break case 'mac': // Install homebrew (todo: if not installed) execSync('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') execSync('install && sudo brew update') // is this right? can it replicate all commands such as update upgrade autoremove? break } return true } // Checks if the given package is installed using the standard repo for your detected OS function isInstalled(packageName, group) { detectOS() if(!distro) { console.log("Your OS was not recognized, so nothing was updated, sorry.") return false } switch(distro) { case 'debian': return execSync("dpkg-query -W -f='${Status}' " + packageName + " 2>/dev/null").includes('ok installed') case 'arch': try { if(!group) { const stdout = execSync("pacman -Qi " + packageName) if(stdout.includes('was not found')) { return false } } else { const stdout = execSync("pacman -Qg " + packageName).toString() if(!stdout.includes(packageName)) { return false } } return true } catch(error) { break } case 'fedora': case 'mac': } } // Uses the standard app repo for your detected OS to install the named package function installPackage(packageName) { detectOS() if(!distro) { console.log("Your OS was not recognized, so nothing was updated, sorry.") return false } switch(distro) { case 'debian': try { execSync('sudo apt install -y ' + packageName) return true } catch(error) { break } case 'arch': try { const result = execSync("sudo pacman -S " + packageName + " --noconfirm").toString() console.log(packageName, 'installed result is', result) return true } catch(error) { break } case 'fedora': case 'mac': console.log('Install on this OS not yet implemented, sorry.') } console.log('Failed to install', packageName + '. Error:', error) return false } // Installs the specified package or packages using the standard repos for your detected OS. Prints console messages if verbose. function installIfNotInstalled(packageNameOrNames, verbose = true, group = false) { if(!Array.isArray(packageNameOrNames)) { if(typeof packageNameOrNames !== 'string') { if(verbose) console.log('Invalid package name provided. Doing nothing.') return null } packageNameOrNames = [ packageNameOrNames ] } let packagesInstalled = 0 let packagesFailed = 0 packageNameOrNames.forEach(packageName => { if(!isInstalled(packageName, group)) { const success = installPackage(packageName) if(success) { if(verbose) console.log('Installed', packageName + '.') packagesInstalled++ } else { if(verbose) console.log('Failed to install', packageName + '.') packagesFailed++ } } else { if(verbose) console.log(packageName, 'already installed.') } }) return { installed: packagesInstalled, failed: packagesFailed } } // Creates the directories to store the AO's database, memes, manual, and maybe other things, ~/.ao by standard export function createAoDirectories() { try { execSync('mkdir -p $HOME/.ao/memes') } catch(error) { console.log('Error creating ~/.ao/memes directory. Maybe it already exists.') } } function installNvm() { try { execSync('[ -z $NVM_DIR ]') execSync('source ~/Alchemy/ingredients/iron && install_nvm') console.log(`Installed nvm.`) return true } catch(err) { return false } } // Installs core dependencies required by Alchemy and the AO export function installRequired() { detectOS() if(!distro) { console.log("Your OS was not recognized, so nothing was installed, sorry.") return false } console.log('Installing Alchemy and AO installation process core dependencies (fast if already installed)...') console.log(`(You may need to input your ${chalk.blue.bold("'sudo' password")} here)`) // Install on every OS installIfNotInstalled(['curl', 'wget', 'git', 'make', 'sqlite3', 'python', 'autoconf-archive']) installNvm() // Install OS-specific requirements switch(distro) { case 'debian': // Some of these might not be required installIfNotInstalled(['build-essential', 'zlib1g-dev', 'libtool-bin', 'autoconf', 'automake autotools-dev', 'libgmp-dev', 'libsqlite3-dev', 'python3', 'python3-mako', 'libsodium-dev', 'pkg-config', 'libev-dev', 'libcurl4-gnutls-dev', 'libssl-dev', 'fakeroot', 'devscripts']) break case 'arch': installIfNotInstalled('base-devel', true, true) installIfNotInstalled(['gmp', 'pkgconf', 'libev', 'python-mako', 'python-pip', 'net-tools', 'zlib', 'libsodium', 'gettext', 'nginx']) break case 'fedora': installIfNotInstalled(['autoconf', 'automake', 'python3', 'python3-mako', 'pkg-config', 'fakeroot', 'devscripts']) break } return true } // Sets node to the current version used by the AO export function setNodeVersion() { execSync('source ~/Alchemy/ingredients/lead && source ~/Alchemy/ingredients/iron && set_node_to v16.13.0') }