cmd-utils 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|