rap 0.13.1 → 0.14.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/History CHANGED
@@ -1,4 +1,11 @@
1
- == 0.17.1 / 2009-06-06
1
+ == 0.14.0 / 2009-06-17
2
+
3
+ * added dependencies directly to Rap::Task
4
+ * removed sh method from Declarations
5
+ (include Rap::Utils instead)
6
+ * updates for Tap-0.18.0
7
+
8
+ == 0.13.1 / 2009-06-06
2
9
 
3
10
  Updates for Tap-0.17.1.
4
11
 
data/README CHANGED
@@ -43,7 +43,7 @@ Now from the command line:
43
43
  --------------------------------------------------------------------------------
44
44
  Says goodnight with a configurable message.
45
45
  --------------------------------------------------------------------------------
46
- usage: rap goodnight OBJ
46
+ usage: tap run -- goodnight OBJ
47
47
 
48
48
  configurations:
49
49
  --message MESSAGE
data/bin/rap CHANGED
@@ -24,6 +24,7 @@ end
24
24
 
25
25
  Dir.glob('[TtRr]apfile{,.rb}').each do |rapfile|
26
26
  next unless File.file?(rapfile)
27
+ env.scan(rapfile, "task|join|middleware")
27
28
  load rapfile
28
29
  end
29
30
 
@@ -52,7 +53,7 @@ when '--help', nil, '-T'
52
53
  end
53
54
 
54
55
  puts
55
- puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
56
+ puts "version #{Rap::VERSION} -- #{Rap::WEBSITE}"
56
57
  else
57
58
  begin
58
59
  schema = Tap::Schema.parse(ARGV)
data/lib/rap.rb CHANGED
@@ -3,4 +3,11 @@ require 'rap/declarations'
3
3
 
4
4
  module Rap
5
5
  autoload(:Rake, 'rap/rake')
6
+
7
+ MAJOR = 0
8
+ MINOR = 14
9
+ TINY = 0
10
+
11
+ VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
12
+ WEBSITE="http://tap.rubyforge.org/rap"
6
13
  end
@@ -1,5 +1,4 @@
1
1
  require 'rap/task'
2
- require 'rap/utils'
3
2
 
4
3
  module Rap
5
4
 
@@ -51,8 +50,6 @@ module Rap
51
50
  # See the {Syntax Reference}[link:files/doc/Syntax%20Reference.html] for more
52
51
  # information.
53
52
  module Declarations
54
- include Utils
55
-
56
53
  # The environment in which declared task classes are registered.
57
54
  # By default a Tap::Env for Dir.pwd.
58
55
  def Declarations.env() @@env ||= Tap::Env.new; end
@@ -238,7 +235,7 @@ module Rap
238
235
  alias desc original_desc
239
236
 
240
237
  # hide remaining Declarations methods (including Utils methods)
241
- private :namespace, :sh
238
+ private :namespace
242
239
  # :startdoc:
243
240
 
244
241
  private
@@ -35,6 +35,24 @@ module Rap
35
35
  class Task < Tap::Task
36
36
  class << self
37
37
 
38
+ # Returns class dependencies
39
+ attr_reader :dependencies
40
+
41
+ # Returns or initializes the instance of self cached with app.
42
+ def instance(app=Tap::App.instance, auto_initialize=true)
43
+ app.cache[self] ||= (auto_initialize ? new({}, app) : nil)
44
+ end
45
+
46
+ def inherited(child) # :nodoc:
47
+ unless child.instance_variable_defined?(:@source_file)
48
+ caller[0] =~ Lazydoc::CALLER_REGEXP
49
+ child.instance_variable_set(:@source_file, File.expand_path($1))
50
+ end
51
+
52
+ child.instance_variable_set(:@dependencies, dependencies.dup)
53
+ super
54
+ end
55
+
38
56
  # Sets actions.
39
57
  attr_writer :actions
40
58
 
@@ -73,7 +91,12 @@ module Rap
73
91
  #
74
92
  def parse!(argv=ARGV, app=Tap::App.instance)
75
93
  instance = super
76
- instance.args = argv
94
+
95
+ # store args on instance and clear so that instance
96
+ # will not be enqued with any inputs
97
+ instance.args = argv.dup
98
+ argv.clear
99
+
77
100
  instance
78
101
  end
79
102
 
@@ -135,62 +158,115 @@ module Rap
135
158
 
136
159
  subclass
137
160
  end
