diff --git a/README.md b/README.md index a8bc55a..c4b994f 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ A package for Arch users is also [available in the AUR](https://aur.archlinux.or Usage: hosts [] hosts add [] + hosts backups [create | [compare | delete | restore | show] ] hosts block ... hosts disable ( | | ) hosts disabled @@ -109,6 +110,31 @@ Description: Add a given IP address and hostname pair, along with an optional comment. ``` +### `hosts backups` + +```text +Usage: + hosts backups + hosts backups create + hosts backups compare + hosts backups delete + hosts backups restore --skip-backup + hosts backups show + +Subcommands: + backups List available backups. + backups create Create a new backup of the hosts file. + backups compare Compare a backup file with the current hosts file. + The diff tool configured for git will be used if + one is set. + backups delete Delete the specified backup. + backups restore Replace the contents of the hosts file with a + specified backup. The hosts file is automatically + backed up before being overwritten unless the + '--skip-backup' flag is specified. + backups show Show the contents of the specified backup file. +``` + ### `hosts block` ```text diff --git a/hosts b/hosts index a76b4fa..a96f2f3 100755 --- a/hosts +++ b/hosts @@ -611,6 +611,7 @@ Version: ${_VERSION} Usage: ${_ME} [] ${_ME} add [] + ${_ME} backups [create | [compare | delete | restore | show] ] ${_ME} block ... ${_ME} disable ( | | ) ${_ME} disabled @@ -634,8 +635,6 @@ Options: Help: ${_ME} help [] - -$(commands) HEREDOC fi } @@ -750,6 +749,148 @@ add() { fi } +# --------------------------------------------------------------------- backups + +desc "backups" < + ${_ME} backups delete + ${_ME} backups restore --skip-backup + ${_ME} backups show + +Subcommands: + backups List available backups. + backups create Create a new backup of the hosts file. + backups compare Compare a backup file with the current hosts file. + The diff tool configured for git will be used if + one is set. + backups delete Delete the specified backup. + backups restore Replace the contents of the hosts file with a + specified backup. The hosts file is automatically + backed up before being overwritten unless the + '--skip-backup' flag is specified. + backups show Show the contents of the specified backup file. +HEREDOC +backups() { + local _subcommand="${1:-}" + shift + + local _hosts_dirname + _hosts_dirname="$(dirname "${HOSTS_PATH}")" + + case "${_subcommand}" in + create) + _verify_write_permissions "$@" + + local _timestamp + _timestamp="$(date +"%Y%m%d%H%M%S")" + + cp "${HOSTS_PATH}" "${HOSTS_PATH}--backup-${_timestamp}" && \ + printf "Backed up to %s--backup-%s\n" "${HOSTS_PATH}" "${_timestamp}" + ;; + compare) + if [[ -z "${1:-}" ]] + then + "$_ME" help backups + exit 1 + elif [[ ! -e "${_hosts_dirname}/${1}" ]] + then + printf "Backup not found: %s\n" "${1:-}" + exit 1 + fi + + local _difftool="diff" + if command -v git &>/dev/null + then + _difftool="$(git config --get merge.tool)" + fi + + "${_difftool}" "${HOSTS_PATH}" "${_hosts_dirname}/${1}" + ;; + delete) + if [[ -z "${1:-}" ]] + then + "$_ME" help backups + exit 1 + fi + + _verify_write_permissions "$@" + + if [[ "${HOSTS_PATH}" != "${_hosts_dirname}/${1:-}" ]] && + [[ -e "${_hosts_dirname}/${1:-}" ]] + then + rm "${_hosts_dirname}/${1:-}" && + printf "Backup deleted: %s\n" "${_hosts_dirname}/${1:-}" + else + printf "Backup not found: %s\n" "${1:-}" + exit 1 + fi + ;; + restore) + if [[ -z "${1:-}" ]] + then + "$_ME" help backups + exit 1 + elif [[ ! -e "${_hosts_dirname}/${1}" ]] + then + printf "Backup not found: %s\n" "${1:-}" + exit 1 + fi + + _verify_write_permissions "$@" + + if [[ "${2:-}" != "--skip-backup" ]] + then + "${_ME}" backups create + fi + + cat "${_hosts_dirname}/${1}" > "${HOSTS_PATH}" && + printf "Restored from backup: %s\n" "${1}" + ;; + show) + if [[ -z "${1:-}" ]] + then + "$_ME" help backups + exit 1 + elif [[ ! -e "${_hosts_dirname}/${1}" ]] + then + printf "Backup not found: %s\n" "${1:-}" + exit 1 + fi + + less "${_hosts_dirname}/${1:-}" + ;; + *) + local _filenames=() + + set +f + for __filename in $(cd "${_hosts_dirname}" && ls -1 hosts* 2> /dev/null) + do + if [[ "${__filename:-}" != "hosts" ]] && \ + [[ ! "${__filename:-}" =~ ^hosts_test..{6}$ ]] + then + _filenames+=("${__filename:-}") + fi + done + set -f + + if ((${#_filenames[@]})) + then + for __filename in "${_filenames[@]:-}" + do + printf "%s\n" "${__filename}" + done + else + printf \ + "No backups found. Create a new backup:\n %s backups create\n" \ + "${_ME}" + fi + ;; + esac +} + # ----------------------------------------------------------------------- block desc "block" < "${_HOSTS_TEMP_PATH}" export HOSTS_PATH="${_HOSTS_TEMP_PATH}" @@ -24,7 +25,7 @@ teardown() { [[ -e "${_HOSTS_TEMP_PATH}" ]] && [[ "${_HOSTS_TEMP_PATH}" =~ ^/tmp/hosts_test ]] then - rm "${_HOSTS_TEMP_PATH}" + rm -f "${_HOSTS_TEMP_DIR}"/hosts_test.* fi }