cmd-utils 1.1.2 → 1.2.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.
- checksums.yaml +4 -4
- data/Gemfile +4 -6
- data/Gemfile.lock +19 -25
- data/README.md +58 -27
- data/Rakefile +5 -5
- data/VERSION +1 -1
- data/cmd-utils.gemspec +21 -20
- data/lib/arg-utils.rb +52 -0
- data/lib/cmd-utils.rb +8 -270
- data/lib/error-utils.rb +56 -0
- data/lib/lookup.rb +4 -1
- data/lib/run-utils.rb +79 -0
- data/lib/ssh-utils.rb +19 -12
- data/lib/talk-utils.rb +160 -0
- data/test/helper.rb +53 -19
- data/test/test-lookup.rb +4 -2
- data/test/test-run-utils.rb +31 -0
- data/test/{test-cmd-utils.rb → test-talk-utils.rb} +8 -59
- metadata +24 -34
- data/test/test_cmd-utils.rb.off +0 -7
data/lib/error-utils.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# error-utils.rb -- simple utilities for managing errors to $stderr
|
2
|
+
#
|
3
|
+
# Alan K. Stebbens <aks@stebbens.org>
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# require 'error-utils'
|
7
|
+
#
|
8
|
+
# Provides:
|
9
|
+
#
|
10
|
+
# error [code,] msg
|
11
|
+
# error( [code]){ msg }
|
12
|
+
# error {[code,] msg }
|
13
|
+
#
|
14
|
+
# errorf [code,] fmt, *args
|
15
|
+
# errorf( [code,] fmt) { *args }
|
16
|
+
# errorf {[code,] fmt, *args }
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'arg-utils'
|
20
|
+
|
21
|
+
# error -- print an error message on STDERR, and then exit.
|
22
|
+
# :call-seq:
|
23
|
+
# error [code], msg
|
24
|
+
# error( [code]) { msg }
|
25
|
+
# error {[[code], msg ] }
|
26
|
+
#
|
27
|
+
# Code defaults to 1 if not given.
|
28
|
+
|
29
|
+
def error *args
|
30
|
+
args = _msgargs(args, block_given?) { yield }
|
31
|
+
code = args.size > 0 && args[0].class == Fixnum ? args.shift : 1
|
32
|
+
$stderr.puts(*args)
|
33
|
+
$stderr.flush
|
34
|
+
exit code
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# errorf -- print a formatted message on STDERR, and then exit
|
39
|
+
#
|
40
|
+
# :call-seq:
|
41
|
+
# errorf [code], fmt, args ..
|
42
|
+
# errorf( [code], fmt) { args .. }
|
43
|
+
# errorf( [code]) { fmt, args .. }
|
44
|
+
# errorf {[[code], fmt, args .. ] }
|
45
|
+
|
46
|
+
def errorf *args
|
47
|
+
args = _fmtargs(args, block_given?) { yield }
|
48
|
+
# default the error code to 1 unless the first argument is a Fixnum
|
49
|
+
code = args.size > 0 && args[0].class == Fixnum ? args.shift : 1
|
50
|
+
$stderr.printf(*args)
|
51
|
+
$stderr.flush
|
52
|
+
exit code
|
53
|
+
end
|
54
|
+
|
55
|
+
# end of error-utils.sh
|
56
|
+
# vim: set ai sw=2
|
data/lib/lookup.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Alan K. Stebbens <aks@stebbens.org>
|
4
4
|
#
|
5
5
|
# require 'lookup'
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# lookup - lookup a keyword in a list, in a case-insensitive, disambiguous way
|
8
8
|
#
|
9
9
|
# :call-seq:
|
@@ -69,3 +69,6 @@ class Hash
|
|
69
69
|
self.keys.lookup(key, err_notfound, err_ambig)
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
# end of lookup.rb
|
74
|
+
# vim: set sw=2 ai
|
data/lib/run-utils.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# run-utils.rb -- simple utilities for running commands
|
2
|
+
#
|
3
|
+
# Alan K. Stebbens <aks@stebbens.org>
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# require 'run-utils'
|
7
|
+
#
|
8
|
+
# Utilities for running commands.
|
9
|
+
|
10
|
+
require 'arg-utils'
|
11
|
+
require 'talk-utils'
|
12
|
+
|
13
|
+
# run -- run a command with support for testing, diagnostics and verbosity
|
14
|
+
# safe_run -- run a command with support for diagnostics and verbosity
|
15
|
+
#
|
16
|
+
# Both may be given optional `errmsg` and `okmsg`, which are printed if given
|
17
|
+
# for the corresponding condition.
|
18
|
+
#
|
19
|
+
# :call-seq:
|
20
|
+
# run cmd
|
21
|
+
# run { cmd }
|
22
|
+
# run cmd, errmsg
|
23
|
+
# run { [cmd, errmsg] }
|
24
|
+
# run { [cmd, errmsg, okmg] }
|
25
|
+
# run cmd, errmsg, okmsg
|
26
|
+
#
|
27
|
+
# safe_run cmd
|
28
|
+
# safe_run cmd, errmsg
|
29
|
+
# safe_run cmd, errmsg, okmsg
|
30
|
+
# safe_run { cmd }
|
31
|
+
# safe_run { [cmd, errmsg] }
|
32
|
+
# safe_run { [cmd, errmsg, okmsg] }
|
33
|
+
#
|
34
|
+
# if `$norun` is set, print `(norun) ` followed by `cmd` on `STDERR`, and
|
35
|
+
# return.
|
36
|
+
#
|
37
|
+
# if `$verbose` is set, print `>> ` followed by `cmd` on `STDERR`.
|
38
|
+
#
|
39
|
+
# Invoke the `cmd` with the `system()` call.
|
40
|
+
#
|
41
|
+
# If there is an error, show the command (preceded by `>> `) if `$verbose` is
|
42
|
+
# not set, then show the error code, followed by the given `errmsg` or the
|
43
|
+
# default error message.
|
44
|
+
#
|
45
|
+
# The `cmd` can be given either as an argument, or as the returned value from a
|
46
|
+
# block. Important: the block should return a string value to be passed to
|
47
|
+
# the system call.
|
48
|
+
|
49
|
+
def safe_run *args
|
50
|
+
args = _msgargs(args, block_given?) { yield }
|
51
|
+
cmd, errmsg, okmsg = args
|
52
|
+
vtalkf ">> %s\n", cmd
|
53
|
+
if cmd
|
54
|
+
if system cmd # invoke the command
|
55
|
+
talk okmsg if okmsg
|
56
|
+
return true
|
57
|
+
else # an error occured
|
58
|
+
qtalkf ">> %s\n", cmd
|
59
|
+
erm = sprintf(errmsg ? errmsg : "Command failed with code %d", $?>>8)
|
60
|
+
talk erm
|
61
|
+
$stderr.flush
|
62
|
+
raise SystemCallError, erm # instead of exit, use raise
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def cmd_run *args
|
68
|
+
args = _msgargs(args, block_given?) { yield }
|
69
|
+
if $norun
|
70
|
+
nrtalk(args.first)
|
71
|
+
elsif args.size > 0
|
72
|
+
safe_run(*args)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
alias run cmd_run
|
77
|
+
|
78
|
+
# end of run-utils.sh
|
79
|
+
# vim: set ai sw=2
|
data/lib/ssh-utils.rb
CHANGED
@@ -9,16 +9,16 @@
|
|
9
9
|
#
|
10
10
|
# require 'ssh-utils'
|
11
11
|
#
|
12
|
-
# on
|
13
|
-
# as
|
14
|
-
# with PATH
|
12
|
+
# on SERVERLIST, :debug = true do |server|
|
13
|
+
# as USER do
|
14
|
+
# with PATH do
|
15
15
|
# remote_run :whoami
|
16
16
|
# end
|
17
17
|
# end
|
18
18
|
# end
|
19
19
|
|
20
20
|
require 'rubygems'
|
21
|
-
require '
|
21
|
+
require 'talk-utils'
|
22
22
|
|
23
23
|
module SSH_Utils
|
24
24
|
|
@@ -53,11 +53,19 @@ module SSH_Utils
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
#
|
56
|
+
# merge_opts_with_env opts
|
57
|
+
#
|
58
|
+
# Invokes merge_env, then merge_opts
|
57
59
|
|
58
|
-
def
|
60
|
+
def merge_opts_with_env opts = {}
|
59
61
|
merge_env (opts = opts.dup)
|
60
62
|
merge_opts opts
|
63
|
+
end
|
64
|
+
|
65
|
+
# on SERVERLIST, :with => %w(PATH RUBYLIB), :debug => [true|false], :norun => [true|false]
|
66
|
+
|
67
|
+
def on servers, opts = {}
|
68
|
+
merge_opts_with_env opts
|
61
69
|
(@servers = servers).each do |server|
|
62
70
|
@server = server
|
63
71
|
talk("--> Running block for server #{server}..") if @opts[:debug] || $debug
|
@@ -69,16 +77,15 @@ module SSH_Utils
|
|
69
77
|
|
70
78
|
def as user, opts = {}
|
71
79
|
@user = user
|
72
|
-
|
73
|
-
merge_opts opts
|
80
|
+
merge_opts_with_env opts
|
74
81
|
yield if block_given?
|
75
82
|
end
|
76
83
|
|
77
84
|
# with ENVARLIST, :VAR1 => value, :debug => ...
|
78
85
|
|
79
86
|
def with env, opts = {}
|
80
|
-
|
81
|
-
|
87
|
+
merge_opts_with_env opts
|
88
|
+
yield if block_given?
|
82
89
|
end
|
83
90
|
|
84
91
|
def ssh_command cmd
|
@@ -116,8 +123,7 @@ module SSH_Utils
|
|
116
123
|
|
117
124
|
|
118
125
|
def remote_run_with_output cmd, opts = {}
|
119
|
-
|
120
|
-
merge_opts opts
|
126
|
+
merge_opts_with_env opts
|
121
127
|
ssh = ssh_command cmd
|
122
128
|
_show_cmd ssh
|
123
129
|
out = nil
|
@@ -131,4 +137,5 @@ end
|
|
131
137
|
|
132
138
|
include SSH_Utils
|
133
139
|
|
140
|
+
# end of ssh-utils.rb
|
134
141
|
# vim: sw=2:ai
|
data/lib/talk-utils.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# talk-utils.rb -- simple utilties for "talking" to $stderr
|
2
|
+
#
|
3
|
+
# Alan K. Stebbens <aks@stebbens.org>
|
4
|
+
#
|
5
|
+
# require 'talk-utils'
|
6
|
+
#
|
7
|
+
# Utilities for option-controlled output, and running commands.
|
8
|
+
#
|
9
|
+
# The output and run methods rely on some external variables:
|
10
|
+
#
|
11
|
+
# $verbose -- enables vtalk(f) output
|
12
|
+
# $norun -- enables nrtalk(f) output and controls the "run" command
|
13
|
+
# $quiet -- enables qtalk(f) output, and disables talk(f) output
|
14
|
+
# $debug -- enables dtalk(f) output
|
15
|
+
#
|
16
|
+
# These routines provide conditional output. The arguments can be given as
|
17
|
+
# part of the the function calls, or, can be provided as the return value of a
|
18
|
+
# block. The advantage of using a block is that the block is not evaluated
|
19
|
+
# unless the conditions requiring output are met. So, if the expression to
|
20
|
+
# compute a value that _might_ be printed is expensive, do the computation
|
21
|
+
# inside a block.
|
22
|
+
#
|
23
|
+
|
24
|
+
require 'arg-utils'
|
25
|
+
|
26
|
+
##
|
27
|
+
# talk - Print msg on STDERR unless `$quiet` is set
|
28
|
+
#
|
29
|
+
# :call-seq:
|
30
|
+
# talk msg ..
|
31
|
+
# talk { msg .. }
|
32
|
+
# talkf fmt, args ...
|
33
|
+
# talkf fmt { [ args ... ] }
|
34
|
+
|
35
|
+
def talk *args
|
36
|
+
if !$quiet && (args.size > 0 || block_given?)
|
37
|
+
$stderr.puts(*_msgargs(args, block_given?) { yield })
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def talkf *args
|
42
|
+
if !$quiet && (args.size > 0 || block_given?)
|
43
|
+
$stderr.printf(*_fmtargs(args, block_given?) { yield } )
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# dtalk - "debug talk"
|
49
|
+
# Print msg on STDERR only if `$debug` is set
|
50
|
+
#
|
51
|
+
# :call-seq:
|
52
|
+
# dtalk msg
|
53
|
+
# dtalk { msg }
|
54
|
+
# dtalkf fmt, args ..
|
55
|
+
# dtalkf fmt { [ args .. ] }
|
56
|
+
|
57
|
+
def dtalk *args
|
58
|
+
if $debug && (args.size > 0 || block_given?)
|
59
|
+
$stderr.puts(*_msgargs(args, block_given?) { yield })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def dtalkf *args
|
64
|
+
if $debug && (args.size> 0 || block_given?)
|
65
|
+
$stderr.printf(*_fmtargs(args, block_given?) { yield })
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# qtalk - "quiet talk"
|
71
|
+
# print msg on STDERR only if `$quiet` is set
|
72
|
+
#
|
73
|
+
# :call-seq:
|
74
|
+
# qtalk msg
|
75
|
+
# qtalk { msg }
|
76
|
+
# qtalkf fmt, args ..
|
77
|
+
# qtalkf fmt { [ args .. ] }
|
78
|
+
|
79
|
+
def qtalk *args
|
80
|
+
if $quiet && (args.size > 0 || block_given?)
|
81
|
+
$stderr.puts(*_msgargs(args, block_given?) { yield })
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def qtalkf *args
|
86
|
+
if $quiet && (args.size > 0 || block_given?)
|
87
|
+
$stderr.printf(*_fmtargs(args, block_given?) { yield } )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# vtalk - "verbose talk"
|
93
|
+
# Print msg on STDERR if `$verbose` is set
|
94
|
+
#
|
95
|
+
# :call-seq:
|
96
|
+
# vtalk msg
|
97
|
+
# vtalk { msg }
|
98
|
+
# vtalkf fmt, args ..
|
99
|
+
# vtalkf fmt { args .. }
|
100
|
+
|
101
|
+
def vtalk *args
|
102
|
+
if $verbose && (args.size > 0 || block_given?)
|
103
|
+
$stderr.puts(*_msgargs(args, block_given?) { yield })
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def vtalkf *args
|
108
|
+
if $verbose && (args.size > 0 || block_given?)
|
109
|
+
$stderr.printf(*_fmtargs(args, block_given?) { yield } )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# nvtalk -- "non-verbose" talk
|
115
|
+
# Print msg on STDERR unless `$verbose` is set
|
116
|
+
#
|
117
|
+
# :call-seq:
|
118
|
+
# nvtalk msg
|
119
|
+
# nvtalk { msg }
|
120
|
+
|
121
|
+
def nvtalk *args
|
122
|
+
unless $verbose && (args.size > 0 || block_given?)
|
123
|
+
$stderr.puts(*_msgargs(args, block_given?) { yield })
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def nvtalkf *args
|
128
|
+
unless $verbose && (args.size > 0 || block_given?)
|
129
|
+
$stderr.printf(*_fmtargs(args, block_given?) { yield } )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# nrtalk -- "no run" talk
|
135
|
+
# Print msg, prefixed with "(norun) ", on STDERR only if `$norun` is set
|
136
|
+
#
|
137
|
+
# :call-seq:
|
138
|
+
# nrtalk msg
|
139
|
+
# nrtalk { msg }
|
140
|
+
# nrtalkf fmt, msg
|
141
|
+
# nrtalkf fmt { msg }
|
142
|
+
|
143
|
+
def nrtalk *args
|
144
|
+
if $norun && (args.size > 0 || block_given?)
|
145
|
+
newargs = _msgargs(args, block_given?) { yield }
|
146
|
+
newargs[0] = '(norun) ' + newargs[0] unless newargs.size == 0 || newargs[0].nil? || newargs[0].include?('(norun)')
|
147
|
+
$stderr.puts(*newargs)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def nrtalkf *args
|
152
|
+
if $norun && (args.size > 0 || block_given?)
|
153
|
+
newargs = _fmtargs(args, block_given?) { yield }
|
154
|
+
newargs[0] = '(norun) ' + newargs[0] unless newargs.size == 0 || newargs[0].nil? || newargs[0].include?('(norun)')
|
155
|
+
$stderr.printf(*newargs)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# end of talk-utils.sh
|
160
|
+
# vim: set ai sw=2
|
data/test/helper.rb
CHANGED
@@ -1,19 +1,5 @@
|
|
1
|
-
|
1
|
+
# test/helper.rb
|
2
2
|
|
3
|
-
module SimpleCov::Configuration
|
4
|
-
def clean_filters
|
5
|
-
@filters = []
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
SimpleCov.configure do
|
10
|
-
clean_filters
|
11
|
-
load_adapter 'test_frameworks'
|
12
|
-
end
|
13
|
-
|
14
|
-
ENV["COVERAGE"] && SimpleCov.start do
|
15
|
-
add_filter "/.rvm/"
|
16
|
-
end
|
17
3
|
require 'rubygems'
|
18
4
|
require 'bundler'
|
19
5
|
begin
|
@@ -24,12 +10,60 @@ rescue Bundler::BundlerError => e
|
|
24
10
|
exit e.status_code
|
25
11
|
end
|
26
12
|
require 'minitest'
|
27
|
-
require '
|
28
|
-
require 'shoulda'
|
13
|
+
require 'minitest/autorun'
|
29
14
|
|
30
15
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
31
16
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
32
|
-
require 'cmd-utils'
|
33
17
|
|
34
|
-
|
18
|
+
module IO_Assert
|
19
|
+
def io_assert ioname, name, actual, expected
|
20
|
+
if expected
|
21
|
+
case expected
|
22
|
+
when TrueClass then refute_empty(actual, "#{name} $#{ioname} should not be empty")
|
23
|
+
when FalseClass then assert_empty(actual, "#{name} $#{ioname} should be empty")
|
24
|
+
when String then assert_match(actual, expected, "#{name} $#{ioname}: expected '#{expected}', got: '#{actual}'")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Gen_Test
|
32
|
+
include IO_Assert
|
33
|
+
|
34
|
+
#def gen_test name, norun, verbose, quiet, debug, output
|
35
|
+
def gen_test name, flags, output
|
36
|
+
$norun = flags.include?('n')
|
37
|
+
$verbose = flags.include?('v')
|
38
|
+
$quiet = flags.include?('q')
|
39
|
+
$debug = flags.include?('d')
|
40
|
+
out, err = capture_io { yield }
|
41
|
+
assert_empty(out, "#{name} $stdout should be empty")
|
42
|
+
io_assert :stderr, name, err, output
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module Run_Test
|
47
|
+
include IO_Assert
|
48
|
+
def run_test name, flags, output=nil, errput=nil
|
49
|
+
$norun = flags.include?('n')
|
50
|
+
$verbose = flags.include?('v')
|
51
|
+
$quiet = flags.include?('q')
|
52
|
+
$debug = flags.include?('d')
|
53
|
+
begin
|
54
|
+
out, err = capture_subprocess_io do
|
55
|
+
begin
|
56
|
+
yield
|
57
|
+
rescue
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue
|
61
|
+
end
|
62
|
+
io_assert :stdout, name, out, output
|
63
|
+
io_assert :stderr, name, err, errput
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Minitest::Test
|
35
69
|
end
|