161
+
162
+ # Sets a class-level dependency; when task class B depends_on another
163
+ # task class A, instances of B are initialized to depend on a shared
164
+ # instance of A. The shared instance is specific to an app and can
165
+ # be accessed through instance(app).
166
+ #
167
+ # If a non-nil name is specified, depends_on will create a reader of
168
+ # the dependency instance.
169
+ #
170
+ # class A < Rap::Task
171
+ # end
172
+ #
173
+ # class B < Rap::Task
174
+ # depends_on :a, A
175
+ # end
176
+ #
177
+ # app = Tap::App.new
178
+ # b = B.new({}, app)
179
+ # b.dependencies # => [A.instance(app)]
180
+ # b.a # => A.instance(app)
181
+ #
182
+ # Returns self.
183
+ def depends_on(name, dependency_class)
184
+ unless dependency_class.ancestors.include?(Rap::Task)
185
+ raise "not a Rap::Task: #{dependency_class}"
186
+ end
187
+
188
+ unless dependencies.include?(dependency_class)
189
+ dependencies << dependency_class
190
+ end
191
+
192
+ if name
193
+ # returns the resolved result of the dependency
194
+ define_method(name) do
195
+ dependency_class.instance(app)
196
+ end
197
+
198
+ public(name)
199
+ end
200
+
201
+ self
202
+ end
138
203
  end
139
204
 
140
- # The result of self, set by call.
141
- attr_reader :result
205
+ instance_variable_set(:@dependencies, [])
142
206
 
143
- # The arguments assigned to self during call.
207
+ # An array of node dependencies
208
+ attr_reader :dependencies
209
+
210
+ # The arguments assigned to self.
144
211
  attr_accessor :args
145
212
 
146
213
  def initialize(config={}, app=Tap::App.instance)
147
214
  super
215
+ @dependencies = []
148
216
  @resolved = false
149
- @result = nil
150
217
  @args = nil
218
+
219
+ # setup class dependencies
220
+ self.class.dependencies.each do |dependency_class|
221
+ depends_on dependency_class.instance(app)
222
+ end
151
223
  end
152
224
 
153
- # Conditional call to the super call; only calls once. Returns result.
154
- def call(*args)
225
+ # Conditional call to the super call; only calls once and with args (if
226
+ # set). Call recursively resolves dependencies and raises an error for
227
+ # circular dependencies.
228
+ #
229
+ def call
230
+ if resolved?
231
+ return
232
+ end
155
233
 
156
- # Declaration tasks function as dependencies, but unlike normal
157
- # dependencies, they CAN take arguments from the command line.
158
- # Such arguments will be set as args, and be used to enque the
159
- # task.
160
- #
161
- # If the task executes from the queue first, args will be
162
- # provided to call and they should equal self.args. If the task
163
- # executes as a dependency first, call will not receive args and
164
- # in that case self.args will be used.
165
- #
166
- # This warns for cases that odd workflows can produce where the
167
- # args have been set and DIFFERENT args are used to enque the task.
168
- # In these cases always go with the pre-set args but warn the issue.
169
- self.args ||= args
170
- unless self.args == args
171
- if @resolved
172
- warn "warn: ignorning dependency task inputs #{args.inspect} (#{self})"
173
- else
174
- warn "warn: invoking dependency task with preset args #{self.args.inspect} and not inputs #{args.inspect} (#{self})"
175
- end
234
+ if resolving?
235
+ raise DependencyError.new(self)
176
236
  end
177
237
 
178
- unless @resolved
179
- @resolved = true
180
- @result = super(*self.args)
238
+ @resolved = nil
239
+ begin
240
+ dependencies.each do |dependency|
241
+ dependency.call
242
+ end
243
+ rescue(DependencyError)
244
+ $!.trace.unshift(self)
245
+ raise $!
181
246
  end
182
- result
247
+
248
+ @resolved = true
249
+ args ? super(*args) : super()
183
250
  end
184
251
 
252
+ # Alias for call.
253
+ def resolve!
254
+ call
255
+ end
256
+
185
257
  # Returns true if already resolved by call.
186
258
  def resolved?
187
- @resolved
259
+ @resolved == true
260
+ end
261
+
262
+ def resolving?
263
+ @resolved == nil
188
264
  end
189
265
 
190
266
  # Resets self so call will call again. Also sets result to nil.
191
267
  def reset
268
+ raise "cannot reset when resolving" if resolving?
192
269
  @resolved = false
193
- @result = nil
194
270
  end
195
271
 
