AntBuilder 0.4.1
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/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
|