From 31871efec3a6292419b0013ee9d20fa5849f192b Mon Sep 17 00:00:00 2001 From: Brian Zalewski <59970525+ProfessorManhattan@users.noreply.github.com> Date: Sun, 14 Jan 2024 08:40:00 +0000 Subject: [PATCH] Latest --- home/.chezmoidata.yaml | 2 + .../executable_install-terminal-theme.tmpl | 21 ++ home/dot_local/bin/executable_installx | 246 +++++++++++++++--- software.yml | 13 + 4 files changed, 243 insertions(+), 39 deletions(-) diff --git a/home/.chezmoidata.yaml b/home/.chezmoidata.yaml index 6fd3c634..030bc92b 100644 --- a/home/.chezmoidata.yaml +++ b/home/.chezmoidata.yaml @@ -910,6 +910,8 @@ softwareGroups: Package-Management: &Package-Management # - homebrew # - whalebrew + - eget + - gup - mise - syncpack - ultra diff --git a/home/dot_local/bin/executable_install-terminal-theme.tmpl b/home/dot_local/bin/executable_install-terminal-theme.tmpl index 50875517..36e5a1ee 100644 --- a/home/dot_local/bin/executable_install-terminal-theme.tmpl +++ b/home/dot_local/bin/executable_install-terminal-theme.tmpl @@ -681,7 +681,28 @@ apply_darwin() { # | # | Applying values on iTerm2 # | =========================================== +export COLOR_01="#282C34" # Black +export COLOR_02="#ED254E" # Red +export COLOR_03="#71F79F" # Green +export COLOR_04="#F9DC5C" # Yellow +export COLOR_05="#7CB7FF" # Blue +export COLOR_06="#C74D89" # Magenta +export COLOR_07="#00C1E4" # Cyan +export COLOR_08="#DCDFE4" # Light gray +export COLOR_09="#4C5058" # Dark gray +export COLOR_10="#FF4972" # Light Red +export COLOR_11="#95FFC3" # Light Green +export COLOR_12="#FFFF80" # Light Yellow +export COLOR_13="#A0DBFF" # Light Blue +export COLOR_14="#EB71AD" # Light Magenta +export COLOR_15="#24E5FF" # Light Cyan +export COLOR_16="#FFFFFF" # White + +export BACKGROUND_COLOR="#161925" # Background Color +export FOREGROUND_COLOR="#C3C7D1" # Foreground Color (text) +export CURSOR_COLOR="$FOREGROUND_COLOR" # Cursor color +export PROFILE_NAME="Betelgeuse" BACKGROUND_COLOR=$(convertNameAndRGBtoITerm "Background Color" "$BACKGROUND_COLOR") FOREGROUND_COLOR=$(convertNameAndRGBtoITerm "Foreground Color" "$FOREGROUND_COLOR") COLOR_01=$(convertNameAndRGBtoITerm "Ansi 0 Color" "$COLOR_01") diff --git a/home/dot_local/bin/executable_installx b/home/dot_local/bin/executable_installx index 4eb2623e..2e6ebdf8 100644 --- a/home/dot_local/bin/executable_installx +++ b/home/dot_local/bin/executable_installx @@ -1,28 +1,51 @@ #!/usr/bin/env zx import osInfo from 'linux-os-info' -let archType, osId, osType +let installOrder, osArch, osId, osType, pkgs, sysType async function getOsInfo() { return osInfo({ mode: 'sync' }) } -function getPkgData(pref, pkg) { - if (pkg[`${pref}:${this.osType()}:${this.osArch()}`]) { - // Handles case like `pipx:windows:x64:` - return `${pref}:${this.osType()}:${this.osArch()}` - } else if (pkg[`${pref}:${this.osId()}:${this.osArch()}`]) { - // Handles case like `pipx:debian:x64:` - return `${pref}:${this.osId()}:${this.osArch()}` - } else if (pkg[`${pref}:${this.osType()}`]) { - // Handles case like `pipx:darwin:` - return `${pref}:${this.osType()}` - } else if (pkg[`${pref}:${this.osId()}`]) { - // Handles case like `pipx:fedora:` - return `${pref}:${this.osType()}` - } else if (pkg[`${pref}`]) { - // Handles case like `pipx:` - return `${pref}` +function getPkgData(pref, pkg, installer) { + if (installer) { + if (pkg[`${pref}:${installer}:${osId}:${osArch}`]) { + return `${pref}:${installer}:${osId}:${osArch}` // Handles case like `_bin:pipx:debian:x64:` + } else if (pkg[`${pref}:${osId}:${installer}:${osArch}`]) { + return `${pref}:${osId}:${installer}:${osArch}` // Handles case like `_bin:debian:pipx:x64:` + } else if (pkg[`${pref}:${installer}:${osType}:${osArch}`]) { + return `${pref}:${installer}:${osType}:${osArch}` // Handles case like `_bin:pipx:windows:x64:` + } else if (pkg[`${pref}:${osType}:${installer}:${osArch}`]) { + return `${pref}:${osType}:${installer}:${osArch}` // Handles case like `_bin:windows:pipx:x64:` + } else if (pkg[`${pref}:${installer}:${osId}`]) { + return `${pref}:${installer}:${osType}` // Handles case like `_bin:pipx:fedora:` + } else if (pkg[`${pref}:${osId}:${installer}`]) { + return `${pref}:${osType}:${installer}` // Handles case like `_bin:fedora:pipx:` + } else if (pkg[`${pref}:${installer}:${osType}`]) { + return `${pref}:${installer}:${osType}` // Handles case like `_bin:pipx:darwin:` + } else if (pkg[`${pref}:${osType}:${installer}`]) { + return `${pref}:${osType}:${installer}` // Handles case like `_bin:darwin:pipx:` + } else if (pkg[`${pref}:${installer}`]) { + return `${pref}` // Handles case like `_bin:pipx:` + } else if (pkg[`${pref}`]) { + return `${pref}` // Handles case like `_bin:` + } else { + return false + } + } else { + if (pkg[`${pref}:${osId}:${osArch}`]) { + return `${pref}:${osId}:${osArch}` // Handles case like `pipx:debian:x64:` + } else if (pkg[`${pref}:${osType}:${osArch}`]) { + return `${pref}:${osType}:${osArch}` // Handles case like `pipx:windows:x64:` + } else if (pkg[`${pref}:${osId}`]) { + return `${pref}:${osType}` // Handles case like `pipx:fedora:` + } else if (pkg[`${pref}:${osType}`]) { + return `${pref}:${osType}` // Handles case like `pipx:darwin:` + } else if (pkg[`${pref}`]) { + return `${pref}` // Handles case like `pipx:` + } else { + return false + } } } @@ -56,39 +79,184 @@ async function getSystemType() { } } +async function getBrewFormulas() { + await $`brew list -1 > brew-list` + return fs.readFileSync('./brew-list').toString().split('\n') +} + +async function getGems() { + await $`gem query --local > gem-list` + return fs.readFileSync('./gem-list').toString().split('\n').map(x => x.split(' ')[0]) +} + +async function getVoltaInstalls() { + await $`volta list --format plain > volta-list` + return fs.readFileSync('./volta-list').toString().split('\n').filter(x => x).map(x => x.split(' ')[1].split('@')[0]) +} + +async function getCrates() { + await $`cargo install --list | awk '/^[[:alnum:]]/ {print $1}' > cargo-list` + return fs.readFileSync('./cargo-list').toString().split('\n') +} + +async function getPipxPackages() { + await $`pipx list --short > pipx-list` + return fs.readFileSync('./pipx-list').toString().split('\n').map(x => x.split(' ')[0]) +} + +async function getPips() { + await $`pip3 list > pip-list` + return fs.readFileSync('./pip-list').toString().split('\n').map(x => x.split(' ')[0]) +} + +function expandDeps(keys) { + for (const i of keys) { + for (const pref of installOrder[sysType]) { + const installKey = getPkgData(pref, pkgs[i], false) + if (installKey) { + const installType = installKey.split(':')[0] + const depsKey = getPkgData('_deps', pkgs[i], installType) + if (depsKey) { + const deps = typeof pkgs[i][depsKey] === 'string' ? [pkgs[i][depsKey]] : pkgs[i][depsKey] + return [...keys, ...expandDeps(deps)] + } + } + } + return [...keys] + } + return [...keys] +} + +async function bundleInstall(brews, casks) { + const lines = [] + for (const cask of casks) { + lines.push(`cask "${cask}"`) + } + for (const brew of brews) { + lines.push(`brew "${brew}"`) + } + fs.writeFileSync('Brewfile', lines.join('\n')) + await $`brew bundle --file Brewfile` +} + +async function installPackages(pkgInstructions) { + const combined = {} + const promises = [] + for (const option of installOrder[sysType]) { + combined[option] = pkgInstructions.filter(x => x.installType === option) + } + if (combined.brew || combined.cask) { + promises.push(bundleInstall(combined.brew ? combined.brew : [], combined.cask ? combined.cask : [])) + } + if (combined.cargo) { + for (const pkg of combined.cargo) { + promises.push($`cargo install ${pkg}`) + } + } + if (combined.go) { + for (const pkg of combined.go) { + promises.push($`go install ${pkg}`) + } + } + if (combined.npm) { + for (const pkg of combined.npm) { + promises.push($`volta install ${pkg}`) + } + } + if (combined.pacman) { + const pacmanPkgs = combined.pacman.map(x => ) + promises.push($`sudo pacman -Sy --noconfirm --needed ${combined.pacman.map}`) + } + if (combined.pipx) { + for (const pkg of combined.pipx) { + promises.push($`pipx install ${pkg}`) + } + } + console.log(combinedInstructions) +} + async function main() { - const initData = await Promise.all([getOsInfo(), getSoftwareDefinitions(), getSystemType()]) - archType = initData[0].arch + cd(await $`mktemp -d`) + const initData = await Promise.all([ + getOsInfo(), + getSoftwareDefinitions(), + getSystemType(), + getBrewFormulas(), + getGems(), + getVoltaInstalls(), + getCrates(), + getPipxPackages(), + getPips() + ]) + osArch = initData[0].arch osId = process.platform === 'win32' ? 'win32' : (process.platform === 'linux' ? initData[0].id : process.platform) osType = process.platform === 'win32' ? 'windows' : process.platform - const installOrder = initData[1].installOrderPreferences - const softwarePackages = initData[1].softwarePackages - const sysType = initData[2] + pkgs = initData[1].softwarePackages + sysType = initData[2] + installOrder = initData[1].installerPreference + const managerLists = { + brew: initData[3], + cargo: initData[6], + gem: initData[4], + npm: initData[5], + pip: initData[8], + pipx: initData[7] + } const installKeys = argv._ - const installInstructions = softwarePackages - .filter(i => installKeys.includes(i)) - .filter(async i => { - const binField = getPkgData('_bin', i) - const whenField = getPkgData('_when', i) - const binCheck = i[binField] && await which(i[binField], { nothrow: true }) - const whenCheck = i[whenField] && await $`${i[whenField]}`.exitCode == 0 - return (i[binField] && !binCheck) || (i[whenField] && whenCheck) - }) + const installInstructions = Object.keys(pkgs) + .filter(i => expandDeps(installKeys).includes(i)) .map(i => { - for (const pref of installOrder) { - const pkgData = getPkgData(pref, i) - if (pkgData) { + for (const pref of installOrder[sysType]) { + const installKey = getPkgData(pref, pkgs[i], false) + if (installKey) { return { - ...x, - installKey + ...pkgs[i], + listKey: i, + installKey, + installType: installKey.split(':')[0], + installList: typeof pkgs[i][installKey] === 'string' ? [pkgs[i][installKey]] : pkgs[i][installKey] } } } - return false + return { + ...pkgs[i], + listKey: i, + installKey: false, + installType: false, + installList: [] + } }) - .filter(i => !!i) - console.log(installInstructions) + .filter(x => x.installKey) + .filter(x => { + // Filter out packages already installed by by package managers + return Object.keys(managerLists).includes(x.installType) + }) + .filter(x => { + // Filter out macOS apps that already have a _app installed + if (x.installType === 'cask') { + const appField = getPkgData('_app', x, x.installType) + if (fs.existsSync(`/Applications/${x[appField]}`) || fs.existsSync(`${os.homedir()}/Applications/${x[appField]}`)) { + return false + } + } + return true + }) + .filter(async x => { + // Filter out packages that already have a bin in the PATH + const binField = getPkgData('_bin', x, x.installType) + const binCheck = x[binField] && await which(x[binField], { nothrow: true }) + return binField ? binCheck : true + }) + .filter(async x => { + // Filter out packages that do not pass _when check + const whenField = getPkgData('_when', x, x.installType) + const whenCheck = x[whenField] && await $`${x[whenField]}`.exitCode == 0 + return whenField ? whenCheck : true + }) + await installPackages(installInstructions) + //.filter(x => x.installKey) + console.log('install instructions', installInstructions) } main() diff --git a/software.yml b/software.yml index 313bcbb5..2359d783 100644 --- a/software.yml +++ b/software.yml @@ -9985,6 +9985,19 @@ softwarePackages: port: restic scoop: restic zypper: restic + gup: + _bin: gup + _github: + _name: Gup + brew: nao1215/tap/gup + go: github.com/nao1215/gup@latest + eget: + _bin: eget + _github: https://github.com/zyedidia/eget + _name: eget + brew: eget + choco: eget + go: github.com/zyedidia/eget@latest ripgrep: _bin: rg _desc: '[ripgrep](https://github.com/BurntSushi/ripgrep) is a line-oriented search tool that recursively searches your current directory for a regex pattern. By default, ripgrep will respect your .gitignore and automatically skip hidden files/directories and binary files. This role also installs ripgrep-all. [ripgrep-all](https://github.com/phiresky/ripgrep-all) is just like ripgrep except it also searches in PDFs, E-Books, Office documents, zip, tar.gz, etc.'