bashly 0.8.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -0
  3. data/bin/bashly +2 -2
  4. data/lib/bashly/cli.rb +2 -3
  5. data/lib/bashly/commands/add.rb +74 -50
  6. data/lib/bashly/commands/base.rb +4 -3
  7. data/lib/bashly/commands/generate.rb +41 -35
  8. data/lib/bashly/commands/init.rb +10 -9
  9. data/lib/bashly/commands/preview.rb +4 -4
  10. data/lib/bashly/commands/validate.rb +8 -7
  11. data/lib/bashly/concerns/asset_helper.rb +1 -1
  12. data/lib/bashly/concerns/completions.rb +24 -15
  13. data/lib/bashly/concerns/renderable.rb +5 -5
  14. data/lib/bashly/concerns/validation_helpers.rb +20 -12
  15. data/lib/bashly/config.rb +1 -1
  16. data/lib/bashly/config_validator.rb +47 -23
  17. data/lib/bashly/deprecation.rb +9 -7
  18. data/lib/bashly/exceptions.rb +1 -1
  19. data/lib/bashly/extensions/array.rb +4 -4
  20. data/lib/bashly/extensions/file.rb +3 -3
  21. data/lib/bashly/extensions/string.rb +6 -6
  22. data/lib/bashly/libraries/base.rb +11 -1
  23. data/lib/bashly/libraries/completions_function.rb +9 -10
  24. data/lib/bashly/libraries/completions_script.rb +7 -8
  25. data/lib/bashly/libraries/completions_yaml.rb +7 -8
  26. data/lib/bashly/libraries/help.rb +36 -0
  27. data/lib/bashly/libraries.yml +3 -1
  28. data/lib/bashly/library.rb +7 -5
  29. data/lib/bashly/message_strings.rb +1 -1
  30. data/lib/bashly/refinements/compose_refinements.rb +2 -2
  31. data/lib/bashly/script/argument.rb +1 -1
  32. data/lib/bashly/script/base.rb +3 -2
  33. data/lib/bashly/script/catch_all.rb +6 -4
  34. data/lib/bashly/script/command.rb +51 -51
  35. data/lib/bashly/script/environment_variable.rb +5 -5
  36. data/lib/bashly/script/flag.rb +7 -7
  37. data/lib/bashly/script/wrapper.rb +5 -4
  38. data/lib/bashly/settings.rb +4 -5
  39. data/lib/bashly/templates/help/help_command.sh +30 -0
  40. data/lib/bashly/templates/lib/colors.sh +2 -2
  41. data/lib/bashly/templates/lib/config.sh +10 -10
  42. data/lib/bashly/templates/lib/yaml.sh +9 -9
  43. data/lib/bashly/templates/test/approvals.bash +36 -12
  44. data/lib/bashly/templates/test/approve +14 -9
  45. data/lib/bashly/version.rb +2 -2
  46. data/lib/bashly/views/command/command_fallback.gtx +2 -2
  47. data/lib/bashly/views/command/command_filter.gtx +9 -9
  48. data/lib/bashly/views/command/dependencies_filter.gtx +7 -2
  49. data/lib/bashly/views/command/fixed_flags_filter.gtx +18 -12
  50. data/lib/bashly/views/command/inspect_args.gtx +2 -2
  51. data/lib/bashly/views/command/normalize_input.gtx +1 -1
  52. data/lib/bashly/views/command/parse_requirements_while.gtx +11 -11
  53. data/lib/bashly/views/command/run.gtx +14 -13
  54. data/lib/bashly/views/command/usage_environment_variables.gtx +1 -1
  55. data/lib/bashly/views/flag/case.gtx +1 -1
  56. data/lib/bashly/views/flag/case_no_arg.gtx +1 -1
  57. metadata +10 -8
  58. data/lib/bashly/libraries/completions.rb +0 -14
@@ -12,7 +12,8 @@ module Bashly
12
12
  end
13
13
 
14
14
  def initialize(options)
15
- raise Error, "Invalid options provided" unless options.respond_to? :keys
15
+ raise Error, 'Invalid options provided' unless options.respond_to? :keys
16
+
16
17
  @options = options
17
18
  end
18
19
 
@@ -21,7 +22,7 @@ module Bashly
21
22
  end
22
23
 
23
24
  def summary
24
- help.empty? ? "" : help.split("\n").first
25
+ help.empty? ? '' : help.split("\n").first
25
26
  end
26
27
 
27
28
  def help
@@ -18,12 +18,15 @@ module Bashly
18
18
  {}
