ratch 1.0.0 → 1.1.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.
data/MANIFEST CHANGED
@@ -1,23 +1,37 @@
1
1
  doc
2
+ doc/log
3
+ doc/log/basic_stats
4
+ doc/log/basic_stats/index.html
5
+ doc/log/stats.log
6
+ doc/log/notes.xml
7
+ doc/log/syntax.log
8
+ doc/log/testunit.log
9
+ MANIFEST
2
10
  test
3
11
  test/README
4
12
  test/test_helper.rb
5
13
  test/test_task.rb
6
14
  README
7
15
  HISTORY
8
- METADATA
16
+ meta
17
+ meta/homepage
18
+ meta/summary
19
+ meta/abstract
20
+ meta/name
21
+ meta/requires
22
+ meta/author
23
+ meta/contact
9
24
  demo
10
25
  demo/tryme1.ratch
11
26
  demo/tryme-task.ratch
12
27
  lib
13
28
  lib/ratch
14
- lib/ratch/runmode.rb
15
- lib/ratch/pathglob.rb
29
+ lib/ratch/commandline.rb
30
+ lib/ratch/emailer.rb
16
31
  lib/ratch/core_ext
17
32
  lib/ratch/core_ext/pathname.rb
18
33
  lib/ratch/core_ext/object.rb
19
34
  lib/ratch/core_ext/facets.rb
20
- lib/ratch/core_ext/filetest.rb
21
35
  lib/ratch/core_ext/to_list.rb
22
36
  lib/ratch/core_ext/to_console.rb
23
37
  lib/ratch/core_ext/string.rb
@@ -30,7 +44,10 @@ lib/ratch/plugin.rb
30
44
  lib/ratch/task.rb
31
45
  lib/ratch/task2.rb
32
46
  lib/ratch/script.rb
47
+ VERSION
33
48
  NEWS
34
49
  bin
35
50
  bin/ratch
51
+ man
52
+ man/ratch.1
36
53
  COPYING
data/NEWS CHANGED
@@ -1,7 +1,12 @@
1
- = Release Notices
1
+ This is the second public release of Ratch.
2
2
 
3
- == 1.0.0 // 2008.08.16
3
+ Folio is now used a Ratch's backend. Folio handles
4
+ a great deal of what Ratch requires, so much of Ratch
5
+ is now just a thin wrapper around Folio.
4
6
 
5
- This is the initial public release of Ratch.
7
+ ### 1.1.0 / 2008-11-21
6
8
 