196
272
  # Collects the inputs into an OpenStruct according to the class arg_names,
@@ -216,5 +292,29 @@ module Rap
216
292
 
217
293
  nil
218
294
  end
295
+
296
+ # Adds the dependency to self.
297
+ def depends_on(dependency)
298
+ raise "cannot depend on self" if dependency == self
299
+ unless dependencies.include?(dependency)
300
+ dependencies << dependency
301
+ end
302
+ self
303
+ end
304
+
305
+ end
306
+
307
+ # Raised for circular dependencies during Rap::Task.resolve!
308
+ class DependencyError < StandardError
309
+ attr_reader :trace
310
+
311
+ def initialize(task)
312
+ @trace = [task]
313
+ super()
314
+ end
315
+
316
+ def message
317
+ "circular dependency: [#{trace.collect {|task| task.class.to_s }.join(', ')}]"
318
+ end
219
319
  end
220
320
  end
@@ -1,18 +1,67 @@
1
+ require 'tempfile'
2
+
1
3
  module Rap
4
+ # Provides several shell utility methods for calling programs.
5
+ #
6
+ # == Windows
7
+ # MSDOS has command line length limits specific to the version of Windows being
8
+ # run (from http://www.ss64.com/nt/cmd.html):
9
+ #
10
+ # Windows NT:: 256 characters
11
+ # Windows 2000:: 2046 characters
12
+ # Windows XP:: 8190 characters
13
+ #
14
+ # Commands longer than these limits fail, usually with something like: 'the input
15
+ # line is too long'
2
16
  module Utils
17
+
18
+ # :startdoc:::-
3
19
  # Run the system command +cmd+, passing the result to the block, if given.
4
20
  # Raises an error if the command fails. Uses the same semantics as
5
21
  # Kernel::exec and Kernel::system.
6
22
  #
7
23
  # Based on FileUtils#sh from Rake.
24
+ # :startdoc:::+
8
25
  def sh(*cmd) # :yields: ok, status
9
26
  ok = system(*cmd)
10
27
 
11
28
  if block_given?
12
29
  yield(ok, $?)
13
30
  else
14
- ok or raise "Command failed with status (#{$?.exitstatus}): [#{cmd.join(' ')}]"
31
+ ok or raise "Command failed with status (#{$?.exitstatus}): [#{ cmd.join(' ')}]"
32
+ end
33
+ end
34
+
35
+ # Runs the system command +cmd+ using sh, redirecting the output to the
36
+ # specified file path. Uses the redirection command:
37
+ #
38
+ # "> \"#{path}\" 2>&1 #{cmd}"
39
+ #
40
+ # This redirection has been tested on Windows, OS X, and Fedora. See
41
+ # http://en.wikipedia.org/wiki/Redirection_(Unix) for pointers on
42
+ # redirection. This style of redirection SHOULD NOT be used with
43
+ # commands that contain other redirections.
44
+ def redirect_sh(cmd, path, &block) # :yields: ok, status
45
+ sh( "> \"#{path}\" 2>&1 #{cmd}", &block)
46
+ end
47
+
48
+ # Runs the system command +cmd+ and returns the output as a string.
49
+ def capture_sh(cmd, quiet=false, &block) # :yields: ok, status, tempfile_path
50
+ tempfile = Tempfile.new('shell_utils')
51
+ tempfile.close
52
+ redirect_sh(cmd, tempfile.path) do |ok, status|
53
+ if block_given?
54
+ yield(ok, $?, tempfile.path)
55
+ else
56
+ ok or raise %Q{Command failed with status (#{$?.exitstatus}): [#{cmd}]
57
+ -------------- command output -------------------
58
+ #{File.read(tempfile.path)}
59
+ -------------------------------------------------
60
+ }
61
+ end
15
62
  end
63
+
64
+ quiet == true ? "" : File.read(tempfile.path)
16
65
  end
17
66
  end
18
67
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-06 00:00:00 -06:00
12
+ date: 2009-06-17 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.17.1
23
+ version: 0.18.0
24
24
  version:
25
25
  description:
26
26
  email: simon.a.chiang@gmail.com
@@ -38,8 +38,8 @@ files:
38
38
  - lib/rap/declarations.rb
39
39
  - lib/rap/description.rb
40
40
  - lib/rap/rake.rb
41
- - lib/rap/utils.rb
42
41
  - lib/rap.rb
42
+ - lib/rap/utils.rb
43
43
  - tap.yml
44
44
  - README
45
45
  - MIT-LICENSE