19
19
  end
20
20
 
21
- new **options
21
+ new(**options)
22
22
  end
23
23
  end
24
24
 
25
25
  def initialize(label: nil, help: nil, required: false, enabled: true)
26
- @label, @help, @required, @enabled = label, help, required, enabled
26
+ @label = label
27
+ @help = help
28
+ @required = required
29
+ @enabled = enabled
27
30
  end
28
31
 
29
32
  def enabled?
@@ -44,10 +47,9 @@ module Bashly
44
47
 
45
48
  def usage_string
46
49
  return nil unless enabled?
50
+
47
51
  required? ? label : "[#{label}]"
48
52
  end
49
-
50
53
  end
51
54
  end
52
55
  end
53
-
@@ -26,7 +26,7 @@ module Bashly
26
26
  # by space. For example, for a command like "docker container run"
27
27
  # the action name is "container run".
28
28
  def action_name
29
- parents.any? ? (parents[1..-1] + [name]).join(' ') : "root"
29
+ parents.any? ? (parents[1..] + [name]).join(' ') : 'root'
30
30
  end
31
31
 
32
32
  # Returns all the possible aliases for this command
@@ -34,28 +34,20 @@ module Bashly
34
34
  [name] + alt
35
35
  end
36
36
 
37
- # Returns an array of all full names (including aliases and aliases of
38
- # parents)
39
- def all_full_names
40
- if parent_command
41
- parent_command.all_full_names.product(aliases).map { |a| a.join ' ' }
42
- else
43
- aliases
44
- end
45
- end
46
-
47
37
  # Returns an array of alternative aliases if any
48
38
  def alt
49
39
  # DEPRECATION 0.8.0
50
40
  options['alias'] ||= options['short']
51
- return [] unless options["alias"]
41
+ return [] unless options['alias']
42
+
52
43
  options['alias'].is_a?(String) ? [options['alias']] : options['alias']
53
44
  end
54
45
 
55
46
  # Returns an array of Arguments
56
47
  def args
57
- return [] unless options["args"]
58
- options["args"].map do |options|
48
+ return [] unless options['args']
49
+
50
+ options['args'].map do |options|
59
51
  Argument.new options
60
52
  end
61
53
  end
@@ -85,8 +77,8 @@ module Bashly
85
77
 
86
78
  command.public_commands.each do |subcommand|
87
79
  result[command.group_string]["#{command.name} #{subcommand.name}"] = {
88
- summary: subcommand.summary_string,
89
- help_only: command.expose != 'always'
80
+ summary: subcommand.summary_string,
81
+ help_only: command.expose != 'always',
90
82
  }
91
83
  end
92
84
  end
@@ -96,13 +88,14 @@ module Bashly
96
88
 
97
89
  # Returns only the names of the Commands
98
90
  def command_names
99
- commands.map &:name
91
+ commands.map(&:name)
100
92
  end
101
93
 
102
94
  # Returns an array of the Commands
103
95
  def commands
104
- return [] unless options["commands"]
105
- options["commands"].map do |options|
96
+ return [] unless options['commands']
97
+
98
+ options['commands'].map do |options|
106
99
  result = Command.new options
107
100
  result.parents = parents + [name]
108
101
  result.parent_command = self
@@ -126,42 +119,51 @@ module Bashly
126
119
  # If any of this command's subcommands has the default option set to
127
120
  # true, this default command will be returned, nil otherwise.
128
121
  def default_command
129
- commands.find { |c| c.default }
122
+ commands.find(&:default)
130
123
  end
131
124
 
132
125
  # Returns an array of all the default Args
133
126
  def default_args
134
- args.select &:default
127
+ args.select(&:default)
135
128
  end
136
129
 
137
130
  # Returns an array of all the default Environment Variables
138
131
  def default_environment_variables
139
- environment_variables.select &:default
132
+ environment_variables.select(&:default)
140
133
  end
141
134
 
142
135
  # Returns an array of all the default Flags
143
136
  def default_flags
144
- flags.select &:default
137
+ flags.select(&:default)
145
138
  end
146
139
 
147
140
  # Returns an array of EnvironmentVariables
148
141
  def environment_variables
149
- return [] unless options["environment_variables"]
150
- options["environment_variables"].map do |options|
142
+ return [] unless options['environment_variables']
143
+
144
+ options['environment_variables'].map do |options|
151
145
  EnvironmentVariable.new options
152
146
  end
153
147
  end
154
148
 