9
+ * 1 Major Change
10
+
11
+ * Overhauled system to use Folio on the backend.
7
12
 
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ ratch 1.1.0 stable (2008-11-22)
@@ -0,0 +1,39 @@
1
+
2
+ <html>
3
+ <head>
4
+ <title>Ratch Code Statistics</title>
5
+ <style>
6
+ h2{margin: 5px 0;}
7
+ table{width: 95%;}
8
+ th{background: #dcc;}
9
+ td{padding: 5px;}
10
+ .basic_stats{margin: 0 auto; width: 800px;}
11
+ </style>
12
+ <link rel="stylesheet" type="text/css" href="stats.css"/>
13
+ </head>
14
+ <body>
15
+ <div class="basic_stats">
16
+ <h1>Ratch -- Basic Code Statistics</h1>
17
+ <table class="counts" border="1">
18
+ <tr><th colspan="9"><h2>Counts</h2></th></tr>
19
+ <tr><th>TYPE</th><th>Total</th><th>Code</th><th>-%-</th><th>Docs</th><th>-%-</th><th>Blank</th><th>-%-</th><th>Files</th></tr>
20
+ <tr><th>Source</th><td>1669</td><td>731</td><td>43%</td><td>635</td><td>38%</td><td>303</td><td>18%</td><td>17</td></tr>
21
+ <tr><th>Test</th><td>50</td><td>30</td><td>1%</td><td>3</td><td>0%</td><td>17</td><td>1%</td><td>2</td></tr>
22
+ <tr><th>Total</th><td>1719</td><td>761</td><td>44%</td><td>638</td><td>37%</td><td>320</td><td>18%</td><td>19</td></tr>
23
+ </table>
24
+ <br/>
25
+ <table class="ratios" border="1">
26
+ <tr><th colspan="6"><h2>Ratios</h2></th></tr>
27
+ <tr><th>x:1</th><th>Code</th><th>Docs</th><th>Blank</th><th>Test</th><th>Total</th></tr>
28
+ <tr><th>Code</th><td> 1.0</td><td> 1.2</td><td> 2.4</td><td> 14.6</td><td> 0.4</td></tr>
29
+ <tr><th>Docs</th><td> 0.9</td><td> 1.0</td><td> 2.1</td><td> 12.7</td><td> 0.4</td></tr>
30
+ <tr><th>Blank</th><td> 0.4</td><td> 0.5</td><td> 1.0</td><td> 6.1</td><td> 0.2</td></tr>
31
+ <tr><th>Test</th><td> 0.1</td><td> 0.1</td><td> 0.2</td><td> 1.0</td><td> 0.0</td></tr>
32
+ <tr><th>Total</th><td> 2.3</td><td> 2.6</td><td> 5.5</td><td> 33.4</td><td> 1.0</td></tr>
33
+ </table>
34
+ <br/>
35
+ <div class="date">Sun Nov 23 14:09:41 -0500 2008</div>
36
+ </div>
37
+ </body>
38
+ </html>
39
+
@@ -0,0 +1,18 @@
1
+ <notes>
2
+ <set label="FIXME">
3
+ <file src="lib/ratch/emailer.rb">
4
+ <note line="154" type="FIXME">FIXME: Does not hide password.</note>
5
+ </file>
6
+ </set>
7
+ <set label="TODO">
8
+ <file src="lib/ratch/dsl.rb">
9
+ <note line="97" type="TODO">TODO: DEPRECATE #sh in favor of #shell (?)</note>
10
+ <note line="115" type="TODO">TODO: Replace these with Folio when Folio&apos;s is as capable.</note>
11
+ <note line="178" type="TODO">TODO: Deprecate these?</note>
12
+ <note line="406" type="TODO">TODO: Put this in FileTest instead?</note>
13
+ </file>
14
+ <file src="lib/ratch/plugin.rb">
15
+ <note line="57" type="TODO">TODO: Allow this to be optional? How?</note>
16
+ </file>
17
+ </set>
18
+ </notes>
@@ -0,0 +1,14 @@
1
+ Ratch Statistics
2
+ Mon Aug 18 15:10:07 -0400 2008
3
+
4
+ TYPE Total Code -%- Docs -%- Blank -%- Files
5
+ Source 1703 820 48% 572 33% 311 18% 18
6
+ Test 50 30 1% 3 0% 17 0% 2
7
+ Total 1753 850 48% 575 32% 328 18% 20
8
+
9
+ RATIO Code Docs Blank Test Total
10
+ Code 1.0 1.4 2.6 16.4 -
11
+ Docs - 1.0 1.8 11.4 -
12
+ Blank - - 1.0 6.2 -
13
+ Test - - - 1.0 -
14
+ Total 2.1 3.0 5.5 34.1 1.0
File without changes
@@ -0,0 +1,156 @@
1
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
2
+ Started
3
+ ..
4
+ Finished in 0.001091 seconds.
5
+
6
+ 2 tests, 2 assertions, 0 failures, 0 errors
7
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
8
+ Started
9
+ ..
10
+ Finished in 0.000625 seconds.
11
+
12
+ 2 tests, 2 assertions, 0 failures, 0 errors
13
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
14
+ Started
15
+ ..
16
+ Finished in 0.001007 seconds.
17
+
18
+ 2 tests, 2 assertions, 0 failures, 0 errors
19
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
20
+ Started
21
+ ..
22
+ Finished in 0.000613 seconds.
23
+
24
+ 2 tests, 2 assertions, 0 failures, 0 errors
25
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
26
+ Started
27
+ ..
28
+ Finished in 0.000791 seconds.
29
+
30
+ 2 tests, 2 assertions, 0 failures, 0 errors
31
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
32
+ Started
33
+ ..
34
+ Finished in 0.000624 seconds.
35
+
36
+ 2 tests, 2 assertions, 0 failures, 0 errors
37
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
38
+ Started
39
+ ..
40
+ Finished in 0.000694 seconds.
41
+
42
+ 2 tests, 2 assertions, 0 failures, 0 errors
43
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
44
+ Started
45
+ ..
46
+ Finished in 0.00107 seconds.
47
+
48
+ 2 tests, 2 assertions, 0 failures, 0 errors
49
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
50
+ Started
51
+ ..
52
+ Finished in 0.00084 seconds.
53
+
54
+ 2 tests, 2 assertions, 0 failures, 0 errors
55
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
56
+ Started
57
+ ..
58
+ Finished in 0.000842 seconds.
59
+
60
+ 2 tests, 2 assertions, 0 failures, 0 errors
61
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
62
+ Started
63
+ ..
64
+ Finished in 0.000838 seconds.
65
+
66
+ 2 tests, 2 assertions, 0 failures, 0 errors
67
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
68
+ Started
69
+ ..
70
+ Finished in 0.000672 seconds.
71
+
72
+ 2 tests, 2 assertions, 0 failures, 0 errors
73
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
74
+ Started
75
+ ..
76
+ Finished in 0.000864 seconds.
77
+
78
+ 2 tests, 2 assertions, 0 failures, 0 errors
79
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
80
+ Started
81
+ ..
82
+ Finished in 0.001295 seconds.
83
+
84
+ 2 tests, 2 assertions, 0 failures, 0 errors
85
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
86
+ Started
87
+ ..
88
+ Finished in 0.000868 seconds.
89
+
90
+ 2 tests, 2 assertions, 0 failures, 0 errors
91
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
92
+ Started
93
+ ..
94
+ Finished in 0.000871 seconds.
95
+
96
+ 2 tests, 2 assertions, 0 failures, 0 errors
97
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
98
+ Started
99
+ ..
100
+ Finished in 0.000838 seconds.
101
+
102
+ 2 tests, 2 assertions, 0 failures, 0 errors
103
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
104
+ Started
105
+ ..
106
+ Finished in 0.000866 seconds.
107
+
108
+ 2 tests, 2 assertions, 0 failures, 0 errors
109
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
110
+ Started
111
+ ..
112
+ Finished in 0.001105 seconds.
113
+
114
+ 2 tests, 2 assertions, 0 failures, 0 errors
115
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
116
+ Started
117
+ ..
118
+ Finished in 0.00067 seconds.
119
+
120
+ 2 tests, 2 assertions, 0 failures, 0 errors
121
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
122
+ Started
123
+ ..
124
+ Finished in 0.000891 seconds.
125
+
126
+ 2 tests, 2 assertions, 0 failures, 0 errors
127
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
128
+ Started
129
+ ..
130
+ Finished in 0.000872 seconds.
131
+
132
+ 2 tests, 2 assertions, 0 failures, 0 errors
133
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
134
+ Started
135
+ ..
136
+ Finished in 0.000836 seconds.
137
+
138
+ 2 tests, 2 assertions, 0 failures, 0 errors
139
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
140
+ Started
141
+ ..
142
+ Finished in 0.000735 seconds.
143
+
144
+ 2 tests, 2 assertions, 0 failures, 0 errors
145
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
146
+ Started
147
+ ..
148
+ Finished in 0.000644 seconds.
149
+
150
+ 2 tests, 2 assertions, 0 failures, 0 errors
151
+ Loaded suite [test/test_helper.rb, test/test_task.rb]
152
+ Started
153
+ ..
154
+ Finished in 0.000666 seconds.
155
+
156
+ 2 tests, 2 assertions, 0 failures, 0 errors
@@ -0,0 +1,16 @@
1
+ require 'clio/commandline'
2
+
3
+ module Ratch
4
+
5
+ class Commandline < Clio::Commandline
6
+ opt('--help' , "display help")
7
+ opt('--trace' , "trace execution")
8
+ opt('--debug' , "debug mode")
9
+ opt('--pretend -p' , "no disk writes")
10
+ opt('--quiet -q' , "run silently")
11
+ opt('--verbose' , "extra output")
12
+ opt('--force' , "force operations")
13
+ end
14
+
15
+ end
16
+
@@ -1,8 +1,5 @@
1
1
  class String
2
2
 
3
- # okay this is a bit much --we should subclass string.
4
- # but it will do for now and we will work this out
5
- # when CLIO is up and running.
6
3
  attr_accessor :color
7
4
 
8
5
  # Find actual filename (casefolding) and returns it.
@@ -37,6 +34,7 @@ class String
37
34
  blank = false
38
35
  end
39
36
  end
37
+ text = text.gsub("\n\n\n","\n\n")
40
38
  return text
41
39
  end
42
40
 
@@ -1,7 +1,7 @@
1
1
  #
2
2
  class Array
3
3
 
4
- # Convert an array into command line parameters.
4
+ # Convert an array into commandline parameters.
5
5
  # The array is accepted in the format of Ruby
6
6
  # method arguments --ie. [arg1, arg2, ..., hash]
7
7
 
@@ -5,24 +5,18 @@ require 'fileutils'
5
5
  require 'ratch/core_ext'
6
6
  require 'ratch/index'
7
7
  require 'ratch/io'
8
- require 'ratch/runmode'
8
+ require 'ratch/commandline'
9
+ require 'ratch/emailer'
9
10
 
10
11
  require 'ratch/task'
11
12
 
12
13
  require 'facets/platform'
13
- require 'facets/arguments'
14
- require 'facets/ziputils'
15
14
 
16
- #require 'annotatable'
15
+ require 'folio'
16
+
17
17
  #require 'facets/openhash'
18
18
  #require 'facets/argvector'
19
19
 
20
- begin
21
- require 'facets/net/smtp_tls'
22
- rescue LoadError
23
- require 'net/smtp'
24
- end
25
-
26
20
 
27
21
  module Ratch
28
22
 
@@ -40,101 +34,49 @@ module Ratch
40
34
 
41
35
  extend self
42
36
 
43
- @runmode = ioc[:mode] || Runmode.load_argv!
44
- @io = ioc[:io] || IO.new(@runmode)
45
- end
37
+ @cli = ioc[:cli] || Commandline.new
38
+ @io = ioc[:io] || IO.new(@cli)
46
39
 
47
- # Delgate run mode settings to Ratch::RunMode object.
48
- def runmode
49
- @runmode
50
- end
40
+ mode = {
41
+ :dryrun => @cli.dryrun?,
42
+ :verbose => @cli.verbose?
43
+ #:noop => ?
44
+ }
51
45
 
52
- # Delgate input/output routines to Ratch::IO object.
53
- def io
54
- @io
46
+ @fio = ioc[:fio] || Folio::Shell.new(mode)
55
47
  end
56
48
 
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
49
+ # Delagate input/output routines to Ratch::IO object.
50
+ attr :io
62
51
 
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
52
+ # Delagate file operations to Folio::Shell.
53
+ attr :fio
72
54
 
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
55
+ # Delagate commandline settings to Ratch::Commandline object.
56
+ attr :cli
82
57
 
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
58
+ alias_method :commandline, :cli
97
59
 
98
- # Current platform.
99
- def current_platform
100
- Platform.local.to_s
101
- end
60
+ # DEPRECATE!
61
+ alias_method :command, :cli
102
62
 
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
63
  #
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
64
+ #def commandline
65
+ # #@commandline ||= ArgVector.new(ARGV)
66
+ # @commandline
67
+ #end
119
68
 
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
69
+ def force? ; cli.force? ; end
70
+ def trace? ; cli.trace? ; end
71
+ def debug? ; cli.debug? ; end
72
+ def pretend? ; cli.pretend? ; end
73
+ def dryrun? ; cli.pretend? ; end
74
+ def quiet? ; cli.quiet? ; end
75
+ def verbose? ; cli.verbose? ; end
76
+
77
+ # Current platform.
78
+ def current_platform
79
+ Platform.local.to_s
138
80
  end
139
81
 
140
82
  # Shell runner.
@@ -152,42 +94,16 @@ module Ratch
152
94
  end
153
95
  end
154
96
 
155
- # TODO: DEPRECATE #sh in favor of #shell.
97
+ # TODO: DEPRECATE #sh in favor of #shell (?)
156
98
  alias_method :sh, :shell
157
99
 
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)
100
+ # Delegate to Filio::Shell.
101
+ def method_missing(s, *a, &b)
102
+ if @fio.respond_to?(s)
103
+ @fio.__send__(s, *a, &b)
104
+ else
105
+ super
106
+ end
191
107
  end
