24 Commits

Author SHA1 Message Date
kevinnls
ed5adc0ac7 version bump 2021-03-18 12:47:24 +05:30
kevinnls
3fead3aecc init: upgrade capabilities 2021-03-18 12:39:15 +05:30
kevinnls
6592c067a0 added --uninstall flag and capabilities
- `--uninstall` searches for all instances of `bak-old.sh` in PATH and
deletes them
- added the `is_command()` function
2021-03-17 02:09:13 +05:30
kevinnls
6676ddafcc add trap to installation script 2021-03-17 01:41:16 +05:30
kevinnls
18d58941af fix file permissions: o+rx
and some cleanup
2021-03-17 01:27:12 +05:30
kevinnls
8a6e42f0c8 configure bak-old to print usage when no args are passed 2021-03-16 20:11:34 +05:30
kevinnls
a3d7c7887e complete installation script with support for curl and wget 2021-03-16 20:10:49 +05:30
kevinnls
289073c584 added text formatting sequences
knocking out the tput dependency
2021-03-16 19:06:36 +05:30
kevinnls
906d847823 in media installation script 2021-03-16 00:41:43 +05:30
kevinnls
0e74eacc1e set up for debugging/dev
- rearranged comments around debug brace expansion so it doesn't look bad when printed due to the `-v` flag
2021-03-15 13:35:39 +05:30
kevinnls
6bb0a8c7e6 init installation script 2021-03-15 12:39:11 +05:30
kevinnls
09890f8dd5 deleted deprecated TODO.md: refer GitHub Issues henceforth 2021-03-14 13:01:43 +05:30
kevinnls
98633dd52e setup TODO for deletion. deprecated. 2021-03-14 12:59:26 +05:30
kevinnls
b5bfcc2fe4 update TODO 2021-03-14 10:35:04 +05:30
kevinnls
8883fbf068 check deps AFTER parsing options
just rearanged code
2021-03-14 10:28:50 +05:30
kevinnls
b08c0332ea improved prompt for missing deps
- newline for each dep
2021-03-14 10:14:04 +05:30
kevinnls
c64850df8d handling unmet dependencies
- will prompt if `realpath` does not exist
- need to work on the heredoc. insert new line for each dep
2021-03-08 02:10:57 +05:30
kevinnls
22571700a8 mark fix in TODO 2021-01-08 02:29:22 +05:30
kevinnls
48f5669511 fix and improve help prompt 2021-01-08 02:28:16 +05:30
kevinnls
721196d163 mark fix in TODO 2021-01-08 02:12:08 +05:30
kevinnls
6ac1dd30e6 enable set -e 2021-01-08 02:05:32 +05:30
kevinnls
a054656d12 cleanup and rearrangement
- rearrange sections
- convert tabs to spaces (thanks VSCode)
- general indentation fixes
2021-01-08 02:03:01 +05:30
kevinnls
e227d0f7dd (TODO) fix link 2021-01-07 22:15:37 +05:30
kevinnls
8e527a6702 add TODO 2021-01-07 22:11:33 +05:30
2 changed files with 404 additions and 120 deletions

View File

