mguymon-buildr 1.4.5-java
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/CHANGELOG +1291 -0
- data/LICENSE +176 -0
- data/NOTICE +26 -0
- data/README.rdoc +134 -0
- data/Rakefile +44 -0
- data/_buildr +35 -0
- data/_jbuildr +35 -0
- data/addon/buildr/antlr.rb +65 -0
- data/addon/buildr/bnd.rb +147 -0
- data/addon/buildr/cobertura.rb +22 -0
- data/addon/buildr/drb.rb +281 -0
- data/addon/buildr/emma.rb +22 -0
- data/addon/buildr/hibernate.rb +149 -0
- data/addon/buildr/javacc.rb +85 -0
- data/addon/buildr/jaxb_xjc.rb +72 -0
- data/addon/buildr/jdepend.rb +60 -0
- data/addon/buildr/jetty.rb +248 -0
- data/addon/buildr/jibx.rb +86 -0
- data/addon/buildr/nailgun.rb +221 -0
- data/addon/buildr/openjpa.rb +88 -0
- data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
- data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
- data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
- data/addon/buildr/protobuf.rb +88 -0
- data/addon/buildr/xmlbeans.rb +93 -0
- data/bin/buildr +19 -0
- data/buildr.buildfile +58 -0
- data/buildr.gemspec +78 -0
- data/doc/_config.yml +1 -0
- data/doc/_layouts/default.html +90 -0
- data/doc/_layouts/preface.html +22 -0
- data/doc/artifacts.textile +217 -0
- data/doc/building.textile +276 -0
- data/doc/contributing.textile +268 -0
- data/doc/css/default.css +236 -0
- data/doc/css/print.css +101 -0
- data/doc/css/syntax.css +23 -0
- data/doc/download.textile +151 -0
- data/doc/extending.textile +212 -0
- data/doc/images/1442160941-frontcover.jpg +0 -0
- data/doc/images/asf-logo.gif +0 -0
- data/doc/images/asf-logo.png +0 -0
- data/doc/images/buildr-hires.png +0 -0
- data/doc/images/buildr.png +0 -0
- data/doc/images/favicon.png +0 -0
- data/doc/images/growl-icon.tiff +0 -0
- data/doc/images/note.png +0 -0
- data/doc/images/project-structure.png +0 -0
- data/doc/images/tip.png +0 -0
- data/doc/images/zbuildr.png +0 -0
- data/doc/images/zbuildr.tif +0 -0
- data/doc/index.textile +109 -0
- data/doc/installing.textile +284 -0
- data/doc/languages.textile +599 -0
- data/doc/mailing_lists.textile +29 -0
- data/doc/more_stuff.textile +845 -0
- data/doc/packaging.textile +618 -0
- data/doc/preface.textile +54 -0
- data/doc/projects.textile +276 -0
- data/doc/quick_start.textile +210 -0
- data/doc/releasing.textile +117 -0
- data/doc/scripts/buildr-git.rb +512 -0
- data/doc/scripts/gitflow.rb +296 -0
- data/doc/scripts/install-jruby.sh +44 -0
- data/doc/scripts/install-linux.sh +73 -0
- data/doc/scripts/install-osx.sh +52 -0
- data/doc/settings_profiles.textile +287 -0
- data/doc/testing.textile +247 -0
- data/etc/KEYS +189 -0
- data/lib/buildr.rb +44 -0
- data/lib/buildr/clojure.rb +34 -0
- data/lib/buildr/clojure/shell.rb +52 -0
- data/lib/buildr/core.rb +34 -0
- data/lib/buildr/core/application.rb +700 -0
- data/lib/buildr/core/build.rb +516 -0
- data/lib/buildr/core/cc.rb +166 -0
- data/lib/buildr/core/checks.rb +253 -0
- data/lib/buildr/core/common.rb +151 -0
- data/lib/buildr/core/compile.rb +622 -0
- data/lib/buildr/core/doc.rb +276 -0
- data/lib/buildr/core/environment.rb +129 -0
- data/lib/buildr/core/filter.rb +404 -0
- data/lib/buildr/core/generate.rb +197 -0
- data/lib/buildr/core/help.rb +119 -0
- data/lib/buildr/core/jrebel.rb +42 -0
- data/lib/buildr/core/linux.rb +30 -0
- data/lib/buildr/core/osx.rb +46 -0
- data/lib/buildr/core/progressbar.rb +161 -0
- data/lib/buildr/core/project.rb +975 -0
- data/lib/buildr/core/run.rb +43 -0
- data/lib/buildr/core/shell.rb +137 -0
- data/lib/buildr/core/test.rb +843 -0
- data/lib/buildr/core/transports.rb +575 -0
- data/lib/buildr/core/util.rb +537 -0
- data/lib/buildr/groovy.rb +20 -0
- data/lib/buildr/groovy/bdd.rb +106 -0
- data/lib/buildr/groovy/compiler.rb +153 -0
- data/lib/buildr/groovy/doc.rb +76 -0
- data/lib/buildr/groovy/shell.rb +57 -0
- data/lib/buildr/ide.rb +19 -0
- data/lib/buildr/ide/eclipse.rb +427 -0
- data/lib/buildr/ide/eclipse/java.rb +53 -0
- data/lib/buildr/ide/eclipse/plugin.rb +71 -0
- data/lib/buildr/ide/eclipse/scala.rb +68 -0
- data/lib/buildr/ide/idea.rb +576 -0
- data/lib/buildr/java.rb +25 -0
- data/lib/buildr/java/ant.rb +94 -0
- data/lib/buildr/java/bdd.rb +460 -0
- data/lib/buildr/java/cobertura.rb +297 -0
- data/lib/buildr/java/commands.rb +223 -0
- data/lib/buildr/java/compiler.rb +135 -0
- data/lib/buildr/java/deprecated.rb +141 -0
- data/lib/buildr/java/doc.rb +86 -0
- data/lib/buildr/java/ecj.rb +69 -0
- data/lib/buildr/java/emma.rb +244 -0
- data/lib/buildr/java/external.rb +73 -0
- data/lib/buildr/java/jruby.rb +122 -0
- data/lib/buildr/java/jtestr_result.rb +295 -0
- data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +142 -0
- data/lib/buildr/java/packaging.rb +734 -0
- data/lib/buildr/java/pom.rb +178 -0
- data/lib/buildr/java/rjb.rb +154 -0
- data/lib/buildr/java/test_result.rb +101 -0
- data/lib/buildr/java/tests.rb +362 -0
- data/lib/buildr/java/version_requirement.rb +172 -0
- data/lib/buildr/packaging.rb +25 -0
- data/lib/buildr/packaging/archive.rb +535 -0
- data/lib/buildr/packaging/artifact.rb +904 -0
- data/lib/buildr/packaging/artifact_namespace.rb +984 -0
- data/lib/buildr/packaging/artifact_search.rb +140 -0
- data/lib/buildr/packaging/gems.rb +105 -0
- data/lib/buildr/packaging/package.rb +249 -0
- data/lib/buildr/packaging/repository_array.rb +108 -0
- data/lib/buildr/packaging/tar.rb +189 -0
- data/lib/buildr/packaging/version_requirement.rb +192 -0
- data/lib/buildr/packaging/zip.rb +178 -0
- data/lib/buildr/packaging/ziptask.rb +356 -0
- data/lib/buildr/resources/buildr.icns +0 -0
- data/lib/buildr/resources/completed.png +0 -0
- data/lib/buildr/resources/failed.png +0 -0
- data/lib/buildr/resources/icons-license.txt +17 -0
- data/lib/buildr/run.rb +195 -0
- data/lib/buildr/scala.rb +26 -0
- data/lib/buildr/scala/bdd.rb +118 -0
- data/lib/buildr/scala/compiler.rb +242 -0
- data/lib/buildr/scala/doc.rb +142 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.java +57 -0
- data/lib/buildr/scala/shell.rb +52 -0
- data/lib/buildr/scala/tests.rb +171 -0
- data/lib/buildr/shell.rb +185 -0
- data/lib/buildr/version.rb +18 -0
- data/rakelib/all-in-one.rake +113 -0
- data/rakelib/checks.rake +57 -0
- data/rakelib/doc.rake +137 -0
- data/rakelib/metrics.rake +39 -0
- data/rakelib/package.rake +73 -0
- data/rakelib/release.rake +160 -0
- data/rakelib/rspec.rake +91 -0
- data/rakelib/setup.rake +66 -0
- data/rakelib/stage.rake +220 -0
- data/spec/addon/bnd_spec.rb +330 -0
- data/spec/addon/drb_spec.rb +328 -0
- data/spec/addon/jaxb_xjc_spec.rb +125 -0
- data/spec/core/application_spec.rb +631 -0
- data/spec/core/build_spec.rb +837 -0
- data/spec/core/cc_spec.rb +224 -0
- data/spec/core/checks_spec.rb +519 -0
- data/spec/core/common_spec.rb +725 -0
- data/spec/core/compile_spec.rb +658 -0
- data/spec/core/doc_spec.rb +195 -0
- data/spec/core/extension_spec.rb +201 -0
- data/spec/core/generate_spec.rb +33 -0
- data/spec/core/project_spec.rb +772 -0
- data/spec/core/run_spec.rb +93 -0
- data/spec/core/shell_spec.rb +146 -0
- data/spec/core/test_spec.rb +1320 -0
- data/spec/core/transport_spec.rb +544 -0
- data/spec/core/util_spec.rb +141 -0
- data/spec/groovy/bdd_spec.rb +80 -0
- data/spec/groovy/compiler_spec.rb +251 -0
- data/spec/groovy/doc_spec.rb +65 -0
- data/spec/ide/eclipse_spec.rb +739 -0
- data/spec/ide/idea_spec.rb +1145 -0
- data/spec/java/ant_spec.rb +37 -0
- data/spec/java/bdd_spec.rb +374 -0
- data/spec/java/cobertura_spec.rb +112 -0
- data/spec/java/commands_spec.rb +93 -0
- data/spec/java/compiler_spec.rb +252 -0
- data/spec/java/doc_spec.rb +56 -0
- data/spec/java/ecj_spec.rb +115 -0
- data/spec/java/emma_spec.rb +121 -0
- data/spec/java/external_spec.rb +56 -0
- data/spec/java/java_spec.rb +132 -0
- data/spec/java/packaging_spec.rb +1266 -0
- data/spec/java/run_spec.rb +78 -0
- data/spec/java/test_coverage_helper.rb +257 -0
- data/spec/java/tests_spec.rb +497 -0
- data/spec/packaging/archive_spec.rb +775 -0
- data/spec/packaging/artifact_namespace_spec.rb +743 -0
- data/spec/packaging/artifact_spec.rb +1074 -0
- data/spec/packaging/packaging_helper.rb +63 -0
- data/spec/packaging/packaging_spec.rb +719 -0
- data/spec/packaging/repository_array_spec.rb +109 -0
- data/spec/sandbox.rb +165 -0
- data/spec/scala/bdd_spec.rb +124 -0
- data/spec/scala/compiler_spec.rb +289 -0
- data/spec/scala/doc_spec.rb +88 -0
- data/spec/scala/scala.rb +38 -0
- data/spec/scala/tests_spec.rb +283 -0
- data/spec/spec_helpers.rb +369 -0
- data/spec/version_requirement_spec.rb +143 -0
- data/spec/xpath_matchers.rb +121 -0
- metadata +600 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with this
|
|
3
|
+
# work for additional information regarding copyright ownership. The ASF
|
|
4
|
+
# licenses this file to you under the Apache License, Version 2.0 (the
|
|
5
|
+
# "License"); you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
13
|
+
# License for the specific language governing permissions and limitations under
|
|
14
|
+
# the License.
|
|
15
|
+
|
|
16
|
+
require 'buildr/core/common'
|
|
17
|
+
require 'buildr/core/project'
|
|
18
|
+
require 'buildr/core/build'
|
|
19
|
+
require 'buildr/core/compile'
|
|
20
|
+
|
|
21
|
+
module Buildr
|
|
22
|
+
class CCTask < Rake::Task
|
|
23
|
+
attr_accessor :delay
|
|
24
|
+
attr_reader :project
|
|
25
|
+
|
|
26
|
+
def initialize(*args)
|
|
27
|
+
super
|
|
28
|
+
@delay = 0.2
|
|
29
|
+
enhance do
|
|
30
|
+
monitor_and_compile
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# run block on sub-projects depth-first, then on this project
|
|
37
|
+
def each_project(&block)
|
|
38
|
+
depth_first = lambda do |p|
|
|
39
|
+
p.projects.each { |c| depth_first.call(c, &block) }
|
|
40
|
+
block.call(p)
|
|
41
|
+
end
|
|
42
|
+
depth_first.call(@project)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def associate_with(project)
|
|
46
|
+
@project = project
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def monitor_and_compile
|
|
50
|
+
# we don't want to actually fail if our dependencies don't succeed
|
|
51
|
+
begin
|
|
52
|
+
each_project { |p| p.test.compile.invoke }
|
|
53
|
+
build_completed(project)
|
|
54
|
+
rescue Exception => ex
|
|
55
|
+
$stderr.puts $terminal.color(ex.message, :red)
|
|
56
|
+
$stderr.puts
|
|
57
|
+
|
|
58
|
+
build_failed(project, ex)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
dirs = []
|
|
62
|
+
each_project do |p|
|
|
63
|
+
dirs += p.compile.sources.map(&:to_s)
|
|
64
|
+
dirs += p.test.compile.sources.map(&:to_s)
|
|
65
|
+
dirs += p.resources.sources.map(&:to_s)
|
|
66
|
+
end
|
|
67
|
+
if dirs.length == 1
|
|
68
|
+
info "Monitoring directory: #{dirs.first}"
|
|
69
|
+
else
|
|
70
|
+
info "Monitoring directories: [#{dirs.join ', '}]"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
timestamps = lambda do
|
|
74
|
+
times = {}
|
|
75
|
+
dirs.each { |d| Dir.glob("#{d}/**/*").map { |f| times[f] = File.mtime f } }
|
|
76
|
+
times
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
old_times = timestamps.call()
|
|
80
|
+
|
|
81
|
+
while true
|
|
82
|
+
sleep delay
|
|
83
|
+
|
|
84
|
+
new_times = timestamps.call()
|
|
85
|
+
changed = changed(new_times, old_times)
|
|
86
|
+
old_times = new_times
|
|
87
|
+
|
|
88
|
+
unless changed.empty?
|
|
89
|
+
info '' # better spacing
|
|
90
|
+
|
|
91
|
+
changed.each do |file|
|
|
92
|
+
info "Detected changes in #{file}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
each_project do |p|
|
|
96
|
+
# transitively reenable prerequisites
|
|
97
|
+
reenable = lambda do |t|
|
|
98
|
+
t = task(t)
|
|
99
|
+
t.reenable
|
|
100
|
+
t.prerequisites.each { |c| reenable.call(c) }
|
|
101
|
+
end
|
|
102
|
+
reenable.call(p.test.compile)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
successful = true
|
|
106
|
+
begin
|
|
107
|
+
each_project { |p| p.test.compile.invoke }
|
|
108
|
+
build_completed(project)
|
|
109
|
+
rescue Exception => ex
|
|
110
|
+
$stderr.puts $terminal.color(ex.message, :red)
|
|
111
|
+
build_failed(project, ex)
|
|
112
|
+
successful = false
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
puts $terminal.color("Build complete", :green) if successful
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def build_completed(project)
|
|
121
|
+
Buildr.application.build_completed('Compilation successful', project.path_to)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def build_failed(project, ex = nil)
|
|
125
|
+
Buildr.application.build_failed('Compilation failed', project.path_to, ex)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def changed(new_times, old_times)
|
|
129
|
+
changed = []
|
|
130
|
+
new_times.each do |(fname,newtime)|
|
|
131
|
+
if old_times[fname].nil? || old_times[fname] < newtime
|
|
132
|
+
changed << fname
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# detect deletion (slower than it could be)
|
|
137
|
+
old_times.each_key do |fname|
|
|
138
|
+
changed << fname unless new_times.has_key? fname
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
changed
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
module CC
|
|
146
|
+
include Extension
|
|
147
|
+
|
|
148
|
+
first_time do
|
|
149
|
+
desc 'Execute continuous compilation, listening to changes'
|
|
150
|
+
Project.local_task('cc') { |name| "Executing continuous compilation for #{name}" }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
before_define do |project|
|
|
154
|
+
cc = CCTask.define_task :cc
|
|
155
|
+
cc.send :associate_with, project
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def cc
|
|
159
|
+
task :cc
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
class Project
|
|
164
|
+
include CC
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with this
|
|
3
|
+
# work for additional information regarding copyright ownership. The ASF
|
|
4
|
+
# licenses this file to you under the Apache License, Version 2.0 (the
|
|
5
|
+
# "License"); you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
13
|
+
# License for the specific language governing permissions and limitations under
|
|
14
|
+
# the License.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
require 'buildr/core/project'
|
|
18
|
+
autoload :RSpec, 'rspec'
|
|
19
|
+
|
|
20
|
+
module Buildr
|
|
21
|
+
# Methods added to Project to allow checking the build.
|
|
22
|
+
module Checks
|
|
23
|
+
|
|
24
|
+
module Matchers #:nodoc:
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
|
|
28
|
+
# Define matchers that operate by calling a method on the tested object.
|
|
29
|
+
# For example:
|
|
30
|
+
# foo.should contain(bar)
|
|
31
|
+
# calls:
|
|
32
|
+
# foo.contain(bar)
|
|
33
|
+
def match_using(*names)
|
|
34
|
+
names.each do |name|
|
|
35
|
+
matcher = Class.new do
|
|
36
|
+
# Initialize with expected arguments (i.e. contain(bar) initializes with bar).
|
|
37
|
+
define_method(:initialize) { |*args| @expects = args }
|
|
38
|
+
# Matches against actual value (i.e. foo.should exist called with foo).
|
|
39
|
+
define_method(:matches?) do |actual|
|
|
40
|
+
@actual = actual
|
|
41
|
+
return actual.send("#{name}?", *@expects) if actual.respond_to?("#{name}?")
|
|
42
|
+
return actual.send(name, *@expects) if actual.respond_to?(name)
|
|
43
|
+
raise "You can't check #{actual}, it doesn't respond to #{name}."
|
|
44
|
+
end
|
|
45
|
+
# Some matchers have arguments, others don't, treat appropriately.
|
|
46
|
+
define_method :failure_message do
|
|
47
|
+
args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
|
|
48
|
+
"Expected #{@actual} to #{name}#{args}"
|
|
49
|
+
end
|
|
50
|
+
define_method :negative_failure_message do
|
|
51
|
+
args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
|
|
52
|
+
"Expected #{@actual} to not #{name}#{args}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
# Define method to create matcher.
|
|
56
|
+
define_method(name) { |*args| matcher.new(*args) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Define delegate matchers for exist and contain methods.
|
|
63
|
+
match_using :exist, :contain
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# An expectation has subject, description and block. The expectation is validated by running the block,
|
|
69
|
+
# and can access the subject from the method #it. The description is used for reporting.
|
|
70
|
+
#
|
|
71
|
+
# The expectation is run by calling #run_against. You can share expectations by running them against
|
|
72
|
+
# different projects (or any other context for that matter).
|
|
73
|
+
#
|
|
74
|
+
# If the subject is missing, it is set to the argument of #run_against, typically the project itself.
|
|
75
|
+
# If the description is missing, it is set from the project. If the block is missing, the default behavior
|
|
76
|
+
# prints "Pending" followed by the description. You can use this to write place holders and fill them later.
|
|
77
|
+
class Expectation
|
|
78
|
+
|
|
79
|
+
attr_reader :description, :subject, :block
|
|
80
|
+
|
|
81
|
+
# :call-seq:
|
|
82
|
+
# initialize(subject, description?) { .... }
|
|
83
|
+
# initialize(description?) { .... }
|
|
84
|
+
#
|
|
85
|
+
# First argument is subject (returned from it method), second argument is description. If you omit the
|
|
86
|
+
# description, it will be set from the subject. If you omit the subject, it will be set from the object
|
|
87
|
+
# passed to run_against.
|
|
88
|
+
def initialize(*args, &block)
|
|
89
|
+
@description = args.pop if String === args.last
|
|
90
|
+
@subject = args.shift
|
|
91
|
+
raise ArgumentError, "Expecting subject followed by description, and either one is optional. Not quite sure what to do with this list of arguments." unless args.empty?
|
|
92
|
+
@block = block || lambda { |klass| info "Pending: #{description}" }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# :call-seq:
|
|
96
|
+
# run_against(context)
|
|
97
|
+
#
|
|
98
|
+
# Runs this expectation against the context object. The context object is different from the subject,
|
|
99
|
+
# but used as the subject if no subject specified (i.e. returned from the it method).
|
|
100
|
+
#
|
|
101
|
+
# This method creates a new context object modeled after the context argument, but a separate object
|
|
102
|
+
# used strictly for running this expectation, and used only once. The context object will pass methods
|
|
103
|
+
# to the context argument, so you can call any method, e.g. package(:jar).
|
|
104
|
+
#
|
|
105
|
+
# It also adds all matchers defined in Buildr and RSpec, and two additional methods:
|
|
106
|
+
# * it() -- Returns the subject.
|
|
107
|
+
# * description() -- Returns the description.
|
|
108
|
+
def run_against(context)
|
|
109
|
+
subject = @subject || context
|
|
110
|
+
description = @description ? "#{subject} #{@description}" : subject.to_s
|
|
111
|
+
# Define anonymous class and load it with:
|
|
112
|
+
# - All instance methods defined in context, so we can pass method calls to the context.
|
|
113
|
+
# - it() method to return subject, description() method to return description.
|
|
114
|
+
# - All matchers defined by Buildr and RSpec.
|
|
115
|
+
klass = Class.new
|
|
116
|
+
klass.instance_eval do
|
|
117
|
+
context.class.instance_methods.each do |method|
|
|
118
|
+
define_method(method) { |*args| context.send(method, *args) } unless instance_methods.include?(method)
|
|
119
|
+
end
|
|
120
|
+
define_method(:it) { subject }
|
|
121
|
+
define_method(:description) { description }
|
|
122
|
+
include ::RSpec::Matchers
|
|
123
|
+
include Matchers
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Run the expectation. We only print the expectation name when tracing (to know they all ran),
|
|
127
|
+
# or when we get a failure.
|
|
128
|
+
begin
|
|
129
|
+
trace description
|
|
130
|
+
klass.new.instance_eval &@block
|
|
131
|
+
rescue Exception=>error
|
|
132
|
+
raise error.exception("#{description}\n#{error}").tap { |wrapped| wrapped.set_backtrace(error.backtrace) }
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
include Extension
|
|
140
|
+
|
|
141
|
+
before_define(:check => :package) do |project|
|
|
142
|
+
# The check task can do any sort of interesting things, but the most important is running expectations.
|
|
143
|
+
project.task("check") do |task|
|
|
144
|
+
project.expectations.inject(true) do |passed, expect|
|
|
145
|
+
begin
|
|
146
|
+
expect.run_against project
|
|
147
|
+
passed
|
|
148
|
+
rescue Exception=>ex
|
|
149
|
+
if verbose
|
|
150
|
+
error ex
|
|
151
|
+
error ex.backtrace.select { |line| line =~ /#{Buildr.application.buildfile}/ }.join("\n")
|
|
152
|
+
end
|
|
153
|
+
false
|
|
154
|
+
end
|
|
155
|
+
end or fail "Checks failed for project #{project.name} (see errors above)."
|
|
156
|
+
end
|
|
157
|
+
project.task("package").enhance do |task|
|
|
158
|
+
# Run all actions before checks.
|
|
159
|
+
task.enhance { project.task("check").invoke }
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# :call-seq:
|
|
165
|
+
# check(description) { ... }
|
|
166
|
+
# check(subject, description) { ... }
|
|
167
|
+
#
|
|
168
|
+
# Adds an expectation. The expectation is run against the project by the check task, executed after packaging.
|
|
169
|
+
# You can access any package created by the project.
|
|
170
|
+
#
|
|
171
|
+
# An expectation is written using a subject, description and block to validate the expectation. For example:
|
|
172
|
+
#
|
|
173
|
+
# For example:
|
|
174
|
+
# check package(:jar), "should exist" do
|
|
175
|
+
# it.should exist
|
|
176
|
+
# end
|
|
177
|
+
# check package(:jar), "should contain a manifest" do
|
|
178
|
+
# it.should contain("META-INF/MANIFEST.MF")
|
|
179
|
+
# end
|
|
180
|
+
# check package(:jar).path("com/acme"), "should contain classes" do
|
|
181
|
+
# it.should_not be_empty
|
|
182
|
+
# end
|
|
183
|
+
# check package(:jar).entry("META-INF/MANIFEST"), "should be a recent license" do
|
|
184
|
+
# it.should contain(/Copyright (C) 2007/)
|
|
185
|
+
# end
|
|
186
|
+
#
|
|
187
|
+
# If you omit the subject, the project is used as the subject. If you omit the description, the subject is
|
|
188
|
+
# used as description.
|
|
189
|
+
#
|
|
190
|
+
# During development you can write placeholder expectations by omitting the block. This will simply report
|
|
191
|
+
# the expectation as pending.
|
|
192
|
+
def check(*args, &block)
|
|
193
|
+
expectations << Checks::Expectation.new(*args, &block)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# :call-seq:
|
|
197
|
+
# expectations() => Expectation*
|
|
198
|
+
#
|
|
199
|
+
# Returns a list of expectations (see #check).
|
|
200
|
+
def expectations()
|
|
201
|
+
@expectations ||= []
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
module Rake #:nodoc:
|
|
210
|
+
class FileTask
|
|
211
|
+
|
|
212
|
+
# :call-seq:
|
|
213
|
+
# exist?() => boolean
|
|
214
|
+
#
|
|
215
|
+
# Returns true if this file exists.
|
|
216
|
+
def exist?()
|
|
217
|
+
File.exist?(name)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# :call-seq:
|
|
221
|
+
# empty?() => boolean
|
|
222
|
+
#
|
|
223
|
+
# Returns true if file/directory is empty.
|
|
224
|
+
def empty?()
|
|
225
|
+
File.directory?(name) ? Dir.glob("#{name}/*").empty? : File.read(name).empty?
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# :call-seq:
|
|
229
|
+
# contain?(pattern*) => boolean
|
|
230
|
+
# contain?(file*) => boolean
|
|
231
|
+
#
|
|
232
|
+
# For a file, returns true if the file content matches against all the arguments. An argument may be
|
|
233
|
+
# a string or regular expression.
|
|
234
|
+
#
|
|
235
|
+
# For a directory, return true if the directory contains the specified files. You can use relative
|
|
236
|
+
# file names and glob patterns (using *, **, etc).
|
|
237
|
+
def contain?(*patterns)
|
|
238
|
+
if File.directory?(name)
|
|
239
|
+
patterns.map { |pattern| "#{name}/#{pattern}" }.all? { |pattern| !Dir[pattern].empty? }
|
|
240
|
+
else
|
|
241
|
+
contents = File.read(name)
|
|
242
|
+
patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
|
|
243
|
+
all? { |pattern| contents =~ pattern }
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class Buildr::Project
|
|
252
|
+
include Buildr::Checks
|
|
253
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with this
|
|
3
|
+
# work for additional information regarding copyright ownership. The ASF
|
|
4
|
+
# licenses this file to you under the Apache License, Version 2.0 (the
|
|
5
|
+
# "License"); you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
13
|
+
# License for the specific language governing permissions and limitations under
|
|
14
|
+
# the License.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
require 'rake'
|
|
18
|
+
require 'buildr/core/util'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
module Buildr
|
|
22
|
+
|
|
23
|
+
# :call-seq:
|
|
24
|
+
# struct(hash) => Struct
|
|
25
|
+
#
|
|
26
|
+
# Convenience method for creating an anonymous Struct.
|
|
27
|
+
#
|
|
28
|
+
# For example:
|
|
29
|
+
# COMMONS = struct(
|
|
30
|
+
# :collections =>'commons-collections:commons-collections:jar:3.1',
|
|
31
|
+
# :lang =>'commons-lang:commons-lang:jar:2.1',
|
|
32
|
+
# :logging =>'commons-logging:commons-logging:jar:1.0.3',
|
|
33
|
+
# )
|
|
34
|
+
#
|
|
35
|
+
# compile.with COMMONS.logging
|
|
36
|
+
def struct(hash)
|
|
37
|
+
Struct.new(nil, *hash.keys).new(*hash.values)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# :call-seq:
|
|
41
|
+
# write(name, content)
|
|
42
|
+
# write(name) { ... }
|
|
43
|
+
#
|
|
44
|
+
# Write the contents into a file. The second form calls the block and writes the result.
|
|
45
|
+
#
|
|
46
|
+
# For example:
|
|
47
|
+
# write 'TIMESTAMP', Time.now
|
|
48
|
+
# write('TIMESTAMP') { Time.now }
|
|
49
|
+
#
|
|
50
|
+
# Yields to the block before writing the file, so you can chain read and write together.
|
|
51
|
+
# For example:
|
|
52
|
+
# write('README') { read('README').sub("${build}", Time.now) }
|
|
53
|
+
def write(name, content = nil)
|
|
54
|
+
mkpath File.dirname(name)
|
|
55
|
+
content = yield if block_given?
|
|
56
|
+
File.open(name.to_s, 'wb') { |file| file.write content.to_s }
|
|
57
|
+
content.to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# :call-seq:
|
|
61
|
+
# read(args) => string
|
|
62
|
+
# read(args) { |string| ... } => result
|
|
63
|
+
#
|
|
64
|
+
# Reads and returns the contents of a file. The second form yields to the block and returns
|
|
65
|
+
# the result of the block. The args passed to read are passed on to File.open.
|
|
66
|
+
#
|
|
67
|
+
# For example:
|
|
68
|
+
# puts read('README')
|
|
69
|
+
# read('README') { |text| puts text }
|
|
70
|
+
def read(*args)
|
|
71
|
+
args[0] = args[0].to_s
|
|
72
|
+
contents = File.open(*args) { |f| f.read }
|
|
73
|
+
if block_given?
|
|
74
|
+
yield contents
|
|
75
|
+
else
|
|
76
|
+
contents
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# :call-seq:
|
|
81
|
+
# download(url_or_uri) => task
|
|
82
|
+
# download(path=>url_or_uri) =>task
|
|
83
|
+
#
|
|
84
|
+
# Create a task that will download a file from a URL.
|
|
85
|
+
#
|
|
86
|
+
# Takes a single argument, a hash with one pair. The key is the file being
|
|
87
|
+
# created, the value if the URL to download. The task executes only if the
|
|
88
|
+
# file does not exist; the URL is not checked for updates.
|
|
89
|
+
#
|
|
90
|
+
# The task will show download progress on the console; if there are MD5/SHA1
|
|
91
|
+
# checksums on the server it will verify the download before saving it.
|
|
92
|
+
#
|
|
93
|
+
# For example:
|
|
94
|
+
# download 'image.jpg'=>'http://example.com/theme/image.jpg'
|
|
95
|
+
def download(args)
|
|
96
|
+
args = URI.parse(args) if String === args
|
|
97
|
+
if URI === args
|
|
98
|
+
# Given only a download URL, download into a temporary file.
|
|
99
|
+
# You can infer the file from task name.
|
|
100
|
+
temp = Tempfile.open(File.basename(args.to_s))
|
|
101
|
+
file(temp.path).tap do |task|
|
|
102
|
+
# Since temporary file exists, force a download.
|
|
103
|
+
class << task ; def needed? ; true ; end ; end
|
|
104
|
+
task.sources << args
|
|
105
|
+
task.enhance { args.download temp }
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
# Download to a file created by the task.
|
|
109
|
+
fail unless args.keys.size == 1
|
|
110
|
+
uri = URI.parse(args.values.first.to_s)
|
|
111
|
+
file(args.keys.first.to_s).tap do |task|
|
|
112
|
+
task.sources << uri
|
|
113
|
+
task.enhance { uri.download task.name }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# A file task that concatenates all its prerequisites to create a new file.
|
|
120
|
+
#
|
|
121
|
+
# For example:
|
|
122
|
+
# concat("master.sql"=>["users.sql", "orders.sql", reports.sql"]
|
|
123
|
+
#
|
|
124
|
+
# See also Buildr#concat.
|
|
125
|
+
class ConcatTask < Rake::FileTask
|
|
126
|
+
def initialize(*args) #:nodoc:
|
|
127
|
+
super
|
|
128
|
+
enhance do |task|
|
|
129
|
+
content = prerequisites.inject("") do |content, prereq|
|
|
130
|
+
content << File.read(prereq.to_s) if File.exists?(prereq) && !File.directory?(prereq)
|
|
131
|
+
content
|
|
132
|
+
end
|
|
133
|
+
File.open(task.name, "wb") { |file| file.write content }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# :call-seq:
|
|
139
|
+
# concat(target=>files) => task
|
|
140
|
+
#
|
|
141
|
+
# Creates and returns a file task that concatenates all its prerequisites to create
|
|
142
|
+
# a new file. See #ConcatTask.
|
|
143
|
+
#
|
|
144
|
+
# For example:
|
|
145
|
+
# concat("master.sql"=>["users.sql", "orders.sql", reports.sql"]
|
|
146
|
+
def concat(args)
|
|
147
|
+
file, arg_names, deps = Buildr.application.resolve_args([args])
|
|
148
|
+
ConcatTask.define_task(File.expand_path(file)=>deps)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end
|