192
108
 
193
109
  # Provides convenient starting points in the file system.
@@ -196,6 +112,7 @@ module Ratch
196
112
  # home #=> #<Pathname:/home/jimmy>
197
113
  # work #=> #<Pathname:/home/jimmy/Documents>
198
114
  #
115
+ # TODO: Replace these with Folio when Folio's is as capable.
199
116
 
200
117
  # Current root path.
201
118
  def root(*args)
@@ -215,10 +132,10 @@ module Ratch
215
132
  alias_method :pwd, :work
216
133
 
217
134
  # Bonus FileUtils features.
218
- def cd(*a,&b)
219
- puts "cd #{a}" if dryrun? or trace?
220
- fileutils.chdir(*a,&b)
221
- end
135
+ #def cd(*a,&b)
136
+ # puts "cd #{a}" if dryrun? or trace?
137
+ # fileutils.chdir(*a,&b)
138
+ #end
222
139
 
223
140
  # Read file.
224
141
  def file_read(path)
@@ -242,13 +159,6 @@ module Ratch
242
159
  alias_method :exist?, :exists? #; module_function :exist?
243
160
  alias_method :path?, :exists? #; module_function :path?
244
161
 
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
162
  # Is a given path a regular file? If +path+ is a glob
253
163
  # then checks to see if all matches are refular files.