149
+ # Returns an array of examples
150
+ def examples
151
+ return nil unless options['examples']
152
+
153
+ options['examples'].is_a?(Array) ? options['examples'] : [options['examples']]
154
+ end
155
+
155
156
  # Returns the bash filename that is expected to hold the user code
156
157
  # for this command
157
158
  def filename
158
- options["filename"] || "#{action_name.to_underscore}_command.sh"
159
+ options['filename'] || "#{action_name.to_underscore}_command.sh"
159
160
  end
160
161
 
161
162
  # Returns an array of Flags
162
163
  def flags
163
- return [] unless options["flags"]
164
- options["flags"].map do |options|
164
+ return [] unless options['flags']
165
+
166
+ options['flags'].map do |options|
165
167
  Flag.new options
166
168
  end
167
169
  end
@@ -186,7 +188,7 @@ module Bashly
186
188
  # Returns the string for the group caption
187
189
  def group_string
188
190
  if group
189
- strings[:group] % { group: group }
191
+ strings[:group] % { group: group }
190
192
  else
191
193
  strings[:commands]
192
194
  end
@@ -194,18 +196,17 @@ module Bashly
194
196
 
195
197
  # Returns a mode identifier
196
198
  def mode
197
- @mode ||= begin
198
- if global_flags? then :global_flags
199
- elsif commands.any? then :commands
200
- elsif args.any? and flags.any? then :args_and_flags
201
- elsif args.any? then :args
202
- elsif flags.any? then :flags
203
- else :empty
204
- end
199
+ @mode ||= if global_flags? then :global_flags
200
+ elsif commands.any? then :commands
201
+ elsif args.any? && flags.any? then :args_and_flags
202
+ elsif args.any? then :args
203
+ elsif flags.any? then :flags
204
+ else
205
+ :empty
205
206
  end
206
207
  end
207
208
 
208
- # Returns an array of all parents. For example, the command
209
+ # Returns an array of all parents. For example, the command
209
210
  # "docker container run" will have [docker, container] as its parents
210
211
  def parents
211
212
  @parents ||= []
@@ -213,7 +214,7 @@ module Bashly
213
214
 
214
215
  # Returns only commands that are not private
215
216
  def public_commands
216
- commands.reject &:private
217
+ commands.reject(&:private)
217
218
  end
218
219
 
219
220
  # Returns true if one of the args is repeatable
@@ -223,17 +224,17 @@ module Bashly
223
224
 
224
225
  # Returns an array of all the required Arguments
225
226
  def required_args
226
- args.select &:required
227
+ args.select(&:required)
227
228
  end
228
229
 
229
230
  # Returns an array of all the required EnvironmentVariables
230
231
  def required_environment_variables
231
- environment_variables.select &:required
232
+ environment_variables.select(&:required)
232
233
  end
233
234
 
234
235
  # Returns an array of all the required Flags
235
236
  def required_flags
236
- flags.select &:required
237
+ flags.select(&:required)
237
238
  end
238
239
 
239
240
  # Returns true if this is the root command (no parents)
@@ -260,21 +261,20 @@ module Bashly
260
261
  result = [full_name]
261
262
 
262
263
  result.push case mode
263
- when :global_flags then ["[OPTIONS]", "COMMAND"]
264
- when :commands then ["COMMAND"]
265
- when :args_and_flags then usage_string_args + ["[OPTIONS]"]
264
+ when :global_flags then ['[OPTIONS]', 'COMMAND']
265
+ when :commands then ['COMMAND']
266
+ when :args_and_flags then usage_string_args + ['[OPTIONS]']
266
267
  when :args then usage_string_args
267
- when :flags then ["[OPTIONS]"]
268
- else nil
268
+ when :flags then ['[OPTIONS]']
269
269
  end
270
270
 
271
271
  result.push catch_all.usage_string if catch_all.enabled? && commands.empty?
272
- result.compact.join " "
272
+ result.compact.join ' '
273
273
  end
274
274
 
275
275
  # Returns an array of args usage_string for the command's usage_string
276
276
  def usage_string_args
277
- args.map { |arg| arg.usage_string }
277
+ args.map(&:usage_string)
278
278
  end
279
279
 
280
280
  # Returns an array of files to include as is inside the script
@@ -286,12 +286,12 @@ module Bashly
286
286
 
287
287
  # Returns an array of all the args with a whitelist
288
288
  def whitelisted_args
289
- args.select &:allowed
289
+ args.select(&:allowed)
290
290
  end
291
291
 
292
292
  # Returns an array of all the flags with a whitelist arg
