Skip to content

Commit f495845

Browse files
committed
Create public lib/existence module
Closes #148. This is the last bit of functionality migrated from https://github.com/mbland/certbot-webroot-setup, providing a standard means of checking for file and command existence and reporting errors.
1 parent dff7f1b commit f495845

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

lib/existence

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#! /usr/bin/env bash
2+
#
3+
# Checks for the existence and accessibility of files and commands
4+
#
5+
# Many of the actual checks are Bash builtins, but these functions provide
6+
# standard error messages to make reporting missing or inaccessible files
7+
# easier. They eliminate a lot of boilerplate from scripts that check for
8+
# initial conditions before processing files and executing commands.
9+
#
10+
# Exports:
11+
# @go.check_file_exists
12+
# Checks whether a file exists and prints an error if not
13+
#
14+
# @go.check_file_readable
15+
# Checks whether a file exists and is readable, and prints an error if not
16+
#
17+
# @go.pick_command
18+
# Selects the first installed command from a list of possible commands/names
19+
#
20+
# @go.check_command_installed
21+
# Checks whether a required command is installed on the system
22+
23+
# Checks whether a file exists and prints an error if not.
24+
#
25+
# Arguments:
26+
# label: Label describing the type of file
27+
# file_path: Path to the file to check
28+
@go.check_file_exists() {
29+
if [[ ! -e "$2" ]]; then
30+
@go.printf "%s doesn't exist: %s\n" "$1" "$2" >&2
31+
return 1
32+
fi
33+
}
34+
35+
# Checks whether a file exists and is readable, and prints an error if not.
36+
#
37+
# Arguments:
38+
# label: Label describing the type of file
39+
# file_path: Path to the file to check
40+
@go.check_file_readable() {
41+
if [[ ! -r "$2" ]]; then
42+
@go.printf "%s doesn't exist or isn't readable: %s\n" "$1" "$2" >&2
43+
return 1
44+
fi
45+
}
46+
47+
# Selects the first installed command from a list of possible commands/names.
48+
#
49+
# This may be used to select from a number of different commands, or to select
50+
# the correct name for a command whose name may differ from system to system.
51+
#
52+
# Arguments:
53+
# result_var: Name of the caller-defined variable for the resulting command
54+
# ...: List of commands from which to select the first available
55+
#
56+
# Returns:
57+
# Zero if any of the commands are installed, nonzero otherwise
58+
@go.pick_command() {
59+
local __go_pick_cmd
60+
for __go_pick_cmd in "${@:2}"; do
61+
if command -v "$__go_pick_cmd" >/dev/null; then
62+
printf -v "$1" -- '%s' "$__go_pick_cmd"
63+
return
64+
fi
65+
done
66+
@go.printf 'None of the following commands were found on the system:\n' >&2
67+
printf ' %s\n' "${@:2}" >&2
68+
return 1
69+
}
70+
71+
# Checks whether a required command is installed on the system.
72+
#
73+
# If the command isn't installed, prints an error message to standard error
74+
# instructing the user to install the required command.
75+
#
76+
# Arguments:
77+
# cmd_name: Name of the command that must be required on the system
78+
# err_msg: Name of the command or other info to use in the error message
79+
#
80+
# Returns:
81+
# Zero if the command is installed, nonzero otherwise
82+
@go.check_command_installed() {
83+
if ! command -v "$1" >/dev/null; then
84+
@go.printf 'Please install %s on your system and try again.\n' \
85+
"${2:-$1}" >&2
86+
return 1
87+
fi
88+
}

tests/existence.bats

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#! /usr/bin/env bats
2+
3+
load environment
4+
5+
setup() {
6+
test_filter
7+
}
8+
9+
teardown() {
10+
@go.remove_test_go_rootdir
11+
}
12+
13+
@test "$SUITE: check_file_exists" {
14+
@go.create_test_go_script '. "$_GO_USE_MODULES" "existence"' \
15+
'@go.check_file_exists "$@"'
16+
run "$TEST_GO_SCRIPT" 'Foo config' "$TEST_GO_ROOTDIR/foo"
17+
assert_failure "Foo config doesn't exist: $TEST_GO_ROOTDIR/foo"
18+
19+
printf '' >"$TEST_GO_ROOTDIR/foo"
20+
run "$TEST_GO_SCRIPT" 'Foo config' "$TEST_GO_ROOTDIR/foo"
21+
assert_success ''
22+
}
23+
24+
@test "$SUITE: check_file_readable" {
25+
@go.create_test_go_script '. "$_GO_USE_MODULES" "existence"' \
26+
'@go.check_file_readable "$@"'
27+
run "$TEST_GO_SCRIPT" 'Foo config' "$TEST_GO_ROOTDIR/foo"
28+
assert_failure \
29+
"Foo config doesn't exist or isn't readable: $TEST_GO_ROOTDIR/foo"
30+
31+
printf '' >"$TEST_GO_ROOTDIR/foo"
32+
run "$TEST_GO_SCRIPT" 'Foo config' "$TEST_GO_ROOTDIR/foo"
33+
assert_success ''
34+
}
35+
36+
@test "$SUITE: check_file_readable fails if no read permission" {
37+
skip_if_cannot_trigger_file_permission_failure
38+
@go.create_test_go_script '. "$_GO_USE_MODULES" "existence"' \
39+
'@go.check_file_readable "$@"'
40+
printf '' >"$TEST_GO_ROOTDIR/foo"
41+
chmod ugo-r "$TEST_GO_ROOTDIR/foo"
42+
43+
run "$TEST_GO_SCRIPT" 'Foo config' "$TEST_GO_ROOTDIR/foo"
44+
assert_failure \
45+
"Foo config doesn't exist or isn't readable: $TEST_GO_ROOTDIR/foo"
46+
}
47+
48+
@test "$SUITE: pick_command" {
49+
@go.create_test_go_script '. "$_GO_USE_MODULES" "existence"' \
50+
'declare selected_cmd' \
51+
'if @go.pick_command "selected_cmd" "$@"; then' \
52+
' printf "%s\n" "$selected_cmd"' \
53+
'else' \
54+
' exit 1' \
55+
'fi'
56+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foo' 'bar' 'baz'
57+
assert_failure "None of the following commands were found on the system:" \
58+
' foo' \
59+
' bar' \
60+
' baz'
61+
62+
stub_program_in_path 'baz'
63+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foo' 'bar' 'baz'
64+
assert_success 'baz'
65+
66+
stub_program_in_path 'bar'
67+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foo' 'bar' 'baz'
68+
assert_success 'bar'
69+
70+
stub_program_in_path 'foo'
71+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foo' 'bar' 'baz'
72+
assert_success 'foo'
73+
}
74+
75+
@test "$SUITE: check_command_installed" {
76+
@go.create_test_go_script '. "$_GO_USE_MODULES" "existence"' \
77+
'@go.check_command_installed "$@"'
78+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foobar'
79+
assert_failure 'Please install foobar on your system and try again.'
80+
81+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foobar' 'Foo Bar'
82+
assert_failure 'Please install Foo Bar on your system and try again.'
83+
84+
stub_program_in_path 'foobar'
85+
PATH="$BATS_TEST_BINDIR:/bin" run "$TEST_GO_SCRIPT" 'foobar' 'Foo Bar'
86+
assert_success ''
87+
}

0 commit comments

Comments
 (0)