254
164
  def file?(path)
@@ -256,11 +166,6 @@ module Ratch
256
166
  paths.not_empty? && paths.all?{ |f| FileTest.file?(f) }
257
167
  end
258
168
 
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
169
  # Is a given path a directory? If +path+ is a glob
265
170
  # checks to see if all matches are directories.
266
171
  def dir?(path)
@@ -269,130 +174,67 @@ module Ratch
269
174
  end
270
175
  alias_method :directory?, :dir? #; module_function :directory?
271
176
 
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?
281
- #
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
177
 
301
- return true if mtimes.empty? # TODO: This the way to go here?
178
+ # TODO: Deprecate these?
302
179
 
303
- File.mtime(path) < mtimes.max
180
+ # Assert that a path exists.
181
+ def exists!(*paths)
182
+ abort "path not found #{path}" unless paths.any?{|path| exists?(path)}
304
183
  end
305
- =end
184
+ alias_method :exist!, :exists! #; module_function :exist!
185
+ alias_method :path!, :exists! #; module_function :path!
306
186
 
307
- # Glob files.
308
- def glob(*args, &blk)
309
- Dir.glob(*args, &blk)
187
+ # Assert that a given path is a file.
188
+ def file!(*paths)
189
+ abort "file not found #{path}" unless paths.any?{|path| file?(path)}
310
190
  end
311
191
 
312
- # Multiglob files.
313
- def multiglob(*args, &blk)
314
- Dir.multiglob(*args, &blk)
192
+ # Assert that a given path is a directory.
193
+ def dir!(*paths)
194
+ paths.each do |path|
195
+ abort "Directory not found: '#{path}'." unless dir?(path)
196
+ end
315
197
  end
198
+ alias_method :directory!, :dir! #; module_function :directory!
316
199
 
317
- # Multiglob recursive.
318
- def multiglob_r(*args, &blk)
319
- Dir.multiglob_r(*args, &blk)
320
- end
321
200
 
322
- # Stage by hard linking included files to a stage directory.
323
- #
324
- # stage_directory Stage directory.
325
- # files Files to link to stage.
201
+ # Load configuration data from a file.
202
+ # Results are cached and and empty Hash is
203
+ # returned if the file is not found.
326
204
  #
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
205
+ # Since they are YAML files, they can optionally
206
+ # end with '.yaml' or '.yml'.
207
+ def configuration(file)
208
+ @configuration ||= {}
209
+ @configuration[file] ||= (
210
+ begin
211
+ configuration!(file)
212
+ rescue LoadError
213
+ Hash.new{ |h,k| h[k] = {} }
350
214
  end
351
- end
352
-
353
- return stage_directory
215
+ )
354
216
  end
355
217
 
356
- # Delegate access to ZipUtils.
218
+ # Load configuration data from a file.
219
+ # The "bang" version will raise an error
220
+ # if file is not found. It also does not
221
+ # cache the results.
357
222
  #
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)
223
+ # Since they are YAML files, they can optionally
224
+ # end with '.yaml' or '.yml'.
225
+ def configuration!(file)
226
+ @configuration ||= {}
227
+ patt = file + "{.yml,.yaml,}"
228
+ path = Dir.glob(patt, File::FNM_CASEFOLD).find{ |f| File.file?(f) }
229
+ if path
230
+ # The || {} is in case the file is empty.
231
+ data = YAML::load(File.open(path)) || {}
232
+ @configuration[file] = data
372
233
  else
373
- raise ArguementError, "unsupported compression format -- #{format}"
234
+ raise LoadError, "Missing file -- #{path}"
374
235
  end
375
236
  end
376
237
 
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
238
  #
397
239
  #
398
240
  def naming_policy(*policies)
@@ -407,7 +249,7 @@ module Ratch
407
249
  #
408
250
  def apply_naming_policy(name, ext)
409
251
  naming_policy.each do |policy|
410
- case policy
252
+ case policy.to_s
411
253
  when /^low/, /^down/
412
254
  name = name.downcase
413
255
  when /^up/
@@ -438,60 +280,141 @@ module Ratch
438
280
  # message Mesage to send -or-
439
281
  # file File that contains message.
