Use loadModules and askUserModuleQuestions
This commit is contained in:
219
install.sh
219
install.sh
@@ -1,208 +1,37 @@
|
||||
#!/usr/bin/env zsh
|
||||
# vi: set expandtab ft=zsh tw=80 ts=2
|
||||
|
||||
function filterModules() {
|
||||
if [ ${#module} -eq 0 ]; then
|
||||
lop debug 'No modules given as arguments. Taking all modules.'
|
||||
modulesToInstall=(${allModules})
|
||||
else
|
||||
lop debug "Given ${#module} modules as arguments: ${module}"
|
||||
[ "${inverse}" = true ] && lop debug 'Taking complement set.'
|
||||
local mod pattern="^.*(${(j.|.)module})\$"
|
||||
modulesToInstall=()
|
||||
for mod in ${allModules}; do
|
||||
local found=false
|
||||
[[ ${mod} =~ ${pattern} ]] && found=true
|
||||
lop debug "Was ${mod} found in ${pattern}: ${found}"
|
||||
if [ "${inverse}" != 'true' -a ${found} = true ]; then
|
||||
lop debug "Adding module ${mod}"
|
||||
modulesToInstall+=(${mod})
|
||||
elif [ "${inverse}" = 'true' -a ${found} = false ]; then
|
||||
lop debug "Adding module ${mod}"
|
||||
modulesToInstall+=(${mod})
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
function runModule() {
|
||||
local mod=$1
|
||||
shift
|
||||
${mod} "$@"
|
||||
}
|
||||
|
||||
function parseQuestionLine() {
|
||||
local questionType parameterName question value arguments args
|
||||
local -A typeMap=([i]=info [p]=password [c]=confirm [s]=select)
|
||||
[ -z "${line}" ] && return
|
||||
[ "${line[2]}" != ':' ] && return 10
|
||||
|
||||
questionType=$typeMap[${line[1]}]
|
||||
[ -z "${questionType}" ] && return 11
|
||||
|
||||
# remove question type
|
||||
[ "${line[3]}" = ' ' ] && line=${line:3} || line=${line:2}
|
||||
|
||||
line=(${(s.=.)line[@]})
|
||||
parameterName=${line[1]}
|
||||
[ -z "${parameterName}" ] && return 12
|
||||
[ "${parameterName[1]}" = - ] && return 13
|
||||
|
||||
# remove parameter name
|
||||
line="${(j.=.)${(@)line:1}}"
|
||||
|
||||
line=("${(s. #.)line}")
|
||||
question=${line[1]}
|
||||
[ -z "${question}" ] && return 14
|
||||
|
||||
# remove question part
|
||||
line="${(j. #.)${(@)line:1}}"
|
||||
|
||||
if [ -n "${line}" ]; then
|
||||
arguments=(${(s.;.)line})
|
||||
for arg in ${arguments}; do
|
||||
arg=("${(s.:.)arg}")
|
||||
[ -z "${arg[1]}" ] && return 15
|
||||
arg[1]="`trim "${arg[1]}"`"
|
||||
arg[2]="`trim "${arg[2]}"`"
|
||||
questionType+=";${(j.:.)arg}"
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
printf -v value '%s\n%s' "${question}" "${questionType}"
|
||||
questions+=("${parameterName}" "${value}")
|
||||
}
|
||||
|
||||
function populateQuestionsWithModuleRequiredInformation() {
|
||||
lop debug "Asking ${mod} for required information"
|
||||
for line in ${(f)"$(runModule "${mod}" show-questions)"}; do
|
||||
lop debug "Says line: ${line}"
|
||||
parseQuestionLine
|
||||
lop debug "Parsing question returned status: $?"
|
||||
done
|
||||
lop debug "Parsed questions are: ${(kv)questions}"
|
||||
}
|
||||
|
||||
function findQuestionArgInInstruction() {
|
||||
local argNameToLookup="$1" arg name value
|
||||
[ -z "${argNameToLookup}" ] && return
|
||||
for arg in ${instructions}; do
|
||||
arg=("${(s.:.)arg}")
|
||||
[ "${#arg}" -lt 2 ] && continue
|
||||
name="${arg[1]}"
|
||||
value="${arg[2]}"
|
||||
[ "${name}" != "${argNameToLookup}" ] && continue
|
||||
argValue="${value}"
|
||||
return
|
||||
done
|
||||
return 10
|
||||
}
|
||||
|
||||
function convertQuestionArgsToAskUserArgs() {
|
||||
local argValue
|
||||
local instructions=("${(s.;.)questionArgs}")
|
||||
local questionType="${instructions[1]}"
|
||||
shift instructions
|
||||
|
||||
if [ "${questionType}" = 'info' ]; then
|
||||
args=(info)
|
||||
if findQuestionArgInInstruction 'default'; then
|
||||
test -n "${argValue}" && args=('-d' "${argValue}" ${args})
|
||||
fi
|
||||
elif [ "${questionType}" = 'password' ]; then
|
||||
args=('-p' info)
|
||||
elif [ "${questionType}" = 'confirm' ]; then
|
||||
args=(confirm)
|
||||
elif [ "${questionType}" = 'select' ]; then
|
||||
findQuestionArgInInstruction 'choose from' || return 10
|
||||
choices=("${(s.,.)argValue}")
|
||||
[ "${#choices}" -ge 1 ] || return 11
|
||||
args=(choose)
|
||||
findQuestionArgInInstruction 'validator' && args+=(-v ${argValue})
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function askUserQuestion() {
|
||||
local choices
|
||||
local questionAndArgs=("${(f)questions[$questionID]}") args=()
|
||||
local question="${questionAndArgs[1]}" questionArgs="${questionAndArgs[2]}"
|
||||
convertQuestionArgsToAskUserArgs
|
||||
lop debug "Converted args for askUser are: ${args}"
|
||||
askUser "${args[@]}" "${question}"
|
||||
value="${REPLY}"
|
||||
}
|
||||
|
||||
function generateConfigKeysFromQuestionID() {
|
||||
setopt localoptions extendedglob
|
||||
[ $# -lt 2 -o -z "$1" -o -z "$2" ] && return
|
||||
local modName="${1}" questID="${2}"
|
||||
modName="${${${${modName//-##/_}/#_/}/%_/}//[^A-Za-z_]/}"
|
||||
questID="${${${${questID//-##/_}/#_/}/%_/}//[^A-Za-z_]/}"
|
||||
configkeys=("${modName}" questions "${questID}")
|
||||
}
|
||||
|
||||
function answerQuestionsFromConfigOrAskUser() {
|
||||
local questionID
|
||||
for questionID in ${(k)questions}; do
|
||||
local value configkeys=()
|
||||
lop debug "Answering question with ID: ${questionID}"
|
||||
generateConfigKeysFromQuestionID "${mod}" "${questionID}"
|
||||
lop debug "Config keys for question are: ${configkeys}"
|
||||
value="`config read "${configkeys[@]}"`"
|
||||
lop debug "Config answer for key is: ${value}"
|
||||
if [ -z "${value}" ]; then
|
||||
lop debug 'Asking user'
|
||||
askUserQuestion
|
||||
lop debug "User answer is: ${value}"
|
||||
[ -n "${config_only}" ] && config write "${value}" "${configkeys[@]}"
|
||||
fi
|
||||
lop debug "Adding answer: ${mod}_${questionID}=${value}"
|
||||
answers+=("${mod}_${questionID}" "${value}")
|
||||
done
|
||||
runModule() {
|
||||
"$@"
|
||||
}
|
||||
|
||||
function askNecessaryQuestions() {
|
||||
local mod
|
||||
local mod= configOnlyArgs=()
|
||||
config setappname "de.astzweig.macos.system-setup"
|
||||
if [ -n "${config_only}" ]; then
|
||||
lop debug "Config only option given with value: ${config_only}"
|
||||
lop -d "Config only option given with value:" -d "${config_only}"
|
||||
config setconfigfile "${config_only}"
|
||||
configOnlyArgs=(-x)
|
||||
elif [ -n "${config}" ]; then
|
||||
config setconfigfile "${config}"
|
||||
fi
|
||||
for mod in ${modulesToInstall}; do
|
||||
local -A questions=()
|
||||
populateQuestionsWithModuleRequiredInformation
|
||||
answerQuestionsFromConfigOrAskUser
|
||||
done
|
||||
askUserModuleQuestions ${configOnlyArgs} -c config -v moduleAnswers ${modulesToInstall}
|
||||
}
|
||||
|
||||
function printModulesToInstall() {
|
||||
lop section 'Modules that will install are:'
|
||||
for mod in "${modulesToInstall}"; do
|
||||
hio info "${mod}"
|
||||
lop -d 'Modules that will install are:' -d "${modulesToInstall}"
|
||||
for mod in "${modulesToInstall[@]}"; do
|
||||
print "${mod}"
|
||||
done | abbreviatePaths
|
||||
exit 0
|
||||
}
|
||||
|
||||
function loadModules() {
|
||||
local mod
|
||||
modpath=("${_DIR}/modules" "${modpath[@]}")
|
||||
lop debug "Module paths are: ${modpath[@]}"
|
||||
allModules=(${(f)"$(find "${modpath[@]}" -type f -perm +u=x -maxdepth 1 2> /dev/null | sort -n)"})
|
||||
for mod in ${allModules}; do
|
||||
lop debug "Found module ${mod}"
|
||||
done
|
||||
filterModules
|
||||
[ "${list}" = true ] && printModulesToInstall
|
||||
}
|
||||
|
||||
function generateModuleOptions() {
|
||||
local value answerKey optionKey
|
||||
for answerKey in ${(k)answers}; do
|
||||
for answerKey in ${(k)moduleAnswers}; do
|
||||
[[ ${answerKey} = ${mod}_* ]] || continue
|
||||
optionKey="${answerKey#${mod}_}"
|
||||
value="${answers[${answerKey}]}"
|
||||
value="${moduleAnswers[${answerKey}]}"
|
||||
if [[ "${optionKey}" =~ ^[[:alpha:]]$ ]]; then
|
||||
moduleOptions+=("-${optionKey}" "${value}")
|
||||
elif [[ "${optionKey}" =~ ^[[:alpha:]][-[:alpha:]]+$ ]]; then
|
||||
@@ -219,8 +48,8 @@ function installModules() {
|
||||
moduleOptions=()
|
||||
filteredOptions=()
|
||||
generateModuleOptions
|
||||
lop debug "Running ${mod}" debug "with ${#moduleOptions} args: ${moduleOptions}"
|
||||
runModule "${mod}" ${moduleOptions}
|
||||
lop -d "Running ${mod}" -d "with ${#moduleOptions} args:" -d "${moduleOptions}"
|
||||
runModule ${mod} ${moduleOptions}
|
||||
done
|
||||
}
|
||||
|
||||
@@ -236,9 +65,9 @@ function isPlistBuddyInstalled() {
|
||||
}
|
||||
|
||||
function checkPrerequisites() {
|
||||
isMacOS || { lop error 'This setup is only for macOS 10.13 and up.'; return 10 }
|
||||
isPlistBuddyInstalled || { lop error 'This setup requires PlistBuddy to be either at /usr/libexec or in any of the PATH directories.'; return 11 }
|
||||
test "`id -u`" -eq 0 || { lop error 'This module requires root access. Please run as root.'; return 11 }
|
||||
isMacOS || { lop -e 'This setup is only for macOS 10.13 and up.'; return 10 }
|
||||
isPlistBuddyInstalled || { lop -e 'This setup requires PlistBuddy to be either at /usr/libexec or in any of the PATH directories.'; return 11 }
|
||||
test "`id -u`" -eq 0 || { lop -e 'This module requires root access. Please run as root.'; return 11 }
|
||||
}
|
||||
|
||||
function main() {
|
||||
@@ -269,11 +98,15 @@ function main() {
|
||||
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
|
||||
USAGE`"
|
||||
local allModules=() modulesToInstall=()
|
||||
local -A answers
|
||||
local -A moduleAnswers
|
||||
configureLogging
|
||||
lop debug "Current working dir is: `pwd`"
|
||||
lop -- debug "Called main with $# args: $@"
|
||||
loadModules
|
||||
lop -d "Current working dir is: `pwd`"
|
||||
lop -d "Called main with $# args: $*"
|
||||
|
||||
modpath+=("${_DIR}/modules")
|
||||
loadModules -v modulesToInstall ${$(echo -m):^^modpath} "${module[@]}"
|
||||
[ "${list}" = true ] && printModulesToInstall
|
||||
|
||||
askNecessaryQuestions
|
||||
[ -z "${config_only}" ] || return 0
|
||||
installModules
|
||||
|
||||
@@ -12,7 +12,7 @@ function checkPrerequisites() {
|
||||
[defaults]=''
|
||||
[launchctl]=''
|
||||
)
|
||||
test "`id -u`" -eq 0 || { lop error 'This module requires root access. Please run as root.'; return 11 }
|
||||
test "`id -u`" -eq 0 || { lop -e 'This module requires root access. Please run as root.'; return 11 }
|
||||
checkCommands
|
||||
}
|
||||
|
||||
@@ -26,26 +26,27 @@ function getQuestions() {
|
||||
}
|
||||
|
||||
function quitSystemPreferences() {
|
||||
lop debug 'Quitting System Preferences App'
|
||||
lop -d 'Quitting System Preferences App'
|
||||
osascript -e 'tell application "System Preferences" to quit'
|
||||
}
|
||||
|
||||
function configureComputerHostname() {
|
||||
lop info 'Configuring computer hostname.' debug "Current hostname: `scutil --get ComputerName`"
|
||||
lop -i 'Configuring computer hostname.'
|
||||
lop -d "Current hostname: `scutil --get ComputerName`"
|
||||
if [[ "`scutil --get ComputerName`" != "${hostname}" ]]; then
|
||||
lop debug 'Hostname of computer has not been set.' debug "Current hostname: `scutil --get ComputerName`"
|
||||
lop -d 'Hostname of computer has not been set.' -d "Current hostname: `scutil --get ComputerName`"
|
||||
|
||||
scutil --set ComputerName "${hostname}"
|
||||
scutil --set HostName "${hostname}"
|
||||
systemsetup -setcomputername "${hostname}" > /dev/null 2>&1
|
||||
systemsetup -setlocalsubnetname "${hostname}" > /dev/null 2>&1
|
||||
else
|
||||
lop debug 'Hostname of computer seems to have already been set. Skipping.' debug "Hostname: `scutil --get ComputerName`"
|
||||
lop -d 'Hostname of computer seems to have already been set. Skipping.' -d "Hostname: `scutil --get ComputerName`"
|
||||
fi
|
||||
}
|
||||
|
||||
function configureBasicSystem(){
|
||||
lop -n info 'Configuring systemsetup and nvram...'
|
||||
lop --no-newline -i 'Configuring systemsetup and nvram...'
|
||||
# Disable the sound effects on boot
|
||||
nvram SystemAudioVolume=" "
|
||||
|
||||
@@ -57,12 +58,12 @@ function configureBasicSystem(){
|
||||
systemsetup -setrestartfreeze on >&! /dev/null
|
||||
systemsetup -f -setremotelogin off >&! /dev/null
|
||||
systemsetup -setremoteappleevents off >&! /dev/null
|
||||
lop success 'done'
|
||||
lop -i 'done'
|
||||
|
||||
}
|
||||
|
||||
function configurePowerManagement() {
|
||||
lop -n info 'Configuring power management...'
|
||||
lop --no-newline -i 'Configuring power management...'
|
||||
cmd=(pmset -a)
|
||||
${cmd} displaysleep 0
|
||||
${cmd} disksleep 0
|
||||
@@ -76,17 +77,17 @@ function configurePowerManagement() {
|
||||
${cmd} halfdim 1
|
||||
${cmd} powernap 1
|
||||
${cmd} hibernatemode 0
|
||||
lop success 'done'
|
||||
lop -i 'done'
|
||||
}
|
||||
|
||||
function configureLoginWindow() {
|
||||
lop -n info 'Configuring login window...'
|
||||
lop --no-newline -i 'Configuring login window...'
|
||||
cmd=(defaults write '/Library/Preferences/com.apple.loginwindow')
|
||||
${cmd} DisableFDEAutoLogin -bool true
|
||||
${cmd} SHOWFULLNAME -bool false
|
||||
${cmd} AdminHostInfo -string HostName
|
||||
${cmd} GuestEnabled -bool false
|
||||
lop success 'done'
|
||||
lop -i 'done'
|
||||
}
|
||||
|
||||
function configure_system() {
|
||||
@@ -96,7 +97,7 @@ function configure_system() {
|
||||
configurePowerManagement
|
||||
configureLoginWindow
|
||||
|
||||
lop info 'Configuring global umask'
|
||||
lop -i 'Configuring global umask'
|
||||
launchctl config user umask 027
|
||||
}
|
||||
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
|
||||
function getDefaultFullname() {
|
||||
local computerName="`scutil --get ComputerName 2> /dev/null`"
|
||||
lop debug 'Default full name based on current computer name is:' debug "$computerName"
|
||||
lop -d 'Default full name based on current computer name is:' -d "$computerName"
|
||||
print "${computerName}"
|
||||
}
|
||||
|
||||
function getDefaultUsername() {
|
||||
local username="`getDefaultFullname | tr '[:upper:]' '[:lower:]' | tr -C '[:alnum:]\n' '-'`"
|
||||
lop debug 'Default username based on current computer name is:' debug "$username"
|
||||
lop -d 'Default username based on current computer name is:' -d "$username"
|
||||
print "${username}"
|
||||
}
|
||||
|
||||
function getUsersWithSecureToken() {
|
||||
local username
|
||||
for username in ${(f)"$(dscl . -list /Users | grep -v '^_.*')"}; do
|
||||
lop -n debug 'Checking if user' debug "${username}" debug 'has a secure token set...'
|
||||
lop --no-newline -d 'Checking if user' -d "${username}" -d 'has a secure token set...'
|
||||
if checkSecureTokenForUser "${username}"; then
|
||||
lop debug 'found'
|
||||
lop -d 'found'
|
||||
secureTokenUsers+=("${username}")
|
||||
else
|
||||
lop debug 'not found'
|
||||
lop -d 'not found'
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -33,14 +33,14 @@ function getDefaultUserPictures() {
|
||||
|
||||
function convertPathToDefaultPicture() {
|
||||
local resolved=''
|
||||
lop debug 'Converting path' debug "${filevault_picture}" debug 'to default picture path if necessary.'
|
||||
lop -d 'Converting path' -d "${filevault_picture}" -d 'to default picture path if necessary.'
|
||||
if [ -r "${filevault_picture}" ]; then
|
||||
lop debug 'Path seems to be a valid path already. Skipping conversion.'
|
||||
lop -d 'Path seems to be a valid path already. Skipping conversion.'
|
||||
return
|
||||
fi
|
||||
pushd -q '/Library/User Pictures'
|
||||
resolved="`find . -type f -path "*${filevault_picture}" 2> /dev/null`"
|
||||
lop debug 'Resolved path is' debug "${resolved}"
|
||||
lop -d 'Resolved path is' -d "${resolved}"
|
||||
popd -q
|
||||
[ -n "${resolved}" -a -r "${resolved}" ] && filevault_picture="${resolved}"
|
||||
}
|
||||
@@ -48,7 +48,7 @@ function convertPathToDefaultPicture() {
|
||||
function isPathToPicture() {
|
||||
local filevault_picture=$1
|
||||
convertPathToDefaultPicture
|
||||
[ -r "${filevault_picture}" ] || { lop debug 'Resolved path is not a valid path. Returning.'; return 10 }
|
||||
[ -r "${filevault_picture}" ] || { lop -d 'Resolved path is not a valid path. Returning.'; return 10 }
|
||||
[[ "${filevault_picture:e:l}" =~ (tif|png|jpeg|jpg) ]] || return 11
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ function doesFileVaultUserExist() {
|
||||
|
||||
function createFileVaultUser() {
|
||||
local un=${filevault_username} fn=${filevault_fullname} pw=${filevault_password}
|
||||
lop -n info 'Creating FileVault user' debug "${un}" info '...'
|
||||
lop --no-newline -d 'Creating FileVault user' -d "${un}" -d '...'
|
||||
sysadminctl -addUser "${un}" -fullName "${fn}" -shell /usr/bin/false -home '/var/empty' -password "${pw}" > /dev/null 2>&1
|
||||
lop success done
|
||||
lop -d done
|
||||
}
|
||||
|
||||
function configureFileVaultUser() {
|
||||
@@ -127,13 +127,11 @@ function allowOnlyFileVaultUserToUnlock() {
|
||||
for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do
|
||||
[ "${fdeuser}" != "${username}" ] && fdesetup remove -user "${fdeuser}"
|
||||
done
|
||||
}
|
||||
|
||||
function configure_system() {
|
||||
checkSecureTokenForUser "${secure_token_user_username}" || { lop error 'The provided secure token user has no secure token.'; return 10 }
|
||||
checkSecureTokenUserPassword || { lop error 'The secure token user password is incorrect.'; return 11 }
|
||||
} function configure_system() {
|
||||
checkSecureTokenForUser "${secure_token_user_username}" || { lop -e 'The provided secure token user has no secure token.'; return 10 }
|
||||
checkSecureTokenUserPassword || { lop -e 'The secure token user password is incorrect.'; return 11 }
|
||||
convertPathToDefaultPicture
|
||||
isPathToPicture "${filevault_picture}" || { lop error 'The provided FileVault user picture is not a valid path to a TIF, PNG or JPEG file.'; return 12 }
|
||||
isPathToPicture "${filevault_picture}" || { lop -e 'The provided FileVault user picture is not a valid path to a TIF, PNG or JPEG file.'; return 12 }
|
||||
|
||||
doesFileVaultUserExist || createFileVaultUser
|
||||
configureFileVaultUser
|
||||
@@ -154,7 +152,7 @@ function checkPrerequisites() {
|
||||
[sysadminctl]=''
|
||||
[scutil]=''
|
||||
)
|
||||
test "`id -u`" -eq 0 || { lop error 'This module requires root access. Please run as root.'; return 11 }
|
||||
test "`id -u`" -eq 0 || { lop -e 'This module requires root access. Please run as root.'; return 11 }
|
||||
checkCommands
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ function checkCommands() {
|
||||
if ! which "${cmd}" >&! /dev/null; then
|
||||
local comment=''
|
||||
[ -n "${cmds[$cmd]}" ] && comment=" ${cmds[$cmd]}"
|
||||
lop error "This module needs ${cmd}${comment} to work."
|
||||
lop -e "This module needs ${cmd}${comment} to work."
|
||||
return 11
|
||||
fi
|
||||
done
|
||||
@@ -30,7 +30,7 @@ function showQuestions() {
|
||||
local questions=()
|
||||
getQuestions
|
||||
for question in ${questions}; do
|
||||
hio info "${question}"
|
||||
hio -- body "${question}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
Describe 'answerQuestionsFromConfigOrAskUser'
|
||||
Include ./install.sh
|
||||
lop setoutput -l panic tostdout
|
||||
mod="testmod"
|
||||
|
||||
It 'does nothing if module has no questions'
|
||||
declare -A questions=()
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq ''
|
||||
The variable 'questions' should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'asks the user if the question is not in the config'
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
Data 'blue'
|
||||
config() {}
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq "What is your favorite color? "
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'does not ask the user if the question is stored in the config'
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
config() { [ "${1}" = read ] && echo red; }
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'stores the answer in the answers array if asking user'
|
||||
declare -A answers
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
config() {}
|
||||
Data 'blue'
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq "What is your favorite color? "
|
||||
The variable "answers[${mod}_question-one]" should eq 'blue'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'stores the answer in the answers array if retrieving from config'
|
||||
declare -A answers
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
config() { [ "${1}" = read ] && echo red; }
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq ''
|
||||
The variable "answers[${mod}_question-one]" should eq 'red'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'does not store the user answer to config'
|
||||
declare -A answers
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
writtenValue=""
|
||||
Data 'red'
|
||||
config() { [ "${1}" = read ] && return; [ "${1}" = write ] && writtenValue="${2}" }
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq "What is your favorite color? "
|
||||
The variable "answers[${mod}_question-one]" should eq 'red'
|
||||
The variable writtenValue should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'does store the user answer to config in config-only mode'
|
||||
declare -A answers
|
||||
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
|
||||
config_only="yes"
|
||||
writtenValue=""
|
||||
Data 'red'
|
||||
config() { [ "${1}" = read ] && return; [ "${1}" = write ] && writtenValue="${2}" }
|
||||
When call answerQuestionsFromConfigOrAskUser
|
||||
The output should eq "What is your favorite color? "
|
||||
The variable "answers[${mod}_question-one]" should eq 'red'
|
||||
The variable writtenValue should eq 'red'
|
||||
The status should be success
|
||||
End
|
||||
End
|
||||
@@ -1,6 +1,7 @@
|
||||
Describe 'askNecessaryQuestions'
|
||||
Include ./install.sh
|
||||
lop setoutput -l panic tostdout
|
||||
askUserModuleQuestions() {}
|
||||
|
||||
It 'sets config app name'
|
||||
appname=''
|
||||
@@ -9,7 +10,7 @@ Describe 'askNecessaryQuestions'
|
||||
The variable 'appname' should eq 'de.astzweig.macos.system-setup'
|
||||
End
|
||||
|
||||
It 'sets config file path'
|
||||
It 'sets config file path in config_only mode'
|
||||
configpath=''
|
||||
config() { [ "$1" = setconfigfile ] && configpath="$2" }
|
||||
config_only='/my/file/path'
|
||||
@@ -17,15 +18,11 @@ Describe 'askNecessaryQuestions'
|
||||
The variable 'configpath' should eq '/my/file/path'
|
||||
End
|
||||
|
||||
It 'writes config to given file'
|
||||
declare -A answers
|
||||
config_only="`mktemp`"
|
||||
modulesToInstall=('mymodule')
|
||||
populateQuestionsWithModuleRequiredInformation() { questions+=('my-question' $'What is my question?\ninfo') }
|
||||
readConfig() { config read mymodule questions my_question }
|
||||
Data 'myanswer'
|
||||
It 'sets config file path in if -c option is given'
|
||||
configpath=''
|
||||
config() { [ "$1" = setconfigfile ] && configpath="$2" }
|
||||
config='/my/file/path'
|
||||
When call askNecessaryQuestions
|
||||
The variable answers should eq 'myanswer'
|
||||
The result of function readConfig should eq 'myanswer'
|
||||
The variable 'configpath' should eq '/my/file/path'
|
||||
End
|
||||
End
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
Describe 'convertQuestionArgsToAskUserArgs'
|
||||
Include ./install.sh
|
||||
|
||||
It 'converts info to info'
|
||||
args=()
|
||||
choices=()
|
||||
questionArgs='info'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The output should eq ''
|
||||
The variable args should eq 'info'
|
||||
The variable choices should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'converts info with default arg to info with default arg'
|
||||
args=()
|
||||
choices=()
|
||||
questionArgs='info;default:Mario Kart'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The output should eq ''
|
||||
The variable args should eq '-d Mario Kart info'
|
||||
The variable choices should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'converts password to -p info'
|
||||
args=() choices=() questionArgs='password'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq '-p info'
|
||||
The variable choices should eq ''
|
||||
End
|
||||
|
||||
It 'converts confirm to confirm'
|
||||
args=() choices=() questionArgs='confirm'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq 'confirm'
|
||||
The variable choices should eq ''
|
||||
End
|
||||
|
||||
It 'returns if type is select but no choose from arg is provided'
|
||||
args=() choices=() questionArgs='select'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq ''
|
||||
The variable choices should eq ''
|
||||
The status should eq 10
|
||||
End
|
||||
|
||||
It 'converts select to choose'
|
||||
args=() choices=() questionArgs='select;choose from:blue,light green,red'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq 'choose'
|
||||
The variable choices should eq 'blue light green red'
|
||||
The variable '#choices' should eq 3
|
||||
End
|
||||
|
||||
It 'converts validator to -v option for choose'
|
||||
args=() choices=() questionArgs='select;validator:is_file;choose from:blue,light green,red'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq 'choose -v is_file'
|
||||
The variable choices should eq 'blue light green red'
|
||||
The variable '#choices' should eq 3
|
||||
End
|
||||
|
||||
It 'finds choose from arg even if many args are provided'
|
||||
args=() choices=() questionArgs='select;first arg:red;choose from:blue,light green,red;after arg:nine;after arg:nine;'
|
||||
When call convertQuestionArgsToAskUserArgs
|
||||
The variable args should eq 'choose'
|
||||
The variable choices should eq 'blue light green red'
|
||||
The variable '#choices' should eq 3
|
||||
End
|
||||
End
|
||||
@@ -1,36 +0,0 @@
|
||||
Describe 'filterModules'
|
||||
Include ./install.sh
|
||||
lop setoutput -l panic tostdout
|
||||
|
||||
It 'returns all modules if no module arg is given'
|
||||
allModules=(module1 module2 'module3 with space') modulesToInstall=()
|
||||
When call filterModules
|
||||
The variable modulesToInstall should eq 'module1 module2 module3 with space'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'returns only mentioned modules'
|
||||
allModules=(module1 module2 'module3 with space') modulesToInstall=()
|
||||
module=('module3 with space' module2)
|
||||
When call filterModules
|
||||
The variable modulesToInstall should eq 'module2 module3 with space'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'matches modules by ending pattern'
|
||||
allModules=(dir1/module1 dir2/module1 /dir/module1/'module3 with space') modulesToInstall=()
|
||||
module=(module1)
|
||||
When call filterModules
|
||||
The variable modulesToInstall should eq 'dir1/module1 dir2/module1'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'returns only not mentioned modules if inversed'
|
||||
allModules=(module1 module2 'module3 with space') modulesToInstall=()
|
||||
module=('module3 with space' module1)
|
||||
inverse=true
|
||||
When call filterModules
|
||||
The variable modulesToInstall should eq 'module2'
|
||||
The status should be success
|
||||
End
|
||||
End
|
||||
@@ -1,40 +0,0 @@
|
||||
Describe 'findQuestionArgInInstruction'
|
||||
Include ./install.sh
|
||||
instructions=('somearg:somevalue' 'default:one' 'choose from:blue,light green,red')
|
||||
|
||||
It 'finds nothing if no arg name given'
|
||||
argValue=''
|
||||
When call findQuestionArgInInstruction
|
||||
The variable argValue should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'finds nothing if arg name does not exist'
|
||||
argValue=''
|
||||
When call findQuestionArgInInstruction 'arg name that does not exist'
|
||||
The variable argValue should eq ''
|
||||
The status should be failure
|
||||
End
|
||||
|
||||
It 'finds nothing if instructions is empty'
|
||||
instructions=()
|
||||
argValue=''
|
||||
When call findQuestionArgInInstruction 'some arg name'
|
||||
The variable argValue should eq ''
|
||||
The status should be failure
|
||||
End
|
||||
|
||||
It 'finds arg value if instructions contains arg as first item'
|
||||
argValue=''
|
||||
When call findQuestionArgInInstruction 'somearg'
|
||||
The variable argValue should eq 'somevalue'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'finds arg value if instructions contains arg among other items'
|
||||
argValue=''
|
||||
When call findQuestionArgInInstruction 'choose from'
|
||||
The variable argValue should eq 'blue,light green,red'
|
||||
The status should be success
|
||||
End
|
||||
End
|
||||
@@ -1,59 +0,0 @@
|
||||
Describe 'generateConfigKeysFromQuestionID'
|
||||
Include ./install.sh
|
||||
|
||||
It 'does nothing if given no arguments'
|
||||
declare -A configkeys=()
|
||||
When call generateConfigKeysFromQuestionID ''
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'does nothing if question id is empty'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID 'somemod' ''
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'generates key when given module name and question id'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID 'somemod' 'somekey'
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq 'somemod questions somekey'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'replaces minus with underscore'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID 'some-mod' 'somekey'
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq 'some_mod questions somekey'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'replaces multiple minus with single underscore'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID 'some---mod' 'so--mekey'
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq 'some_mod questions so_mekey'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'replaces underscores at the begin and end of string'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID '--some-mod' '--somekey-'
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq 'some_mod questions somekey'
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'removes all chars but [A-Za-z_]'
|
||||
declare configkeys=()
|
||||
When call generateConfigKeysFromQuestionID '*some≠{mod' '?`somekey'
|
||||
The output should eq ''
|
||||
The variable 'configkeys' should eq 'somemod questions somekey'
|
||||
The status should be success
|
||||
End
|
||||
End
|
||||
@@ -2,7 +2,7 @@ Describe 'generateModuleOptions'
|
||||
Include ./install.sh
|
||||
|
||||
It 'does nothing if answers array is empty'
|
||||
declare -A answers=()
|
||||
declare -A moduleAnswers=()
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
The output should eq ''
|
||||
@@ -11,7 +11,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'does nothing if answers does not contain module answers'
|
||||
declare -A answers=('some-module_name' 'answer')
|
||||
declare -A moduleAnswers=('some-module_name' 'answer')
|
||||
mod='module/my-module'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -21,7 +21,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'prefixes single char option names with a dash'
|
||||
declare -A answers=('mymodule_n' 'my name')
|
||||
declare -A moduleAnswers=('mymodule_n' 'my name')
|
||||
mod='mymodule'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -31,7 +31,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'does not prefix single char option name with dash if it is already a dash'
|
||||
declare -A answers=('mymodule_-' 'my name')
|
||||
declare -A moduleAnswers=('mymodule_-' 'my name')
|
||||
mod='mymodule'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -41,7 +41,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'prefixes multi char option names with double dash'
|
||||
declare -A answers=('mymodule_your-name' 'my name')
|
||||
declare -A moduleAnswers=('mymodule_your-name' 'my name')
|
||||
mod='mymodule'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -51,7 +51,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'does not prefix multi char option names with double dash if it starts with a dash'
|
||||
declare -A answers=('mymodule_-your-name' 'my name')
|
||||
declare -A moduleAnswers=('mymodule_-your-name' 'my name')
|
||||
mod='mymodule'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -61,7 +61,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'works with modules that contains slashes'
|
||||
declare -A answers=('/some/dir/mymodule_your-name' 'my name')
|
||||
declare -A moduleAnswers=('/some/dir/mymodule_your-name' 'my name')
|
||||
mod='/some/dir/mymodule'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
@@ -71,7 +71,7 @@ Describe 'generateModuleOptions'
|
||||
End
|
||||
|
||||
It 'works with modules that contains spaces'
|
||||
declare -A answers=('/some/dir with spaces/mymodule with spaces_your-name' 'my name')
|
||||
declare -A moduleAnswers=('/some/dir with spaces/mymodule with spaces_your-name' 'my name')
|
||||
mod='/some/dir with spaces/mymodule with spaces'
|
||||
moduleOptions=()
|
||||
When call generateModuleOptions
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
Describe 'installModules'
|
||||
Include ./install.sh
|
||||
lop setoutput -l panic tostdout
|
||||
output=()
|
||||
runModule() { output=("$@") }
|
||||
|
||||
It 'does nothing if modules array is empty'
|
||||
declare -A modulesToInstall=() answers=()
|
||||
declare -A modulesToInstall=() moduleAnswers=()
|
||||
called=false
|
||||
generateModuleOptions() { called=true }
|
||||
When call installModules
|
||||
@@ -14,7 +15,7 @@ Describe 'installModules'
|
||||
End
|
||||
|
||||
It 'calls the module without options if answers is empty'
|
||||
declare -A answers=()
|
||||
declare -A moduleAnswers=()
|
||||
modulesToInstall=('/modules/my module')
|
||||
When call installModules
|
||||
The output should eq ''
|
||||
@@ -23,7 +24,7 @@ Describe 'installModules'
|
||||
End
|
||||
|
||||
It 'calls the module with given answers as options'
|
||||
declare -A answers=('/modules/my module_name' 'hercules')
|
||||
declare -A moduleAnswers=('/modules/my module_name' 'hercules')
|
||||
modulesToInstall=('/modules/my module')
|
||||
When call installModules
|
||||
The output should eq ''
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
Describe 'parseQuestionLine'
|
||||
Include ./install.sh
|
||||
|
||||
It 'does nothing if the line is empty'
|
||||
line=''
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'does nothing if the line does not have a question type'
|
||||
line='some value here'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should eq 10
|
||||
End
|
||||
|
||||
It 'does nothing if the line does not have a valid question type'
|
||||
line='z: some value here'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should eq 11
|
||||
End
|
||||
|
||||
It 'does nothing if the line does not have a parameter name'
|
||||
line='i: '
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should eq 12
|
||||
End
|
||||
|
||||
It 'does nothing if the parameter name starts with a dash'
|
||||
line='i: -parameter-name=Is this my question?'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should eq 13
|
||||
End
|
||||
|
||||
It 'does nothing if the line does not have a question'
|
||||
line='i: parameter-name='
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The status should eq 14
|
||||
End
|
||||
|
||||
It 'extends outer questions associative array with question'
|
||||
declare -A questions
|
||||
line='i: parameter-name=What parameter do you like? #'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The line 1 of variable 'questions[parameter-name]' should eq 'What parameter do you like?'
|
||||
The line 2 of variable 'questions[parameter-name]' should eq info
|
||||
The status should be success
|
||||
End
|
||||
|
||||
It 'ignores empty arguments'
|
||||
declare -A questions
|
||||
line='i: parameter-name=What parameter do you like? # some arg: some value;;'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The line 1 of variable 'questions[parameter-name]' should eq 'What parameter do you like?'
|
||||
The status should eq 0
|
||||
End
|
||||
|
||||
It 'does nothing if an argument does not contain a name'
|
||||
declare -A questions
|
||||
line='i: parameter-name=What parameter do you like? # some arg: some value;:some value;'
|
||||
When call parseQuestionLine
|
||||
The output should eq ''
|
||||
The variable 'questions' should eq ''
|
||||
The status should eq 15
|
||||
End
|
||||
|
||||
It 'writes question type to outer questions associative array'
|
||||
declare -A questions
|
||||
line='s: parameter-name=What parameter do you like? # choose from: blue,red,light green; default: blue'
|
||||
When call parseQuestionLine
|
||||
The line 2 of variable 'questions[parameter-name]' should eq 'select;choose from:blue,red,light green;default:blue'
|
||||
End
|
||||
End
|
||||
|
||||
Describe "parseQuestionLine type renaming"
|
||||
Include ./install.sh
|
||||
Parameters
|
||||
i info
|
||||
p password
|
||||
c confirm
|
||||
s select
|
||||
End
|
||||
|
||||
It "converts $1 to $2"
|
||||
declare -A questions
|
||||
line="${1}: parameter-name=What parameter do you like? #"
|
||||
When call parseQuestionLine
|
||||
The line 2 of variable 'questions[parameter-name]' should eq "$2"
|
||||
End
|
||||
End
|
||||
2
zshlib
2
zshlib
Submodule zshlib updated: 626500e18c...35636db264
Reference in New Issue
Block a user