// Functions related to OS and installing software
import chalk from 'chalk'
import { execSync } from 'child_process'
// Exits ao-cli if has been run with sudo or while logged in as root/superuser using su
export function exitIfRoot ( ) {
try {
let loggedInUserUnixID = parseInt ( execSync ( 'echo $EUID' ) . toString ( ) )
if ( loggedInUserUnixID === 0 ) {
console . log ( ` ${ chalk . red . bold ( exclaim ( ) ) } Seems you're running this script as a superuser. ` )
console . log ( 'That might cause some issues with permissions and whatnot. Run this script as your default user (without sudo) and I\'ll ask you when I need superuser permissions.' )
process . exit ( 1 )
}
} catch ( err ) {
console . log ( 'Error checking whether or not you are root. Continuing but please do not run ao-cli as root or sudo! It will install things with admin privileges and then you won\'t be able to access them.' )
}
}
// 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' )
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
export 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 }
}
// Returns true if npm install (npm i) has been run in the given path, otherwise false. Also returns false if the folder does not exist.
// Note that npm packages are totally different from (normal) packages installed the OS's bundled package manager. They are node packages.
export async function isNpmPackageInstalled ( path , verbose = false ) {
try {
const stdout = execSync ( 'cd ' + folderPath + ' && npm list 2>&1' )
return true
} catch ( error ) {
const missingLocalPackagesCount = error . output . toString ( ) . match ( /npm ERR! missing:/g ) . length || 0
if ( missingLocalPackagesCount ) {
if ( verbose ) console . log ( path , 'has' , missingLocalPackagesCount , 'npm packages left to install.' )
} else {
if ( verbose ) console . log ( 'Error while checking if npm package at' , path , 'is installed:' , error )
}
}
return false
}