You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
7.0 KiB
223 lines
7.0 KiB
// 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') |
|
}
|
|
|