@@ -5,23 +5,37 @@
# - another Linux user tired of # # - another Linux user tired of #
# type cp file file.bak # # type cp file file.bak #
################################### ###################################
version='0.1.0-beta' version='0.1.1-beta'
### IFS precautions ### IFS precautions #
OLDIFS="$IFS" OLDIFS="$IFS"
unset IFS unset IFS
### error precautions
set -e
#####################
### parse parameters debug(){ ### function to call when $DEBUG is set
# file names set -xv
# `-d` dest dir
# `-b | -o` mode: cloned file suffix
# ` ` follow symlinks
# ` ` lightweight copies
debug(){
set -xev
} }
# text formatting escape sequences
txt_bold='\e[1m'
txt_red='\e[31m'
txt_green='\e[32m'
txt_yellow='\e[33m'
txt_0='\e[0m'
is_command(){
if { command -v "$1"; } >/dev/null 2>/dev/null; then
return 0
else
return 1
fi
}
###############################################################################
# f() FOR PRINTING PROMPTS
#############################
print_usage(){ print_usage(){
cat << HERE cat << HERE
$(tput bold; tput setaf 3)${0##*/}$(tput sgr0) $(tput bold; tput setaf 3)${0##*/}$(tput sgr0)
@@ -31,190 +45,289 @@ $(tput bold)USAGE$(tput sgr0)
$(tput bold)OPTIONS$(tput sgr0) $(tput bold)OPTIONS$(tput sgr0)
Suffix for FILES -- only one can be used Suffix for FILES -- only one can be used
-b $(tput bold).bak$(tput sgr0) [default] -b .bak [default]
-o $(tput bold).old$(tput sgr0) -o .old
Destination for clones Destination for clones
-d save the clones in DESTINATION -d save the clones in DESTINATION
[default] is the current directory [default] is same as source file
Lightweight copies Lightweight copies
-0 create if possible [default] -0 create if possible [default]
reuse data blocks unless modified
-1 force regular copies -1 force regular copies
copy data blocks completely
Recursive clone Recursive clone
-r clone a directory and its contents -r clone a directory and its contents
Help and Version
-h display this help menu
-v print version
HERE HERE
} }
print_version(){ print_version(){
cat << HERE cat << HERE
$(tput bold)${0##*/}: v${version}$(tput sgr0) $(tput bold)${0##*/}: v${version}$(tput sgr0)
by https://github.com/kevinnls by https://github.com/kevinnls
HERE HERE
} }
print_err(){
tput setaf 1
case $1 in
bo)
echo "ERROR: modes backup and old cannot co-exist"
;;
01)
echo "ERROR: lightweight copy modes cannot co-exist"
;;
x)
echo "ERROR: unrecognised flags"
tput sgr0
print_usage
;;
*)
echo "UNKNOWN ERROR"
esac
tput sgr0
exit 1
}
print_err_deps(){
tput setaf 1
cat <<- EOF
${0##*/} has the following unmet dependencies:${1/:/
- }
EOF
tput sgr0
exit 1
}
copy_succ(){
echo "$(tput setaf 2; tput bold)${1}.${2:-bak}$(tput sgr0)"
}
copy_fail(){
echo "$(tput setaf 1; tput bold)${1}$(tput sgr0)"
}
copy_nofile(){
echo "$(tput setaf 1; tput bold)${1}$(tput sgr0) : file does not exist"
}
###############################################################################
# f() FOR SETTING OPTIONS
############################
set_dest(){ set_dest(){
if [[ -n "$1" ]] && ! realpath -e "$1" >/dev/null 2>&1 ;then if [[ -n "$1" ]] && ! realpath -e "$1" >/dev/null 2>&1 ;then
echo $1 does not exist echo $1 does not exist
echo creating now... echo creating now...
mkdir -p $(realpath "$1") mkdir -p $(realpath "$1")
[[ $? -ne 0 ]] && exit 1 [[ $? -ne 0 ]] && exit 1
fi fi
dest=$(realpath "$1") dest=$(realpath "$1")
} }
set_mode(){ set_mode(){
if [[ -z $mode ]]; then if [[ -z $mode ]]; then
mode=$1 mode=$1
else else
print_error 'bo' print_err 'bo'
fi fi
} }
set_weight(){ set_weight(){
if [[ -z "$weight" ]]; then if [[ -z "$weight" ]]; then
weight="$1" weight="$1"
else else
print_error '01' print_err '01'
fi fi
} }
add_file(){ add_file(){
files=("${files[@]}" "$1") files=("${files[@]}" "$1")
} }
###############################################################################
# f() FOR PARSING PARAMS AND OPTIONS
#######################################
in_combi(){ in_combi(){
[[ "$combi" =~ [:alnum:]*($1){1}[:alnum:]* ]] [[ "$combi" =~ [:alnum:]*($1){1}[:alnum:]* ]]
} }
un_combi(){ un_combi(){
combi=${combi/$1/} combi=${combi/$1/}
} }
parse_combined(){ parse_combined(){
combi="${1/-/}" combi="${1/-/}"
if in_combi 'b';then if in_combi 'b';then
set_mode bak set_mode bak
un_combi 'b' un_combi 'b'
fi fi
if in_combi 'o'; then if in_combi 'o'; then
set_mode old set_mode old
un_combi 'o' un_combi 'o'
fi fi
if in_combi '0'; then if in_combi '0'; then
set_weight 'auto' set_weight 'auto'
un_combi '0' un_combi '0'
fi fi
if in_combi '1'; then if in_combi '1'; then
set_weight 'never' set_weight 'never'
un_combi '1' un_combi '1'
fi fi
[[ "$combi" =~ [:alnum:]*(d){1} ]] && set_dest $2 && ret=2 [[ "$combi" =~ [:alnum:]*(d){1} ]] && set_dest $2 && ret=2
# setting return value to 2 to shift 2 in caller
# in case of -d <dest>
if [[ -z "$combi" ]]; then if [[ -z "$combi" ]]; then
return ${ret:-1} return ${ret:-1}
else else
print_error 'x' print_err 'x'
exit 1 exit 1
fi fi
} }
print_error(){ ### enable debugging if ###
tput setaf 1
case $1 in
bo)
echo "ERROR: modes backup and old cannot co-exist"
;;
01)
echo "ERROR: lightweight copy modes cannot co-exist"
;;
x)
echo "ERROR: unrecognised flags"
tput sgr0
print_usage
;;
*)
echo "UNKNOWN ERROR"
esac
tput sgr0
exit 1
}
copy_succ(){
echo "$(tput setaf 2; tput bold)$file.${mode:-bak}$(tput sgr0)"
}
copy_fail(){
echo "$(tput setaf 1; tput bold)$file$(tput sgr0)"
}
copy_nofile(){
echo "$(tput setaf 1; tput bold)$file$(tput sgr0) : file does not exist"
}
### enable debugging ###
${DEBUG+debug} ### ${DEBUG+debug} ###
### if $DEBUG is set ### ### $DEBUG is set ###
############################################################################### ###############################################################################
# SANITISING PARAMS AND OPTIONS # SANITISING PARAMS AND OPTIONS
################################ ##################################
if [[ "$1" == "--uninstall" ]]; then
install_locs=($(which -a bak-old.sh || echo ''))
echo "uninstalling script..."
echo
if [[ ${#install_locs[@]} -lt 1 ]]; then
echo -e "${txt_yellow}bak-old.sh installation not found in PATH${txt_0}"
exit 0
else
fail_count=0
set +e
for instance in "${install_locs[@]}"; do
rm -f $instance 2>/dev/null
if [[ $? -eq 0 ]]; then
echo -e "${txt_green}$instance deleted!${txt_0}"
else
fail_count=$(( fail_count + 1 ))
echo -e "${txt_red}$instance not deleted:${txt_0} try with sudo or as root"
fi
done
set -e
echo -e "${txt_bold}=========="
if [[ fail_count -eq 0 ]]; then
echo -e "${txt_green} bak-old.sh has been completely removed${txt_0}"
exit 0
else
echo -e "${txt_red} bak-old.sh not completely removed${txt_0}"
exit 1
fi
fi
fi
if [[ "$1" == "--up" ]]; then
if is_command curl; then
downloader='curl -fsSL'
elif is_command wget; then
downloader='wget -qO-'
else
echo -e "${txt_red}${txt_bold}ERR: wget or curl required for upgrading bak-old.sh${txt_0}"
fi
latest_version="$(${downloader} 'https://api.github.com/repos/kevinnls/bak-old/releases/latest' | awk -F \" '/tag_name/ {print $(NF-1)}')"
download_url="https://github.com/kevinnls/bak-old/releases/download/${latest_version}/install.sh"
${downloader} ${download_url} | bash
exit 0
fi
if [[ $# -eq 0 ]]; then
print_usage
fi
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case $1 in case $1 in
'-h' ) '-h' )
print_usage print_usage
exit 0 exit 0
;; ;;
'-v' ) '-v' )
print_version print_version
exit 0 exit 0
;; ;;
'-r' ) '-r' )
recurse='-r' #set_recurse recurse='-r' #set_recurse
shift 1 shift 1
;; ;;
'-d' ) '-d' )
set_dest "$2" set_dest "$2"
shift 2 shift 2
;; ;;
'-b' ) '-b' )
set_mode 'bak' set_mode 'bak'
shift 1 shift 1
;; ;;
'-o' ) '-o' )
set_mode 'old' set_mode 'old'
shift 1 shift 1
;; ;;
'-0' ) '-0' )
set_weight 'auto' set_weight 'auto'
shift 1 shift 1
;; ;;
'-1') '-1')
set_weight 'never' set_weight 'never'
shift 1 shift 1
;; ;;
-* ) -* )
parse_combined "$1" "$2" parse_combined "$1" "$2"
shift $? shift $?
;; ;;
* ) * )
add_file "$1" add_file "$1"
shift 1 shift 1
;; ;;
esac esac
done done
###############################################################################
# CHECKING DEPS
##################
deps=(realpath)
################################################################################ for dep in $deps; do
# THE ACTUAL COPYING CODE if is_command "$dep" >/dev/null; then
########################## continue
for file in "${files[@]}"; do
if realpath -e "$file" >/dev/null 2>&1 ;then
src_filepath="$(realpath "$file")"
dst_filepath="${dest:-${src_filepath%/*}}"
dst_filename="${src_filepath##*/}.${mode:-bak}"
cp_weight="--reflink=${weight:-auto}"
cp ${recurse} ${cp_weight} "$src_filepath" "$dst_filepath/$dst_filename"
[[ $? -eq 0 ]] && copy_succ || copy_fail
else else
copy_nofile missing=":${dep}"
fi fi
done done
### reset IFS if [[ -n ${missing} ]]; then
IFS="$OLDIFS" print_err_deps $missing
fi
###############################################################################
# THE ACTUAL COPYING CODE
############################
for file in "${files[@]}"; do
if realpath -e "$file" >/dev/null 2>&1 ;then
src_filepath="$(realpath "$file")"
dst_filepath="${dest:-${src_filepath%/*}}"
dst_filename="${src_filepath##*/}.${mode:-bak}"
cp_weight="--reflink=${weight:-auto}"
cp ${recurse} ${cp_weight} "$src_filepath" "$dst_filepath/$dst_filename"
[[ $? -eq 0 ]] && copy_succ $file $mode || copy_fail $file
else
copy_nofile $file
fi
done
### reset IFS###
IFS="$OLDIFS" #
################

