ratch 0.4.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/COPYING +17 -669
  2. data/HISTORY +6 -0
  3. data/MANIFEST +36 -0
  4. data/METADATA +14 -0
  5. data/NEWS +7 -0
  6. data/README +67 -17
  7. data/bin/ratch +5 -78
  8. data/demo/tryme-task.ratch +12 -0
  9. data/demo/tryme1.ratch +6 -0
  10. data/lib/ratch/core_ext.rb +6 -0
  11. data/lib/ratch/core_ext/facets.rb +1 -0
  12. data/lib/ratch/core_ext/filetest.rb +52 -0
  13. data/lib/ratch/core_ext/object.rb +8 -0
  14. data/lib/ratch/core_ext/pathname.rb +38 -0
  15. data/lib/ratch/core_ext/string.rb +44 -0
  16. data/lib/ratch/{dsl/console.rb → core_ext/to_console.rb} +2 -76
  17. data/lib/ratch/core_ext/to_list.rb +29 -0
  18. data/lib/ratch/dsl.rb +494 -49
  19. data/lib/ratch/index.rb +4 -0
  20. data/lib/ratch/io.rb +116 -0
  21. data/lib/ratch/pathglob.rb +73 -0
  22. data/lib/ratch/plugin.rb +55 -0
  23. data/lib/ratch/runmode.rb +69 -0
  24. data/lib/ratch/script.rb +52 -0
  25. data/lib/ratch/service.rb +33 -0
  26. data/lib/ratch/task.rb +249 -0
  27. data/lib/ratch/task2.rb +298 -0
  28. data/test/README +1 -0
  29. data/test/test_helper.rb +4 -0
  30. data/test/test_task.rb +46 -0
  31. metadata +90 -150
  32. data/CHANGES +0 -22
  33. data/TODO +0 -2
  34. data/bin/lt +0 -56
  35. data/bin/ludo +0 -14
  36. data/bin/manifest +0 -451
  37. data/bin/ratch-find +0 -21
  38. data/demo/WILMA +0 -1
  39. data/demo/XR +0 -9
  40. data/demo/lib/foo/foo.rb +0 -7
  41. data/demo/p.rb +0 -9
  42. data/demo/r.rb +0 -6
  43. data/demo/t.rb +0 -3
  44. data/demo/task/config.yaml +0 -4
  45. data/demo/task/one +0 -6
  46. data/demo/task/simplebuild +0 -15
  47. data/demo/task/stats +0 -4
  48. data/demo/task/task +0 -6
  49. data/demo/task/tryme +0 -10
  50. data/lib/ratch/dsl/argv.rb +0 -112
  51. data/lib/ratch/dsl/batch.rb +0 -232
  52. data/lib/ratch/dsl/build.rb +0 -174
  53. data/lib/ratch/dsl/email.rb +0 -108
  54. data/lib/ratch/dsl/file.rb +0 -205
  55. data/lib/ratch/dsl/meta.rb +0 -125
  56. data/lib/ratch/dsl/options.rb +0 -98
  57. data/lib/ratch/dsl/setup.rb +0 -124
  58. data/lib/ratch/dsl/sign.rb +0 -243
  59. data/lib/ratch/dsl/stage.rb +0 -147
  60. data/lib/ratch/dsl/task.rb +0 -139
  61. data/lib/ratch/dsl/upload.rb +0 -436
  62. data/lib/ratch/dsl/zip.rb +0 -59
  63. data/lib/ratch/extra/email.rb +0 -5
  64. data/lib/ratch/extra/stage.rb +0 -5
  65. data/lib/ratch/extra/zip.rb +0 -5
  66. data/lib/ratch/manager.rb +0 -53
  67. data/lib/ratch/manifest.rb +0 -540
  68. data/lib/ratch/metadata/information.rb +0 -258
  69. data/lib/ratch/metadata/package.rb +0 -108
  70. data/lib/ratch/metadata/project.rb +0 -523
  71. data/lib/ratch/metadata/release.rb +0 -108
  72. data/lib/ratch/support/errors.rb +0 -4
  73. data/lib/ratch/support/filename.rb +0 -18
  74. data/lib/ratch/support/filetest.rb +0 -29
  75. data/lib/ratch/toolset/ruby/announce +0 -224
  76. data/lib/ratch/toolset/ruby/compile +0 -49
  77. data/lib/ratch/toolset/ruby/install +0 -77
  78. data/lib/ratch/toolset/ruby/notes +0 -185
  79. data/lib/ratch/toolset/ruby/pack/gem +0 -93
  80. data/lib/ratch/toolset/ruby/pack/tgz +0 -46
  81. data/lib/ratch/toolset/ruby/pack/zip +0 -46
  82. data/lib/ratch/toolset/ruby/publish +0 -57
  83. data/lib/ratch/toolset/ruby/release +0 -8
  84. data/lib/ratch/toolset/ruby/setup +0 -1616
  85. data/lib/ratch/toolset/ruby/stamp +0 -33
  86. data/lib/ratch/toolset/ruby/stats +0 -138
  87. data/lib/ratch/toolset/ruby/test/crosstest +0 -305
  88. data/lib/ratch/toolset/ruby/test/extest +0 -129
  89. data/lib/ratch/toolset/ruby/test/isotest +0 -293
  90. data/lib/ratch/toolset/ruby/test/load +0 -39
  91. data/lib/ratch/toolset/ruby/test/loadtest +0 -28
  92. data/lib/ratch/toolset/ruby/test/syntax +0 -29
  93. data/lib/ratch/toolset/ruby/test/test +0 -26
  94. data/lib/ratch/toolset/sandbox/query +0 -11
  95. data/man/ratch.man +0 -73
  96. data/meta/MANIFEST +0 -130
  97. data/meta/config.yaml +0 -9
  98. data/meta/icli.yaml +0 -16
  99. data/meta/project.yaml +0 -20
  100. data/meta/ratch.roll +0 -2
  101. data/meta/xProjectInfo +0 -41
  102. data/task/clobber/package +0 -10
  103. data/task/man +0 -14
  104. data/task/publish +0 -57
  105. data/task/release +0 -9
  106. data/task/setup +0 -1616
  107. data/task/stats +0 -138
