Compare commits
30 Commits
8153393d8d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e1ea39a90 | ||
|
|
cd8f2b7c0d | ||
|
|
48fe726f31 | ||
| 5d9b2d56e5 | |||
| ea86be7b01 | |||
| b7664ad8a7 | |||
| 37542773e3 | |||
| 7c8d81f080 | |||
| 854c19f35f | |||
| 87df4b6d7d | |||
| 8bca66a7bb | |||
|
|
8def65f683 | ||
|
|
563a29aa58 | ||
|
|
0fbcf46307 | ||
|
|
59f627914d | ||
|
|
d4d03b0bb3 | ||
|
|
ad7007a8ee | ||
|
|
6cdd744093 | ||
|
|
604789d9a9 | ||
|
|
53b8527e12 | ||
|
|
e44c48efbd | ||
|
|
b008d4ebb0 | ||
|
|
d4a39b5dd5 | ||
|
|
1953b01148 | ||
|
|
3f2f23a446 | ||
|
|
5c1a6998b7 | ||
|
|
60fc6580d8 | ||
|
|
dd6875b79a | ||
|
|
aef49d322f | ||
|
|
82e5747b67 |
22
README.md
22
README.md
@@ -1,16 +1,19 @@
|
|||||||
# macOS System
|
# macOS System
|
||||||
|
|
||||||
Scripts to align a macOS system to Astzweig system configuration.
|
Scripts to align a macOS system to Astzweig system configuration.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
```zsh
|
```zsh
|
||||||
/bin/zsh -c "$(curl -fsSL https://raw.githubusercontent.com/astzweig/macos-system/main/bootstrap.sh)"
|
/bin/zsh -c "$(curl -fsSL https://git.tabshift.dev/spacebar/macos-system/raw/branch/main/bootstrap.sh)"
|
||||||
```
|
```
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
1. Run all setup from a temporary directory and delete it in the end
|
1. Run all setup from a temporary directory and delete it in the end
|
||||||
|
|
||||||
## Process
|
## Process
|
||||||
|
|
||||||
1. `install.sh` queries all modules for their required information
|
1. `install.sh` queries all modules for their required information
|
||||||
1. The modules print their required information to stdout using the format as described below.
|
1. The modules print their required information to stdout using the format as described below.
|
||||||
1. `install.sh` parses those informations and tries to read them from a configuration file.
|
1. `install.sh` parses those informations and tries to read them from a configuration file.
|
||||||
@@ -18,14 +21,17 @@ Scripts to align a macOS system to Astzweig system configuration.
|
|||||||
1. `install.sh` then runs the modules with their required informations passed in as parameter values.
|
1. `install.sh` then runs the modules with their required informations passed in as parameter values.
|
||||||
|
|
||||||
## License exclusion
|
## License exclusion
|
||||||
|
|
||||||
The license does not cover the file [Astzweig.png](resources/user-pictures/Astzweig.png).
|
The license does not cover the file [Astzweig.png](resources/user-pictures/Astzweig.png).
|
||||||
|
|
||||||
## Required Information Format
|
## Required Information Format
|
||||||
|
|
||||||
Modules must print their required information to stdout if they're called with
|
Modules must print their required information to stdout if they're called with
|
||||||
`show-questions` command. Required information are all information the module
|
`show-questions` command. Required information are all information the module
|
||||||
might want to ask the user in order to configure some aspect of the system.
|
might want to ask the user in order to configure some aspect of the system.
|
||||||
|
|
||||||
### Schema
|
### Schema
|
||||||
|
|
||||||
The general schema is:
|
The general schema is:
|
||||||
|
|
||||||
```zsh
|
```zsh
|
||||||
@@ -33,14 +39,15 @@ The general schema is:
|
|||||||
s: --highlight-color=What color shall your system highlight color be? # choose from: blue,red,light green;
|
s: --highlight-color=What color shall your system highlight color be? # choose from: blue,red,light green;
|
||||||
p: --user-password=What color shall your system highlight color be?
|
p: --user-password=What color shall your system highlight color be?
|
||||||
```
|
```
|
||||||
|
|
||||||
The letter at the beginning is the question type:
|
The letter at the beginning is the question type:
|
||||||
|
|
||||||
| Question type | Description | Arguments |
|
| Question type | Description | Arguments |
|
||||||
| ------------- | ----------- | --------- |
|
| ------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||||
| i (info) | A question where the user has no restrictions on input | `default`: a default answer. |
|
| i (info) | A question where the user has no restrictions on input | `default`: a default answer. |
|
||||||
| p (password) | A question where the user input is not printed to standard output. | - |
|
| p (password) | A question where the user input is not printed to standard output. | - |
|
||||||
| c (confirm) | A yes/no question where the user is allowed to answer yes or no. | - |
|
| c (confirm) | A yes/no question where the user is allowed to answer yes or no. | - |
|
||||||
| s (select) | A list of choices where the user can select one using numbers. | `choose from`: a comma separated list of possible select values. |
|
| s (select) | A list of choices where the user can select one using numbers. | `choose from`: a comma separated list of possible select values. |
|
||||||
|
|
||||||
`<PARAMETER NAME>` is the the parameter name, that will receive the user answer
|
`<PARAMETER NAME>` is the the parameter name, that will receive the user answer
|
||||||
when the module is called. Single char parameter names will be prefixed with a
|
when the module is called. Single char parameter names will be prefixed with a
|
||||||
@@ -50,4 +57,5 @@ the parameter name `highlight-color` becomes `--highlight-color <user response>`
|
|||||||
`<QUESTION>` must contain any punctuation you want to show.
|
`<QUESTION>` must contain any punctuation you want to show.
|
||||||
|
|
||||||
[^zshlib-askUser]: Currently supported: info, password, confirm, choose. They map to [zshlib/askUser][zshlib-overview] commands.
|
[^zshlib-askUser]: Currently supported: info, password, confirm, choose. They map to [zshlib/askUser][zshlib-overview] commands.
|
||||||
|
|
||||||
[zshlib-overview]: https://github.com/astzweig/zshlib#whats-included
|
[zshlib-overview]: https://github.com/astzweig/zshlib#whats-included
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
# vi: set ft=zsh tw=80 ts=2
|
|
||||||
|
|
||||||
function _installMASApp() {
|
|
||||||
mas install ${id} &> /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function installMASApp() {
|
|
||||||
local appName="$1"
|
|
||||||
local id="$2"
|
|
||||||
indicateActivity -- "Install ${appName} app" _installMASApp
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
lop -y h1 -- -i 'Install Mac AppStore Apps'
|
|
||||||
installMASApp 'Affinity Designer 2' 1616831348
|
|
||||||
installMASApp 'Affinity Photo 2' 1616822987
|
|
||||||
installMASApp 'Affinity Publisher 2' 1606941598
|
|
||||||
installMASApp 'AusweisApp' 948660805
|
|
||||||
installMASApp 'Compressor' 424390742
|
|
||||||
installMASApp 'Developer' 640199958
|
|
||||||
installMASApp 'Diagrams' 1276248849
|
|
||||||
installMASApp 'Final Cut Pro' 424389933
|
|
||||||
installMASApp 'Iconographer Mini' 1541509510
|
|
||||||
installMASApp 'iMazing Profile Editor' 1487860882
|
|
||||||
installMASApp 'Infuse' 1136220934
|
|
||||||
installMASApp 'Keka' 470158793
|
|
||||||
installMASApp 'Keynote' 409183694
|
|
||||||
installMASApp 'Mass Rename' 1175416599
|
|
||||||
installMASApp 'Microsoft Excel' 462058435
|
|
||||||
installMASApp 'Microsoft Word' 462054704
|
|
||||||
installMASApp 'Motion' 434290957
|
|
||||||
installMASApp 'Numbers' 409203825
|
|
||||||
installMASApp 'Outbank' 1094255754
|
|
||||||
installMASApp 'Pages' 409201541
|
|
||||||
installMASApp 'Pixelmator Pro' 1289583905
|
|
||||||
installMASApp 'SnippetsLab' 1006087419
|
|
||||||
installMASApp 'WorkingHours' 1495643653
|
|
||||||
installMASApp 'Xcode' 497799835
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
|
|
||||||
source autoload-zshlib
|
|
||||||
main "$@"
|
|
||||||
fi
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
# vi: set ft=zsh tw=80 ts=2
|
|
||||||
|
|
||||||
function configureLogging() {
|
|
||||||
local output=tostdout level=info
|
|
||||||
[ -n "${logfile}" ] && output=${logfile}
|
|
||||||
[ "${verbose}" = true ] && level=debug
|
|
||||||
lop setoutput -l ${level} ${output}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUsage() {
|
|
||||||
local cmdName=$1 text=''
|
|
||||||
read -r -d '' text <<- USAGE
|
|
||||||
Usage:
|
|
||||||
$cmdName [-v] [-d FILE] --hostname NAME
|
|
||||||
|
|
||||||
Configure host specific settings.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--hostname NAME Set NAME as current host's host name.
|
|
||||||
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
|
|
||||||
-v, --verbose Be more verbose.
|
|
||||||
----
|
|
||||||
$cmdName 0.1.0
|
|
||||||
Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG
|
|
||||||
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
|
|
||||||
USAGE
|
|
||||||
print -- ${text}
|
|
||||||
}
|
|
||||||
|
|
||||||
function quitSystemPreferences() {
|
|
||||||
ps -A -o pid,comm | grep "MacOS/System Settings" | awk '{print "kill -9 " $1}' | /bin/sh
|
|
||||||
}
|
|
||||||
|
|
||||||
function setComputerName() {
|
|
||||||
scutil --set ComputerName "${hostname}"
|
|
||||||
scutil --set HostName "${hostname}"
|
|
||||||
scutil --set LocalHostName "${hostname}"
|
|
||||||
systemsetup -setcomputername "${hostname}"
|
|
||||||
systemsetup -setlocalsubnetname "${hostname}"
|
|
||||||
}
|
|
||||||
|
|
||||||
function configureComputerHostname() {
|
|
||||||
local currentComputerName="`scutil --get ComputerName`"
|
|
||||||
if [[ "${currentComputerName}" != "${hostname}" ]]; then
|
|
||||||
lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}."
|
|
||||||
indicateActivity -- 'Set computer name' setComputerName
|
|
||||||
else
|
|
||||||
lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function requireRootPrivileges() {
|
|
||||||
[[ `id -u` -eq 0 ]] || { lop -- -e 'Need root access to change hostname. Aborting.'; return 10 }
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
local cmdPath=${1} cmdName=${1:t}
|
|
||||||
shift
|
|
||||||
eval "`getUsage $cmdName | docopts -f -V - -h - : "$@"`"
|
|
||||||
configureLogging
|
|
||||||
requireRootPrivileges || return $?
|
|
||||||
|
|
||||||
lop -y h1 -- -i 'Configure System Settings'
|
|
||||||
indicateActivity -- 'Quitting System Preferences' quitSystemPreferences
|
|
||||||
configureComputerHostname
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
|
|
||||||
_DIR="${0:A:h}"
|
|
||||||
source autoload-zshlib
|
|
||||||
main $0 "$@"
|
|
||||||
fi
|
|
||||||
45
bin/azw-setup-host
Executable file
45
bin/azw-setup-host
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
# vi: set ft=zsh tw=80 ts=2
|
||||||
|
|
||||||
|
function _installMASApp() {
|
||||||
|
mas install ${id} &> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
function installMASApp() {
|
||||||
|
local appName="$1"
|
||||||
|
local id="$2"
|
||||||
|
indicateActivity -- "Install ${appName} app" _installMASApp
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
lop -y h1 -- -i 'Install Mac AppStore Apps'
|
||||||
|
installMASApp 'AusweisApp' 948660805
|
||||||
|
installMASApp 'Compressor' 424390742
|
||||||
|
installMASApp 'Developer' 640199958
|
||||||
|
installMASApp 'Diagrams' 1276248849
|
||||||
|
installMASApp 'Final Cut Pro' 424389933
|
||||||
|
installMASApp 'Iconographer Mini' 1541509510
|
||||||
|
installMASApp 'iMazing Profile Editor' 1487860882
|
||||||
|
installMASApp 'Infuse' 1136220934
|
||||||
|
installMASApp 'Keka' 470158793
|
||||||
|
installMASApp 'Keynote' 409183694
|
||||||
|
installMASApp 'Mass Rename' 1175416599
|
||||||
|
installMASApp 'Microsoft Excel' 462058435
|
||||||
|
installMASApp 'Microsoft Word' 462054704
|
||||||
|
installMASApp 'Motion' 434290957
|
||||||
|
installMASApp 'Numbers' 409203825
|
||||||
|
installMASApp 'Outbank' 1094255754
|
||||||
|
installMASApp 'Pages' 409201541
|
||||||
|
installMASApp 'Parallels Desktop' 1085114709
|
||||||
|
installMASApp 'Pixelmator Pro' 1289583905
|
||||||
|
installMASApp 'SnippetsLab' 1006087419
|
||||||
|
installMASApp 'Tim' 1449619230
|
||||||
|
installMASApp 'WorkingHours' 1495643653
|
||||||
|
installMASApp 'Xcode' 497799835
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
|
||||||
|
_DIR="${0:A:h}"
|
||||||
|
source autoload-zshlib
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
185
bin/azw-setup-user
Executable file
185
bin/azw-setup-user
Executable file
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
# vi: set ft=zsh tw=80 ts=2
|
||||||
|
|
||||||
|
function getExecPrerequisites() {
|
||||||
|
cmds+=(
|
||||||
|
[launchctl]=''
|
||||||
|
[git]=''
|
||||||
|
[mkdir]=''
|
||||||
|
[chmod]=''
|
||||||
|
[]=''
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideFolders() {
|
||||||
|
chflags hidden ${HOME}/bin
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkExecPrerequisites() {
|
||||||
|
local -A cmds
|
||||||
|
getExecPrerequisites || return
|
||||||
|
checkCommands -m 'This script needs %1$s to work. Please install and retry.' ${(k)cmds} || return
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureInstallPrefix() {
|
||||||
|
local dirPath= desc=
|
||||||
|
for dirPath desc in ${homebrew_prefix} 'Creating install prefix' ${homebrew_directory} 'Creating Homebrew directory'; do
|
||||||
|
if [[ ! -d ${dirPath} ]]; then
|
||||||
|
indicateActivity -- ${desc} createDirAndLogOnFailure ${dirPath}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDirAndLogOnFailure() {
|
||||||
|
local dirPath=$1
|
||||||
|
mkdir -p ${dirPath} 2> /dev/null || {
|
||||||
|
loptty -- -e 'Could not create directory' -e $dirPath
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
chmod 744 ${dirPath}
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadHomebrew() {
|
||||||
|
local git_homebrew_remote=`getDefaultGitHomebrewURL`
|
||||||
|
pushd -q ${homebrew_directory} || return 10
|
||||||
|
test -d ".git" && return
|
||||||
|
git init -q
|
||||||
|
git config remote.origin.url "${git_homebrew_remote}"
|
||||||
|
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
|
||||||
|
git config core.autocrlf false
|
||||||
|
git config --replace-all homebrew.analyticsmessage false
|
||||||
|
git config --replace-all homebrew.caskanalyticsmessage false
|
||||||
|
git fetch --quiet --force origin > /dev/null
|
||||||
|
git fetch --quiet --force --tags origin > /dev/null
|
||||||
|
git reset --hard origin/master
|
||||||
|
popd -q
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCanonicalBrewPath() {
|
||||||
|
local brewPath=${homebrew_directory}/bin/brew
|
||||||
|
if [[ $brewPath == $HOME* ]]; then
|
||||||
|
brewPath="\${HOME}${brewPath#$HOME}"
|
||||||
|
fi
|
||||||
|
echo $brewPath
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBrewCallerScript() {
|
||||||
|
local cmdPath=${HOME}/bin/brew
|
||||||
|
local brewPath=`getCanonicalBrewPath`
|
||||||
|
[[ -f ${cmdPath} ]] && rm ${cmdPath}
|
||||||
|
mkdir -p ${cmdPath:h}
|
||||||
|
cat <<- BREWCALLER > ${cmdPath}
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
export HOMEBREW_CASK_OPTS="--no-quarantine \${HOMEBREW_CASK_OPTS}"
|
||||||
|
export HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
export HOMEBREW_NO_ANALYTICS=1
|
||||||
|
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
|
||||||
|
export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1
|
||||||
|
"${brewPath}" "\$@"
|
||||||
|
BREWCALLER
|
||||||
|
chown $(id -un):$(id -gn) ${cmdPath}
|
||||||
|
chmod u=rwx,go=r ${cmdPath}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBrewPeriodicScript() {
|
||||||
|
local brewPath=`getCanonicalBrewPath`
|
||||||
|
local cmdPath=${HOME}/bin/brew-periodic
|
||||||
|
[[ -f ${cmdPath} ]] && rm ${cmdPath}
|
||||||
|
mkdir -p ${cmdPath:h}
|
||||||
|
cat <<- BREWCALLER > ${cmdPath}
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
local brew='${brewPath}'
|
||||||
|
\$brew update
|
||||||
|
\$brew upgrade --greedy
|
||||||
|
\$brew cleanup
|
||||||
|
BREWCALLER
|
||||||
|
chown $(id -un):$(id -gn) ${cmdPath}
|
||||||
|
chmod u=rwx,go=r ${cmdPath}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBrew() {
|
||||||
|
local brewPath=${homebrew_directory}/bin/brew
|
||||||
|
${brewPath} update --force --quiet
|
||||||
|
chmod go-w "${homebrew_directory}/share/zsh"
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLaunchDaemonsPlist() {
|
||||||
|
local uid=`id -u`
|
||||||
|
local serviceName="de.astzweig.macos.launchagents.$1"
|
||||||
|
local launchAgentPath=${HOME}/Library/LaunchAgents
|
||||||
|
local launcherPath="${launchAgentPath}/${serviceName}.plist"
|
||||||
|
[[ -d ${launchAgentPath} ]] || mkdir ${launchAgentPath} || return
|
||||||
|
[[ -f ${launcherPath} ]] && {
|
||||||
|
launchctl disable gui/${uid}/${serviceName}
|
||||||
|
rm ${launcherPath}
|
||||||
|
}
|
||||||
|
cat <<- LAUNCHDPLIST > ${launcherPath}
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>${serviceName}</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>${HOME}/bin/brew-periodic</string>
|
||||||
|
</array>
|
||||||
|
<key>StartInterval</key>
|
||||||
|
<integer>1800</integer>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
LAUNCHDPLIST
|
||||||
|
chmod u=rw,go=r ${launcherPath}
|
||||||
|
launchctl enable gui/${uid}/${serviceName} &> /dev/null
|
||||||
|
launchctl bootstrap gui/${uid}/ ${launcherPath} &> /dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
function installHomebrewUpdater() {
|
||||||
|
createLaunchDaemonsPlist brew-updater
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultHomebrewPrefix() {
|
||||||
|
print -- ${HOMEBREW_PREFIX:-${HOME}/Library/Application Support}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHomebrewDirectoryPath() {
|
||||||
|
print -- ${homebrew_prefix:-$(getDefaultHomebrewPrefix)}/Homebrew
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultGitHomebrewURL() {
|
||||||
|
print -- ${HOMEBREW_BREW_GIT_REMOTE:-https://github.com/Homebrew/brew.git}
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureFolders() {
|
||||||
|
local dirPath
|
||||||
|
for dirPath in ${HOME}/bin ${HOME}/.vim/{backups,swaps}; do
|
||||||
|
[[ ! -d ${dirPath} ]] && indicateActivity -- "Creating ${dirPath}" mkdir ${dirPath}
|
||||||
|
done
|
||||||
|
indicateActivity -- 'Hide folders' hideFolders
|
||||||
|
}
|
||||||
|
|
||||||
|
function installNode() {
|
||||||
|
volta install node
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
lop -y h1 -- -i 'Setup User'
|
||||||
|
[[ $(id -u) -eq 0 ]] && { loptty -- -e 'Command must not be run as root.' -e $dirPath; return 16 }
|
||||||
|
configureFolders
|
||||||
|
indicateActivity -- 'Install node' installNode
|
||||||
|
local homebrew_prefix=`getDefaultHomebrewPrefix`
|
||||||
|
local homebrew_directory=`getHomebrewDirectoryPath`
|
||||||
|
checkExecPrerequisites || return 17
|
||||||
|
configureInstallPrefix || return 10
|
||||||
|
indicateActivity -- 'Downloading Homebrew' downloadHomebrew || return 11
|
||||||
|
indicateActivity -- 'Create brew caller script' createBrewCallerScript || return 12
|
||||||
|
indicateActivity -- 'Create brew periodic script' createBrewPeriodicScript || return 13
|
||||||
|
indicateActivity -- 'Update brew' updateBrew || return 14
|
||||||
|
indicateActivity -- 'Install Homebrew updater' installHomebrewUpdater || return 15
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then
|
||||||
|
_DIR="${0:A:h}"
|
||||||
|
source autoload-zshlib
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
@@ -107,7 +107,7 @@ function ensureDocopts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cloneMacOSSystemRepo() {
|
function cloneMacOSSystemRepo() {
|
||||||
local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://github.com/astzweig/macos-system.git}"
|
local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://git.tabshift.dev/spacebar/macos-system.git}"
|
||||||
git clone --depth 1 -q "${repoUrl}" . 2> /dev/null || return 10
|
git clone --depth 1 -q "${repoUrl}" . 2> /dev/null || return 10
|
||||||
[ -n "${MACOS_SYSTEM_REPO_BRANCH}" ] && git checkout -q ${MACOS_SYSTEM_REPO_BRANCH} 2> /dev/null || true
|
[ -n "${MACOS_SYSTEM_REPO_BRANCH}" ] && git checkout -q ${MACOS_SYSTEM_REPO_BRANCH} 2> /dev/null || true
|
||||||
}
|
}
|
||||||
|
|||||||
54
modules/00a-sudo-settings.sh
Executable file
54
modules/00a-sudo-settings.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
# vi: set ft=zsh tw=80 ts=2
|
||||||
|
|
||||||
|
function ensureTRBernsteinCanUpdateSystem() {
|
||||||
|
local username=$1
|
||||||
|
local sudoersFile='/etc/sudoers.d/allow-softwareupdate-for-all'
|
||||||
|
[[ -f ${sudoersFile} ]] && return
|
||||||
|
cat <<- SUDOERS > "${sudoersFile}"
|
||||||
|
trbernstein ALL=(root) NOPASSWD: /usr/sbin/softwareupdate -irR --user admin
|
||||||
|
SUDOERS
|
||||||
|
chown root:wheel "${sudoersFile}" || return 10
|
||||||
|
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_system() {
|
||||||
|
lop -y h1 -- -i 'Configure sudoers files'
|
||||||
|
ensurePathOrLogError ${dstDir} 'Could not install binaries.' || return 10
|
||||||
|
indicateActivity -- "Allow trbernstein user to install updates using softwareupdate" ensureTRBernsteinCanUpdateSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExecPrerequisites() {
|
||||||
|
cmds=(
|
||||||
|
[cat]=''
|
||||||
|
[chown]=''
|
||||||
|
[chmod]=''
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUsage() {
|
||||||
|
read -r -d '' text <<- USAGE
|
||||||
|
Usage:
|
||||||
|
$cmdName show-questions [<modkey> <modans>]...
|
||||||
|
$cmdName [-v] [-d FILE]
|
||||||
|
|
||||||
|
Add sudo rules to:
|
||||||
|
1. allow trbernstein user to install updates using softwareupdate
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
|
||||||
|
-v, --verbose Be more verbose.
|
||||||
|
----
|
||||||
|
$cmdName 0.1.0
|
||||||
|
Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG
|
||||||
|
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
|
||||||
|
USAGE
|
||||||
|
print -- ${text}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
|
||||||
|
_DIR="${0:A:h}"
|
||||||
|
test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 }
|
||||||
|
source "${ASTZWEIG_MACOS_SYSTEM_LIB}"
|
||||||
|
module_main $0 "$@"
|
||||||
|
fi
|
||||||
@@ -39,7 +39,7 @@ function configurePowerManagement() {
|
|||||||
${cmd} sleep 0
|
${cmd} sleep 0
|
||||||
${cmd} womp 0
|
${cmd} womp 0
|
||||||
${cmd} acwake 0
|
${cmd} acwake 0
|
||||||
${cmd} proximitywake 0
|
${cmd} proximitywake 1
|
||||||
${cmd} destroyfvkeyonstandby 1
|
${cmd} destroyfvkeyonstandby 1
|
||||||
pmset -b acwake 1
|
pmset -b acwake 1
|
||||||
${cmd} lidwake 1
|
${cmd} lidwake 1
|
||||||
@@ -65,6 +65,24 @@ function configureMacOSFirewall() {
|
|||||||
${cmd} --setallowsignedapp on
|
${cmd} --setallowsignedapp on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setComputerName() {
|
||||||
|
scutil --set ComputerName "${hostname}"
|
||||||
|
scutil --set HostName "${hostname}"
|
||||||
|
scutil --set LocalHostName "${hostname}"
|
||||||
|
systemsetup -setcomputername "${hostname}"
|
||||||
|
systemsetup -setlocalsubnetname "${hostname}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureComputerHostname() {
|
||||||
|
local currentComputerName="`scutil --get ComputerName`"
|
||||||
|
if [[ "${currentComputerName}" != "${hostname}" ]]; then
|
||||||
|
lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}."
|
||||||
|
indicateActivity -- 'Set computer name' setComputerName
|
||||||
|
else
|
||||||
|
lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function configure_system() {
|
function configure_system() {
|
||||||
lop -y h1 -- -i 'Configure System Settings'
|
lop -y h1 -- -i 'Configure System Settings'
|
||||||
indicateActivity -- 'Quitting System Preferences' quitSystemPreferences
|
indicateActivity -- 'Quitting System Preferences' quitSystemPreferences
|
||||||
@@ -73,6 +91,13 @@ function configure_system() {
|
|||||||
indicateActivity -- 'Configuring login window' configureLoginWindow
|
indicateActivity -- 'Configuring login window' configureLoginWindow
|
||||||
indicateActivity -- 'Configure global umask' launchctl config user umask 027
|
indicateActivity -- 'Configure global umask' launchctl config user umask 027
|
||||||
indicateActivity -- 'Configure macOS firewall' configureMacOSFirewall
|
indicateActivity -- 'Configure macOS firewall' configureMacOSFirewall
|
||||||
|
configureComputerHostname
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQuestions() {
|
||||||
|
questions=(
|
||||||
|
'i: hostname=What shall the systems hostname be?'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUsage() {
|
function getUsage() {
|
||||||
@@ -80,11 +105,12 @@ function getUsage() {
|
|||||||
read -r -d '' text <<- USAGE
|
read -r -d '' text <<- USAGE
|
||||||
Usage:
|
Usage:
|
||||||
$cmdName show-questions [<modkey> <modans>]...
|
$cmdName show-questions [<modkey> <modans>]...
|
||||||
$cmdName [-v] [-d FILE]
|
$cmdName [-v] [-d FILE] --hostname NAME
|
||||||
|
|
||||||
Set energy, network and basic preferences.
|
Set energy, network and basic preferences.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
--hostname NAME Set NAME as current host's host name.
|
||||||
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
|
-d FILE, --logfile FILE Print log message to logfile instead of stdout.
|
||||||
-v, --verbose Be more verbose.
|
-v, --verbose Be more verbose.
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -35,13 +35,18 @@ function ensureUserCanRunPasswordlessSudo() {
|
|||||||
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
|
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ensureUserCanNoLongerRunPasswordlessSudo() {
|
||||||
|
local username=$1
|
||||||
|
local sudoersFile="/etc/sudoers.d/no-auth-sudo-for-${username}"
|
||||||
|
[[ ! -f ${sudoersFile} ]] || rm ${sudoersFile}
|
||||||
|
}
|
||||||
|
|
||||||
function getFirstFreeRoleAccountID() {
|
function getFirstFreeRoleAccountID() {
|
||||||
local minUserID=450
|
local minUserID=200
|
||||||
local maxUserID=499
|
local maxUserID=400
|
||||||
local uname_machine=$(/usr/bin/uname -m)
|
if is-at-least 13.0 $(sw_vers -productVersion); then
|
||||||
if [[ ${uname_machine} == "arm64" ]]; then
|
minUserID=450
|
||||||
minUserID=200
|
maxUserID=499
|
||||||
maxUserID=400
|
|
||||||
fi
|
fi
|
||||||
dscl . -list '/Users' UniqueID | grep '_.*' | sort -n -k2 | awk -v i=${minUserID} '$2>='${minUserID}' && $2<'${maxUserID}' {if(i < $2) { print i; nextfile} else i=$2+1;} END {if(i <= '${maxUserID}' && ($2 < '${minUserID}' || $2 > '${maxUserID}')) print i;}'
|
dscl . -list '/Users' UniqueID | grep '_.*' | sort -n -k2 | awk -v i=${minUserID} '$2>='${minUserID}' && $2<'${maxUserID}' {if(i < $2) { print i; nextfile} else i=$2+1;} END {if(i <= '${maxUserID}' && ($2 < '${minUserID}' || $2 > '${maxUserID}')) print i;}'
|
||||||
}
|
}
|
||||||
@@ -96,28 +101,93 @@ function getHomebrewRepositoryPath() {
|
|||||||
|
|
||||||
function createBrewCallerScript() {
|
function createBrewCallerScript() {
|
||||||
ensureLocalBinFolder
|
ensureLocalBinFolder
|
||||||
|
local uname_machine=$(/usr/bin/uname -m)
|
||||||
local username=${homebrew_username}
|
local username=${homebrew_username}
|
||||||
local brewCallerPath="/usr/local/bin/brew"
|
local homebrewRepositoryPath="$(getHomebrewRepositoryPath)"
|
||||||
[ -f "${brewCallerPath}" ] && rm "${brewCallerPath}"
|
local brewCallerPath="${homebrewRepositoryPath}/bin/brew-caller"
|
||||||
cat <<- BREWCALLER > ${brewCallerPath}
|
local brewCallerSymlink="/usr/local/bin/brew"
|
||||||
#!/usr/bin/env zsh
|
[[ -f "${brewCallerPath}" ]] && rm "${brewCallerPath}"
|
||||||
if [ "\$(id -un)" != "${username}" ]; then
|
[[ -f "${brewCallerSymlink}" || -h "${brewCallerSymlink}" ]] && rm "${brewCallerSymlink}"
|
||||||
echo 'brew will be run as ${username} user.' >&2
|
[[ ${uname_machine} == "arm64" ]] && brewCallerPath=${brewCallerSymlink}
|
||||||
sudo -E -u "${username}" "\$0" "\$@"
|
cat <<- BREWCALLER | clang -x c -O2 -Wall -o "${brewCallerPath}" -
|
||||||
exit \$?
|
#include <unistd.h>
|
||||||
fi
|
#include <sys/types.h>
|
||||||
export HOMEBREW_CACHE="${homebrew_cache}"
|
#include <sys/stat.h>
|
||||||
export HOMEBREW_LOGS="${homebrew_log}"
|
#include <pwd.h>
|
||||||
export HOMEBREW_CASK_OPTS="--no-quarantine \${HOMEBREW_CASK_OPTS}"
|
#include <grp.h>
|
||||||
export HOMEBREW_NO_AUTO_UPDATE=1
|
#include <stdlib.h>
|
||||||
export HOMEBREW_NO_ANALYTICS=1
|
#include <stdio.h>
|
||||||
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
|
#include <string.h>
|
||||||
export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1
|
#include <errno.h>
|
||||||
umask 002
|
|
||||||
"$(getHomebrewRepositoryPath)/bin/brew" "\$@"
|
extern char **environ;
|
||||||
|
|
||||||
|
char *format_env(const char *env_name, const char *format) {
|
||||||
|
if (!env_name || !format) return NULL;
|
||||||
|
const char *value = getenv(env_name);
|
||||||
|
if (!value) return NULL;
|
||||||
|
int formatted_len = snprintf(NULL, 0, format, value);
|
||||||
|
if (formatted_len < 0) return NULL;
|
||||||
|
char *formatted_value = malloc(formatted_len + 1);
|
||||||
|
if (!formatted_value) return NULL;
|
||||||
|
snprintf(formatted_value, formatted_len + 1, format, value);
|
||||||
|
size_t result_len = strlen(env_name) + 1 + formatted_len;
|
||||||
|
char *result = malloc(result_len + 1);
|
||||||
|
if (!result) { free(formatted_value); return NULL; }
|
||||||
|
sprintf(result, "%s=%s", env_name, formatted_value);
|
||||||
|
free(formatted_value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HOMEBREW_USER "${username}"
|
||||||
|
#define HOMEBREW_DIR "${homebrewRepositoryPath}/bin"
|
||||||
|
#define BREW_PATH HOMEBREW_DIR "/brew"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct passwd *pw;
|
||||||
|
uid_t target_uid;
|
||||||
|
gid_t target_gid;
|
||||||
|
|
||||||
|
pw = getpwnam(HOMEBREW_USER);
|
||||||
|
if (!pw) { fprintf(stderr, "Error: user %s not found\n", HOMEBREW_USER); return 1; }
|
||||||
|
target_uid = pw->pw_uid;
|
||||||
|
target_gid = pw->pw_gid;
|
||||||
|
|
||||||
|
char *new_environ[] = {
|
||||||
|
"PATH=" HOMEBREW_DIR ":/usr/bin:/bin:/usr/sbin:/sbin",
|
||||||
|
"HOMEBREW_CACHE=${homebrew_cache}",
|
||||||
|
"HOMEBREW_LOGS=${homebrew_log}",
|
||||||
|
format_env("HOME", "%s"),
|
||||||
|
format_env("HOMEBREW_CASK_OPTS", "--no-quarantine %s"),
|
||||||
|
"HOMEBREW_PREFIX=${homebrewRepositoryPath}",
|
||||||
|
"HOMEBREW_CELLAR=${homebrewRepositoryPath}/Cellar",
|
||||||
|
"HOMEBREW_NO_AUTO_UPDATE=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS_THIS_RUN=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (setegid(target_gid) != 0) { fprintf(stderr, "setegid(%d): %s\n", target_gid, strerror(errno)); return 1; }
|
||||||
|
|
||||||
|
if (seteuid(target_uid) != 0) { fprintf(stderr, "seteuid(%d): %s\n", target_uid, strerror(errno)); return 1; }
|
||||||
|
|
||||||
|
char **newargv = malloc((argc + 1) * sizeof(char *));
|
||||||
|
if (!newargv) { fprintf(stderr, "malloc failed for new argv\n"); return 1; }
|
||||||
|
|
||||||
|
newargv[0] = (char *)BREW_PATH;
|
||||||
|
for (int i = 1; i < argc; ++i) newargv[i] = argv[i];
|
||||||
|
newargv[argc] = NULL;
|
||||||
|
umask(0002);
|
||||||
|
|
||||||
|
execve(BREW_PATH, newargv, new_environ);
|
||||||
|
fprintf(stderr, "execv(%s) failed: %s\n", BREW_PATH, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
BREWCALLER
|
BREWCALLER
|
||||||
chown root:admin ${brewCallerPath}
|
chown root:admin ${brewCallerPath}
|
||||||
chmod ug+x,o-x ${brewCallerPath}
|
chmod 4550 ${brewCallerPath}
|
||||||
|
[[ ${uname_machine} == "arm64" ]] || ln -s "${brewCallerPath}" "${brewCallerSymlink}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBrewPeriodicScript() {
|
function createBrewPeriodicScript() {
|
||||||
@@ -136,9 +206,8 @@ function createBrewPeriodicScript() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function installHomebrewCore() {
|
function installHomebrewCore() {
|
||||||
export NONINTERACTIVE=1
|
[ ! -d $(getHomebrewRepositoryPath) ] || return
|
||||||
[ ! -d $(getHomebrewRepositoryPath) ] || return
|
NONINTERACTIVE=1 HOME= sudo --preserve-env=NONINTERACTIVE,HOME -u "${homebrew_username}" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||||
sudo --preserve-env=NONINTERACTIVE -u "${homebrew_username}" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
[ -d $(getHomebrewRepositoryPath) ]
|
[ -d $(getHomebrewRepositoryPath) ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +282,7 @@ function configure_system() {
|
|||||||
ensureHomebrewCacheDirectory || return 13
|
ensureHomebrewCacheDirectory || return 13
|
||||||
ensureHomebrewLogDirectory || return 14
|
ensureHomebrewLogDirectory || return 14
|
||||||
indicateActivity 'Install Homebrew core' installHomebrewCore || return 15
|
indicateActivity 'Install Homebrew core' installHomebrewCore || return 15
|
||||||
|
indicateActivity 'Ensure Homebrew user can nolonger run passwordless sudo' ensureUserCanNoLongerRunPasswordlessSudo ${homebrew_username} || return 20
|
||||||
indicateActivity 'Create brew caller script' createBrewCallerScript || return 16
|
indicateActivity 'Create brew caller script' createBrewCallerScript || return 16
|
||||||
indicateActivity 'Create brew periodic script' createBrewPeriodicScript || return 17
|
indicateActivity 'Create brew periodic script' createBrewPeriodicScript || return 17
|
||||||
indicateActivity 'Install Homebrew updater' installHomebrewUpdater || return 18
|
indicateActivity 'Install Homebrew updater' installHomebrewUpdater || return 18
|
||||||
@@ -285,6 +355,7 @@ function getUsage() {
|
|||||||
|
|
||||||
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
|
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
|
||||||
test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 }
|
test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 }
|
||||||
|
autoload is-at-least
|
||||||
source "${ASTZWEIG_MACOS_SYSTEM_LIB}"
|
source "${ASTZWEIG_MACOS_SYSTEM_LIB}"
|
||||||
module_main $0 "$@"
|
module_main $0 "$@"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
function brewInstall() {
|
function brewInstall() {
|
||||||
local identifier="$1"
|
local identifier="$1"
|
||||||
local cask="${2:+--cask}"
|
local cask="${2:+--cask}"
|
||||||
indicateActivity -- "Installing ${identifier}${cask:+ (Cask)}" ${homebrew_path} install -q ${cask} ${identifier}
|
HOME=/Users/Shared indicateActivity -- "Installing ${identifier}${cask:+ (Cask)}" sudo -u _homebrew ${homebrew_path} install -q ${cask} ${identifier}
|
||||||
}
|
}
|
||||||
|
|
||||||
function installCask() {
|
function installCask() {
|
||||||
@@ -26,7 +26,9 @@ function installCasks() {
|
|||||||
installCask devonthink
|
installCask devonthink
|
||||||
installCask firefox
|
installCask firefox
|
||||||
installCask hazel
|
installCask hazel
|
||||||
|
installCask hopper-disassembler
|
||||||
installCask istat-menus
|
installCask istat-menus
|
||||||
|
installCask jdownloader
|
||||||
installCask launchcontrol
|
installCask launchcontrol
|
||||||
installCask makemkv
|
installCask makemkv
|
||||||
installCask network-radar
|
installCask network-radar
|
||||||
@@ -34,6 +36,7 @@ function installCasks() {
|
|||||||
installCask orbstack
|
installCask orbstack
|
||||||
installCask rapidapi
|
installCask rapidapi
|
||||||
installCask rectangle
|
installCask rectangle
|
||||||
|
installCask serverbuddy
|
||||||
installCask sf-symbols
|
installCask sf-symbols
|
||||||
installCask sketch
|
installCask sketch
|
||||||
installCask suspicious-package
|
installCask suspicious-package
|
||||||
@@ -56,13 +59,14 @@ function installBrews() {
|
|||||||
lop -y body:h1 -- -i 'Installing Homebrew formulas'
|
lop -y body:h1 -- -i 'Installing Homebrew formulas'
|
||||||
installBrew mas
|
installBrew mas
|
||||||
if ! isDebug; then
|
if ! isDebug; then
|
||||||
installBrew bun
|
installBrew chezmoi
|
||||||
installBrew cocogitto
|
installBrew cocogitto
|
||||||
installBrew composer
|
installBrew composer
|
||||||
installBrew curl
|
installBrew curl
|
||||||
installBrew docker
|
installBrew docker
|
||||||
installBrew docker-buildx
|
installBrew docker-buildx
|
||||||
installBrew exiftool
|
installBrew exiftool
|
||||||
|
installBrew f2
|
||||||
installBrew ffmpeg
|
installBrew ffmpeg
|
||||||
installBrew gnupg
|
installBrew gnupg
|
||||||
installBrew go
|
installBrew go
|
||||||
@@ -71,18 +75,16 @@ function installBrews() {
|
|||||||
installBrew imap-backup
|
installBrew imap-backup
|
||||||
installBrew imapsync
|
installBrew imapsync
|
||||||
installBrew nmap
|
installBrew nmap
|
||||||
installBrew node
|
|
||||||
installBrew pdfgrep
|
installBrew pdfgrep
|
||||||
installBrew php
|
installBrew php
|
||||||
installBrew python
|
installBrew python
|
||||||
installBrew qpdf
|
installBrew qpdf
|
||||||
installBrew rcm
|
|
||||||
installBrew ruby
|
installBrew ruby
|
||||||
installBrew 'hay-kot/scaffold-tap/scaffold'
|
|
||||||
installBrew 'lemoony/tap/snipkit'
|
installBrew 'lemoony/tap/snipkit'
|
||||||
installBrew sqlite
|
installBrew sqlite
|
||||||
installBrew tree
|
installBrew tree
|
||||||
installBrew tidy-html5
|
installBrew tidy-html5
|
||||||
|
installBrew volta
|
||||||
installBrew yq
|
installBrew yq
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user