698 lines
16 KiB
Bash
Executable File
698 lines
16 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
#
|
|
# Common constants and functions used by the blackbox_* utilities.
|
|
#
|
|
|
|
# Usage:
|
|
#
|
|
# set -e
|
|
# source "${0%/*}/_blackbox_common.sh"
|
|
|
|
# Load additional useful functions
|
|
source "${0%/*}"/_stack_lib.sh
|
|
|
|
# Where are we?
|
|
: "${BLACKBOX_HOME:="$(cd "${0%/*}" ; pwd)"}" ;
|
|
|
|
# What are the candidates for the blackbox data directory?
|
|
declare -a BLACKBOXDATA_CANDIDATES
|
|
BLACKBOXDATA_CANDIDATES=(
|
|
'keyrings/live'
|
|
'.blackbox'
|
|
)
|
|
|
|
# If $EDITOR is not set, set it to "vi":
|
|
: "${EDITOR:=vi}" ;
|
|
|
|
# Allow overriding gpg command
|
|
: "${GPG:=gpg}" ;
|
|
|
|
function physical_directory_of() {
|
|
local d=$(dirname "$1")
|
|
local f=$(basename "$1")
|
|
(cd "$d" && echo "$(pwd -P | sed 's/\/$//')/$f" )
|
|
}
|
|
|
|
# Set REPOBASE to the top of the repository
|
|
# Set VCS_TYPE to 'git', 'hg', 'svn' or 'unknown'
|
|
if which >/dev/null 2>/dev/null git && git rev-parse --show-toplevel >/dev/null 2>&1 ; then
|
|
VCS_TYPE=git
|
|
REPOBASE=$(git rev-parse --show-toplevel)
|
|
elif [ -d ".svn" ] ; then
|
|
# Find topmost dir with .svn sub-dir
|
|
parent=""
|
|
grandparent="."
|
|
while [ -d "$grandparent/.svn" ]; do
|
|
parent=$grandparent
|
|
grandparent="$parent/.."
|
|
done
|
|
|
|
REPOBASE=$(cd "$parent" ; pwd)
|
|
VCS_TYPE=svn
|
|
elif which >/dev/null 2>/dev/null hg && hg root >/dev/null 2>&1 ; then
|
|
# NOTE: hg has to be tested last because it always "succeeds".
|
|
VCS_TYPE=hg
|
|
REPOBASE=$(hg root 2>/dev/null)
|
|
else
|
|
# We aren't in a repo at all. Assume the cwd is the root
|
|
# of the tree.
|
|
VCS_TYPE=unknown
|
|
REPOBASE="$(pwd)"
|
|
fi
|
|
export VCS_TYPE
|
|
export REPOBASE=$(physical_directory_of "$REPOBASE")
|
|
# FIXME: Verify this function by checking for .hg or .git
|
|
# after determining what we believe to be the answer.
|
|
|
|
if [[ -n "$BLACKBOX_REPOBASE" ]]; then
|
|
echo "Using custom repobase: $BLACKBOX_REPOBASE" >&2
|
|
export REPOBASE="$BLACKBOX_REPOBASE"
|
|
fi
|
|
|
|
if [ -z "$BLACKBOXDATA" ] ; then
|
|
BLACKBOXDATA="${BLACKBOXDATA_CANDIDATES[0]}"
|
|
for candidate in ${BLACKBOXDATA_CANDIDATES[@]} ; do
|
|
if [ -d "$REPOBASE/$candidate" ] ; then
|
|
BLACKBOXDATA="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
KEYRINGDIR="$REPOBASE/$BLACKBOXDATA"
|
|
BB_ADMINS_FILE="blackbox-admins.txt"
|
|
BB_ADMINS="${KEYRINGDIR}/${BB_ADMINS_FILE}"
|
|
BB_FILES_FILE="blackbox-files.txt"
|
|
BB_FILES="${KEYRINGDIR}/${BB_FILES_FILE}"
|
|
SECRING="${KEYRINGDIR}/secring.gpg"
|
|
: "${DECRYPT_UMASK:=0022}" ;
|
|
# : ${DECRYPT_UMASK:=o=} ;
|
|
|
|
# Checks if $1 is 0 bytes, and if $1/keyrings
|
|
# is a directory
|
|
function is_blackbox_repo() {
|
|
if [[ -n "$1" ]] && [[ -d "$1/keyrings" ]]; then
|
|
return 0 # Yep, its a repo
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Return error if not on cryptlist.
|
|
function is_on_cryptlist() {
|
|
# Assumes $1 does NOT have the .gpg extension
|
|
file_contains_line "$BB_FILES" "$(vcs_relative_path "$1")"
|
|
}
|
|
|
|
# Exit with error if a file exists.
|
|
function fail_if_exists() {
|
|
if [[ -f "$1" ]]; then
|
|
echo ERROR: "$1" exists. "$2" >&2
|
|
echo Exiting... >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Exit with error if a file is missing.
|
|
function fail_if_not_exists() {
|
|
if [[ ! -f "$1" ]]; then
|
|
echo ERROR: "$1" not found. "$2" >&2
|
|
echo Exiting... >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Exit we we aren't in a VCS repo.
|
|
function fail_if_not_in_repo() {
|
|
if [[ $VCS_TYPE = "unknown" ]]; then
|
|
echo "ERROR: This must be run in a VCS repo: git, hg, or svn." >&2
|
|
echo Exiting... >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Exit with error if filename is not registered on blackbox list.
|
|
function fail_if_not_on_cryptlist() {
|
|
# Assumes $1 does NOT have the .gpg extension
|
|
|
|
local name="$1"
|
|
|
|
if ! is_on_cryptlist "$name" ; then
|
|
echo "ERROR: $name not found in $BB_FILES" >&2
|
|
echo "PWD=$(/usr/bin/env pwd)" >&2
|
|
echo 'Exiting...' >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Exit with error if keychain contains secret keys.
|
|
function fail_if_keychain_has_secrets() {
|
|
if [[ -s ${SECRING} ]]; then
|
|
echo 'ERROR: The file' "$SECRING" 'should be empty.' >&2
|
|
echo 'Did someone accidentally add this private key to the ring?' >&2
|
|
echo 'Exiting...' >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function get_pubring_path() {
|
|
if [[ -f "${KEYRINGDIR}/pubring.gpg" ]]; then
|
|
echo "${KEYRINGDIR}/pubring.gpg"
|
|
else
|
|
echo "${KEYRINGDIR}/pubring.kbx"
|
|
fi
|
|
}
|
|
|
|
# Output the unencrypted filename.
|
|
function get_unencrypted_filename() {
|
|
echo "$(dirname "$1")/$(basename "$1" .gpg)" | sed -e 's#^\./##'
|
|
}
|
|
|
|
# Output the encrypted filename.
|
|
function get_encrypted_filename() {
|
|
echo "$(dirname "$1")/$(basename "$1" .gpg).gpg" | sed -e 's#^\./##'
|
|
}
|
|
|
|
# Prepare keychain for use.
|
|
function prepare_keychain() {
|
|
local keyringasc
|
|
echo '========== Importing keychain: START' >&2
|
|
# Works with gpg 2.0
|
|
#$GPG --import "$(get_pubring_path)" 2>&1 | egrep -v 'not changed$' >&2
|
|
# Works with gpg 2.0 and 2.1
|
|
# NB: We must export the keys to a format that can be imported.
|
|
make_self_deleting_tempfile keyringasc
|
|
export LANG="C.UTF-8"
|
|
|
|
#if gpg2 is installed next to gpg like on ubuntu 16
|
|
if [[ "$GPG" != "gpg2" ]]; then
|
|
$GPG --export --no-default-keyring --keyring "$(get_pubring_path)" >"$keyringasc"
|
|
$GPG --import "$keyringasc" 2>&1 | egrep -v 'not changed$' >&2
|
|
else
|
|
$GPG --keyring "$(get_pubring_path)" --export | $GPG --import
|
|
fi
|
|
|
|
echo '========== Importing keychain: DONE' >&2
|
|
}
|
|
|
|
# Add file to list of encrypted files.
|
|
function add_filename_to_cryptlist() {
|
|
# If the name is already on the list, this is a no-op.
|
|
# However no matter what the datestamp is updated.
|
|
|
|
# https://github.com/koalaman/shellcheck/wiki/SC2155
|
|
local name
|
|
name=$(vcs_relative_path "$1")
|
|
|
|
if file_contains_line "$BB_FILES" "$name" ; then
|
|
echo "========== File is registered. No need to add to list."
|
|
else
|
|
echo "========== Adding file to list."
|
|
touch "$BB_FILES"
|
|
sort -u -o "$BB_FILES" <(echo "$name") "$BB_FILES"
|
|
fi
|
|
}
|
|
|
|
# Removes a file from the list of encrypted files
|
|
function remove_filename_from_cryptlist() {
|
|
# If the name is not already on the list, this is a no-op.
|
|
|
|
# https://github.com/koalaman/shellcheck/wiki/SC2155
|
|
local name
|
|
name=$(vcs_relative_path "$1")
|
|
|
|
if ! file_contains_line "$BB_FILES" "$name" ; then
|
|
echo "========== File is not registered. No need to remove from list."
|
|
else
|
|
echo "========== Removing file from list."
|
|
remove_line "$BB_FILES" "$name"
|
|
fi
|
|
}
|
|
|
|
# Print out who the current BB ADMINS are:
|
|
function disclose_admins() {
|
|
echo "========== blackbox administrators are:"
|
|
cat "$BB_ADMINS"
|
|
}
|
|
|
|
# Encrypt file, overwriting .gpg if it exists.
|
|
function encrypt_file() {
|
|
local unencrypted
|
|
local encrypted
|
|
unencrypted="$1"
|
|
encrypted="$2"
|
|
|
|
echo "========== Encrypting: $unencrypted" >&2
|
|
$GPG --use-agent --yes --trust-model=always --encrypt -o "$encrypted" $(awk '{ print "-r" $1 }' < "$BB_ADMINS") "$unencrypted" >&2
|
|
echo '========== Encrypting: DONE' >&2
|
|
}
|
|
|
|
# Decrypt .gpg file, asking "yes/no" before overwriting unencrypted file.
|
|
function decrypt_file() {
|
|
local encrypted
|
|
local unencrypted
|
|
local old_umask
|
|
encrypted="$1"
|
|
unencrypted="$2"
|
|
|
|
echo "========== EXTRACTING $unencrypted" >&2
|
|
|
|
old_umask=$(umask)
|
|
umask "$DECRYPT_UMASK"
|
|
$GPG --use-agent -q --decrypt -o "$unencrypted" "$encrypted" >&2
|
|
umask "$old_umask"
|
|
}
|
|
|
|
# Decrypt .gpg file, overwriting unencrypted file if it exists.
|
|
function decrypt_file_overwrite() {
|
|
local encrypted
|
|
local unencrypted
|
|
local old_hash
|
|
local new_hash
|
|
local old_umask
|
|
encrypted="$1"
|
|
unencrypted="$2"
|
|
|
|
if [[ -f "$unencrypted" ]]; then
|
|
old_hash=$(md5sum_file "$unencrypted")
|
|
else
|
|
old_hash=unmatchable
|
|
fi
|
|
|
|
old_umask=$(umask)
|
|
umask "$DECRYPT_UMASK"
|
|
$GPG --use-agent --yes -q --decrypt -o "$unencrypted" "$encrypted" >&2
|
|
umask "$old_umask"
|
|
|
|
new_hash=$(md5sum_file "$unencrypted")
|
|
if [[ "$old_hash" != "$new_hash" ]]; then
|
|
echo "========== EXTRACTED $unencrypted" >&2
|
|
fi
|
|
}
|
|
|
|
# Shred a file. If shred binary does not exist, delete it.
|
|
function shred_file() {
|
|
local name
|
|
local CMD
|
|
local OPT
|
|
name="$1"
|
|
|
|
if which shred >/dev/null 2>/dev/null ; then
|
|
CMD=shred
|
|
OPT=-u
|
|
elif which srm >/dev/null 2>/dev/null ; then
|
|
#NOTE: srm by default uses 35-pass Gutmann algorithm
|
|
CMD=srm
|
|
OPT=-f
|
|
elif _F=$(mktemp); rm -P "${_F}" >/dev/null 2>/dev/null ; then
|
|
CMD=rm
|
|
OPT=-Pf
|
|
else
|
|
echo "shred_file: WARNING: No secure deletion utility (shred or srm) present; using insecure rm" >&2
|
|
CMD=rm
|
|
OPT=-f
|
|
fi
|
|
|
|
$CMD $OPT -- "$name"
|
|
}
|
|
|
|
# $1 is the name of a file that contains a list of files.
|
|
# For each filename, output the individual subdirectories
|
|
# leading up to that file. i.e. one one/two one/two/three
|
|
function enumerate_subdirs() {
|
|
local listfile
|
|
local dir
|
|
local filename
|
|
listfile="$1"
|
|
|
|
while read filename; do
|
|
dir=$(dirname "$filename")
|
|
while [[ $dir != '.' && $dir != '/' ]]; do
|
|
echo "$dir"
|
|
dir=$(dirname "$dir")
|
|
done
|
|
done <"$listfile" | sort -u
|
|
}
|
|
|
|
|
|
# chdir to the base of the repo.
|
|
function change_to_vcs_root() {
|
|
# if vcs_root not explicitly defined, use $REPOBASE
|
|
|
|
local rbase=${1:-$REPOBASE} # use $1 but if unset use $REPOBASE
|
|
|
|
cd "$rbase"
|
|
|
|
}
|
|
|
|
# $1 is a string pointing to a directory. Outputs a
|
|
# list of valid blackbox repos,relative to $1
|
|
function enumerate_blackbox_repos() {
|
|
if [[ -z "$1" ]]; then
|
|
echo "enumerate_blackbox_repos: ERROR: No Repo provided to Enumerate"
|
|
exit 1
|
|
fi
|
|
|
|
# https://github.com/koalaman/shellcheck/wiki/Sc2045
|
|
for dir in $1*/; do
|
|
if is_blackbox_repo "$dir"; then
|
|
echo "$dir"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Output the path of a file relative to the repo base
|
|
function vcs_relative_path() {
|
|
# Usage: vcs_relative_path file
|
|
local name="$1"
|
|
#python -c 'import os ; print(os.path.relpath("'"$(pwd -P)"'/'"$name"'", "'"$REPOBASE"'"))'
|
|
local p=$( printf "%s" "$( pwd -P )/${1}" | sed 's#//*#/#g' )
|
|
local name="${p#$REPOBASE}"
|
|
name=$( printf "%s" "$name" | sed 's#^/##g' | sed 's#/$##g' )
|
|
printf "%s" "$name"
|
|
}
|
|
|
|
# Removes a line from a text file
|
|
function remove_line() {
|
|
local tempfile
|
|
|
|
make_self_deleting_tempfile tempfile
|
|
|
|
# Ensure source file exists
|
|
touch "$1"
|
|
grep -Fsxv "$2" "$1" > "$tempfile" || true
|
|
|
|
# Using cat+rm instead of cp will preserve permissions/ownership
|
|
cat "$tempfile" > "$1"
|
|
}
|
|
|
|
# Determine if a file contains a given line
|
|
function file_contains_line() {
|
|
# $1: the file
|
|
# $2: the line
|
|
grep -xsqF "$2" "$1"
|
|
}
|
|
|
|
#
|
|
# Portability Section:
|
|
#
|
|
|
|
#
|
|
# Abstract the difference between Linux and Mac OS X:
|
|
#
|
|
|
|
function md5sum_file() {
|
|
# Portably generate the MD5 hash of file $1.
|
|
case $(uname -s) in
|
|
Darwin | FreeBSD )
|
|
md5 -r "$1" | awk '{ print $1 }'
|
|
;;
|
|
Linux | CYGWIN* | MINGW* )
|
|
md5sum "$1" | awk '{ print $1 }'
|
|
;;
|
|
* )
|
|
echo 'ERROR: Unknown OS. Exiting. (md5sum_file)'
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function cp_permissions() {
|
|
# Copy the perms of $1 onto $2 .. end.
|
|
case $(uname -s) in
|
|
Darwin )
|
|
chmod $( stat -f '%p' "$1" ) "${@:2}"
|
|
;;
|
|
FreeBSD )
|
|
chmod $( stat -f '%p' "$1" | sed -e "s/^100//" ) "${@:2}"
|
|
;;
|
|
Linux | CYGWIN* | MINGW* )
|
|
if [[ -e /etc/alpine-release ]]; then
|
|
chmod $( stat -c '%a' "$1" ) "${@:2}"
|
|
else
|
|
chmod --reference "$1" "${@:2}"
|
|
fi
|
|
;;
|
|
* )
|
|
echo 'ERROR: Unknown OS. Exiting. (cp_permissions)'
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
#
|
|
# Abstract the difference between git and hg:
|
|
#
|
|
|
|
# Is this file in the current repo?
|
|
function is_in_vcs() {
|
|
is_in_$VCS_TYPE "$@"
|
|
}
|
|
# Mercurial
|
|
function is_in_hg() {
|
|
local filename
|
|
filename="$1"
|
|
|
|
if hg locate "$filename" ; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi
|
|
}
|
|
# Git:
|
|
function is_in_git() {
|
|
local filename
|
|
filename="$1"
|
|
|
|
if git ls-files --error-unmatch >/dev/null 2>&1 -- "$filename" ; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi
|
|
}
|
|
# Subversion
|
|
function is_in_svn() {
|
|
local filename
|
|
filename="$1"
|
|
|
|
if svn list "$filename" ; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi
|
|
}
|
|
# Perforce
|
|
function is_in_p4() {
|
|
local filename
|
|
filename="$1"
|
|
|
|
if p4 list "$filename" ; then
|
|
echo true
|
|
else
|
|
echo false
|
|
fi
|
|
}
|
|
# No repo
|
|
function is_in_unknown() {
|
|
echo true
|
|
}
|
|
|
|
|
|
# Add a file to the repo (but don't commit it).
|
|
function vcs_add() {
|
|
vcs_add_$VCS_TYPE "$@"
|
|
}
|
|
# Mercurial
|
|
function vcs_add_hg() {
|
|
hg add "$@"
|
|
}
|
|
# Git
|
|
function vcs_add_git() {
|
|
git add "$@"
|
|
}
|
|
# Subversion
|
|
function vcs_add_svn() {
|
|
svn add --parents "$@"
|
|
}
|
|
# Perfoce
|
|
function vcs_add_p4() {
|
|
p4 add "$@"
|
|
}
|
|
# No repo
|
|
function vcs_add_unknown() {
|
|
:
|
|
}
|
|
|
|
|
|
# Commit a file to the repo
|
|
function vcs_commit() {
|
|
vcs_commit_$VCS_TYPE "$@"
|
|
}
|
|
# Mercurial
|
|
function vcs_commit_hg() {
|
|
hg commit -m "$@"
|
|
}
|
|
# Git
|
|
function vcs_commit_git() {
|
|
git commit -m "$@"
|
|
}
|
|
# Subversion
|
|
function vcs_commit_svn() {
|
|
svn commit -m "$@"
|
|
}
|
|
# Perforce
|
|
function vcs_commit_p4() {
|
|
p4 submit -d "$@"
|
|
}
|
|
# No repo
|
|
function vcs_commit_unknown() {
|
|
:
|
|
}
|
|
|
|
|
|
# Remove file from repo, even if it was deleted locally already.
|
|
# If it doesn't exist yet in the repo, it should be a no-op.
|
|
function vcs_remove() {
|
|
vcs_remove_$VCS_TYPE "$@"
|
|
}
|
|
# Mercurial
|
|
function vcs_remove_hg() {
|
|
hg rm -A -- "$@"
|
|
}
|
|
# Git
|
|
function vcs_remove_git() {
|
|
git rm --ignore-unmatch -f -- "$@"
|
|
}
|
|
# Subversion
|
|
function vcs_remove_svn() {
|
|
svn delete "$@"
|
|
}
|
|
# Perforce
|
|
function vcs_remove_p4() {
|
|
p4 delete "$@"
|
|
}
|
|
# No repo
|
|
function vcs_remove_unknown() {
|
|
:
|
|
}
|
|
|
|
# Get a path for the ignore file if possible in current vcs
|
|
function vcs_ignore_file_path() {
|
|
vcs_ignore_file_path_$VCS_TYPE
|
|
}
|
|
# Mercurial
|
|
function vcs_ignore_file_path_hg() {
|
|
echo "$REPOBASE/.hgignore"
|
|
}
|
|
# Git
|
|
function vcs_ignore_file_path_git() {
|
|
echo "$REPOBASE/.gitignore"
|
|
}
|
|
|
|
|
|
# Ignore a file in a repo. If it was already ignored, this is a no-op.
|
|
function vcs_ignore() {
|
|
local file
|
|
for file in "$@"; do
|
|
vcs_ignore_$VCS_TYPE "$file"
|
|
done
|
|
}
|
|
# Mercurial
|
|
function vcs_ignore_hg() {
|
|
vcs_ignore_generic_file "$(vcs_ignore_file_path)" "$file"
|
|
}
|
|
# Git
|
|
function vcs_ignore_git() {
|
|
vcs_ignore_generic_file "$(vcs_ignore_file_path)" "$file"
|
|
git add "$REPOBASE/.gitignore"
|
|
}
|
|
# Subversion
|
|
function vcs_ignore_svn() {
|
|
svn propset svn:ignore "$file" "$(vcs_relative_path)"
|
|
}
|
|
# Perforce
|
|
function vcs_ignore_p4() {
|
|
:
|
|
}
|
|
# No repo
|
|
function vcs_ignore_unknown() {
|
|
:
|
|
}
|
|
# Generic - add line to file
|
|
function vcs_ignore_generic_file() {
|
|
local file
|
|
file="$(vcs_relative_path "$2")"
|
|
file="${file/\$\//}"
|
|
file="$(echo "/$file" | sed 's/\([\*\?]\)/\\\1/g')"
|
|
if ! file_contains_line "$1" "$file" ; then
|
|
echo "$file" >> "$1"
|
|
vcs_add "$1"
|
|
fi
|
|
}
|
|
|
|
|
|
# Notice (un-ignore) a file in a repo. If it was not ignored, this is
|
|
# a no-op
|
|
function vcs_notice() {
|
|
local file
|
|
for file in "$@"; do
|
|
vcs_notice_$VCS_TYPE "$file"
|
|
done
|
|
}
|
|
# Mercurial
|
|
function vcs_notice_hg() {
|
|
vcs_notice_generic_file "$REPOBASE/.hgignore" "$file"
|
|
}
|
|
# Git
|
|
function vcs_notice_git() {
|
|
vcs_notice_generic_file "$REPOBASE/.gitignore" "$file"
|
|
git add "$REPOBASE/.gitignore"
|
|
}
|
|
# Subversion
|
|
function vcs_notice_svn() {
|
|
svn propdel svn:ignore "$(vcs_relative_path "$file")"
|
|
}
|
|
# Perforce
|
|
function vcs_notice_p4() {
|
|
:
|
|
}
|
|
# No repo
|
|
function vcs_notice_unknown() {
|
|
:
|
|
}
|
|
# Generic - remove line to file
|
|
function vcs_notice_generic_file() {
|
|
local file
|
|
file="$(vcs_relative_path "$2")"
|
|
file="${file/\$\//}"
|
|
file="$(echo "/$file" | sed 's/\([\*\?]\)/\\\1/g')"
|
|
if file_contains_line "$1" "$file" ; then
|
|
remove_line "$1" "$file"
|
|
vcs_add "$1"
|
|
fi
|
|
if file_contains_line "$1" "${file:1}" ; then
|
|
echo "WARNING: Found a non-absolute ignore match in $1"
|
|
echo "WARNING: Confirm the pattern is intended to only exclude $file"
|
|
echo "WARNING: If so, manually update the ignore file"
|
|
fi
|
|
}
|
|
|
|
function gpg_agent_version_check() {
|
|
if ! hash 'gpg-agent' &> /dev/null; then
|
|
return 1
|
|
fi
|
|
local gpg_agent_version=$(gpg-agent --version | head -1 | awk '{ print $3 }' | tr -d '\n')
|
|
semverLT $gpg_agent_version "2.1.0"
|
|
}
|
|
|
|
function gpg_agent_notice() {
|
|
if [[ $(gpg_agent_version_check) == '0' && -z $GPG_AGENT_INFO ]];then
|
|
echo 'WARNING: You probably want to run gpg-agent as'
|
|
echo 'you will be asked for your passphrase many times.'
|
|
echo 'Example: $ eval $(gpg-agent --daemon)'
|
|
read -r -p 'Press CTRL-C now to stop. ENTER to continue: '
|
|
fi
|
|
}
|