further improved installer, renamed completion file
This commit is contained in:
parent
62e996290e
commit
46d064bcdd
|
@ -2,19 +2,27 @@
|
||||||
|
|
||||||
# Generate an installer script using the most recent version of qq2clone
|
# Generate an installer script using the most recent version of qq2clone
|
||||||
|
|
||||||
|
declare -a arc_files=( qq2clone lv_api_do qq2clone.1
|
||||||
|
qq2clone-completion.bash )
|
||||||
|
declare -a req_files=( "${arc_files[@]}" inst_fragment.bash )
|
||||||
|
|
||||||
{ [[ -e lv_api_do ]] && [[ -e qq2clone ]] &&
|
has_req=1
|
||||||
[[ -e "inst_fragment.bash" ]] ; } ||
|
for file in "${req_files[@]}"; do
|
||||||
{ echo "Current working directory does not contain required files"
|
if [[ ! -e "$file" ]]; then
|
||||||
exit 1; }
|
has_req=0
|
||||||
|
echo "Current working directory missing file '$file'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
((has_req)) || exit 1
|
||||||
|
|
||||||
|
echo "Generating script"
|
||||||
{
|
{
|
||||||
echo "#!/bin/bash"
|
echo "#!/bin/bash"
|
||||||
echo
|
echo
|
||||||
echo "# This script generated automatically by gen_installer.bash"
|
echo "# This script generated automatically by gen_installer.bash"
|
||||||
echo ""
|
echo
|
||||||
echo -n "archive='"
|
echo "archive='"
|
||||||
tar -cz qq2clone lv_api_do | base64
|
tar -cz "${arc_files[@]}" | base64
|
||||||
echo "'"
|
echo "'"
|
||||||
echo
|
echo
|
||||||
cat inst_fragment.bash
|
cat inst_fragment.bash
|
||||||
|
|
|
@ -5,17 +5,19 @@
|
||||||
|
|
||||||
temp_dir="$(mktemp -d)" ||
|
temp_dir="$(mktemp -d)" ||
|
||||||
{ echo "Failed to create temp directory"; exit 1; }
|
{ echo "Failed to create temp directory"; exit 1; }
|
||||||
|
trap "rm -rf \"${temp_dir:?}\" &>/dev/null" EXIT
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "$archive" | base64 -d > "${temp_dir}/archive.tgz" &&
|
|
||||||
cd "$temp_dir" &&
|
cd "$temp_dir" &&
|
||||||
tar -xzf archive.tgz
|
echo "$archive" | base64 -d > archive.tgz &&
|
||||||
|
tar -xzf archive.tgz &&
|
||||||
|
rm archive.tgz
|
||||||
} || { echo "Problem unpacking data to $temp_dir"; exit 1; }
|
} || { echo "Problem unpacking data to $temp_dir"; exit 1; }
|
||||||
|
|
||||||
declare input="" location="${HOME}/storage-qq2clone"
|
declare input="" location="${HOME}/storage-qq2clone"
|
||||||
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
||||||
echo "[y/n] Use default storage directory '$location'?"
|
echo "[y/n] Use default storage directory '$location'?"
|
||||||
read -rn1 input
|
read -rn1 input; echo
|
||||||
done
|
done
|
||||||
|
|
||||||
while [[ ! "$input" =~ (y|Y) ]]; do
|
while [[ ! "$input" =~ (y|Y) ]]; do
|
||||||
|
@ -23,28 +25,105 @@ while [[ ! "$input" =~ (y|Y) ]]; do
|
||||||
read -r location
|
read -r location
|
||||||
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
||||||
echo "[y/n] Accept location \'$location\' ?"
|
echo "[y/n] Accept location \'$location\' ?"
|
||||||
read -rn 1 input
|
read -rn 1 input; echo
|
||||||
done
|
done
|
||||||
[[ "$input" =~ (y|Y) ]] && break
|
|
||||||
done
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
{
|
{
|
||||||
mkdir -p "${HOME}/.config" &&
|
mkdir -p "${HOME}/.config" &&
|
||||||
echo "$location" > "${HOME}/.config/qq2clone"
|
echo "$location" > "${HOME}/.config/qq2clone"
|
||||||
} || { echo "Failed to create ${HOME}/.config/qq2clone"; exit 1; }
|
} || { echo "Failed to write to ${HOME}/.config/qq2clone"; exit 1; }
|
||||||
|
|
||||||
{
|
{
|
||||||
mkdir -p "$location" &&
|
mkdir -p "$location" &&
|
||||||
touch "$location/qq2clone" &&
|
find -mindepth 1 -exec mv \{\} "$location"/\{\} \;
|
||||||
touch "$location/lv_api_do"
|
|
||||||
} || { echo "Cannot create/write to '$location'"; exit 1; }
|
} || { echo "Cannot create/write to '$location'"; exit 1; }
|
||||||
|
|
||||||
{
|
if { command -v sudo &>/dev/null || [[ "$USER" == "root" ]]; }; then
|
||||||
mv "${temp_dir}/qq2clone" "${location}/" &&
|
|
||||||
mv "${temp_dir}/lv_api_do" "${location}/"
|
|
||||||
} || { echo "Unexpected filesystem permissions error"; exit 1; }
|
|
||||||
|
|
||||||
|
input=""
|
||||||
|
while : ; do
|
||||||
|
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
||||||
|
echo "[y/n] Move main script file to /usr/bin/qq2clone ?"
|
||||||
|
read -rn 1 input; echo
|
||||||
|
done
|
||||||
|
if [[ "$input" =~ ^(y|Y)$ ]]; then
|
||||||
|
success=1
|
||||||
|
if [[ "$USER" == "root" ]]; then
|
||||||
|
mv "${location}/qq2clone" /usr/bin/qq2clone || success=0
|
||||||
|
else
|
||||||
|
sudo mv "${location}/qq2clone" /usr/bin/qq2clone || success=0
|
||||||
|
fi
|
||||||
|
((success)) && { echo "File moved"; break; }
|
||||||
|
echo "Attempt failed."; input=""; continue
|
||||||
|
else
|
||||||
|
echo "You have chosen to leave the main script file at:"
|
||||||
|
echo " ${location}/qq2clone"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
input=""
|
||||||
|
while : ; do
|
||||||
|
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
||||||
|
echo "[y/n] Move man page to /usr/local/man/man1/qq2clone.1 ?"
|
||||||
|
read -rn 1 input; echo
|
||||||
|
done
|
||||||
|
if [[ "$input" =~ ^(y|Y)$ ]]; then
|
||||||
|
success=1
|
||||||
|
if [[ "$USER" == "root" ]]; then
|
||||||
|
{
|
||||||
|
mkdir -p /usr/local/man/man1 &&
|
||||||
|
mv "${location}/qq2clone.1" /usr/local/man/man1/qq2clone.1
|
||||||
|
} ||
|
||||||
|
success=0
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sudo mkdir -p /usr/local/man/man1 &&
|
||||||
|
sudo mv "${location}/qq2clone.1" /usr/local/man/man1/qq2clone.1
|
||||||
|
} ||
|
||||||
|
success=0
|
||||||
|
fi
|
||||||
|
((success)) && { echo "File moved"; break; }
|
||||||
|
echo "Attempt failed."; input=""; continue
|
||||||
|
else
|
||||||
|
echo "You have chosen to leave the man page at:"
|
||||||
|
echo " ${location}/qq2clone.1"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "sudo is not installed on this system, so script and man page files"
|
||||||
|
echo "will not be moved to /usr/bin/ and /usr/share/man"
|
||||||
|
echo " [Main script] ${location}/qq2clone"
|
||||||
|
echo " [Man page] ${location}/qq2clone.1"
|
||||||
|
echo "Manually move these files to desired location on this system"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
input=""
|
||||||
|
while [[ ! "$input" =~ ^(y|n|Y|N)$ ]]; do
|
||||||
|
echo "[y/n] qq2clone has a bash completion script. Modify ~/.bashrc to"
|
||||||
|
echo " source the completion script?"
|
||||||
|
read -rn 1 input; echo
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$input" =~ ^(y|Y)$ ]]; then
|
||||||
|
if echo "source ${location}/qq2clone-completion.bash" >> \
|
||||||
|
"${HOME}/.bashrc"; then
|
||||||
|
echo ".bashrc modified."
|
||||||
|
else
|
||||||
|
echo "Failed to write to ${HOME}/.bashrc . Completion script is"
|
||||||
|
echo "available at:"
|
||||||
|
echo " ${location}/qq2clone-completion.bash"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Completion script is available at:"
|
||||||
|
echo " ${location}/qq2clone-completion.bash"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "Setup complete"
|
||||||
# TODO Replace qq2clone first_time_setup
|
# TODO Replace qq2clone first_time_setup
|
||||||
# TODO offer to 'install' by placing in path
|
|
||||||
|
|
||||||
rm -rf "${temp_dir:?}" &>/dev/null
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Bash completion for qq2clone
|
||||||
|
|
||||||
|
_qq2clone () {
|
||||||
|
|
||||||
|
QQ2_DIR="$(<"${HOME:?}/.config/qq2clone")"
|
||||||
|
[[ -e "${QQ2_DIR}/qq2clone.db" ]] || return 1
|
||||||
|
|
||||||
|
declare -a templates
|
||||||
|
declare line
|
||||||
|
while read -r line; do
|
||||||
|
templates=( "${templates[@]}" "$line" )
|
||||||
|
done < <("sqlite3" --batch "${QQ2_DIR}/qq2clone.db" \
|
||||||
|
"select name from TEMPLATES")
|
||||||
|
declare -a COMS FLAGS
|
||||||
|
COMS=( check clone config connect copy-template delete-template destroy \
|
||||||
|
edit exec import-template list list-templates modify-template restore \
|
||||||
|
resume rm rm-shred rm-wipe save save-rm start suspend )
|
||||||
|
FLAGS=( connection copy-disks no-spice use-spice help no-run quiet quieter \
|
||||||
|
run spicy storage template verbose virt-viewer )
|
||||||
|
|
||||||
|
local LAST_ARG THIS_ARG B4_LAST_ARG P set_coms
|
||||||
|
(( COMP_CWORD > 0 )) &&
|
||||||
|
LAST_ARG="${COMP_WORDS[$((COMP_CWORD - 1))]}"
|
||||||
|
(( COMP_CWORD > 1 )) &&
|
||||||
|
B4_LAST_ARG="${COMP_WORDS[$((COMP_CWORD - 2))]}"
|
||||||
|
THIS_ARG="${COMP_WORDS[$COMP_CWORD]}"
|
||||||
|
set_coms="connect|destroy|exec|resume|rm|rm\-shred|rm\-wipe|save|save\-rm|"
|
||||||
|
set_coms="${set_coms}start|suspend|restore"
|
||||||
|
|
||||||
|
[[ "$THIS_ARG" =~ ^('./'|'/') ]] &&
|
||||||
|
{ read -ra COMPREPLY < <(compgen -f "$THIS_ARG" | tr "\n" " " ); return 0; }
|
||||||
|
|
||||||
|
declare -a suggestions
|
||||||
|
|
||||||
|
if [[ "$THIS_ARG" =~ ^\-\- ]]; then
|
||||||
|
suggestions=("${FLAGS[@]}")
|
||||||
|
P="--"
|
||||||
|
elif [[ "$LAST_ARG" =~ ^(\-|modify|delete|copy)\-template$ ]] ||
|
||||||
|
[[ "$LAST_ARG" == "template-snapshot" ]] ||
|
||||||
|
[[ "$LAST_ARG" == "-t" ]]; then
|
||||||
|
suggestions=( "${templates[@]}" )
|
||||||
|
elif [[ "$LAST_ARG" =~ ^(\-\-storage|\-s)$ ]]; then
|
||||||
|
read -ra suggestions < <(virsh pool-list --name | tr -d '\n')
|
||||||
|
elif [[ "$LAST_ARG" == "config" ]]; then
|
||||||
|
suggestions=( list edit info )
|
||||||
|
elif [[ "$LAST_ARG" =~ ^(${set_coms})$ ]]; then
|
||||||
|
suggestions=( all running saved off in-shutdown idle paused crashed )
|
||||||
|
suggestions=( "${suggestions[@]}" pmsuspended )
|
||||||
|
elif [[ "$LAST_ARG" == "list" ]] &&
|
||||||
|
[[ ! "$B4_LAST_ARG" == "config" ]]; then
|
||||||
|
suggestions=( all xml )
|
||||||
|
else
|
||||||
|
local curr_com word elem
|
||||||
|
for word in "${COMP_WORDS[@]}"; do
|
||||||
|
for elem in "${COMS[@]}"; do
|
||||||
|
[[ "$elem" == "$word" ]] && { curr_com="$word"; break 2; }
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "$curr_com" ]]; then
|
||||||
|
if [[ "$curr_com" == "modify-template" ]] &&
|
||||||
|
[[ "${COMP_WORDS[$((COMP_CWORD - 2))]}" == "$curr_com" ]]; then
|
||||||
|
suggestions=( edit prepare-image commit-image discard-image \
|
||||||
|
destroy-image rename )
|
||||||
|
elif [[ "$curr_com" == config ]] &&
|
||||||
|
[[ "${COMP_WORDS[$((COMP_CWORD - 2))]}" == "$curr_com" ]] &&
|
||||||
|
[[ "$LAST_ARG" =~ ^(info|edit)$ ]]; then
|
||||||
|
suggestions=(NORUN QUIET USE_SPICE SPICY STORAGE S_TIMEOUT TEMPLATE \
|
||||||
|
TEMPLATE_DIR)
|
||||||
|
else
|
||||||
|
suggestions=( )
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
suggestions=("${COMS[@]}")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local i
|
||||||
|
declare -a comp
|
||||||
|
for ((i=0;i<${#suggestions[@]};i++)); do
|
||||||
|
if [[ "${P}${suggestions["$i"]}" =~ ^"${THIS_ARG}" ]]; then
|
||||||
|
comp=( "${comp[@]}" "${suggestions["$i"]}" )
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
(( ${#comp} > 0 )) &&
|
||||||
|
|
||||||
|
read -ra COMPREPLY < <(compgen -P "${P}" -W "${comp[*]}" | tr "\n" " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _qq2clone qq2clone
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue