buildr 1.2.10 → 1.3.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.
Files changed (154) hide show
  1. data/CHANGELOG +566 -268
  2. data/DISCLAIMER +7 -1
  3. data/KEYS +151 -0
  4. data/NOTICE +23 -8
  5. data/README +122 -22
  6. data/Rakefile +49 -229
  7. data/{lib → addon}/buildr/antlr.rb +23 -10
  8. data/addon/buildr/cobertura.rb +232 -0
  9. data/{lib → addon}/buildr/hibernate.rb +20 -4
  10. data/{lib → addon}/buildr/javacc.rb +27 -12
  11. data/addon/buildr/jdepend.rb +60 -0
  12. data/{lib → addon}/buildr/jetty.rb +34 -18
  13. data/addon/buildr/nailgun.rb +892 -0
  14. data/{lib → addon}/buildr/openjpa.rb +23 -6
  15. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  16. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  17. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  18. data/{lib/buildr/jetty → addon/buildr/org/apache/buildr}/JettyWrapper.java +19 -0
  19. data/{lib → addon}/buildr/xmlbeans.rb +39 -14
  20. data/bin/buildr +21 -7
  21. data/buildr.gemspec +50 -0
  22. data/doc/css/default.css +225 -0
  23. data/doc/css/print.css +95 -0
  24. data/doc/css/syntax.css +43 -0
  25. data/doc/images/apache-incubator-logo.png +0 -0
  26. data/doc/images/buildr-hires.png +0 -0
  27. data/doc/images/buildr.png +0 -0
  28. data/doc/images/note.png +0 -0
  29. data/doc/images/tip.png +0 -0
  30. data/doc/images/zbuildr.tif +0 -0
  31. data/doc/pages/artifacts.textile +317 -0
  32. data/doc/pages/building.textile +501 -0
  33. data/doc/pages/contributing.textile +178 -0
  34. data/doc/pages/download.textile +25 -0
  35. data/doc/pages/extending.textile +229 -0
  36. data/doc/pages/getting_started.textile +337 -0
  37. data/doc/pages/index.textile +63 -0
  38. data/doc/pages/mailing_lists.textile +17 -0
  39. data/doc/pages/more_stuff.textile +367 -0
  40. data/doc/pages/packaging.textile +592 -0
  41. data/doc/pages/projects.textile +449 -0
  42. data/doc/pages/recipes.textile +127 -0
  43. data/doc/pages/settings_profiles.textile +339 -0
  44. data/doc/pages/testing.textile +475 -0
  45. data/doc/pages/troubleshooting.textile +121 -0
  46. data/doc/pages/whats_new.textile +389 -0
  47. data/doc/print.haml +52 -0
  48. data/doc/print.toc.yaml +28 -0
  49. data/doc/scripts/buildr-git.rb +411 -0
  50. data/doc/scripts/install-jruby.sh +44 -0
  51. data/doc/scripts/install-linux.sh +64 -0
  52. data/doc/scripts/install-osx.sh +52 -0
  53. data/doc/site.haml +55 -0
  54. data/doc/site.toc.yaml +44 -0
  55. data/lib/buildr.rb +28 -45
  56. data/lib/buildr/core.rb +27 -0
  57. data/lib/buildr/core/application.rb +373 -0
  58. data/lib/buildr/core/application_cli.rb +134 -0
  59. data/lib/{core → buildr/core}/build.rb +91 -77
  60. data/lib/{core → buildr/core}/checks.rb +116 -95
  61. data/lib/buildr/core/common.rb +155 -0
  62. data/lib/buildr/core/compile.rb +594 -0
  63. data/lib/buildr/core/environment.rb +120 -0
  64. data/lib/buildr/core/filter.rb +258 -0
  65. data/lib/{core → buildr/core}/generate.rb +22 -5
  66. data/lib/buildr/core/help.rb +118 -0
  67. data/lib/buildr/core/progressbar.rb +156 -0
  68. data/lib/{core → buildr/core}/project.rb +468 -213
  69. data/lib/buildr/core/test.rb +690 -0
  70. data/lib/{core → buildr/core}/transports.rb +107 -127
  71. data/lib/buildr/core/util.rb +235 -0
  72. data/lib/buildr/ide.rb +19 -0
  73. data/lib/{java → buildr/ide}/eclipse.rb +86 -60
  74. data/lib/{java → buildr/ide}/idea.ipr.template +16 -0
  75. data/lib/buildr/ide/idea.rb +194 -0
  76. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  77. data/lib/buildr/ide/idea7x.rb +210 -0
  78. data/lib/buildr/java.rb +26 -0
  79. data/lib/buildr/java/ant.rb +71 -0
  80. data/lib/buildr/java/bdd_frameworks.rb +267 -0
  81. data/lib/buildr/java/commands.rb +210 -0
  82. data/lib/buildr/java/compilers.rb +432 -0
  83. data/lib/buildr/java/deprecated.rb +141 -0
  84. data/lib/buildr/java/groovyc.rb +137 -0
  85. data/lib/buildr/java/jruby.rb +99 -0
  86. data/lib/buildr/java/org/apache/buildr/BuildrNail$Main.class +0 -0
  87. data/lib/buildr/java/org/apache/buildr/BuildrNail.class +0 -0
  88. data/lib/buildr/java/org/apache/buildr/BuildrNail.java +41 -0
  89. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  90. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +116 -0
  91. data/lib/buildr/java/packaging.rb +706 -0
  92. data/lib/{java → buildr/java}/pom.rb +20 -4
  93. data/lib/buildr/java/rjb.rb +142 -0
  94. data/lib/buildr/java/test_frameworks.rb +290 -0
  95. data/lib/buildr/java/version_requirement.rb +172 -0
  96. data/lib/buildr/packaging.rb +21 -0
  97. data/lib/{java → buildr/packaging}/artifact.rb +170 -179
  98. data/lib/buildr/packaging/artifact_namespace.rb +957 -0
  99. data/lib/buildr/packaging/artifact_search.rb +140 -0
  100. data/lib/buildr/packaging/gems.rb +102 -0
  101. data/lib/buildr/packaging/package.rb +233 -0
  102. data/lib/{tasks → buildr/packaging}/tar.rb +18 -1
  103. data/lib/{tasks → buildr/packaging}/zip.rb +153 -105
  104. data/rakelib/apache.rake +126 -0
  105. data/rakelib/changelog.rake +56 -0
  106. data/rakelib/doc.rake +103 -0
  107. data/rakelib/package.rake +44 -0
  108. data/rakelib/release.rake +53 -0
  109. data/rakelib/rspec.rake +81 -0
  110. data/rakelib/rubyforge.rake +45 -0
  111. data/rakelib/scm.rake +49 -0
  112. data/rakelib/setup.rake +59 -0
  113. data/rakelib/stage.rake +45 -0
  114. data/spec/application_spec.rb +316 -0
  115. data/spec/archive_spec.rb +494 -0
  116. data/spec/artifact_namespace_spec.rb +635 -0
  117. data/spec/artifact_spec.rb +738 -0
  118. data/spec/build_spec.rb +193 -0
  119. data/spec/checks_spec.rb +537 -0
  120. data/spec/common_spec.rb +579 -0
  121. data/spec/compile_spec.rb +561 -0
  122. data/spec/groovy_compilers_spec.rb +239 -0
  123. data/spec/java_bdd_frameworks_spec.rb +238 -0
  124. data/spec/java_compilers_spec.rb +446 -0
  125. data/spec/java_packaging_spec.rb +1042 -0
  126. data/spec/java_test_frameworks_spec.rb +414 -0
  127. data/spec/packaging_helper.rb +63 -0
  128. data/spec/packaging_spec.rb +589 -0
  129. data/spec/project_spec.rb +739 -0
  130. data/spec/sandbox.rb +116 -0
  131. data/spec/scala_compilers_spec.rb +239 -0
  132. data/spec/spec.opts +6 -0
  133. data/spec/spec_helpers.rb +283 -0
  134. data/spec/test_spec.rb +871 -0
  135. data/spec/transport_spec.rb +300 -0
  136. data/spec/version_requirement_spec.rb +115 -0
  137. metadata +188 -77
  138. data/lib/buildr/cobertura.rb +0 -89
  139. data/lib/buildr/jdepend.rb +0 -40
  140. data/lib/buildr/jetty/JettyWrapper$1.class +0 -0
  141. data/lib/buildr/jetty/JettyWrapper$BuildrHandler.class +0 -0
  142. data/lib/buildr/jetty/JettyWrapper.class +0 -0
  143. data/lib/buildr/scala.rb +0 -368
  144. data/lib/core/application.rb +0 -188
  145. data/lib/core/common.rb +0 -562
  146. data/lib/core/help.rb +0 -72
  147. data/lib/core/rake_ext.rb +0 -81
  148. data/lib/java/ant.rb +0 -71
  149. data/lib/java/compile.rb +0 -589
  150. data/lib/java/idea.rb +0 -159
  151. data/lib/java/java.rb +0 -432
  152. data/lib/java/packaging.rb +0 -581
  153. data/lib/java/test.rb +0 -795
  154. data/lib/tasks/concat.rb +0 -35
