AntBuilder 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README +24 -0
- data/classpath/README +16 -0
- data/classpath/leafcutter-src.jar +0 -0
- data/classpath/leafcutter.jar +0 -0
- data/classpath/log4j.properties +4 -0
- data/docs/index.html +517 -0
- data/docs/index_html_7cda332d.jpg +0 -0
- data/docs/publish.bat +4 -0
- data/examples/basic/check_install.rb +6 -0
- data/examples/jruby/build.rb +361 -0
- data/examples/jruby/readme.txt +14 -0
- data/examples/script1/env/dev/environment.jar +0 -0
- data/examples/script1/env/prod/environment.jar +0 -0
- data/examples/script1/env/test/environment.jar +0 -0
- data/examples/script1/readme.txt +16 -0
- data/examples/script1/update_version.rb +91 -0
- data/examples/script1/version.txt +20 -0
- data/lib/antbuilder.rb +13 -0
- data/lib/builder/antbuilder.rb +225 -0
- data/lib/builder/blankslate.rb +55 -0
- data/lib/builder/xmlbase.rb +153 -0
- metadata +70 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
Project Version : V1-0-0
|
2
|
+
Tagged by : Joe Smith
|
3
|
+
Comments : First try
|
4
|
+
|
5
|
+
Project Version : V1-1-1
|
6
|
+
Tagged by : Denis Menace
|
7
|
+
Comments : Lots of features added
|
8
|
+
|
9
|
+
Project Version : V1-2-3
|
10
|
+
Tagged by : Tim James
|
11
|
+
Comments : RFC183492/1 RFC183342/3
|
12
|
+
|
13
|
+
Project Version : V1-2-7
|
14
|
+
Tagged by : Tim James
|
15
|
+
Comments : RFC293646/4
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
data/lib/antbuilder.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2006 by Tim Azzopardi (tim@tigerfive.com).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'builder/antbuilder'
|
13
|
+
|
@@ -0,0 +1,225 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2005 by Tim Azzopardi (tim@tigerfive.com).
|
4
|
+
# All rights reserved.
|
5
|
+
|
6
|
+
# Permission is granted for use, copying, modification, distribution,
|
7
|
+
# and distribution of modified versions of this work as long as the
|
8
|
+
# above copyright notice is included.
|
9
|
+
#++
|
10
|
+
require 'builder/xmlbase'
|
11
|
+
|
12
|
+
require 'java'
|
13
|
+
include_class 'org.leafcutter.core.TaskRunner'
|
14
|
+
|
15
|
+
module Builder
|
16
|
+
|
17
|
+
class AntBuilder < XmlBase
|
18
|
+
|
19
|
+
# Create an ant markup builder. Parameters are specified by an
|
20
|
+
# option hash.
|
21
|
+
#
|
22
|
+
# :target=><em>target_object</em>::
|
23
|
+
# Object receiving the markup. +out+ must respond to the
|
24
|
+
# <tt><<</tt> operator. The default is a plain string target.
|
25
|
+
# :indent=><em>indentation</em>::
|
26
|
+
# Number of spaces used for indentation. The default is no
|
27
|
+
# indentation and no line breaks.
|
28
|
+
# :margin=><em>initial_indentation_level</em>::
|
29
|
+
# Amount of initial indentation (specified in levels, not
|
30
|
+
# spaces).
|
31
|
+
#
|
32
|
+
def initialize(options={})
|
33
|
+
indent = options[:indent] || 0
|
34
|
+
margin = options[:margin] || 0
|
35
|
+
super(indent, margin)
|
36
|
+
@target = options[:target] || ""
|
37
|
+
@debug = options[:debug]
|
38
|
+
@debug = false if @debug.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Return the target of the builder.
|
42
|
+
def target!
|
43
|
+
@target
|
44
|
+
end
|
45
|
+
|
46
|
+
def _check_for_circular_dependencies(call_stack, some_method_name)
|
47
|
+
# remove noise from the stack - all we want left are the ant task methods
|
48
|
+
method_name_on_stack_regexp = /`\w+'/
|
49
|
+
call_stack.reject!{|c| c =~ /#{__FILE__}/ or c=~ /`instance_eval'/ or c=~ /`each'/ or not c=~ method_name_on_stack_regexp }
|
50
|
+
|
51
|
+
# collect just those lines that look like method names
|
52
|
+
call_stack.collect!{|c| (method_name_on_stack_regexp.match(c))[0] }
|
53
|
+
|
54
|
+
# check whether some_method_name is on the stack
|
55
|
+
call_stack.each do |c|
|
56
|
+
if c=~ /`#{some_method_name}'/
|
57
|
+
# circular dependecy detected
|
58
|
+
err = call_stack.inject(some_method_name){|message,method_name| "#{message} <- #{method_name}"}
|
59
|
+
raise RuntimeError, "\nBUILD FAILED\nCircular dependency: #{err}", []
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# implement the ant depends clause
|
65
|
+
def depends(*ant_task_dependecies)
|
66
|
+
|
67
|
+
# who called me?
|
68
|
+
my_caller_matcher = caller[0].match(/`(\w+)'/)
|
69
|
+
my_caller = my_caller_matcher[1] if not my_caller_matcher.nil?
|
70
|
+
|
71
|
+
# Call the dependencies if they haven't been called already
|
72
|
+
for ant_task_dependency in ant_task_dependecies
|
73
|
+
|
74
|
+
if not respond_to?(ant_task_dependency)
|
75
|
+
raise RuntimeError, "\nBUILD FAILED\nTarget '#{ant_task_dependency}' does not exist in this project. It is used from target `#{my_caller}'.", []
|
76
|
+
end
|
77
|
+
_check_for_circular_dependencies(caller, ant_task_dependency.to_s)
|
78
|
+
|
79
|
+
cmd = "puts \"\n#{ant_task_dependency}:\" if not @__#{ant_task_dependency}__.nil?; @__#{ant_task_dependency}__ ||= #{ant_task_dependency} || true"
|
80
|
+
puts "#{cmd}" if @debug
|
81
|
+
instance_eval(cmd)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Now print the name of the calling task, from the first line of stack
|
85
|
+
puts
|
86
|
+
puts "#{my_caller}:"
|
87
|
+
|
88
|
+
# and make sure we also record the fact that the caller has been called (as we have done for its dependencies)
|
89
|
+
instance_eval("@__#{my_caller}__ = true ")
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# Subclasses ONLY can use this at the end of their class definition to run targets from the command line like ant does.
|
94
|
+
# For example:
|
95
|
+
# "jruby build.rb clean compile release" is like saying "ant clean compile release # this is any comment"
|
96
|
+
def AntBuilder.run_targets_from_command_line
|
97
|
+
# self would be expected to be a subclass here, because AntBuilder doesnt define any 'ant_target'
|
98
|
+
builder = self.new
|
99
|
+
ARGV.each do |ant_target|
|
100
|
+
return if ant_target == "#"
|
101
|
+
if builder.respond_to?(ant_target)
|
102
|
+
builder.instance_eval("builder.#{ant_target}")
|
103
|
+
else
|
104
|
+
raise RuntimeError, "\nBUILD FAILED\nTarget '#{ant_target}' does not exist in this project.", []
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
########################################################################
|
112
|
+
# NOTE: All private methods of a builder object are prefixed when
|
113
|
+
# a "_" character to avoid possible conflict with ant tags.
|
114
|
+
########################################################################
|
115
|
+
|
116
|
+
def _execute ()
|
117
|
+
# Remove the outer brackets as requied by the leafcutter syntax
|
118
|
+
cmd = @target.slice(1,@target.size-2)
|
119
|
+
puts __FILE__ << " _execute " << cmd if @debug
|
120
|
+
case cmd
|
121
|
+
when /^([\w]+) id=([\w.]+)(\()/
|
122
|
+
# leafcutter supports ant references explicitly http://ant.apache.org/manual/using.html#references
|
123
|
+
# An ant reference of form for example path id=project.class.path
|
124
|
+
reference = $1 +$3 + $' #'
|
125
|
+
reference_name = $2
|
126
|
+
puts __FILE__ << " _execute " << "TaskRunner.addReference(\"#{reference_name}\",\"#{reference}\");" if@debug
|
127
|
+
TaskRunner.addReference(reference_name, reference);
|
128
|
+
when /taskdef .* name=(\w+)/
|
129
|
+
name=$1
|
130
|
+
# match on classname
|
131
|
+
cmd =~ /classname=([\w.]+)/
|
132
|
+
classname = $1
|
133
|
+
puts __FILE__ << " _execute " << "TaskRunner.addTaskDef(\"#{name}\",\"#{classname}\");" if@debug
|
134
|
+
TaskRunner.addTaskDef(name, classname)
|
135
|
+
else
|
136
|
+
# The "normal" case of some ant command
|
137
|
+
|
138
|
+
# get the ant properties before the ant command
|
139
|
+
ant_properties_before = _get_ant_properties_as_hash
|
140
|
+
|
141
|
+
begin
|
142
|
+
puts __FILE__ << " _execute " << "TaskRunner.run(\"#{cmd}\");" if@debug
|
143
|
+
TaskRunner.run(cmd);
|
144
|
+
rescue
|
145
|
+
raise RuntimeError, "BUILD FAILED\n#{$!}", []
|
146
|
+
end
|
147
|
+
|
148
|
+
# get the ant properties after the ant command
|
149
|
+
ant_properties_after = _get_ant_properties_as_hash
|
150
|
+
|
151
|
+
# get the new ant properties after the command (if any).
|
152
|
+
# (Remember ant properties can't be redefined so we only need the new ones.)
|
153
|
+
ant_properties_new = ant_properties_after.select{|k, v| not ant_properties_before.has_key?(k) }
|
154
|
+
|
155
|
+
# define the ant properies as ruby instance variables
|
156
|
+
ant_properties_new.each do | k,v |
|
157
|
+
|
158
|
+
# property name may contain alot of different wacky characters which are not legal in ruby instance variable names
|
159
|
+
# so replace all wacky characters with underscores
|
160
|
+
k.gsub!(/\W/, "_")
|
161
|
+
|
162
|
+
# Replace \ with \\ : this is hell : some windows env vars can look like "C:\some\windows\dir"
|
163
|
+
v.gsub!(/\\/, "\\\\\\\\")
|
164
|
+
v.gsub!(/"/, "\\\"")
|
165
|
+
decl = "@#{k}=\"#{v}\""
|
166
|
+
puts "About to define ruby instance variable: " << decl if @debug
|
167
|
+
instance_eval(decl)
|
168
|
+
puts "Defined ruby instance variable: " << decl << " read back as: " << instance_eval("@#{k}") if @debug
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
@target = ''
|
174
|
+
end
|
175
|
+
|
176
|
+
def _get_ant_properties_as_hash
|
177
|
+
hash = Hash.new
|
178
|
+
TaskRunner.getAntProjectProperties.each { | k,v | hash[k] = v }
|
179
|
+
hash
|
180
|
+
end
|
181
|
+
|
182
|
+
# Insert text directly in to the builder's target.
|
183
|
+
def _text(text)
|
184
|
+
@target << text
|
185
|
+
end
|
186
|
+
|
187
|
+
def _indent
|
188
|
+
raise ArgumentError, "It looks like this object has not been initialized. Did the object get an initialize call?" if @target.nil?
|
189
|
+
super
|
190
|
+
end
|
191
|
+
|
192
|
+
def method_missing(sym, *args, &block)
|
193
|
+
ret = super
|
194
|
+
_execute if @level==0
|
195
|
+
ret
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
# Start an tag. If <tt>end_too</tt> is true, then the start
|
200
|
+
# tag is also the end tag
|
201
|
+
def _start_tag(sym, attrs, end_too=false)
|
202
|
+
@target << "(#{sym}"
|
203
|
+
_insert_attributes(attrs)
|
204
|
+
@target << ")" if end_too
|
205
|
+
# @target << ")"
|
206
|
+
end
|
207
|
+
|
208
|
+
# Insert an ending tag.
|
209
|
+
def _end_tag(sym)
|
210
|
+
@target << ")"
|
211
|
+
end
|
212
|
+
|
213
|
+
# Insert the attributes (given in the hash).
|
214
|
+
def _insert_attributes(attrs)
|
215
|
+
return if attrs.nil?
|
216
|
+
attrs.each do |k, v|
|
217
|
+
# if the attribute value contains spaces then put single quotes around the string
|
218
|
+
v = "'#{v}'" if v =~ " "
|
219
|
+
@target << %{ #{k}=#{v}}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end # class
|
224
|
+
|
225
|
+
end # module
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
4
|
+
# Copyright 2005 by Tim Azzopardi (tim@tigerfive.com).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#++
|
11
|
+
|
12
|
+
module Builder
|
13
|
+
|
14
|
+
# BlankSlate provides an abstract base class with no predefined
|
15
|
+
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
|
16
|
+
# BlankSlate is useful as a base class when writing classes that
|
17
|
+
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
18
|
+
class BlankSlate
|
19
|
+
class << self
|
20
|
+
def hide(name)
|
21
|
+
undef_method name if
|
22
|
+
instance_methods.include?(name.to_s) and
|
23
|
+
name !~ /^(__|instance_eval)/ and
|
24
|
+
name !~ /^(__|respond_to?)/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
instance_methods.each { |m| hide(m) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Since Ruby is very dynamic, methods added to the ancestors of
|
33
|
+
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
34
|
+
# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
|
35
|
+
module Kernel
|
36
|
+
class << self
|
37
|
+
alias_method :blank_slate_method_added, :method_added
|
38
|
+
def method_added(name)
|
39
|
+
blank_slate_method_added(name)
|
40
|
+
return if self != Kernel
|
41
|
+
Builder::BlankSlate.hide(name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Object
|
47
|
+
class << self
|
48
|
+
alias_method :blank_slate_method_added, :method_added
|
49
|
+
def method_added(name)
|
50
|
+
blank_slate_method_added(name)
|
51
|
+
return if self != Object
|
52
|
+
Builder::BlankSlate.hide(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
4
|
+
# All rights reserved.
|
5
|
+
|
6
|
+
# Permission is granted for use, copying, modification, distribution,
|
7
|
+
# and distribution of modified versions of this work as long as the
|
8
|
+
# above copyright notice is included.
|
9
|
+
#++
|
10
|
+
|
11
|
+
require 'builder/blankslate'
|
12
|
+
|
13
|
+
module Builder
|
14
|
+
|
15
|
+
# Generic error for builder
|
16
|
+
class IllegalBlockError < RuntimeError; end
|
17
|
+
|
18
|
+
# XmlBase is a base class for building XML builders. See
|
19
|
+
# Builder::XmlMarkup and Builder::XmlEvents for examples.
|
20
|
+
class XmlBase < BlankSlate
|
21
|
+
|
22
|
+
# Create an XML markup builder.
|
23
|
+
#
|
24
|
+
# out:: Object receiving the markup.1 +out+ must respond to
|
25
|
+
# <tt><<</tt>.
|
26
|
+
# indent:: Number of spaces used for indentation (0 implies no
|
27
|
+
# indentation and no line breaks).
|
28
|
+
# initial:: Level of initial indentation.
|
29
|
+
#
|
30
|
+
def initialize(indent=0, initial=0)
|
31
|
+
@indent = indent
|
32
|
+
@level = initial
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create a tag named +sym+. Other than the first argument which
|
36
|
+
# is the tag name, the arguements are the same as the tags
|
37
|
+
# implemented via <tt>method_missing</tt>.
|
38
|
+
def tag!(sym, *args, &block)
|
39
|
+
self.__send__(sym, *args, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create XML markup based on the name of the method. This method
|
43
|
+
# is never invoked directly, but is called for each markup method
|
44
|
+
# in the markup block.
|
45
|
+
def method_missing(sym, *args, &block)
|
46
|
+
text = nil
|
47
|
+
attrs = nil
|
48
|
+
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
49
|
+
args.each do |arg|
|
50
|
+
case arg
|
51
|
+
when Hash
|
52
|
+
attrs ||= {}
|
53
|
+
attrs.merge!(arg)
|
54
|
+
else
|
55
|
+
text ||= ''
|
56
|
+
text << arg.to_s
|
57
|
+
end
|
58
|
+
end
|
59
|
+
if block
|
60
|
+
unless text.nil?
|
61
|
+
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
62
|
+
end
|
63
|
+
_capture_outer_self(block) if @self.nil?
|
64
|
+
_indent
|
65
|
+
_start_tag(sym, attrs)
|
66
|
+
_newline
|
67
|
+
_nested_structures(block)
|
68
|
+
_indent
|
69
|
+
_end_tag(sym)
|
70
|
+
_newline
|
71
|
+
elsif text.nil?
|
72
|
+
_indent
|
73
|
+
_start_tag(sym, attrs, true)
|
74
|
+
_newline
|
75
|
+
else
|
76
|
+
_indent
|
77
|
+
_start_tag(sym, attrs)
|
78
|
+
text! text
|
79
|
+
_end_tag(sym)
|
80
|
+
_newline
|
81
|
+
end
|
82
|
+
@target
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
# Append text to the output target. Escape any markup. May be
|
88
|
+
# used within the markup brakets as:
|
89
|
+
#
|
90
|
+
# builder.p { |b| b.br; b.text! "HI" } #=> <p><br/>HI</p>
|
91
|
+
def text!(text)
|
92
|
+
_text(_escape(text))
|
93
|
+
end
|
94
|
+
|
95
|
+
# Append text to the output target without escaping any markup.
|
96
|
+
# May be used within the markup brakets as:
|
97
|
+
#
|
98
|
+
# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
|
99
|
+
#
|
100
|
+
# This is useful when using non-builder enabled software that
|
101
|
+
# generates strings. Just insert the string directly into the
|
102
|
+
# builder without changing the inserted markup.
|
103
|
+
#
|
104
|
+
# It is also useful for stacking builder objects. Builders only
|
105
|
+
# use <tt><<</tt> to append to the target, so by supporting this
|
106
|
+
# method/operation builders can use other builders as their
|
107
|
+
# targets.
|
108
|
+
def <<(text)
|
109
|
+
_text(text)
|
110
|
+
end
|
111
|
+
|
112
|
+
# For some reason, nil? is sent to the XmlMarkup object. If nil?
|
113
|
+
# is not defined and method_missing is invoked, some strange kind
|
114
|
+
# of recursion happens. Since nil? won't ever be an XML tag, it
|
115
|
+
# is pretty safe to define it here. (Note: this is an example of
|
116
|
+
# cargo cult programming,
|
117
|
+
# cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
|
118
|
+
def nil?
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def _escape(text)
|
125
|
+
text.
|
126
|
+
gsub(%r{&}, '&').
|
127
|
+
gsub(%r{<}, '<').
|
128
|
+
gsub(%r{>}, '>')
|
129
|
+
end
|
130
|
+
|
131
|
+
def _capture_outer_self(block)
|
132
|
+
@self = eval("self", block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def _newline
|
136
|
+
return if @indent == 0
|
137
|
+
text! "\n"
|
138
|
+
end
|
139
|
+
|
140
|
+
def _indent
|
141
|
+
return if @indent == 0 || @level == 0
|
142
|
+
text!(" " * (@level * @indent))
|
143
|
+
end
|
144
|
+
|
145
|
+
def _nested_structures(block)
|
146
|
+
@level += 1
|
147
|
+
block.call(self)
|
148
|
+
ensure
|
149
|
+
@level -= 1
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|