falsework 1.3.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.rdoc +6 -5
- data/Rakefile +14 -10
- data/bin/falsework +25 -25
- data/doc/NEWS.rdoc +18 -0
- data/doc/README.rdoc +6 -5
- data/doc/TODO.org +2 -1
- data/lib/falsework/cliconfig.rb +135 -0
- data/lib/falsework/cliutils.rb +112 -0
- data/lib/falsework/meta.rb +1 -1
- data/lib/falsework/mould.rb +23 -20
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/#config.yaml +0 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/.gitignore.#erb +0 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/Gemfile +1 -1
- data/lib/falsework/templates/{ruby-naive/doc → ruby-cli}/README.rdoc +1 -1
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/Rakefile +0 -0
- data/lib/falsework/templates/ruby-cli/bin/%%@project%% +26 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/#doc.rdoc +1 -1
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/LICENSE +0 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/NEWS.rdoc +0 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli/doc}/README.rdoc +1 -1
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/etc/%%@project%%.yaml +0 -0
- data/lib/falsework/templates/ruby-cli/lib/%%@project%%/cliconfig.rb +137 -0
- data/lib/falsework/templates/ruby-cli/lib/%%@project%%/cliutils.rb +114 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/lib/%%@project%%/meta.rb +0 -0
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/helper.rb +1 -1
- data/lib/falsework/templates/{ruby-naive/test/helper_trestle.rb → ruby-cli/test/helper_cliutils.rb} +4 -4
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/rake_git.rb +2 -2
- data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/test_%%@project%%.rb +0 -0
- data/test/helper.rb +1 -1
- data/test/{helper_trestle.rb → helper_cliutils.rb} +3 -3
- data/test/rake_erb_templates.rb +3 -3
- data/test/rake_git.rb +1 -1
- data/test/templates/config-02.yaml +2 -0
- data/test/test_cl.rb +9 -5
- data/test/test_exe.rb +26 -21
- metadata +31 -26
- data/lib/falsework/templates/ruby-naive/bin/%%@project%% +0 -31
- data/lib/falsework/templates/ruby-naive/lib/%%@project%%/trestle.rb +0 -230
- data/lib/falsework/trestle.rb +0 -228
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ falsework--A primitive scaffold generator for writing CLI programs.
|
|
10
10
|
|
11
11
|
==Description
|
12
12
|
|
13
|
-
The falsework utility ships with 2 templates: <tt>ruby-
|
13
|
+
The falsework utility ships with 2 templates: <tt>ruby-cli</tt> and
|
14
14
|
<tt>c-glib</tt>.
|
15
15
|
|
16
16
|
Initially the template spec was designed only for Ruby projects but
|
@@ -53,8 +53,9 @@ list:: Do nothing except listing all available
|
|
53
53
|
|
54
54
|
listdirs:: Do nothing except listing all available
|
55
55
|
templates directories. You can add another
|
56
|
-
directory
|
57
|
-
the config file. (<tt>tdir</tt> is an
|
56
|
+
directory by modifying <tt>tdir</tt> option
|
57
|
+
in the config file. (<tt>tdir</tt> is an
|
58
|
+
array).
|
58
59
|
|
59
60
|
new NAME:: Create a new project. It creates a directory
|
60
61
|
<i>NAME</i> and populates it with files.
|
@@ -73,7 +74,7 @@ test NAME:: Add a new test in
|
|
73
74
|
|
74
75
|
upgrade:: 'Inject' or upgrade some vital files from the
|
75
76
|
template into the project. Currently only
|
76
|
-
'ruby-
|
77
|
+
'ruby-cli' template supports this.
|
77
78
|
|
78
79
|
The options are as follows:
|
79
80
|
|
@@ -82,7 +83,7 @@ The options are as follows:
|
|
82
83
|
-b:: A batch mode. (No questions asked.)
|
83
84
|
|
84
85
|
--no-git:: Don't create a Git repository. Don't use
|
85
|
-
this for 'ruby-
|
86
|
+
this for 'ruby-cli' template.
|
86
87
|
|
87
88
|
--config-dirs:: List all possible locations for the
|
88
89
|
configuration file. The first found wins.
|
data/Rakefile
CHANGED
@@ -18,15 +18,15 @@ require_relative 'test/rake_git'
|
|
18
18
|
#
|
19
19
|
require_relative 'test/rake_erb_templates'
|
20
20
|
|
21
|
-
ERB_DYN_SKELETON = erb_skeletons(Meta::NAME, 'ruby-
|
21
|
+
ERB_DYN_SKELETON = erb_skeletons(Meta::NAME, 'ruby-cli')
|
22
22
|
ERB_DYN_SKELETON.each {|k, v|
|
23
23
|
file k => [v] do |t|
|
24
|
-
erb_make(Meta::NAME, 'ruby-
|
24
|
+
erb_make(Meta::NAME, 'ruby-cli', t.name, t.prerequisites[0])
|
25
25
|
end
|
26
26
|
}
|
27
27
|
|
28
|
-
desc "Generate some erb templates for ruby-
|
29
|
-
task
|
28
|
+
desc "Generate some erb templates for ruby-cli template"
|
29
|
+
task cli: ERB_DYN_SKELETON.keys
|
30
30
|
|
31
31
|
CLOBBER.concat ERB_DYN_SKELETON.keys
|
32
32
|
#pp CLOBBER
|
@@ -35,6 +35,10 @@ CLOBBER.concat ERB_DYN_SKELETON.keys
|
|
35
35
|
# Gem staff
|
36
36
|
#
|
37
37
|
|
38
|
+
rdoc_task_excl = 'lib/**/templates/**/*'
|
39
|
+
rdoc_spec_excl = 'lib/.+/templates/'
|
40
|
+
rdoc_main = 'doc/README.rdoc'
|
41
|
+
|
38
42
|
spec = Gem::Specification.new {|i|
|
39
43
|
i.name = Meta::NAME
|
40
44
|
i.version = `bin/#{i.name} -V`
|
@@ -53,25 +57,25 @@ spec = Gem::Specification.new {|i|
|
|
53
57
|
|
54
58
|
i.test_files = FileList['test/test_*.rb']
|
55
59
|
|
56
|
-
i.rdoc_options << '-m' << '
|
60
|
+
i.rdoc_options << '-m' << rdoc_main << '-x' << rdoc_spec_excl
|
57
61
|
i.extra_rdoc_files = FileList['doc/*']
|
58
62
|
|
59
63
|
i.add_dependency('git', '>= 1.2.5')
|
60
|
-
i.add_dependency('open4', '>= 1.
|
64
|
+
i.add_dependency('open4', '>= 1.3.0')
|
61
65
|
}
|
62
66
|
|
63
67
|
Gem::PackageTask.new(spec).define
|
64
68
|
|
65
|
-
task default: [:
|
69
|
+
task default: [:cli, :repackage]
|
66
70
|
|
67
71
|
RDoc::Task.new('html') do |i|
|
68
|
-
i.main =
|
72
|
+
i.main = rdoc_main
|
69
73
|
i.rdoc_files = FileList['doc/*', 'lib/**/*.rb']
|
70
|
-
i.rdoc_files.exclude
|
74
|
+
i.rdoc_files.exclude rdoc_task_excl
|
71
75
|
end
|
72
76
|
|
73
77
|
Rake::TestTask.new do |i|
|
74
78
|
i.test_files = FileList['test/test_*.rb']
|
75
79
|
end
|
76
80
|
|
77
|
-
task test: [:
|
81
|
+
task test: [:cli]
|
data/bin/falsework
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*-ruby-*-
|
3
3
|
|
4
|
+
require_relative '../lib/falsework/cliconfig'
|
4
5
|
require_relative '../lib/falsework/mould'
|
5
6
|
|
6
7
|
include Falsework
|
7
8
|
|
8
|
-
$conf =
|
9
|
-
$t = Trestle.new($conf)
|
10
|
-
|
9
|
+
$conf = CliConfig.new
|
11
10
|
$conf[:banner] = <<EOF
|
12
11
|
Usage: #{File.basename($0)} [options] command ...
|
13
12
|
Available commands: list, listdirs, (new|exe|doc|test) NAME, upgrade.
|
@@ -24,9 +23,9 @@ def add_files(mode, files)
|
|
24
23
|
m = Mould.new(File.basename(Dir.pwd), $conf[:template],
|
25
24
|
$conf[:user], $conf[:email], $conf[:gecos])
|
26
25
|
files.each {|i|
|
27
|
-
created = m.add(mode, i) rescue
|
26
|
+
created = m.add(mode, i) rescue CliUtils.errx(1, $!.to_s)
|
28
27
|
if created.size > 0
|
29
|
-
created.each {|idx|
|
28
|
+
created.each {|idx| CliUtils.veputs(1, idx) }
|
30
29
|
else
|
31
30
|
r = false
|
32
31
|
end
|
@@ -35,34 +34,35 @@ def add_files(mode, files)
|
|
35
34
|
r
|
36
35
|
end
|
37
36
|
|
38
|
-
# --[ main ]------------------------------------------------------------
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
o.on('--
|
44
|
-
o.on('--
|
45
|
-
o.on('--
|
46
|
-
o.on('-
|
47
|
-
|
48
|
-
|
38
|
+
### main
|
39
|
+
|
40
|
+
$conf.load {|o|
|
41
|
+
o.on('--user STR', 'Github user.') {|i| $conf[:user] = i }
|
42
|
+
o.on('--gecos STR', 'A gecos-like string.') {|i| $conf[:gecos] = i }
|
43
|
+
o.on('--email STR') {|i| $conf[:email] = i }
|
44
|
+
o.on('--no-git', "Don't create a git repo.",
|
45
|
+
"(Will break 'ruby-cli'.)") { $conf[:git] = false }
|
46
|
+
o.on('-t NAME', 'A template name.') {|i| $conf[:template] = i }
|
47
|
+
o.on('-b', 'Run in a batch mode and',
|
48
|
+
'don\'t ask any questions.') { $conf[:batch] = true }
|
49
49
|
}
|
50
50
|
|
51
|
-
|
51
|
+
CliUtils.errx(EX_USAGE, $conf[:banner]) if (ARGV.size < 2 && ARGV[0] !~ /list|upgrade/)
|
52
52
|
|
53
53
|
# print our env
|
54
54
|
if $conf[:verbose] >= 2
|
55
|
-
puts
|
55
|
+
puts "Lib dir: #{CliUtils::DIR_LIB_SRC}"
|
56
56
|
pp $conf
|
57
57
|
end
|
58
58
|
|
59
59
|
# modify a list of available template directories
|
60
|
-
Mould.template_dirs_add $conf[:tdir]
|
60
|
+
Mould.template_dirs_add $conf[:tdir].map {|i| Pathname.new i} if $conf[:tdir]
|
61
61
|
|
62
62
|
case ARGV[0]
|
63
63
|
when 'list'
|
64
64
|
Mould.templates.each {|name, loc|
|
65
|
-
loc = '(system)' if loc == Mould.class_variable_get(:@@template_dirs)[0] +
|
65
|
+
loc = '(system)' if loc == (Mould.class_variable_get(:@@template_dirs)[0] + name).to_s
|
66
66
|
puts "%-30s %s" % [name, loc]
|
67
67
|
}
|
68
68
|
|
@@ -82,11 +82,11 @@ when 'upgrade'
|
|
82
82
|
$conf[:user], $conf[:email], $conf[:gecos])
|
83
83
|
m.verbose = true if $conf[:verbose] > 0
|
84
84
|
m.batch = $conf[:batch]
|
85
|
-
m.upgrade() rescue
|
85
|
+
m.upgrade() rescue CliUtils.errx(1, $!.to_s)
|
86
86
|
|
87
87
|
when 'new'
|
88
88
|
if File.dirname(ARGV[1]) != '.'
|
89
|
-
Dir.chdir(File.dirname(ARGV[1])) rescue
|
89
|
+
Dir.chdir(File.dirname(ARGV[1])) rescue CliUtils.errx(1, "cannot chdir to '#{File.dirname(ARGV[1])}'")
|
90
90
|
ARGV[1] = File.basename ARGV[1]
|
91
91
|
end
|
92
92
|
|
@@ -94,7 +94,7 @@ when 'new'
|
|
94
94
|
m = Mould.new(ARGV[1], $conf[:template],
|
95
95
|
$conf[:user], $conf[:email], $conf[:gecos])
|
96
96
|
rescue
|
97
|
-
|
97
|
+
CliUtils.errx 1, $!
|
98
98
|
end
|
99
99
|
m.verbose = true if $conf[:verbose] > 0
|
100
100
|
m.project_seed
|
@@ -102,12 +102,12 @@ when 'new'
|
|
102
102
|
# create a git repository
|
103
103
|
if $conf[:git]
|
104
104
|
Dir.chdir m.project
|
105
|
-
|
105
|
+
CliUtils.veputs(1, "Creating a git repository in #{Dir.pwd}... __NNL__")
|
106
106
|
g = Git.init
|
107
107
|
g.add '.'
|
108
108
|
g.commit "Initial import from #{Falsework::Meta::NAME} #{Falsework::Meta::VERSION}."
|
109
|
-
|
109
|
+
CliUtils.veputs(1, 'OK')
|
110
110
|
end
|
111
111
|
else
|
112
|
-
|
112
|
+
CliUtils.errx(1, "unknown command: " + ARGV[0])
|
113
113
|
end
|
data/doc/NEWS.rdoc
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 2.0.0
|
2
|
+
|
3
|
+
Fri Jan 27 22:11:06 EET 2012
|
4
|
+
|
5
|
+
* <b>WARNING:</b> 'ruby-naive' template is now called 'ruby-cli'. <b>You
|
6
|
+
cannot upgrade to it</b> because everything changed in it to be more
|
7
|
+
pretty.
|
8
|
+
|
9
|
+
* New command: listdirs.
|
10
|
+
|
11
|
+
* User can specify additional directories for templates.
|
12
|
+
|
13
|
+
=== 1.3.1
|
14
|
+
|
15
|
+
Fri Jan 27 12:07:55 EET 2012
|
16
|
+
|
17
|
+
* Fixed exclude pattern in gemspec for rdoc.
|
18
|
+
|
1
19
|
=== 1.3.0
|
2
20
|
|
3
21
|
Mon Nov 7 07:15:00 EET 2011
|
data/doc/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ falsework--A primitive scaffold generator for writing CLI programs.
|
|
10
10
|
|
11
11
|
==Description
|
12
12
|
|
13
|
-
The falsework utility ships with 2 templates: <tt>ruby-
|
13
|
+
The falsework utility ships with 2 templates: <tt>ruby-cli</tt> and
|
14
14
|
<tt>c-glib</tt>.
|
15
15
|
|
16
16
|
Initially the template spec was designed only for Ruby projects but
|
@@ -53,8 +53,9 @@ list:: Do nothing except listing all available
|
|
53
53
|
|
54
54
|
listdirs:: Do nothing except listing all available
|
55
55
|
templates directories. You can add another
|
56
|
-
directory
|
57
|
-
the config file. (<tt>tdir</tt> is an
|
56
|
+
directory by modifying <tt>tdir</tt> option
|
57
|
+
in the config file. (<tt>tdir</tt> is an
|
58
|
+
array).
|
58
59
|
|
59
60
|
new NAME:: Create a new project. It creates a directory
|
60
61
|
<i>NAME</i> and populates it with files.
|
@@ -73,7 +74,7 @@ test NAME:: Add a new test in
|
|
73
74
|
|
74
75
|
upgrade:: 'Inject' or upgrade some vital files from the
|
75
76
|
template into the project. Currently only
|
76
|
-
'ruby-
|
77
|
+
'ruby-cli' template supports this.
|
77
78
|
|
78
79
|
The options are as follows:
|
79
80
|
|
@@ -82,7 +83,7 @@ The options are as follows:
|
|
82
83
|
-b:: A batch mode. (No questions asked.)
|
83
84
|
|
84
85
|
--no-git:: Don't create a Git repository. Don't use
|
85
|
-
this for 'ruby-
|
86
|
+
this for 'ruby-cli' template.
|
86
87
|
|
87
88
|
--config-dirs:: List all possible locations for the
|
88
89
|
configuration file. The first found wins.
|
data/doc/TODO.org
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
* TODO In the distant future [3/
|
1
|
+
* TODO In the distant future [3/7] [42%]
|
2
2
|
|
3
3
|
- [-] more templates [1/4]
|
4
4
|
- [X] c glib
|
@@ -11,3 +11,4 @@
|
|
11
11
|
- [ ] describe c-glib template
|
12
12
|
- [X] normalize 'name' of the project before actually making a template
|
13
13
|
- [X] target_uuid variable for exe/doc/test templates
|
14
|
+
- [ ] relocate templates from lib/falsework directory to project root
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# :erb: ruby-cli
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'yaml'
|
5
|
+
require 'optparse'
|
6
|
+
require 'shellwords'
|
7
|
+
|
8
|
+
require_relative 'cliutils'
|
9
|
+
|
10
|
+
module Falsework
|
11
|
+
|
12
|
+
# Load configuration from 3 places (starting from least significant):
|
13
|
+
# config file, env variable, command line.
|
14
|
+
class CliConfig
|
15
|
+
# Possible config file locations.
|
16
|
+
DIR_CONFIG = [Pathname.new(Dir.home) + ".#{Meta::NAME}",
|
17
|
+
Pathname.new('/etc'),
|
18
|
+
Pathname.new('/usr/etc'),
|
19
|
+
Pathname.new('/usr/local/etc'),
|
20
|
+
CliUtils::DIR_LIB_SRC.parent.parent + 'etc']
|
21
|
+
|
22
|
+
# Example:
|
23
|
+
#
|
24
|
+
# conf = CliConfig.new
|
25
|
+
# conf[:my_option] = 123
|
26
|
+
# conf.load
|
27
|
+
def initialize
|
28
|
+
@conf = Hash.new
|
29
|
+
@conf[:verbose] = 0
|
30
|
+
@conf[:banner] = "Usage: #{File.basename($0)} [options]"
|
31
|
+
@conf[:config_name] = Meta::NAME + '.yaml'
|
32
|
+
@conf[:config_env] = Meta::NAME.upcase + '_CONF'
|
33
|
+
@conf[:config_dirs] = DIR_CONFIG
|
34
|
+
end
|
35
|
+
|
36
|
+
# Setter for @conf
|
37
|
+
def []=(key, val)
|
38
|
+
CliUtils.verbose = val if key == :verbose # sync verbosity levels
|
39
|
+
@conf[key] = val
|
40
|
+
end
|
41
|
+
|
42
|
+
# Getter for @conf
|
43
|
+
def [](key)
|
44
|
+
@conf[key]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return a full path to a config file or nil if no config file found.
|
48
|
+
def getConfigPath
|
49
|
+
if @conf[:config_name].index('/')
|
50
|
+
return @conf[:config_name] if File.file?(@conf[:config_name])
|
51
|
+
else
|
52
|
+
@conf[:config_dirs].each {|i|
|
53
|
+
r = Pathname.new(i) + @conf[:config_name]
|
54
|
+
return r if File.file?(r)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
CliUtils.warnx "no config file '#{@conf[:config_name]}' found" if @conf[:verbose] >= 2
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Load a config from file. Return true on success or false otherwise.
|
63
|
+
def loadFile
|
64
|
+
file = getConfigPath
|
65
|
+
return false unless file
|
66
|
+
|
67
|
+
CliUtils::veputs(2, "Loading #{File.basename(file)}... " + CliUtils::NNL_MARK)
|
68
|
+
myconf = YAML.load_file(file) rescue CliUtils.errx(1, "cannot parse config #{file}: #{$!}")
|
69
|
+
# preserve existing values
|
70
|
+
@conf.merge!(myconf) {|key, oldval, newval| oldval }
|
71
|
+
CliUtils::veputs(2, "OK")
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
# Check if options in array opts are in @conf.
|
76
|
+
def requiredOptions?(opts)
|
77
|
+
opts.each {|idx|
|
78
|
+
if !@conf.key?(idx.to_sym) || !@conf[idx.to_sym]
|
79
|
+
CliUtils.errx(1, "option #{idx} is either nil or missing")
|
80
|
+
end
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
# Parse CLO and env variable. If block is given it is passed with
|
85
|
+
# OptionParser object as a parameter.
|
86
|
+
def optParse
|
87
|
+
o = OptionParser.new do |o|
|
88
|
+
o.banner = @conf[:banner]
|
89
|
+
o.banner = @conf[:banner]
|
90
|
+
o.on('-v', 'Be more verbose.') { |i|
|
91
|
+
self[:verbose] += 1
|
92
|
+
}
|
93
|
+
o.on('-V', '--version', 'Show version & exit.') { |i|
|
94
|
+
puts Meta::VERSION
|
95
|
+
exit 0
|
96
|
+
}
|
97
|
+
o.on('--config NAME',
|
98
|
+
"Set a config name or file",
|
99
|
+
"(default is #{@conf[:config_name]}).") {|arg|
|
100
|
+
@conf[:config_name] = arg
|
101
|
+
}
|
102
|
+
o.on('--config-dirs', 'Show possible config locations.') {
|
103
|
+
mark = false
|
104
|
+
@conf[:config_dirs].each { |idx|
|
105
|
+
f = Pathname(idx) + @conf[:config_name]
|
106
|
+
if File.file?(f) && !mark
|
107
|
+
puts "* #{f}"
|
108
|
+
mark = true
|
109
|
+
else
|
110
|
+
puts " #{f}"
|
111
|
+
end
|
112
|
+
}
|
113
|
+
exit 0
|
114
|
+
}
|
115
|
+
|
116
|
+
yield o if block_given?
|
117
|
+
|
118
|
+
env = nil
|
119
|
+
env = ENV[@conf[:config_env]].shellsplit if ENV.key?(@conf[:config_env])
|
120
|
+
[env, ARGV].each { |i| o.parse!(i) if i }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Parse CLO, env variables and load config file.
|
125
|
+
#
|
126
|
+
# [reqOpts] an array of requied options
|
127
|
+
# [&block] a optional block for OptionParser
|
128
|
+
def load(reqOpts = [], &block)
|
129
|
+
optParse &block
|
130
|
+
loadFile
|
131
|
+
requiredOptions?(reqOpts)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# :erb: ruby-cli
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'open4'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
require_relative 'meta'
|
8
|
+
|
9
|
+
module Falsework
|
10
|
+
|
11
|
+
# Preferable exit codes. See sysexits(3) in FreeBSD.
|
12
|
+
EX_OK = 0
|
13
|
+
EX_USAGE = 64
|
14
|
+
EX_DATAERR = 65
|
15
|
+
EX_NOINPUT = 66
|
16
|
+
EX_NOUSER = 67
|
17
|
+
EX_NOHOST = 68
|
18
|
+
EX_UNAVAILABLE = 69
|
19
|
+
EX_SOFTWARE = 70
|
20
|
+
EX_OSERR = 71
|
21
|
+
EX_OSFILE = 72
|
22
|
+
EX_CANTCREAT = 73
|
23
|
+
EX_IOERR = 74
|
24
|
+
EX_TEMPFAIL = 75
|
25
|
+
EX_PROTOCOL = 76
|
26
|
+
EX_NOPERM = 77
|
27
|
+
EX_CONFIG = 78
|
28
|
+
|
29
|
+
# Common routines useful in any CLI program.
|
30
|
+
class CliUtils
|
31
|
+
# Physical location of program libraries.
|
32
|
+
DIR_LIB_SRC = Pathname.new File.dirname(__FILE__)
|
33
|
+
# veputs uses this to decide to put a newline or not to put.
|
34
|
+
NNL_MARK = '__NNL__'
|
35
|
+
|
36
|
+
# Class-wide verbosity level.
|
37
|
+
@@verbose = 0
|
38
|
+
|
39
|
+
# Setter.
|
40
|
+
def self.verbose=(val)
|
41
|
+
@@verbose = val
|
42
|
+
end
|
43
|
+
|
44
|
+
# Getter.
|
45
|
+
def self.getVerbose
|
46
|
+
@@verbose
|
47
|
+
end
|
48
|
+
|
49
|
+
# A handy check. Use it like:
|
50
|
+
#
|
51
|
+
# puts (CliUtils.debug ? "DEBUG mode" : "")
|
52
|
+
def self.debug
|
53
|
+
@@verbose >= 2
|
54
|
+
end
|
55
|
+
|
56
|
+
# A handy method that return a nicely formatted current global
|
57
|
+
# backtrace.
|
58
|
+
def self.getBacktrace
|
59
|
+
"#{$!}\n\nBacktrace:\n\n#{$!.backtrace.join("\n")}"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Print an error msg & exit if exit_code > 0.
|
63
|
+
def self.errx(exit_code = 0, msg)
|
64
|
+
$stderr.puts File.basename($0) + ' error: ' + msg.to_s
|
65
|
+
exit exit_code if exit_code > 0
|
66
|
+
end
|
67
|
+
|
68
|
+
# Print a warning.
|
69
|
+
def self.warnx(msg)
|
70
|
+
$stderr.puts File.basename($0) + ' warning: ' + msg.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
# [level] Verbosity level.
|
74
|
+
# [msg] A message to print.
|
75
|
+
#
|
76
|
+
# Don't print msg with a newline if it contains NNL_MARK at the end.
|
77
|
+
def self.veputs(level, msg)
|
78
|
+
t = msg.dup
|
79
|
+
|
80
|
+
nnl = false
|
81
|
+
if t.match(/#{NNL_MARK}$/)
|
82
|
+
t.sub!(/#{$&}/, '')
|
83
|
+
nnl = true
|
84
|
+
end
|
85
|
+
|
86
|
+
if @@verbose >= level
|
87
|
+
nnl ? print(t) : print("#{t}\n")
|
88
|
+
$stdout.flush
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Analogue to a shell command +which+.
|
93
|
+
def self.which(file)
|
94
|
+
return true if file =~ %r%\A/% and File.exist? file
|
95
|
+
|
96
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path|
|
97
|
+
File.exist? File.join(path, file)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Execute cmd and return an array [exit_status, stderr, stdout].
|
102
|
+
def self.exec(cmd)
|
103
|
+
so = sr = ''
|
104
|
+
status = Open4::popen4(cmd) { |pid, stdin, stdout, stderr|
|
105
|
+
so = stdout.read
|
106
|
+
sr = stderr.read
|
107
|
+
}
|
108
|
+
[status.exitstatus, sr, so]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|