171
install.sh Executable file
View File

@@ -0,0 +1,171 @@
#!/bin/bash
###################################
# install script for bak-old.sh #
# authored by github.com/kevinnls #
# - another Linux user tired of #
# type cp file file.bak #
###################################
set -e
VERSION='v0.1.0-beta'
work_dir=/tmp/bak-old_installation/
tmp_file_path="$work_dir/bak-old.sh"
download_url="https://github.com/kevinnls/bak-old/releases/download/${VERSION}/bak-old.sh"
# list of known downloaders and options for download
declare -A dlers
dlers[curl]="curl -fsSLRo $tmp_file_path"
dlers[wget]="wget -qO $tmp_file_path"
# list of possible destinations for root user
r_dstdirs=('/usr/local/bin'
'/usr/bin'
'/bin')
# list of possible destinations for normal user
u_dstdirs=("$HOME/.local/bin"
"$HOME/bin")
declare downloader
declare dest_dir
debug(){ ### function to call when $DEBUG is set
set -xv
}
is_command(){ ### function to check if a command exists
{ command -v $1;} >/dev/null && return 0 || return 1
}
# text formatting escape sequences
txt_bold='\e[1m'
txt_red='\e[31m'
txt_green='\e[32m'
txt_yellow='\e[33m'
txt_0='\e[0m'
err_no_downloader(){
echo -e "$(cat <<- EOM
${txt_bold}${txt_red}ERR: missing dependencies${txt_0}
required by this installation script:
- wget OR curl
install either application using your package manager and try again
alternatively, you can manually download the file from
$download_url
to a directory in your PATH
EOM
)"
exit 1
}
err_no_dest_in_path(){
echo -e "$(cat <<-EOM
${txt_bold}${txt_red}ERR: no preconfigured destinations are in your PATH${txt_0}
check your PATH variable configuration
or specify the destination with -d
EOM
)"
exit 1
}
err_no_home_dir(){
echo -e "$(cat <<- EOM
${txt_bold}${txt_red}ERR: $(whoami) does not have a valid home directory${txt_0}
EOM
)"
exit 1
}
err_unknown(){
echo -e "$(cat <<-EOM
${txt_bold}${txt_red}ERR: some unhandled error has occurred${txt_0}
EOM
)"
exit 1
}
install_success(){
echo -e "$(cat <<-EOM
${txt_bold}${txt_green}SUCCESS: bak-old.sh has been installed successfully${txt_0}
EOM
)"
bak-old.sh -h
exit 0
}
install_failure(){
echo -e "$(cat <<-EOM
${txt_bold}${txt_green}FAILUR: failed to install bak-old.sh :(${txt_0}
EOM
)"
exit 127
}
find_dler(){
for dler in ${!dlers[@]}; do
is_command $dler && downloader="${dlers[$dler]}"
[[ -n "$downloader" ]] && return
done
[[ -z "$downloader" ]] && err_no_downloader
}
find_dest_dir(){
local user_id=$(id -u)
local dirlist
if [[ user_id -eq 0 ]]; then
dirlist=(${r_dstdirs[@]})
elif [[ -d "$HOME" ]]; then
dirlist=(${u_dstdirs[@]})
elif [[ ! -d "$HOME" ]]; then
err_no_home_dir
else
err_unknown
fi
for dir in ${dirlist[@]}; do
if [[ "$PATH" =~ /*:${dir}* ]] || [[ "$PATH" =~ /*${dir}:* ]]; then
dest_dir="$dir"
fi
[[ -n "$dest_dir" ]] && return
done
[[ -z "$dest_dir" ]] && err_no_dest_in_path
}
download(){
$downloader $download_url
}
setup() {
# setup
# create temp dir for installation work
mkdir -p "$work_dir"
cd "$work_dir"
}
cleanup(){
# cleanup
cd "$HOME"
rm -rf "$work_dir"
exit ${1-0}
}
trap "cleanup 1" SIGHUP SIGINT SIGTERM ERR
install(){
setup
find_dler
find_dest_dir
download
chmod 755 "$tmp_file_path"
mv "$tmp_file_path" "${dest_dir}/"
is_command bak-old.sh && install_success || install_failure
}
### enable debugging if ###
${DEBUG+debug} ###
### $DEBUG is set ###
install