@@ -0,0 +1,29 @@
1
+ class Array
2
+
3
+ def to_list
4
+ self
5
+ end
6
+
7
+ end
8
+
9
+ class NilClass
10
+
11
+ def to_list
12
+ []
13
+ end
14
+
15
+ end
16
+
17
+ class String
18
+
19
+ # Helper method for cleaning list options.
20
+ # This will split the option on ':' or ';'
21
+ # if it is a string, rather than an array.
22
+ # And it will make sure there are no nil elements.
23
+
24
+ def to_list
25
+ split(/[:;,\n]/)
26
+ end
27
+
28
+ end
29
+
@@ -1,52 +1,497 @@
1
- # = TITLE:
2
- #
3
- # Main DSL Loader
4
- #
5
- # = COPYING:
6
- #
7
- # Copyright (c) 2007 Psi T Corp.
8
- #
9
- # This file is part of the ProUtils' Ratch program.
10
- #
11
- # Ratch is free software: you can redistribute it and/or modify
12
- # it under the terms of the GNU General Public License as published by
13
- # the Free Software Foundation, either version 3 of the License, or
14
- # (at your option) any later version.
15
- #
16
- # Ratch is distributed in the hope that it will be useful,
17
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- # GNU General Public License for more details.
1
+ require 'yaml'
2
+ require 'rbconfig' # replace with facets/rbsystem?
3
+ require 'fileutils'
4
+
5
+ require 'ratch/core_ext'
6
+ require 'ratch/index'
7
+ require 'ratch/io'
8
+ require 'ratch/runmode'
9
+
10
+ require 'ratch/task'
11
+
12
+ require 'facets/platform'
13
+ require 'facets/arguments'
14
+ require 'facets/ziputils'
15
+
16
+ #require 'annotatable'
17
+ #require 'facets/openhash'
18
+ #require 'facets/argvector'
19
+
20
+ begin
21
+ require 'facets/net/smtp_tls'
22
+ rescue LoadError
23
+ require 'net/smtp'
24
+ end
25
+
26
+
27
+ module Ratch
28
+
29
+ # = Ratch DSL
30
+ #
31
+ # The DSL class is the heart of Ratch, it provides all the convenece methods
32
+ # that make Ratch so convenient for writing Ruby-based batch script.
33
+ #
34
+ class DSL < Module
35
+
36
+ #
37
+ def initialize(ioc={})
38
+ include Taskable
39
+ include Taskable::Dsl
40
+
41
+ extend self
42
+
43
+ @runmode = ioc[:mode] || Runmode.load_argv!
44
+ @io = ioc[:io] || IO.new(@runmode)
45
+ end
46
+
47
+ # Delgate run mode settings to Ratch::RunMode object.
48
+ def runmode
49
+ @runmode
50
+ end
51
+
52
+ # Delgate input/output routines to Ratch::IO object.
53
+ def io
54
+ @io
55
+ end
56
+
57
+ # Delegate file system routines to FileUtils or FileUtils::DryRun,
58
+ # depending on dryrun mode.
59
+ def fileutils
60
+ dryrun? ? ::FileUtils::DryRun : ::FileUtils
61
+ end
62
+
63
+ # Add FileUtils Features
64
+ ::FileUtils.private_instance_methods(false).each do |meth|
65
+ next if meth =~ /^fu_/
66
+ module_eval %{
67
+ def #{meth}(*a,&b)
68
+ fileutils.#{meth}(*a,&b)
69
+ end
70
+ }
71
+ end
72
+
73
+ # Add FileTest Features
74
+ ::FileTest.private_instance_methods(false).each do |meth|
75
+ next if meth =~ /^fu_/
76
+ module_eval %{
77
+ def #{meth}(*a,&b)
78
+ FileTest.#{meth}(*a,&b)
79
+ end
80
+ }
81
+ end
82
+
83
+ #attr_writer :noharm
84
+ #attr_writer :force
85
+ #attr_writer :trace
86
+ #attr_writer :debug
87
+ #attr_writer :quiet
88
+ #alias_method :dryrun=, :noharm=
89
+
90
+ def force? ; runmode.force? ; end
91
+ def trace? ; runmode.trace? ; end
92
+ def debug? ; runmode.debug? ; end
93
+ def noharm? ; runmode.noharm? ; end
94
+ def dryrun? ; runmode.dryrun? ; end
95
+ def quiet? ; runmode.quiet? ; end
96
+ def verbose? ; runmode.verbose? ; end
97
+
98
+ # Current platform.
99
+ def current_platform
100
+ Platform.local.to_s
101
+ end
102
+
103
+ # Load configuration data from a file.
104
+ # Reesults are cached and and empty Hash is
105
+ # returned if the file is not found.
106
+ #
107
+ # Since they are YAML files, they can optionally
108
+ # end with '.yaml' or '.yml'.
109
+ def configuration(file)
110
+ @configuration ||= {}
111
+ @configuration[file] ||= (
112
+ begin
113
+ configuration!(file)
114
+ rescue LoadError
115
+ Hash.new{ |h,k| h[k] = {} }
116
+ end
117
+ )
118
+ end
119
+
120
+ # Load configuration data from a file.
121
+ # The "bang" version will raise an error
122
+ # if file is not found. It also does not
123
+ # cache the results.
124
+ #
125
+ # Since they are YAML files, they can optionally
126
+ # end with '.yaml' or '.yml'.
127
+ def configuration!(file)
128
+ @configuration ||= {}
129
+ patt = file + "{.yml,.yaml,}"
130
+ path = Dir.glob(patt, File::FNM_CASEFOLD).find{ |f| File.file?(f) }
131
+ if path
132
+ # The || {} is in case the file is empty.
133
+ data = YAML::load(File.open(path)) || {}
134
+ @configuration[file] = data
135
+ else
136
+ raise LoadError, "Missing file -- #{path}"
137
+ end
138
+ end
139
+
140
+ # Shell runner.
141
+ def shell(cmd)
142
+ if dryrun?
143
+ puts cmd
144
+ true
145
+ else
146
+ puts "--> system call: #{cmd}" if trace?
147
+ if quiet?
148
+ silently{ system(cmd) }
149
+ else
150
+ system(cmd)
151
+ end
152
+ end
153
+ end
154
+
155
+ # TODO: DEPRECATE #sh in favor of #shell.
156
+ alias_method :sh, :shell
157
+
158
+ #
159
+ def commandline
160
+ #@commandline ||= ArgVector.new(ARGV)
161
+ @commandline ||= CLI::Arguments.new #(ARGV)
162
+ end
163
+
164
+ # Duplicate of ARGV.
165
+ #def argv
166
+ # @argv ||= ARGV.dup
167
+ #end
168
+
169
+
170
+ # Convert command line argv to args.
171
+ #
172
+ # TODO Is this implmented as expected?
173
+ #def command_parameters
174
+ # ARGV.to_params
175
+ #end
176
+
177
+ # Internal status report.
178
+ # Only output if dryrun or trace mode.
179
+ def status(message)
180
+ io.status(message)
181
+ end
182
+
183
+ # Convenient method to get simple console reply.
184
+ def ask(question, answers=nil)
185
+ io.ask(question, answers)
186
+ end
187
+
188
+ # Ask for a password. (FIXME: only for unix so far)
189
+ def password(prompt=nil)
190
+ io.password(prompt)
191
+ end
192
+
193
+ # Provides convenient starting points in the file system.
194
+ #
195
+ # root #=> #<Pathname:/>
196
+ # home #=> #<Pathname:/home/jimmy>
197
+ # work #=> #<Pathname:/home/jimmy/Documents>
198
+ #
199
+
200
+ # Current root path.
201
+ def root(*args)
202
+ Pathname['/', *args]
203
+ end
204
+
205
+ # Current home path.
206
+ def home(*args)
207
+ Pathname['~', *args].expand_path
208
+ end
209
+
210
+ # Current working path.
211
+ def work(*args)
212
+ Pathname['.', *args]
213
+ end
214
+
215
+ alias_method :pwd, :work
216
+
217
+ # Bonus FileUtils features.
218
+ def cd(*a,&b)
219
+ puts "cd #{a}" if dryrun? or trace?
220
+ fileutils.chdir(*a,&b)
221
+ end
222
+
223
+ # Read file.
224
+ def file_read(path)
225
+ File.read(path)
226
+ end
227
+
228
+ # Write file.
229
+ def file_write(path, text)
230
+ if dryrun?
231
+ puts "write #{path}"
232
+ else
233
+ File.open(path, 'w'){ |f| f << text }
234
+ end
235
+ end
236
+
237
+ # Assert that a path exists.
238
+ def exists?(path)
239
+ paths = Dir.glob(path)
240
+ paths.not_empty?
241
+ end
242
+ alias_method :exist?, :exists? #; module_function :exist?
243
+ alias_method :path?, :exists? #; module_function :path?
244
+
245
+ # Assert that a path exists.
246
+ def exists!(*paths)
247
+ abort "path not found #{path}" unless paths.any?{|path| exists?(path)}
248
+ end
249
+ alias_method :exist!, :exists! #; module_function :exist!
250
+ alias_method :path!, :exists! #; module_function :path!
251
+
252
+ # Is a given path a regular file? If +path+ is a glob
253
+ # then checks to see if all matches are refular files.
254
+ def file?(path)
255
+ paths = Dir.glob(path)
256
+ paths.not_empty? && paths.all?{ |f| FileTest.file?(f) }
257
+ end
258
+
259
+ # Assert that a given path is a file.
260
+ def file!(*paths)
261
+ abort "file not found #{path}" unless paths.any?{|path| file?(path)}
262
+ end
263
+
264
+ # Is a given path a directory? If +path+ is a glob
265
+ # checks to see if all matches are directories.
266
+ def dir?(path)
267
+ paths = Dir.glob(path)
268
+ paths.not_empty? && paths.all?{ |f| FileTest.directory?(f) }
269
+ end
270
+ alias_method :directory?, :dir? #; module_function :directory?
271
+
272
+ # Assert that a given path is a directory.
273
+ def dir!(*paths)
274
+ paths.each do |path|
275
+ abort "Directory not found: '#{path}'." unless dir?(path)
276
+ end
277
+ end
278
+ alias_method :directory!, :dir! #; module_function :directory!
279
+
280
+ # # Is a file a task?
20
281
  #
