Use loadModules and askUserModuleQuestions

This commit is contained in:
Rezart Qelibari
2022-03-08 12:42:48 +01:00
parent 79693877b2
commit 322a2aa757
14 changed files with 77 additions and 628 deletions

View File

@@ -1,208 +1,37 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
# vi: set expandtab ft=zsh tw=80 ts=2 # vi: set expandtab ft=zsh tw=80 ts=2
function filterModules() { runModule() {
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
} }
function askNecessaryQuestions() { function askNecessaryQuestions() {
local mod local mod= configOnlyArgs=()
config setappname "de.astzweig.macos.system-setup" config setappname "de.astzweig.macos.system-setup"
if [ -n "${config_only}" ]; then 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}" config setconfigfile "${config_only}"
configOnlyArgs=(-x)
elif [ -n "${config}" ]; then
config setconfigfile "${config}"
fi fi
for mod in ${modulesToInstall}; do askUserModuleQuestions ${configOnlyArgs} -c config -v moduleAnswers ${modulesToInstall}
local -A questions=()
populateQuestionsWithModuleRequiredInformation
answerQuestionsFromConfigOrAskUser
done
} }
function printModulesToInstall() { function printModulesToInstall() {
lop section 'Modules that will install are:' lop -d 'Modules that will install are:' -d "${modulesToInstall}"
for mod in "${modulesToInstall}"; do for mod in "${modulesToInstall[@]}"; do
hio info "${mod}" print "${mod}"
done | abbreviatePaths done | abbreviatePaths
exit 0 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() { function generateModuleOptions() {
local value answerKey optionKey local value answerKey optionKey
for answerKey in ${(k)answers}; do for answerKey in ${(k)moduleAnswers}; do
[[ ${answerKey} = ${mod}_* ]] || continue [[ ${answerKey} = ${mod}_* ]] || continue
optionKey="${answerKey#${mod}_}" optionKey="${answerKey#${mod}_}"
value="${answers[${answerKey}]}" value="${moduleAnswers[${answerKey}]}"
if [[ "${optionKey}" =~ ^[[:alpha:]]$ ]]; then if [[ "${optionKey}" =~ ^[[:alpha:]]$ ]]; then
moduleOptions+=("-${optionKey}" "${value}") moduleOptions+=("-${optionKey}" "${value}")
elif [[ "${optionKey}" =~ ^[[:alpha:]][-[:alpha:]]+$ ]]; then elif [[ "${optionKey}" =~ ^[[:alpha:]][-[:alpha:]]+$ ]]; then
@@ -219,8 +48,8 @@ function installModules() {
moduleOptions=() moduleOptions=()
filteredOptions=() filteredOptions=()
generateModuleOptions generateModuleOptions
lop debug "Running ${mod}" debug "with ${#moduleOptions} args: ${moduleOptions}" lop -d "Running ${mod}" -d "with ${#moduleOptions} args:" -d "${moduleOptions}"
runModule "${mod}" ${moduleOptions} runModule ${mod} ${moduleOptions}
done done
} }
@@ -236,9 +65,9 @@ function isPlistBuddyInstalled() {
} }
function checkPrerequisites() { function checkPrerequisites() {
isMacOS || { lop error 'This setup is only for macOS 10.13 and up.'; return 10 } isMacOS || { lop -e '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 } 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 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 }
} }
function main() { function main() {
@@ -269,11 +98,15 @@ function main() {
License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law.
USAGE`" USAGE`"
local allModules=() modulesToInstall=() local allModules=() modulesToInstall=()
local -A answers local -A moduleAnswers
configureLogging configureLogging
lop debug "Current working dir is: `pwd`" lop -d "Current working dir is: `pwd`"
lop -- debug "Called main with $# args: $@" lop -d "Called main with $# args: $*"
loadModules
modpath+=("${_DIR}/modules")
loadModules -v modulesToInstall ${$(echo -m):^^modpath} "${module[@]}"
[ "${list}" = true ] && printModulesToInstall
askNecessaryQuestions askNecessaryQuestions
[ -z "${config_only}" ] || return 0 [ -z "${config_only}" ] || return 0
installModules installModules

View File

@@ -12,7 +12,7 @@ function checkPrerequisites() {
[defaults]='' [defaults]=''
[launchctl]='' [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 checkCommands
} }
@@ -26,26 +26,27 @@ function getQuestions() {
} }
function quitSystemPreferences() { function quitSystemPreferences() {
lop debug 'Quitting System Preferences App' lop -d 'Quitting System Preferences App'
osascript -e 'tell application "System Preferences" to quit' osascript -e 'tell application "System Preferences" to quit'
} }
function configureComputerHostname() { 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 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 ComputerName "${hostname}"
scutil --set HostName "${hostname}" scutil --set HostName "${hostname}"
systemsetup -setcomputername "${hostname}" > /dev/null 2>&1 systemsetup -setcomputername "${hostname}" > /dev/null 2>&1
systemsetup -setlocalsubnetname "${hostname}" > /dev/null 2>&1 systemsetup -setlocalsubnetname "${hostname}" > /dev/null 2>&1
else 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 fi
} }
function configureBasicSystem(){ function configureBasicSystem(){
lop -n info 'Configuring systemsetup and nvram...' lop --no-newline -i 'Configuring systemsetup and nvram...'
# Disable the sound effects on boot # Disable the sound effects on boot
nvram SystemAudioVolume=" " nvram SystemAudioVolume=" "
@@ -57,12 +58,12 @@ function configureBasicSystem(){
systemsetup -setrestartfreeze on >&! /dev/null systemsetup -setrestartfreeze on >&! /dev/null
systemsetup -f -setremotelogin off >&! /dev/null systemsetup -f -setremotelogin off >&! /dev/null
systemsetup -setremoteappleevents off >&! /dev/null systemsetup -setremoteappleevents off >&! /dev/null
lop success 'done' lop -i 'done'
} }
function configurePowerManagement() { function configurePowerManagement() {
lop -n info 'Configuring power management...' lop --no-newline -i 'Configuring power management...'
cmd=(pmset -a) cmd=(pmset -a)
${cmd} displaysleep 0 ${cmd} displaysleep 0
${cmd} disksleep 0 ${cmd} disksleep 0
@@ -76,17 +77,17 @@ function configurePowerManagement() {
${cmd} halfdim 1 ${cmd} halfdim 1
${cmd} powernap 1 ${cmd} powernap 1
${cmd} hibernatemode 0 ${cmd} hibernatemode 0
lop success 'done' lop -i 'done'
} }
function configureLoginWindow() { function configureLoginWindow() {
lop -n info 'Configuring login window...' lop --no-newline -i 'Configuring login window...'
cmd=(defaults write '/Library/Preferences/com.apple.loginwindow') cmd=(defaults write '/Library/Preferences/com.apple.loginwindow')
${cmd} DisableFDEAutoLogin -bool true ${cmd} DisableFDEAutoLogin -bool true
${cmd} SHOWFULLNAME -bool false ${cmd} SHOWFULLNAME -bool false
${cmd} AdminHostInfo -string HostName ${cmd} AdminHostInfo -string HostName
${cmd} GuestEnabled -bool false ${cmd} GuestEnabled -bool false
lop success 'done' lop -i 'done'
} }
function configure_system() { function configure_system() {
@@ -96,7 +97,7 @@ function configure_system() {
configurePowerManagement configurePowerManagement
configureLoginWindow configureLoginWindow
lop info 'Configuring global umask' lop -i 'Configuring global umask'
launchctl config user umask 027 launchctl config user umask 027
} }

View File

@@ -2,25 +2,25 @@
function getDefaultFullname() { function getDefaultFullname() {
local computerName="`scutil --get ComputerName 2> /dev/null`" 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}" print "${computerName}"
} }
function getDefaultUsername() { function getDefaultUsername() {
local username="`getDefaultFullname | tr '[:upper:]' '[:lower:]' | tr -C '[:alnum:]\n' '-'`" 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}" print "${username}"
} }
function getUsersWithSecureToken() { function getUsersWithSecureToken() {
local username local username
for username in ${(f)"$(dscl . -list /Users | grep -v '^_.*')"}; do 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 if checkSecureTokenForUser "${username}"; then
lop debug 'found' lop -d 'found'
secureTokenUsers+=("${username}") secureTokenUsers+=("${username}")
else else
lop debug 'not found' lop -d 'not found'
fi fi
done done
} }
@@ -33,14 +33,14 @@ function getDefaultUserPictures() {
function convertPathToDefaultPicture() { function convertPathToDefaultPicture() {
local resolved='' 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 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 return
fi fi
pushd -q '/Library/User Pictures' pushd -q '/Library/User Pictures'
resolved="`find . -type f -path "*${filevault_picture}" 2> /dev/null`" 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 popd -q
[ -n "${resolved}" -a -r "${resolved}" ] && filevault_picture="${resolved}" [ -n "${resolved}" -a -r "${resolved}" ] && filevault_picture="${resolved}"
} }
@@ -48,7 +48,7 @@ function convertPathToDefaultPicture() {
function isPathToPicture() { function isPathToPicture() {
local filevault_picture=$1 local filevault_picture=$1
convertPathToDefaultPicture 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 [[ "${filevault_picture:e:l}" =~ (tif|png|jpeg|jpg) ]] || return 11
} }
@@ -67,9 +67,9 @@ function doesFileVaultUserExist() {
function createFileVaultUser() { function createFileVaultUser() {
local un=${filevault_username} fn=${filevault_fullname} pw=${filevault_password} 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 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() { function configureFileVaultUser() {
@@ -127,13 +127,11 @@ function allowOnlyFileVaultUserToUnlock() {
for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do
[ "${fdeuser}" != "${username}" ] && fdesetup remove -user "${fdeuser}" [ "${fdeuser}" != "${username}" ] && fdesetup remove -user "${fdeuser}"
done done
} } function configure_system() {
checkSecureTokenForUser "${secure_token_user_username}" || { lop -e 'The provided secure token user has no secure token.'; return 10 }
function configure_system() { checkSecureTokenUserPassword || { lop -e 'The secure token user password is incorrect.'; return 11 }
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 }
convertPathToDefaultPicture 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 doesFileVaultUserExist || createFileVaultUser
configureFileVaultUser configureFileVaultUser
@@ -154,7 +152,7 @@ function checkPrerequisites() {
[sysadminctl]='' [sysadminctl]=''
[scutil]='' [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 checkCommands
} }

View File

@@ -20,7 +20,7 @@ function checkCommands() {
if ! which "${cmd}" >&! /dev/null; then if ! which "${cmd}" >&! /dev/null; then
local comment='' local comment=''
[ -n "${cmds[$cmd]}" ] && comment=" ${cmds[$cmd]}" [ -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 return 11
fi fi
done done
@@ -30,7 +30,7 @@ function showQuestions() {
local questions=() local questions=()
getQuestions getQuestions
for question in ${questions}; do for question in ${questions}; do
hio info "${question}" hio -- body "${question}"
done done
} }

View File

@@ -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

View File

@@ -1,6 +1,7 @@
Describe 'askNecessaryQuestions' Describe 'askNecessaryQuestions'
Include ./install.sh Include ./install.sh
lop setoutput -l panic tostdout lop setoutput -l panic tostdout
askUserModuleQuestions() {}
It 'sets config app name' It 'sets config app name'
appname='' appname=''
@@ -9,7 +10,7 @@ Describe 'askNecessaryQuestions'
The variable 'appname' should eq 'de.astzweig.macos.system-setup' The variable 'appname' should eq 'de.astzweig.macos.system-setup'
End End
It 'sets config file path' It 'sets config file path in config_only mode'
configpath='' configpath=''
config() { [ "$1" = setconfigfile ] && configpath="$2" } config() { [ "$1" = setconfigfile ] && configpath="$2" }
config_only='/my/file/path' config_only='/my/file/path'
@@ -17,15 +18,11 @@ Describe 'askNecessaryQuestions'
The variable 'configpath' should eq '/my/file/path' The variable 'configpath' should eq '/my/file/path'
End End
It 'writes config to given file' It 'sets config file path in if -c option is given'
declare -A answers configpath=''
config_only="`mktemp`" config() { [ "$1" = setconfigfile ] && configpath="$2" }
modulesToInstall=('mymodule') config='/my/file/path'
populateQuestionsWithModuleRequiredInformation() { questions+=('my-question' $'What is my question?\ninfo') }
readConfig() { config read mymodule questions my_question }
Data 'myanswer'
When call askNecessaryQuestions When call askNecessaryQuestions
The variable answers should eq 'myanswer' The variable 'configpath' should eq '/my/file/path'
The result of function readConfig should eq 'myanswer'
End End
End End

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -2,7 +2,7 @@ Describe 'generateModuleOptions'
Include ./install.sh Include ./install.sh
It 'does nothing if answers array is empty' It 'does nothing if answers array is empty'
declare -A answers=() declare -A moduleAnswers=()
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
The output should eq '' The output should eq ''
@@ -11,7 +11,7 @@ Describe 'generateModuleOptions'
End End
It 'does nothing if answers does not contain module answers' 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' mod='module/my-module'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -21,7 +21,7 @@ Describe 'generateModuleOptions'
End End
It 'prefixes single char option names with a dash' 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' mod='mymodule'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -31,7 +31,7 @@ Describe 'generateModuleOptions'
End End
It 'does not prefix single char option name with dash if it is already a dash' 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' mod='mymodule'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -41,7 +41,7 @@ Describe 'generateModuleOptions'
End End
It 'prefixes multi char option names with double dash' 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' mod='mymodule'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -51,7 +51,7 @@ Describe 'generateModuleOptions'
End End
It 'does not prefix multi char option names with double dash if it starts with a dash' 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' mod='mymodule'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -61,7 +61,7 @@ Describe 'generateModuleOptions'
End End
It 'works with modules that contains slashes' 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' mod='/some/dir/mymodule'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions
@@ -71,7 +71,7 @@ Describe 'generateModuleOptions'
End End
It 'works with modules that contains spaces' 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' mod='/some/dir with spaces/mymodule with spaces'
moduleOptions=() moduleOptions=()
When call generateModuleOptions When call generateModuleOptions

View File

@@ -1,10 +1,11 @@
Describe 'installModules' Describe 'installModules'
Include ./install.sh Include ./install.sh
lop setoutput -l panic tostdout
output=() output=()
runModule() { output=("$@") } runModule() { output=("$@") }
It 'does nothing if modules array is empty' It 'does nothing if modules array is empty'
declare -A modulesToInstall=() answers=() declare -A modulesToInstall=() moduleAnswers=()
called=false called=false
generateModuleOptions() { called=true } generateModuleOptions() { called=true }
When call installModules When call installModules
@@ -14,7 +15,7 @@ Describe 'installModules'
End End
It 'calls the module without options if answers is empty' It 'calls the module without options if answers is empty'
declare -A answers=() declare -A moduleAnswers=()
modulesToInstall=('/modules/my module') modulesToInstall=('/modules/my module')
When call installModules When call installModules
The output should eq '' The output should eq ''
@@ -23,7 +24,7 @@ Describe 'installModules'
End End
It 'calls the module with given answers as options' 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') modulesToInstall=('/modules/my module')
When call installModules When call installModules
The output should eq '' The output should eq ''

View File

@@ -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

Submodule zshlib updated: 626500e18c...35636db264