falsework 1.3.0 → 2.0.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 (41) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +2 -2
  3. data/README.rdoc +6 -5
  4. data/Rakefile +14 -10
  5. data/bin/falsework +25 -25
  6. data/doc/NEWS.rdoc +18 -0
  7. data/doc/README.rdoc +6 -5
  8. data/doc/TODO.org +2 -1
  9. data/lib/falsework/cliconfig.rb +135 -0
  10. data/lib/falsework/cliutils.rb +112 -0
  11. data/lib/falsework/meta.rb +1 -1
  12. data/lib/falsework/mould.rb +23 -20
  13. data/lib/falsework/templates/{ruby-naive → ruby-cli}/#config.yaml +0 -0
  14. data/lib/falsework/templates/{ruby-naive → ruby-cli}/.gitignore.#erb +0 -0
  15. data/lib/falsework/templates/{ruby-naive → ruby-cli}/Gemfile +1 -1
  16. data/lib/falsework/templates/{ruby-naive/doc → ruby-cli}/README.rdoc +1 -1
  17. data/lib/falsework/templates/{ruby-naive → ruby-cli}/Rakefile +0 -0
  18. data/lib/falsework/templates/ruby-cli/bin/%%@project%% +26 -0
  19. data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/#doc.rdoc +1 -1
  20. data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/LICENSE +0 -0
  21. data/lib/falsework/templates/{ruby-naive → ruby-cli}/doc/NEWS.rdoc +0 -0
  22. data/lib/falsework/templates/{ruby-naive → ruby-cli/doc}/README.rdoc +1 -1
  23. data/lib/falsework/templates/{ruby-naive → ruby-cli}/etc/%%@project%%.yaml +0 -0
  24. data/lib/falsework/templates/ruby-cli/lib/%%@project%%/cliconfig.rb +137 -0
  25. data/lib/falsework/templates/ruby-cli/lib/%%@project%%/cliutils.rb +114 -0
  26. data/lib/falsework/templates/{ruby-naive → ruby-cli}/lib/%%@project%%/meta.rb +0 -0
  27. data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/helper.rb +1 -1
  28. data/lib/falsework/templates/{ruby-naive/test/helper_trestle.rb → ruby-cli/test/helper_cliutils.rb} +4 -4
  29. data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/rake_git.rb +2 -2
  30. data/lib/falsework/templates/{ruby-naive → ruby-cli}/test/test_%%@project%%.rb +0 -0
  31. data/test/helper.rb +1 -1
  32. data/test/{helper_trestle.rb → helper_cliutils.rb} +3 -3
  33. data/test/rake_erb_templates.rb +3 -3
  34. data/test/rake_git.rb +1 -1
  35. data/test/templates/config-02.yaml +2 -0
  36. data/test/test_cl.rb +9 -5
  37. data/test/test_exe.rb +26 -21
  38. metadata +31 -26
  39. data/lib/falsework/templates/ruby-naive/bin/%%@project%% +0 -31
  40. data/lib/falsework/templates/ruby-naive/lib/%%@project%%/trestle.rb +0 -230
  41. data/lib/falsework/trestle.rb +0 -228