293
293
  def whitelisted_flags
294
- flags.select &:allowed
294
+ flags.select(&:allowed)
295
295
  end
296
296
  end
297
297
  end
@@ -3,15 +3,15 @@ module Bashly
3
3
  class EnvironmentVariable < Base
4
4
  class << self
5
5
  def option_keys
6
- @option_keys ||= %i[default help name required]
6
+ @option_keys ||= %i[default help name required private]
7
7
  end
8
8
  end
9
-
9
+
10
10
  def usage_string(extended: false)
11
11
  result = [name.upcase]
12
- result << strings[:required] if required and extended
13
- result.join " "
12
+ result << strings[:required] if required && extended
13
+ result.join ' '
14
14
  end
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -11,9 +11,9 @@ module Bashly
11
11
  ]
12
12
  end
13
13
  end
14
-
14
+
15
15
  def aliases
16
- if long and short
16
+ if long && short
17
17
  [long, short]
18
18
  elsif long
19
19
  [long]
@@ -27,12 +27,12 @@ module Bashly
27
27
  end
28
28
 
29
29
  def usage_string(extended: false)
30
- result = [aliases.join(", ")]
30
+ result = [aliases.join(', ')]
31
31
  result << arg.upcase if arg
32
- result << strings[:required] if required and extended
33
- result << strings[:repeatable] if repeatable and extended
34
- result.join " "
32
+ result << strings[:required] if required && extended
33
+ result << strings[:repeatable] if repeatable && extended
34
+ result.join ' '
35
35
  end
36
36
  end
37
37
  end
38
- end
38
+ end
@@ -6,7 +6,8 @@ module Bashly
6
6
  attr_reader :command, :function_name
7
7
 
8
8
  def initialize(command, function_name = nil)
9
- @command, @function_name = command, function_name
9
+ @command = command
10
+ @function_name = function_name
10
11
  end
11
12
 
12
13
  def code(tab_indent: false)
@@ -38,13 +39,13 @@ module Bashly
38
39
  end
39
40
 
40
41
  def default_header
41
- result = render('header')
42
+ result = render 'header'
42
43
  result += render('bash3_bouncer') unless function_name
43
44
  result
44
45
  end
45
46
 
46
47
  def body
47
- @body ||= command.render('master_script')
48
+ @body ||= command.render 'master_script'
48
49
  end
49
50
 
50
51
  def custom_header_path
@@ -52,4 +53,4 @@ module Bashly
52
53
  end
53
54
  end
54
55
  end
55
- end
56
+ end
@@ -51,8 +51,8 @@ module Bashly
51
51
  def get(key)
52
52
  case env_value key
53
53
  when nil then config[key.to_s]
54
- when "0", "false", "no" then false
55
- when "1", "true", "yes" then true
54
+ when '0', 'false', 'no' then false
55
+ when '1', 'true', 'yes' then true
56
56
  else env_value key
57
57
  end
58
58
  end
@@ -70,13 +70,12 @@ module Bashly
70
70
  end
71
71
 
72
72
  def defsult_settings
73
- @defsult_settings ||= Config.new(default_settings_path)
73
+ @defsult_settings ||= Config.new default_settings_path
74
74
  end
75
75
 
76
76
  def default_settings_path
77
- asset "templates/settings.yml"
77
+ asset 'templates/settings.yml'
78
78
  end
79
-
80
79
  end
81
80
  end
82
81
  end
@@ -0,0 +1,30 @@
1
+ ## Help command [@bashly-upgrade help]
2
+ ## This file is a part of Bashly standard library
3
+ ##
4
+ ## Add this as a command to your bashly.yml:
5
+ ##
6
+ ## commands:
7
+ ## - name: help
8
+ ## help: Show help about a command
9
+ ## args:
10
+ ## - name: command
11
+ ## help: Help subject
12
+ ##
13
+ command="${args[command]}"
14
+ long_usage=yes
15
+
16
+ if [[ -z "$command" ]]; then
17
+ # No command argument, show the global help
18
+ help_function=%{name}_usage
19
+ else
20
+ # Show the help for the requested command
21
+ help_function="%{name}_${command}_usage"
22
+ fi
23
+
24
+ # Call the help function if it exists
25
+ if [[ $(type -t "$help_function") ]]; then
26
+ "$help_function"
27
+ else
28
+ echo "No help available for this command"
29
+ exit 1
30
+ fi
@@ -14,9 +14,9 @@ print_in_color() {
14
14
  local color="$1"
15
15
  shift
16
16
  if [[ -z ${NO_COLOR+x} ]]; then
17
- printf "$color%b\e[0m\n" "$*";
17
+ printf "$color%b\e[0m\n" "$*"
18
18
  else
19
- printf "%b\n" "$*";
19
+ printf "%b\n" "$*"
20
20
  fi
21
21
  }