21
- # You should have received a copy of the GNU General Public License
22
- # along with Ratch. If not, see <http://www.gnu.org/licenses/>.
23
-
24
- require 'yaml' # make it generally available
25
- require 'rbconfig' # replace with facets/system?
26
-
27
- require 'ratch/dsl/options'
28
- require 'ratch/dsl/batch'
29
- require 'ratch/dsl/build'
30
- require 'ratch/dsl/task'
31
- require 'ratch/dsl/console'
32
- require 'ratch/dsl/file'
33
- require 'ratch/dsl/argv'
34
- require 'ratch/dsl/meta'
35
-
36
- # Load ratch dsl functionality into toplevel.
37
- # This loads into the toplevel's metaclass b/c we don't want
38
- # all these utilies to invade every object [do we?]
39
-
40
- class << self
41
- include Ratch::Dsl::Options
42
- include Ratch::Dsl::Batch
43
- include Ratch::Dsl::Builds
44
- include Ratch::Dsl::Tasks
45
- include Ratch::Dsl::Filing
46
- include Ratch::Dsl::Console
47
- include Ratch::Dsl::Argv
48
- include Ratch::Dsl::Meta
282
+ # def task?(path)
283
+ # task = File.dirname($0) + "/#{path}"
284
+ # task.chomp!('!')
285
+ # task if FileTest.file?(task) && FileTest.executable?(task)
286
+ # end
287
+
288
+ =begin
289
+ # Does a path need updating, based on given +sources+?
290
+ # This compares mtimes of give paths. Returns false
291
+ # if the path needs to be updated.
292
+ #
293
+ # TODO: Put this in FileTest instead?
294
+
295
+ def out_of_date?(path, *sources)
296
+ return true unless File.exist?(path)
297
+
298
+ sources = sources.collect{ |source| Dir.glob(source) }.flatten
299
+ mtimes = sources.collect{ |file| File.mtime(file) }
300
+
301
+ return true if mtimes.empty? # TODO: This the way to go here?
302
+
303
+ File.mtime(path) < mtimes.max
304
+ end
305
+ =end
306
+
307
+ # Glob files.
308
+ def glob(*args, &blk)
309
+ Dir.glob(*args, &blk)
310
+ end
311
+
312
+ # Multiglob files.
313
+ def multiglob(*args, &blk)
314
+ Dir.multiglob(*args, &blk)
315
+ end
316
+
317
+ # Multiglob recursive.
318
+ def multiglob_r(*args, &blk)
319
+ Dir.multiglob_r(*args, &blk)
320
+ end
321
+
322
+ # Stage by hard linking included files to a stage directory.
323
+ #
324
+ # stage_directory Stage directory.
325
+ # files Files to link to stage.
326
+ #
327
+ # TODO: Rename to linkstage or something less likely to name clash?
328
+
329
+ def stage(stage_directory, files)
330
+ return stage_directory if dryrun? # Don't link to stage if dryrun.
331
+
332
+ if File.directory?(stage_directory) # Ensure existance of staging area
333
+ #raise(OverwriteError, stage_directory) unless force?
334
+ rm_r(stage_directory)
335
+ end
336
+
337
+ mkdir_p(stage_directory) #dir = File.expand_path(stage)
338
+
339
+ #files = package.filelist #+ [package.manifest_file]
340
+
341
+ # TODO Dryrun test here or before folder creation?
342
+ files.each do |f| # Link files into staging area.
343
+ file = File.join(stage_directory, f)
344
+ if File.directory?(f)
345
+ mkdir_p(file)
346
+ else
347
+ unless File.exist?(file) and File.mtime(file) >= File.mtime(f)
348
+ ln(f, file) #safe_ln ?
349
+ end
350
+ end
351
+ end
352
+
353
+ return stage_directory
354
+ end
355
+
356
+ # Delegate access to ZipUtils.
357
+ #
358
+ def ziputils
359
+ dryrun? ? ::ZipUtils::DryRun : ::ZipUtils
360
+ end
361
+
362
+ # Compress directory.
363
+
364
+ def compress(format, folder, file=nil, options={})
365
+ case format.to_s.downcase
366
+ when 'zip'
367
+ ziputils.zip(folder, file, options)
368
+ when 'tgz'
369
+ ziputils.tgz(folder, file, options)
370
+ when 'tbz', 'bzip'
371
+ ziputils.tar_bzip(folder, file, options)
372
+ else
373
+ raise ArguementError, "unsupported compression format -- #{format}"
374
+ end
375
+ end
376
+
377
+ # Create a zip file of a directory.
378
+ #
379
+ def zip(folder, file=nil, options={})
380
+ ziputils.zip(folder, file, options)
381
+ end
382
+
383
+ # Create a tar.bz2 file of a directory.
384
+ #
385
+ def tar_bzip(folder, file=nil, options={})
386
+ ziputils.tar_bzip(folder, file, options)
387
+ end
388
+
389
+ # Create a tgz file of a directory.
390
+ #
391
+ def tar_gzip(folder, file=nil, options={})
392
+ ziputils.tar_gzip(folder, file, options)
393
+ end
394
+ alias_method :tgz, :tar_gzip
395
+
396
+ #
397
+ #
398
+ def naming_policy(*policies)
399
+ if policies.empty?
400
+ @naming_policy ||= ['down', 'ext']
401
+ else
402
+ @naming_policy = policies
403
+ end
404
+ end
405
+
406
+ #
407
+ #
408
+ def apply_naming_policy(name, ext)
409
+ naming_policy.each do |policy|
410
+ case policy
411
+ when /^low/, /^down/
412
+ name = name.downcase
413
+ when /^up/
414
+ name = name.upcase
415
+ when /^cap/
416
+ name = name.capitalize
417
+ when /^ext/
418
+ name = name + ".#{ext}"
419
+ end
420
+ end
421
+ name
422
+ end
423
+
424
+ # Email function to easily send out an email.
425
+ #
426
+ # Settings:
427
+ #
428
+ # subject Subject of email message.
429
+ # from Message FROM address [email].
430
+ # to Email address to send announcemnt.
431
+ # server Email server to route message.
432
+ # port Email server's port.
433
+ # domain Email server's domain name.
434
+ # account Email account name if needed.
435
+ # password Password for login..
436
+ # login Login type: plain, cram_md5 or login [plain].
437
+ # secure Uses TLS security, true or false? [false]
438
+ # message Mesage to send -or-
439
+ # file File that contains message.
440
+ #
441
+ def email(message, settings)
442
+ settings ||= {}
443
+ settings.rekey
444
+
445
+ server = settings[:server]
446
+ account = settings[:account] || ENV['EMAIL_ACCOUNT']
447
+ passwd = settings[:password] || ENV['EMAIL_PASSWORD']
448
+ login = settings[:login].to_sym
449
+ subject = settings[:subject]
450
+ mail_to = settings[:to] || settings[:mail_to]
451
+ mail_from = settings[:from] || settings[:mail_from]
452
+ secure = settings[:secure]
453
+ domain = settings[:domain] || server
454
+
455
+ port ||= (secure ? 465 : 25)
456
+ account ||= mail_from
457
+ login ||= :plain
458
+
459
+ #mail_to = nil if mail_to.empty?
460
+
461
+ raise ArgumentError, "missing email field -- server" unless server
462
+ raise ArgumentError, "missing email field -- account" unless account
463
+ raise ArgumentError, "missing email field -- subject" unless subject
464
+ raise ArgumentError, "missing email field -- to" unless mail_to
465
+ raise ArgumentError, "missing email field -- from" unless mail_from
466
+
467
+ passwd ||= password(account)
468
+
469
+ mail_to = [mail_to].flatten.compact
470
+
471
+ msg = ""
472
+ msg << "From: #{mail_from}\n"
473
+ msg << "To: #{mail_to.join(';')}\n"
474
+ msg << "Subject: #{subject}\n"
475
+ msg << ""
476
+ msg << message
477
+
478
+ begin
479
+ Net::SMTP.enable_tls if Net::SMTP.respond_to?(:enable_tls) and secure
480
+ Net::SMTP.start(server, port, domain, account, passwd, login) do |s|
481
+ s.send_message( msg, mail_from, mail_to )
482
+ end
483
+ puts "Email sent successfully to #{mail_to.join(';')}."
484
+ return true
485
+ rescue => e
486
+ if trace?
487
+ raise e
488
+ else
489
+ abort "Email delivery failed."
490
+ end
491
+ end
492
+ end
493
+
494
+ end
495
+
49
496
  end
50
497
 
51
- # run main task
52
- END { run_main }