@@ -1,228 +0,0 @@
1
- # :erb:
2
- require 'yaml'
3
- require 'shellwords.rb'
4
- require 'optparse'
5
- require 'pp'
6
- require 'open4'
7
-
8
- require_relative 'meta'
9
-
10
- module Falsework
11
- # A common routines from falsework with love.
12
- class Trestle
13
-
14
- # Execute _cmd_ and return a list [exit_status, stderr,
15
- # stdout]. Very handy.
16
- def self.cmd_run(cmd)
17
- so = sr = ''
18
- status = Open4::popen4(cmd) { |pid, stdin, stdout, stderr|
19
- so = stdout.read
20
- sr = stderr.read
21
- }
22
- [status.exitstatus, sr, so]
23
- end
24
-
25
- # Return a directory with program libraries.
26
- def self.gem_libdir
27
- t = ["#{File.dirname(File.realpath($0))}/../lib/#{Falsework::Meta::NAME}",
28
- "#{Gem.dir}/gems/#{Falsework::Meta::NAME}-#{Falsework::Meta::VERSION}/lib/#{Falsework::Meta::NAME}",
29
- "lib/#{Falsework::Meta::NAME}"]
30
- t.each {|i| return i if File.readable?(i) }
31
- fail "all paths are invalid: #{t}"
32
- end
33
-
34
- # Analogue to shell command +which+.
35
- def self.in_path?(file)
36
- return true if file =~ %r%\A/% and File.exist? file
37
-
38
- ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path|
39
- File.exist? File.join(path, file)
40
- end
41
- end
42
-
43
- # Print an error message _t_ and exit if _ec_ > 0.
44
- def self.errx(ec, t)
45
- $stderr.puts File.basename($0) + ' error: ' + t.to_s
46
- exit ec if ec > 0
47
- end
48
-
49
- # Print a warning.
50
- def self.warnx(t)
51
- $stderr.puts File.basename($0) + ' warning: ' + t.to_s
52
- end
53
-
54
- # #veputs uses this to decide to put a newline or not to put.
55
- NNL_MARK = '__NNL__'
56
-
57
- # Use this in your CL options to check if modifying some variable is
58
- # not an idempotent act.
59
- attr_reader :cl_opt_protect
60
-
61
- # [conf] Typically must be a reference to some global variable.
62
- def initialize(conf)
63
- @conf = conf
64
- @conf[:verbose] = 0
65
- @conf[:banner] = "Usage: #{File.basename($0)} [options]"
66
- @conf[:config] = Meta::NAME + '.yaml'
67
- @conf[:config_dirs] = [ENV['HOME']+'/.'+Meta::NAME,
68
- File.absolute_path("#{File.dirname(File.realpath($0))}/../etc"),
69
- '/usr/etc', '/usr/local/etc', '/etc',
70
- "#{Gem.dir}/gems/#{Meta::NAME}-#{Meta::VERSION}/etc"
71
- ]
72
- @conf[:config_env] = [Meta::NAME.upcase + '_CONF']
73
-
74
- @cl_parsing_times = 0 # not used
75
- @cl_opt_protect = false
76
- end
77
-
78
- # [level] A verbose level.
79
- # [t] A string to print.
80
- #
81
- # Don't print _t_ with a newline if it contains NNL_MARK at the end.
82
- def veputs(level, t)
83
- t = t.dup
84
- nnl = nil
85
- if t.match(/#{NNL_MARK}$/)
86
- t.sub!(/#{$&}/, '')
87
- nnl = 1
88
- end
89
-
90
- if @conf[:verbose] >= level
91
- nnl ? print(t) : print("#{t}\n")
92
- $stdout.flush
93
- end
94
- end
95
-
96
- # Run all configuration parsing in a batch.
97
- #
98
- # [rvars] A list of variable names which must be in the
99
- # configuration file.
100
- #
101
- # If no block is given, only standard CL options will be analysed.
102
- def config_parse(rvars, &block)
103
- cb = ->(b, src) {
104
- if b
105
- block.call src
106
- else
107
- # very basic default options
108
- cl_parse(src, nil, true)
109
- end
110
- }
111
-
112
- # 1. parse env
113
- @conf[:config_env].each {|i|
114
- # puts '0 run:'
115
- cb.call(block_given?, ENV[i].shellsplit) if ENV.key?(i)
116
- }
117
-
118
- # 2. parse CL in case of '--config' option
119
- # puts "\n1 run"
120
- @cl_opt_protect = true
121
- cb.call(block_given?, ARGV.dup)
122
- @cl_opt_protect = false
123
-
124
- # 3. load the configuration file & do the final CL parsing
125
- begin
126
- # puts "\n2 run"
127
- r = config_flat_load(rvars)
128
- rescue
129
- Trestle.errx(1, "cannot load config: #{Trestle.get_backtrace}")
130
- end
131
- veputs(1, "OK") if r
132
- cb.call(block_given?, ARGV)
133
- end
134
-
135
- # Load a config file immediately if it contains '/' in its name,
136
- # otherwise search through several dirs for it.
137
- #
138
- # [rvars] a list of requied variables in the config
139
- #
140
- # Return a loaded filename or nil on error.
141
- def config_flat_load(rvars)
142
- p = ->(f) {
143
- veputs(1, "Loading #{f}... " + NNL_MARK)
144
- if File.file?(f)
145
- begin
146
- myconf = YAML.load_file(f)
147
- rescue
148
- abort("cannot parse #{f}: #{$!}")
149
- end
150
- rvars.each { |i|
151
- fail "missing or nil '#{i}' in #{f}" if ! myconf.key?(i.to_sym) || ! myconf[i.to_sym]
152
- }
153
- @conf.merge!(myconf)
154
- return @conf[:config]
155
- end
156
-
157
- veputs(1, "FAILED")
158
- return nil
159
- }
160
-
161
- if @conf[:config].index('/')
162
- return p.call(@conf[:config])
163
- else
164
- @conf[:config_dirs].each {|dir|
165
- return dir+'/'+@conf[:config] if p.call(dir + '/' + @conf[:config])
166
- }
167
- end
168
-
169
- return nil
170
- end
171
-
172
-
173
- # Parses CL-like options.
174
- #
175
- # [src] An array of options (usually +ARGV+).
176
- #
177
- # If _o_ is non nil function parses _src_ immediately, otherwise it
178
- # only creates +OptionParser+ object and return it (if _simple_ is
179
- # false).
180
- def cl_parse(src, o = nil, simple = false)
181
- if ! o then
182
- # puts "NEW o (#{cl_opt_protect})" + src.to_s
183
- o = OptionParser.new
184
- o.banner = @conf[:banner]
185
- o.on('-v', 'Be more verbose.') { |i|
186
- # puts "cl_parsing_times "+cl_parsing_times.to_s
187
- @conf[:verbose] += 1 unless cl_opt_protect
188
- }
189
- o.on('-V', 'Show version & exit.') { |i|
190
- puts Meta::VERSION
191
- exit 0
192
- }
193
- o.on('--config NAME', "Set a config name (default is #{@conf[:config]}).") {|i|
194
- @conf[:config] = i
195
- }
196
- o.on('--config-dirs', 'Show possible config locations.') {
197
- mark = false
198
- @conf[:config_dirs].each { |idx|
199
- f = idx + '/' + @conf[:config]
200
- if File.readable?(f) && !mark
201
- puts "* " + f
202
- mark = true
203
- else
204
- puts " " + f
205
- end
206
- }
207
- exit 0
208
- }
209
-
210
- return o if ! simple
211
- end
212
-
213
- begin
214
- o.parse!(src)
215
- @cl_parsing_times += 1
216
- rescue
217
- Trestle.errx(1, $!.to_s)
218
- end
219
- end
220
-
221
- # A handy proc that return a nice formatted current global
222
- # backtrace.
223
- def self.get_backtrace
224
- "#{$!}\n\nBacktrace:\n\n#{$!.backtrace.join("\n")}"
225
- end
226
-
227
- end # trestle
228
- end