22
22
 
@@ -24,13 +24,13 @@ config_get() {
24
24
  local value=""
25
25
 
26
26
  config_init
27
-
27
+
28
28
  while IFS= read -r line || [ -n "$line" ]; do
29
29
  if [[ $line =~ $regex ]]; then
30
30
  value="${BASH_REMATCH[1]}"
31
31
  break
32
32
  fi
33
- done < "$CONFIG_FILE"
33
+ done <"$CONFIG_FILE"
34
34
 
35
35
  echo "$value"
36
36
  }
@@ -48,7 +48,7 @@ config_set() {
48
48
  local output=""
49
49
  local found_key=""
50
50
  local newline
51
-
51
+
52
52
  while IFS= read -r line || [ -n "$line" ]; do
53
53
  newline=$line
54
54
  if [[ $line =~ $regex ]]; then
@@ -58,13 +58,13 @@ config_set() {
58
58
  elif [[ $line ]]; then
59
59
  output="$output$line\n"
60
60
  fi
61
- done < "$CONFIG_FILE"
61
+ done <"$CONFIG_FILE"
62
62
 
63
63
  if [[ -z $found_key ]]; then
64
64
  output="$output$key = $value\n"
65
65
  fi
66
66
 
67
- printf "%b\n" "$output" > "$CONFIG_FILE"
67
+ printf "%b\n" "$output" >"$CONFIG_FILE"
68
68
  }
69
69
 
70
70
  ## Delete a key from the config.
@@ -81,9 +81,9 @@ config_del() {
81
81
  if [[ $line ]] && [[ ! $line =~ $regex ]]; then
82
82
  output="$output$line\n"
83
83
  fi
84
- done < "$CONFIG_FILE"
84
+ done <"$CONFIG_FILE"
85
85
 
86
- printf "%b\n" "$output" > "$CONFIG_FILE"
86
+ printf "%b\n" "$output" >"$CONFIG_FILE"
87
87
  }
88
88
 
89
89
  ## Show the config file
@@ -106,20 +106,20 @@ config_keys() {
106
106
 
107
107
  local keys=()
108
108
  local key
109
-
109
+
110
110
  while IFS= read -r line || [ -n "$line" ]; do
111
111
  if [[ $line =~ $regex ]]; then
112
112
  key="${BASH_REMATCH[1]}"
113
113
  keys+=("$key")
114
114
  fi
115
- done < "$CONFIG_FILE"
115
+ done <"$CONFIG_FILE"
116
116
  echo "${keys[@]}"
117
117
  }
118
118
 
119
119
  ## Returns true if the specified key exists in the config file.
120
120
  ## Usage:
121
121
  ##
122
- ## if config_has_key "key" ; then
122
+ ## if config_has_key "key"; then
123
123
  ## echo "key exists"
124
124
  ## fi
125
125
  ##
@@ -11,16 +11,16 @@
11
11
  ## eval $(yaml_load "settings.yml") # create variables in scope
12
12
  ##
13
13
  yaml_load() {
14
- local prefix=$2
15
- local s='[[:space:]]*' w='[a-zA-Z0-9_]*'
16
- local fs
14
+ local prefix=$2
15
+ local s='[[:space:]]*' w='[a-zA-Z0-9_]*'
16
+ local fs
17
17
 
18
- fs=$(echo @|tr @ '\034')
18
+ fs=$(echo @ | tr @ '\034')
19
19
 
20
- sed -ne "s|^\($s\):|\1|" \
21
- -e "s|^\($s\)\($w\)$s:${s}[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
22
- -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
23
- awk -F"$fs" '{
20
+ sed -ne "s|^\($s\):|\1|" \
21
+ -e "s|^\($s\)\($w\)$s:${s}[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
22
+ -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
23
+ awk -F"$fs" '{
24
24
  indent = length($1)/2;
25
25
  vname[indent] = $2;
26
26
  for (i in vname) {if (i > indent) {delete vname[i]}}
@@ -28,5 +28,5 @@ yaml_load() {
28
28
  vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
29
29
  printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3);
30
30
  }
31
- }'
31
+ }'
32
32
  }