440
282
  #
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
283
+ def email(options)
284
+ emailer = Emailer.new(options.rekey)
285
+ success = emailer.email
286
+ if Exception === success
287
+ puts "Email failed: #{success.message}."
288
+ else
289
+ puts "Email sent successfully to #{success.join(';')}."
491
290
  end
492
291
  end
493
292
 
293
+
294
+ # Internal status report.
295
+ # Only output if dryrun or trace mode.
296
+ def status(message)
297
+ io.status(message)
298
+ end
299
+
300
+ # Convenient method to get simple console reply.
301
+ def ask(question, answers=nil)
302
+ io.ask(question, answers)
303
+ end
304
+
305
+ # Ask for a password. (FIXME: only for unix so far)
306
+ def password(prompt=nil)
307
+ io.password(prompt)
308
+ end
309
+
494
310
  end
495
311
 
496
312
  end
497
313
 
314
+
315
+
316
+
317
+
318
+
319
+
320
+ # Delegate file system routines to FileUtils or FileUtils::DryRun,
321
+ # depending on dryrun mode.
322
+ #def fileutils
323
+ # dryrun? ? ::FileUtils::DryRun : ::FileUtils
324
+ #end
325
+
326
+ # Add FileUtils Features
327
+ #::FileUtils.private_instance_methods(false).each do |meth|
328
+ # next if meth =~ /^fu_/
329
+ # module_eval %{
330
+ # def #{meth}(*a,&b)
331
+ # fileutils.#{meth}(*a,&b)
332
+ # end
333
+ # }
334
+ #end
335
+
336
+ # Add FileTest Features
337
+ #::FileTest.private_instance_methods(false).each do |meth|
338
+ # next if meth =~ /^fu_/
339
+ # module_eval %{
340
+ # def #{meth}(*a,&b)
341
+ # FileTest.#{meth}(*a,&b)
342
+ # end
343
+ # }
344
+ #end
345
+
346
+ # # Delegate access to ZipUtils.
347
+ # #
348
+ # def ziputils
349
+ # dryrun? ? ::ZipUtils::DryRun : ::ZipUtils
350
+ # end
351
+
352
+ # # Compress directory.
353
+ # #
354
+ # def compress(format, folder, file=nil, options={})
355
+ # case format.to_s.downcase
356
+ # when 'zip'
357
+ # ziputils.zip(folder, file, options)
358
+ # when 'tgz'
359
+ # ziputils.tgz(folder, file, options)
360
+ # when 'tbz', 'bzip'
361
+ # ziputils.tar_bzip(folder, file, options)
362
+ # else
363
+ # raise ArguementError, "unsupported compression format -- #{format}"
364
+ # end
365
+ # end
366
+
367
+ # # Create a zip file of a directory.
368
+ # #
369
+ # def zip(folder, file=nil, options={})
370
+ # ziputils.zip(folder, file, options)
371
+ # end
372
+
373
+ # # Create a tar.bz2 file of a directory.
374
+ # #
375
+ # def tar_bzip(folder, file=nil, options={})
376
+ # ziputils.tar_bzip(folder, file, options)
377
+ # end
378
+
379
+ # # Create a tgz file of a directory.
380
+ # #
381
+ # def tar_gzip(folder, file=nil, options={})
382
+ # ziputils.tar_gzip(folder, file, options)
383
+ # end
384
+ # alias_method :tgz, :tar_gzip
385
+
386
+ # Glob files.
387
+ #def glob(*args, &blk)
388
+ # Dir.glob(*args, &blk)
389
+ #end
390
+
391
+ # Multiglob files.
392
+ #def multiglob(*args, &blk)
393
+ # Dir.multiglob(*args, &blk)
394
+ #end
395
+
396
+ # Multiglob recursive.
397
+ #def multiglob_r(*args, &blk)
398
+ # Dir.multiglob_r(*args, &blk)
399
+ #end
400
+
401
+ =begin
402
+ # Does a path need updating, based on given +sources+?
403
+ # This compares mtimes of give paths. Returns false
404
+ # if the path needs to be updated.
405
+ #
406
+ # TODO: Put this in FileTest instead?
407
+
408
+ def out_of_date?(path, *sources)
409
+ return true unless File.exist?(path)
410
+
411
+ sources = sources.collect{ |source| Dir.glob(source) }.flatten
412
+ mtimes = sources.collect{ |file| File.mtime(file) }
413
+
414
+ return true if mtimes.empty? # TODO: This the way to go here?
415
+
416
+ File.mtime(path) < mtimes.max
417
+ end
418
+ =end
419
+
420
+