@@ -1,188 +0,0 @@
1
- module Buildr
2
-
3
- # When running from +rake+, we already have an Application setup and must plug into it,
4
- # since the top-level tasks come from there. When running from +buildr+, we get to load
5
- # Rake and set everything up, and we use our own Application full of cool Buildr features.
6
- if defined?(Rake)
7
- Rake.application.top_level_tasks.unshift task("buildr:initialize")
8
- else
9
-
10
- require "rake"
11
-
12
- class Application < Rake::Application #:nodoc:
13
-
14
- DEFAULT_BUILDFILES = ["buildfile", "Buildfile"] + DEFAULT_RAKEFILES
15
-
16
- OPTIONS = [ # :nodoc:
17
- ['--help', '-H', GetoptLong::NO_ARGUMENT,
18
- "Display this help message."],
19
- ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
20
- "Do not search parent directories for the buildfile."],
21
- ['--quiet', '-q', GetoptLong::NO_ARGUMENT,
22
- "Do not log messages to standard output."],
23
- ['--buildfile', '-f', GetoptLong::REQUIRED_ARGUMENT,
24
- "Use FILE as the buildfile."],
25
- ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
26
- "Require MODULE before executing buildfile."],
27
- ['--trace', '-t', GetoptLong::NO_ARGUMENT,
28
- "Turn on invoke/execute tracing, enable full backtrace."],
29
- ['--version', '-V', GetoptLong::NO_ARGUMENT,
30
- "Display the program version."],
31
- ['--environment', '-e', GetoptLong::REQUIRED_ARGUMENT,
32
- "Environment name (e.g. development, test, production)."],
33
- ['--freeze', "-F", GetoptLong::NO_ARGUMENT,
34
- "Freezes the Buildfile so it always uses Buildr version #{Buildr::VERSION}"],
35
- ['--unfreeze', "-U", GetoptLong::NO_ARGUMENT,
36
- "Unfreezes the Buildfile to use the latest version of Buildr"]
37
- ]
38
-
39
- def initialize()
40
- super
41
- @rakefiles = DEFAULT_BUILDFILES
42
- @name = "Buildr"
43
- @requires = []
44
- opts = GetoptLong.new(*command_line_options)
45
- opts.each { |opt, value| do_option(opt, value) }
46
- collect_tasks
47
- top_level_tasks.unshift "buildr:initialize"
48
- end
49
-
50
- def run()
51
- standard_exception_handling do
52
- find_buildfile
53
- load_buildfile
54
- top_level
55
- end
56
- end
57
-
58
- def do_option(opt, value)
59
- case opt
60
- when '--help'
61
- help
62
- exit
63
- when "--buildfile"
64
- @rakefiles.clear
65
- @rakefiles << value
66
- when '--version'
67
- puts "Buildr, version #{Buildr::VERSION}"
68
- exit
69
- when '--environment'
70
- ENV['BUILDR_ENV'] = value
71
- when "--freeze"
72
- find_buildfile
73
- puts "Freezing the Buildfile so it always uses Buildr version #{Buildr::VERSION}"
74
- original = File.read(rakefile)
75
- if original =~ /gem\s*(["'])buildr\1/
76
- modified = original.sub(/gem\s*(["'])buildr\1\s*,\s*(["']).*\2/, %{gem "buildr", "#{Buildr::VERSION}"})
77
- else
78
- modified = %{gem "buildr", "#{Buildr::VERSION}"\n} + original
79
- end
80
- File.open(rakefile, "w") { |file| file.write modified }
81
- exit
82
- when "--unfreeze"
83
- find_buildfile
84
- puts "Unfreezing the Buildfile to use the latest version of Buildr from your Gems repository."
85
- modified = File.read(rakefile).sub(/^\s*gem\s*(["'])buildr\1.*\n/, "")
86
- File.open(rakefile, "w") { |file| file.write modified }
87
- exit
88
- when "--require"
89
- @requires << value
90
- when "--nosearch", "--quiet", "--trace"
91
- super
92
- end
93
- end
94
-
95
- def find_buildfile()
96
- here = Dir.pwd
97
- while ! have_rakefile
98
- Dir.chdir("..")
99
- if Dir.pwd == here || options.nosearch
100
- error = "No Buildfile found (looking for: #{@rakefiles.join(', ')})"
101
- if STDIN.isatty
102
- chdir(original_dir) { task("generate").invoke }
103
- exit 1
104
- else
105
- raise error
106
- end
107
- end
108
- here = Dir.pwd
109
- end
110
- end
111
-
112
- def load_buildfile()
113
- @requires.each { |name| require name }
114
- puts Buildr.environment ? "(in #{Dir.pwd}, #{Buildr.environment})" : "(in #{Dir.pwd})"
115
- load File.expand_path(@rakefile) if @rakefile != ''
116
- load_imports
117
- end
118
-
119
- def usage()
120
- puts "Buildr #{Buildr::VERSION}"
121
- puts
122
- puts "Usage:"
123
- puts " buildr [-f buildfile] {options} targets..."
124
- end
125
-
126
- def help()
127
- usage
128
- puts
129
- puts "Options:"
130
- OPTIONS.sort.each do |long, short, mode, desc|
131
- if mode == GetoptLong::REQUIRED_ARGUMENT
132
- if desc =~ /\b([A-Z]{2,})\b/
133
- long = long + "=#{$1}"
134
- end
135
- end
136
- printf " %-20s (%s)\n", long, short
137
- printf " %s\n", desc
138
- end
139
- puts
140
- puts "For help with your buildfile:"
141
- puts " buildr help"
142
- end
143
-
144
- def command_line_options
145
- OPTIONS.collect { |lst| lst[0..-2] }
146
- end
147
- end
148
-
149
- Rake.application = Buildr::Application.new
150
- end
151
-
152
-
153
- class << self
154
-
155
- # Loads buildr.rake files from users home directory and project directory.
156
- # Loads custom tasks from .rake files in tasks directory.
157
- def load_tasks_and_local_files() #:nodoc:
158
- return false if @build_files
159
- # Load the settings files.
160
- @build_files = [ File.expand_path("buildr.rb", Gem::user_home), "buildr.rb" ].select { |file| File.exist?(file) }
161
- @build_files += [ File.expand_path("buildr.rake", Gem::user_home), File.expand_path("buildr.rake") ].
162
- select { |file| File.exist?(file) }.each { |file| warn "Please use '#{file.ext('rb')}' instead of '#{file}'" }
163
- #Load local tasks that can be used in the Buildfile.
164
- @build_files += Dir["#{Dir.pwd}/tasks/*.rake"]
165
- @build_files.each do |file|
166
- unless $LOADED_FEATURES.include?(file)
167
- load file
168
- $LOADED_FEATURES << file
169
- end
170
- end
171
- true
172
- end
173
-
174
- # :call-seq:
175
- # build_files() => files
176
- #
177
- # Returns a list of build files. These are files used by the build,
178
- def build_files()
179
- [Rake.application.rakefile].compact + @build_files
180
- end
181
-
182
- task "buildr:initialize" do
183
- Buildr.load_tasks_and_local_files
184
- end
185
-
186
- end
187
-
188
- end
@@ -1,562 +0,0 @@
1
- require "tempfile"
2
- require "pathname"
3
- require "core/transports"
4
- require "open-uri"
5
- require "uri/open-sftp"
6
-
7
-
8
- class Hash
9
-
10
- class << self
11
-
12
- # :call-seq:
13
- # Hash.from_java_properties(string)
14
- #
15
- # Returns a hash from a string in the Java properties file format. For example:
16
- # str = "foo=bar\nbaz=fab"
17
- # Hash.from_properties(str)
18
- # => { "foo"=>"bar", "baz"=>"fab" }.to_properties
19
- def from_java_properties(string)
20
- string.gsub(/\\\n/, "").split("\n").select { |line| line =~ /^[^#].*=.*/ }.
21
- map { |line| line.gsub(/\\[trnf\\]/) { |escaped| {?t=>"\t", ?r=>"\r", ?n=>"\n", ?f=>"\f", ?\\=>"\\"}[escaped[1]] } }.
22
- map { |line| line.split("=") }.
23
- inject({}) { |hash, (name, value)| hash.merge(name=>value) }
24
- end
25
-
26
- end
27
-
28
- # :call-seq:
29
- # only(keys*) => hash
30
- #
31
- # Returns a new hash with only the specified keys.
32
- #
33
- # For example:
34
- # { :a=>1, :b=>2, :c=>3, :d=>4 }.only(:a, :c)
35
- # => { :a=>1, :c=>3 }
36
- def only(*keys)
37
- keys.inject({}) { |hash, key| has_key?(key) ? hash.merge(key=>self[key]) : hash }
38
- end
39
-
40
-
41
- # :call-seq:
42
- # except(keys*) => hash
43
- #
44
- # Returns a new hash without the specified keys.
45
- #
46
- # For example:
47
- # { :a=>1, :b=>2, :c=>3, :d=>4 }.except(:a, :c)
48
- # => { :b=>2, :d=>4 }
49
- def except(*keys)
50
- (self.keys - keys).inject({}) { |hash, key| hash.merge(key=>self[key]) }
51
- end
52
-
53
- # :call-seq:
54
- # to_java_properties() => string
55
- #
56
- # Convert hash to string format used for Java properties file. For example:
57
- # { "foo"=>"bar", "baz"=>"fab" }.to_properties
58
- # => foo=bar
59
- # baz=fab
60
- def to_java_properties()
61
- keys.sort.map { |key|
62
- value = self[key].gsub(/[\t\r\n\f\\]/) { |escape| "\\" + {"\t"=>"t", "\r"=>"r", "\n"=>"n", "\f"=>"f", "\\"=>"\\"}[escape] }
63
- "#{key}=#{value}"
64
- }.join("\n")
65
- end
66
-
67
- end
68
-
69
-
70
- module Buildr
71
-
72
- # Collection of options for controlling Buildr. For example for running builds without running
73
- # test cases, using a proxy server, JVM arguments, etc. You access this object by calling options,
74
- # for example:
75
- # options.proxy.http = "http://proxy.acme.com:8080"
76
- # options.java_args = "-Xmx512M"
77
- class Options
78
-
79
- # We use this to present environment variable as arrays.
80
- class EnvArray < Array #:nodoc:
81
-
82
- def initialize(name)
83
- @name = name.upcase
84
- replace((ENV[@name] || ENV[@name.downcase] || "").split(/\s*,\s*/).reject(&:empty?))
85
- end
86
-
87
- (Array.instance_methods - Object.instance_methods - Enumerable.instance_methods).sort.each do |method|
88
- class_eval %{def #{method}(*args, &block) ; result = super ; write ; result ; end}
89
- end
90
-
91
- private
92
-
93
- def write()
94
- ENV[@name.downcase] = nil
95
- ENV[@name] = map(&:to_s).join(",")
96
- end
97
-
98
- end
99
-
100
- # Wraps around the proxy environment variables:
101
- # * :http -- HTTP_PROXY
102
- # * :exclude -- NO_PROXY
103
- class Proxies
104
-
105
- # Returns the HTTP_PROXY URL.
106
- def http()
107
- ENV["HTTP_PROXY"] || ENV["http_proxy"]
108
- end
109
-
110
- # Sets the HTTP_PROXY URL.
111
- def http=(url)
112
- ENV["http_proxy"] = nil
113
- ENV["HTTP_PROXY"] = url
114
- end
115
-
116
- # Returns list of hosts to exclude from proxying (NO_PROXY).
117
- def exclude()
118
- @exclude ||= EnvArray.new("NO_PROXY")
119
- end
120
-
121
- # Sets list of hosts to exclude from proxy (NO_PROXY). Accepts host name, array of names,
122
- # or nil to clear the list.
123
- def exclude=(url)
124
- exclude.clear
125
- exclude.concat [url].flatten if url
126
- exclude
127
- end
128
-
129
- end
130
-
131
- # :call-seq:
132
- # proxy() => options
133
- #
134
- # Returns the proxy options. Currently supported options are:
135
- # * :http -- HTTP proxy for use when downloading.
136
- # * :exclude -- Do not use proxy for these hosts/domains.
137
- #
138
- # For example:
139
- # options.proxy.http = "http://proxy.acme.com:8080"
140
- # You can also set it using the environment variable HTTP_PROXY.
141
- #
142
- # You can exclude individual hosts from being proxied, or entire domains, for example:
143
- # options.proxy.exclude = "optimus"
144
- # options.proxy.exclude = ["optimus", "prime"]
145
- # options.proxy.exclude << "*.internal"
146
- def proxy()
147
- @proxy ||= Proxies.new
148
- end
149
-
150
- end
151
-
152
- class << self
153
-
154
- # :call-seq:
155
- # options() => Options
156
- #
157
- # Returns the Buildr options. See Options.
158
- def options()
159
- @options ||= Options.new
160
- end
161
-
162
- end
163
-
164
- # :call-seq:
165
- # options() => Options
166
- #
167
- # Returns the Buildr options. See Options.
168
- def options()
169
- Buildr.options
170
- end
171
-
172
- # :call-seq:
173
- # environment() => string or nil
174
- #
175
- # Returns the environment name. Use this when your build depends on the environment,
176
- # for example, development, production, etc. The value comes from the BUILDR_ENV environment variable.
177
- #
178
- # For example:
179
- # buildr -e production
180
- def environment()
181
- ENV['BUILDR_ENV']
182
- end
183
-
184
- # :call-seq:
185
- # environment(env)
186
- #
187
- # Sets the environment name.
188
- def environment=(env)
189
- ENV['BUILDR_ENV'] = env
190
- end
191
-
192
- # :call-seq:
193
- # struct(hash) => Struct
194
- #
195
- # Convenience method for creating an anonymous Struct.
196
- #
197
- # For example:
198
- # COMMONS = struct(
199
- # :collections =>"commons-collections:commons-collections:jar:3.1",
200
- # :lang =>"commons-lang:commons-lang:jar:2.1",
201
- # :logging =>"commons-logging:commons-logging:jar:1.0.3",
202
- # )
203
- #
204
- # compile.with COMMONS.logging
205
- def struct(hash)
206
- Struct.new(nil, *hash.keys).new(*hash.values)
207
- end
208
-
209
- # :call-seq:
210
- # write(name, content)
211
- # write(name) { ... }
212
- #
213
- # Write the contents into a file. The second form calls the block and writes the result.
214
- #
215
- # For example:
216
- # write "TIMESTAMP", Time.now
217
- # write("TIMESTAMP") { Time.now }
218
- #
219
- # Yields to the block before writing the file, so you can chain read and write together.
220
- # For example:
221
- # write("README") { read("README").sub("${build}", Time.now) }
222
- def write(name, content = nil)
223
- mkpath File.dirname(name), :verbose=>false
224
- content = yield if block_given?
225
- File.open(name.to_s, "wb") { |file| file.write content.to_s }
226
- content.to_s
227
- end
228
-
229
- # :call-seq:
230
- # read(name) => string
231
- # read(name) { |string| ... } => result
232
- #
233
- # Reads and returns the contents of a file. The second form yields to the block and returns
234
- # the result of the block.
235
- #
236
- # For example:
237
- # puts read("README")
238
- # read("README") { |text| puts text }
239
- def read(name)
240
- contents = File.open(name.to_s) { |f| f.read }
241
- if block_given?
242
- yield contents
243
- else
244
- contents
245
- end
246
- end
247
-
248
- # :call-seq:
249
- # download(url_or_uri) => task
250
- # download(path=>url_or_uri) =>task
251
- #
252
- # Create a task that will download a file from a URL.
253
- #
254
- # Takes a single argument, a hash with one pair. The key is the file being
255
- # created, the value if the URL to download. The task executes only if the
256
- # file does not exist; the URL is not checked for updates.
257
- #
258
- # The task will show download progress on the console; if there are MD5/SHA1
259
- # checksums on the server it will verify the download before saving it.
260
- #
261
- # For example:
262
- # download "image.jpg"=>"http://example.com/theme/image.jpg"
263
- def download(args)
264
- args = URI.parse(args) if String === args
265
- if URI === args
266
- # Given only a download URL, download into a temporary file.
267
- # You can infer the file from task name.
268
- temp = Tempfile.open(File.basename(args.to_s))
269
- file(temp.path).tap do |task|
270
- # Since temporary file exists, force a download.
271
- class << task ; def needed?() ; true ; end ; end
272
- task.sources << args
273
- task.enhance { args.download temp }
274
- end
275
- else
276
- # Download to a file created by the task.
277
- fail unless args.keys.size == 1
278
- uri = URI.parse(args.values.first.to_s)
279
- file_create(args.keys.first).tap do |task|
280
- task.sources << uri
281
- task.enhance { uri.download task.name }
282
- end
283
- end
284
-
285
- end
286
-
287
-
288
- # A filter knows how to copy files from one directory to another, applying mappings to the
289
- # contents of these files.
290
- #
291
- # You can specify the mapping using a Hash, and it will map ${key} fields found in each source
292
- # file into the appropriate value in the target file. For example:
293
- # filter.using "version"=>"1.2", "build"=>Time.now
294
- # will replace all occurrences of <tt>${version}</tt> with <tt>1.2</tt>, and <tt>${build}</tt>
295
- # with the current date/time.
296
- #
297
- # You can also specify the mapping by passing a proc or a method, that will be called for
298
- # each source file, with the file name and content, returning the modified content.
299
- #
300
- # Without any mapping, the filter simply copies files from the source directory into the target
301
- # directory.
302
- #
303
- # A filter has one target directory, but you can specify any number of source directories,
304
- # either when creating the filter or calling #from. Include/exclude patterns are specified
305
- # relative to the source directories, so:
306
- # filter.include "*.png"
307
- # will only include PNG files from any of the source directories.
308
- #
309
- # See Buildr#filter.
310
- class Filter
311
-
312
- def initialize() #:nodoc:
313
- @include = []
314
- @exclude = []
315
- @sources = []
316
- end
317
-
318
- # Returns the list of source directories (each being a file task).
319
- attr_reader :sources
320
-
321
- # *Deprecated* Use #sources instead.
322
- def source()
323
- warn_deprecated "Please use sources instead."
324
- @sources.first
325
- end
326
-
327
- # *Deprecated* Use #from instead.
328
- def source=(dir)
329
- warn_deprecated "Please use from instead."
330
- from(dir)
331
- end
332
-
333
- # :call-seq:
334
- # from(*sources) => self
335
- #
336
- # Adds additional directories from which to copy resources.
337
- #
338
- # For example:
339
- # filter.from("src").into("target").using("build"=>Time.now)
340
- def from(*sources)
341
- @sources |= sources.flatten.map { |dir| file(File.expand_path(dir.to_s)) }
342
- self
343
- end
344
-
345
- # The target directory as a file task.
346
- attr_reader :target
347
-
348
- # :call-seq:
349
- # into(dir) => self
350
- #
351
- # Sets the target directory into which files are copied and returns self.
352
- #
353
- # For example:
354
- # filter.from("src").into("target").using("build"=>Time.now)
355
- def into(dir)
356
- @target = file(File.expand_path(dir.to_s)) { |task| run if target == task && !sources.empty? }
357
- self
358
- end
359
-
360
- # :call-seq:
361
- # include(*files) => self
362
- #
363
- # Specifies files to include and returns self. See FileList#include.
364
- #
365
- # By default all files are included. You can use this method to only include specific
366
- # files form the source directory.
367
- def include(*files)
368
- @include += files
369
- self
370
- end
371
- alias :add :include
372
-
373
- # :call-seq:
374
- # exclude(*files) => self
375
- #
376
- # Specifies files to exclude and returns self. See FileList#exclude.
377
- def exclude(*files)
378
- @exclude += files
379
- self
380
- end
381
-
382
- # The mapping. See #using.
383
- attr_accessor :mapping
384
-
385
- # The mapper to use. See #using.
386
- attr_accessor :mapper
387
-
388
- # :call-seq:
389
- # using(mapping) => self
390
- # using() { |file_name, contents| ... } => self
391
- #
392
- # Specifies the mapping to use and returns self.
393
- #
394
- # The most typical mapping uses a Hash, and the default mapping uses the Maven style, so
395
- # <code>${key}</code> are mapped to the values. You can change that by passing a different
396
- # format as the first argument. Currently supports:
397
- # * :ant -- Map <code>@key@</code>.
398
- # * :maven -- Map <code>${key}</code> (default).
399
- # * :ruby -- Map <code>#{key}</code>.
400
- # * Regexp -- Maps the matched data (e.g. <code>/=(.*?)=/</code>
401
- #
402
- # For example:
403
- # filter.using "version"=>"1.2"
404
- # Is the same as:
405
- # filter.using :maven, "version"=>"1.2"
406
- #
407
- # You can also pass a proc or method. It will be called with the file name and content,
408
- # to return the mapped content.
409
- #
410
- # Without any mapping, all files are copied as is.
411
- def using(*args, &block)
412
- case args.first
413
- when Hash # Maven hash mapping
414
- using :maven, *args
415
- when Symbol # Mapping from a method
416
- raise ArgumentError, "Expected mapper type followed by mapping hash" unless args.size == 2 && Hash === args[1]
417
- @mapper, @mapping = *args
418
- when Regexp # Mapping using a regular expression
419
- raise ArgumentError, "Expected regular expression followed by mapping hash" unless args.size == 2 && Hash === args[1]
420
- @mapper, @mapping = *args
421
- else
422
- raise ArgumentError, "Expected proc, method or a block" if args.size > 1 || (args.first && block)
423
- @mapping = args.first || block
424
- end
425
- self
426
- end
427
-
428
- # :call-seq:
429
- # run() => boolean
430
- #
431
- # Runs the filter.
432
- def run()
433
- raise "No source directory specified, where am I going to find the files to filter?" if sources.empty?
434
- sources.each { |source| raise "Source directory #{source} doesn't exist" unless File.exist?(source.to_s) }
435
- raise "No target directory specified, where am I going to copy the files to?" if target.nil?
436
-
437
- copy_map = sources.flatten.map(&:to_s).inject({}) do |map, source|
438
- base = Pathname.new(source)
439
- files = FileList.recursive(source).
440
- map { |file| Pathname.new(file).relative_path_from(base).to_s }.
441
- select { |file| @include.empty? || @include.any? { |pattern| File.fnmatch(pattern, file) } }.
442
- reject { |file| @exclude.any? { |pattern| File.fnmatch(pattern, file) } }
443
- files.each do |file|
444
- src, dest = File.expand_path(file, source), File.expand_path(file, target.to_s)
445
- map[file] = src if !File.exist?(dest) || File.stat(src).mtime > File.stat(dest).mtime
446
- end
447
- map
448
- end
449
-
450
- return false if copy_map.empty?
451
-
452
- verbose(Rake.application.options.trace || false) do
453
- mkpath target.to_s
454
- copy_map.each do |path, source|
455
- dest = File.expand_path(path, target.to_s)
456
- if File.directory?(source)
457
- mkpath dest
458
- else
459
- mkpath File.dirname(dest)
460
- case mapping
461
- when Proc, Method # Call on input, accept output.
462
- mapped = mapping.call(path, File.open(source, "rb") { |file| file.read })
463
- File.open(dest, "wb") { |file| file.write mapped }
464
- when Hash # Map ${key} to value
465
- content = File.open(source, "rb") { |file| file.read }
466
- if Symbol === @mapper
467
- mapped = send("#{@mapper}_mapper", content) { |key| mapping[key] }
468
- else
469
- mapped = regexp_mapper(content) { |key| mapping[key] }
470
- end
471
- #gsub(/\$\{[^}]*\}/) { |str| mapping[str[2..-2]] || str }
472
- File.open(dest, "wb") { |file| file.write mapped }
473
- when nil # No mapping.
474
- cp source, dest
475
- File.chmod(0664, dest)
476
- else
477
- fail "Filter can be a hash (key=>value), or a proc/method; I don't understand #{mapping}"
478
- end
479
- end
480
- end
481
- touch target.to_s
482
- end
483
- true
484
- end
485
-
486
- # Returns the target directory.
487
- def to_s()
488
- @target.to_s
489
- end
490
-
491
- private
492
-
493
- def maven_mapper(content)
494
- content.gsub(/\$\{.*?\}/) { |str| yield(str[2..-2]) || str }
495
- end
496
-
497
- def ant_mapper(content)
498
- content.gsub(/@.*?@/) { |str| yield(str[1..-2]) || str }
499
- end
500
-
501
- def ruby_mapper(content)
502
- content.gsub(/#\{.*?\}/) { |str| yield(str[2..-2]) || str }
503
- end
504
-
505
- def regexp_mapper(content)
506
- content.gsub(@mapper) { |str| yield(str.scan(@mapper).join) || str }
507
- end
508
-
509
- end
510
-
511
- # :call-seq:
512
- # filter(*source) => Filter
513
- #
514
- # Creates a filter that will copy files from the source directory(ies) into the target directory.
515
- # You can extend the filter to modify files by mapping <tt>${key}</tt> into values in each
516
- # of the copied files, and by including or excluding specific files.
517
- #
518
- # A filter is not a task, you must call the Filter#run method to execute it.
519
- #
520
- # For example, to copy all files from one directory to another:
521
- # filter("src/files").into("target/classes").run
522
- # To include only the text files, and replace each instance of <tt>${build}</tt> with the current
523
- # date/time:
524
- # filter("src/files").into("target/classes").include("*.txt").using("build"=>Time.now).run
525
- def filter(*sources)
526
- Filter.new.from(*sources)
527
- end
528
-
529
- end
530
-
531
-
532
- # Add a touch of colors (red) to warnings.
533
- HighLine.use_color = PLATFORM !~ /win32/
534
- module Kernel #:nodoc:
535
-
536
- def warn_with_color(message)
537
- warn_without_color $terminal.color(message.to_s, :red)
538
- end
539
- alias_method_chain :warn, :color
540
-
541
- # :call-seq:
542
- # warn_deprecated(message)
543
- #
544
- # Use with deprecated methods and classes. This method automatically adds the file name and line number,
545
- # and the text "Deprecated" before the message, and eliminated duplicate warnings. It only warns when
546
- # running in verbose mode.
547
- #
548
- # For example:
549
- # warn_deprecated "Please use new_foo instead of foo."
550
- def warn_deprecated(message) #:nodoc:
551
- return unless verbose
552
- "#{caller[1]}: Deprecated: #{message}".tap do |message|
553
- @deprecated ||= {}
554
- unless @deprecated[message]
555
- @deprecated[message] = true
556
- warn message
557
- end
558
- end
559
- end
560
-
561
- end
562
-