@@ -1,14 +1,14 @@
1
- # approvals.bash v0.2.7
1
+ # approvals.bash v0.3.3
2
2
  #
3
3
  # Interactive approval testing for Bash.
4
4
  # https://github.com/DannyBen/approvals.bash
5
5
  approve() {
6
6
  local expected approval approval_file actual cmd
7
7
  approvals_dir=${APPROVALS_DIR:=approvals}
8
-
8
+
9
9
  cmd=$1
10
- actual=$(eval "$cmd" 2>&1)
11
- last_exit_code=$?
10
+ last_exit_code=0
11
+ actual=$(eval "$cmd" 2>&1) || last_exit_code=$?
12
12
  approval=$(printf "%b" "$cmd" | tr -s -c "[:alnum:]" _)
13
13
  approval_file="$approvals_dir/${2:-"$approval"}"
14
14
 
@@ -26,26 +26,32 @@ approve() {
26
26
  fi
27
27
 
28
28
  if [[ "$(printf "%b" "$actual")" = "$(printf "%b" "$expected")" ]]; then
29
- green "PASS $cmd"
29
+ pass "$cmd"
30
30
  else
31
31
  echo "--- [$(blue "diff: $cmd")] ---"
32
- $diff_cmd <(printf "%b" "$expected\n") <(printf "%b" "$actual\n" ) | tail -n +4
32
+ $diff_cmd <(printf "%b" "$expected\n") <(printf "%b" "$actual\n") | tail -n +4
33
33
  echo "--- [$(blue "diff: $cmd")] ---"
34
34
  user_approval "$cmd" "$actual" "$approval_file"
35
35
  fi
36
36
  }
37
37
 
38
38
  describe() {
39
- cyan "TEST $*"
39
+ echo
40
+ blue "= $*"
41
+ }
42
+
43
+ context() {
44
+ echo
45
+ magenta "= $*"
40
46
  }
41
47
 
42
48
  fail() {
43
- red "FAIL $*"
49
+ red " FAILED: $*"
44
50
  exit 1
45
51
  }
46
52
 
47
53
  pass() {
48
- green "PASS $*"
54
+ green " approved: $*"
49
55
  return 0
50
56
  }
51
57
 
@@ -74,19 +80,37 @@ user_approval() {
74
80
  fail "$cmd"
75
81
  fi
76
82
 
77
- echo
83
+ echo
78
84
  printf "[A]pprove? \n"
79
85
  response=$(bash -c "read -n 1 key; echo \$key")
80
86
  printf "\r"
81
87
  if [[ $response =~ [Aa] ]]; then
82
- printf "%b\n" "$actual" > "$approval_file"
88
+ printf "%b\n" "$actual" >"$approval_file"
83
89
  pass "$cmd"
84
90
  else
85
91
  fail "$cmd"
86
92
  fi
87
93
  }
88
94
 
89
- if diff --help | grep -- --color > /dev/null 2>&1; then
95
+ onexit() {
96
+ exitcode=$?
97
+ if [[ "$exitcode" == 0 ]]; then
98
+ green "\nFinished successfully"
99
+ else
100
+ red "\nFinished with failures"
101
+ fi
102
+ exit $exitcode
103
+ }
104
+
105
+ onerror() {
106
+ fail "Caller: $(caller)"
107
+ }
108
+
109
+ set -e
110
+ trap 'onexit' EXIT
111
+ trap 'onerror' ERR
112
+
113
+ if diff --help | grep -- --color >/dev/null 2>&1; then
90
114
  diff_cmd="diff --unified --color=always"
91
115
  else
92
116
  diff_cmd="diff --unified"
@@ -3,18 +3,23 @@
3
3
 
4
4
  cd ./test || exit
5
5
  source approvals.bash
6
- PATH="$PATH:../"
7
6
 
8
7
  # Update me
9
- cli=download
8
+ cli=./download
10
9
 
11
- # Tests
12
- describe "root command"
13
- approve "$cli"
14
- approve "$cli --help"
10
+ # Tests (context, describe and indentation are optional)
11
+ context "when DEBUG is on"
12
+ export DEBUG=1
15
13
 
16
- describe "some other command"
17
- approve "$cli other"
18
- approve "$cli other --help"
14
+ describe "root command"
15
+ approve "$cli"
16
+ approve "$cli --help"
17
+
18
+ context "when DEBUG is off"
19
+ unset DEBUG
20
+
21
+ describe "some other command"
22
+ approve "$cli other"
23
+ approve "$cli other --help"
19
24
 
20
25
  # ...more tests...