buildr 1.3.0-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 +780 -0
- data/DISCLAIMER +7 -0
- data/KEYS +151 -0
- data/LICENSE +176 -0
- data/NOTICE +31 -0
- data/README +173 -0
- data/Rakefile +63 -0
- data/addon/buildr/antlr.rb +65 -0
- data/addon/buildr/cobertura.rb +232 -0
- data/addon/buildr/hibernate.rb +142 -0
- data/addon/buildr/javacc.rb +85 -0
- data/addon/buildr/jdepend.rb +60 -0
- data/addon/buildr/jetty.rb +248 -0
- data/addon/buildr/nailgun.rb +892 -0
- data/addon/buildr/openjpa.rb +90 -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/xmlbeans.rb +93 -0
- data/bin/buildr +21 -0
- data/buildr.gemspec +50 -0
- data/doc/css/default.css +225 -0
- data/doc/css/print.css +95 -0
- data/doc/css/syntax.css +43 -0
- data/doc/images/apache-incubator-logo.png +0 -0
- data/doc/images/buildr-hires.png +0 -0
- data/doc/images/buildr.png +0 -0
- data/doc/images/note.png +0 -0
- data/doc/images/tip.png +0 -0
- data/doc/images/zbuildr.tif +0 -0
- data/doc/pages/artifacts.textile +317 -0
- data/doc/pages/building.textile +501 -0
- data/doc/pages/contributing.textile +178 -0
- data/doc/pages/download.textile +25 -0
- data/doc/pages/extending.textile +229 -0
- data/doc/pages/getting_started.textile +337 -0
- data/doc/pages/index.textile +63 -0
- data/doc/pages/mailing_lists.textile +17 -0
- data/doc/pages/more_stuff.textile +367 -0
- data/doc/pages/packaging.textile +592 -0
- data/doc/pages/projects.textile +449 -0
- data/doc/pages/recipes.textile +127 -0
- data/doc/pages/settings_profiles.textile +339 -0
- data/doc/pages/testing.textile +475 -0
- data/doc/pages/troubleshooting.textile +121 -0
- data/doc/pages/whats_new.textile +389 -0
- data/doc/print.haml +52 -0
- data/doc/print.toc.yaml +28 -0
- data/doc/scripts/buildr-git.rb +411 -0
- data/doc/scripts/install-jruby.sh +44 -0
- data/doc/scripts/install-linux.sh +64 -0
- data/doc/scripts/install-osx.sh +52 -0
- data/doc/site.haml +55 -0
- data/doc/site.toc.yaml +44 -0
- data/lib/buildr.rb +47 -0
- data/lib/buildr/core.rb +27 -0
- data/lib/buildr/core/application.rb +373 -0
- data/lib/buildr/core/application_cli.rb +134 -0
- data/lib/buildr/core/build.rb +262 -0
- data/lib/buildr/core/checks.rb +382 -0
- data/lib/buildr/core/common.rb +155 -0
- data/lib/buildr/core/compile.rb +594 -0
- data/lib/buildr/core/environment.rb +120 -0
- data/lib/buildr/core/filter.rb +258 -0
- data/lib/buildr/core/generate.rb +195 -0
- data/lib/buildr/core/help.rb +118 -0
- data/lib/buildr/core/progressbar.rb +156 -0
- data/lib/buildr/core/project.rb +890 -0
- data/lib/buildr/core/test.rb +690 -0
- data/lib/buildr/core/transports.rb +486 -0
- data/lib/buildr/core/util.rb +235 -0
- data/lib/buildr/ide.rb +19 -0
- data/lib/buildr/ide/eclipse.rb +181 -0
- data/lib/buildr/ide/idea.ipr.template +300 -0
- data/lib/buildr/ide/idea.rb +194 -0
- data/lib/buildr/ide/idea7x.ipr.template +290 -0
- data/lib/buildr/ide/idea7x.rb +210 -0
- data/lib/buildr/java.rb +26 -0
- data/lib/buildr/java/ant.rb +71 -0
- data/lib/buildr/java/bdd_frameworks.rb +267 -0
- data/lib/buildr/java/commands.rb +210 -0
- data/lib/buildr/java/compilers.rb +432 -0
- data/lib/buildr/java/deprecated.rb +141 -0
- data/lib/buildr/java/groovyc.rb +137 -0
- data/lib/buildr/java/jruby.rb +99 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail$Main.class +0 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail.class +0 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail.java +41 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +116 -0
- data/lib/buildr/java/packaging.rb +706 -0
- data/lib/buildr/java/pom.rb +178 -0
- data/lib/buildr/java/rjb.rb +142 -0
- data/lib/buildr/java/test_frameworks.rb +290 -0
- data/lib/buildr/java/version_requirement.rb +172 -0
- data/lib/buildr/packaging.rb +21 -0
- data/lib/buildr/packaging/artifact.rb +729 -0
- data/lib/buildr/packaging/artifact_namespace.rb +957 -0
- data/lib/buildr/packaging/artifact_search.rb +140 -0
- data/lib/buildr/packaging/gems.rb +102 -0
- data/lib/buildr/packaging/package.rb +233 -0
- data/lib/buildr/packaging/tar.rb +104 -0
- data/lib/buildr/packaging/zip.rb +719 -0
- data/rakelib/apache.rake +126 -0
- data/rakelib/changelog.rake +56 -0
- data/rakelib/doc.rake +103 -0
- data/rakelib/package.rake +44 -0
- data/rakelib/release.rake +53 -0
- data/rakelib/rspec.rake +81 -0
- data/rakelib/rubyforge.rake +45 -0
- data/rakelib/scm.rake +49 -0
- data/rakelib/setup.rake +59 -0
- data/rakelib/stage.rake +45 -0
- data/spec/application_spec.rb +316 -0
- data/spec/archive_spec.rb +494 -0
- data/spec/artifact_namespace_spec.rb +635 -0
- data/spec/artifact_spec.rb +738 -0
- data/spec/build_spec.rb +193 -0
- data/spec/checks_spec.rb +537 -0
- data/spec/common_spec.rb +579 -0
- data/spec/compile_spec.rb +561 -0
- data/spec/groovy_compilers_spec.rb +239 -0
- data/spec/java_bdd_frameworks_spec.rb +238 -0
- data/spec/java_compilers_spec.rb +446 -0
- data/spec/java_packaging_spec.rb +1042 -0
- data/spec/java_test_frameworks_spec.rb +414 -0
- data/spec/packaging_helper.rb +63 -0
- data/spec/packaging_spec.rb +589 -0
- data/spec/project_spec.rb +739 -0
- data/spec/sandbox.rb +116 -0
- data/spec/scala_compilers_spec.rb +239 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helpers.rb +283 -0
- data/spec/test_spec.rb +871 -0
- data/spec/transport_spec.rb +300 -0
- data/spec/version_requirement_spec.rb +115 -0
- metadata +324 -0
|
@@ -0,0 +1,134 @@
|
|
|
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
|
+
# Portion of this file derived from Rake.
|
|
17
|
+
# Copyright (c) 2003, 2004 Jim Weirich
|
|
18
|
+
#
|
|
19
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
20
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
21
|
+
# in the Software without restriction, including without limitation the rights
|
|
22
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
23
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
24
|
+
# furnished to do so, subject to the following conditions:
|
|
25
|
+
#
|
|
26
|
+
# The above copyright notice and this permission notice shall be included in
|
|
27
|
+
# all copies or substantial portions of the Software.
|
|
28
|
+
#
|
|
29
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
30
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
32
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
33
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
34
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
35
|
+
# SOFTWARE.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
require 'getoptlong'
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
module Buildr
|
|
42
|
+
module CommandLineInterface
|
|
43
|
+
|
|
44
|
+
OPTIONS = [ # :nodoc:
|
|
45
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT,
|
|
46
|
+
'Display this help message.'],
|
|
47
|
+
['--nosearch', '-n', GetoptLong::NO_ARGUMENT,
|
|
48
|
+
'Do not search parent directories for the buildfile.'],
|
|
49
|
+
['--quiet', '-q', GetoptLong::NO_ARGUMENT,
|
|
50
|
+
'Do not log messages to standard output.'],
|
|
51
|
+
['--buildfile', '-f', GetoptLong::REQUIRED_ARGUMENT,
|
|
52
|
+
'Use FILE as the buildfile.'],
|
|
53
|
+
['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
|
|
54
|
+
'Require MODULE before executing buildfile.'],
|
|
55
|
+
['--trace', '-t', GetoptLong::NO_ARGUMENT,
|
|
56
|
+
'Turn on invoke/execute tracing, enable full backtrace.'],
|
|
57
|
+
['--version', '-v', GetoptLong::NO_ARGUMENT,
|
|
58
|
+
'Display the program version.'],
|
|
59
|
+
['--environment', '-e', GetoptLong::REQUIRED_ARGUMENT,
|
|
60
|
+
'Environment name (e.g. development, test, production).']
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
def collect_tasks
|
|
64
|
+
top_level_tasks.clear
|
|
65
|
+
ARGV.each do |arg|
|
|
66
|
+
if arg =~ /^(\w+)=(.*)$/
|
|
67
|
+
ENV[$1.upcase] = $2
|
|
68
|
+
else
|
|
69
|
+
top_level_tasks << arg
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
top_level_tasks.push("default") if top_level_tasks.size == 0
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def parse_options
|
|
76
|
+
opts = GetoptLong.new(*command_line_options)
|
|
77
|
+
opts.each { |opt, value| do_option(opt, value) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def do_option(opt, value)
|
|
81
|
+
case opt
|
|
82
|
+
when '--help'
|
|
83
|
+
help
|
|
84
|
+
exit
|
|
85
|
+
when '--buildfile'
|
|
86
|
+
rakefiles.clear
|
|
87
|
+
rakefiles << value
|
|
88
|
+
when '--version'
|
|
89
|
+
puts version
|
|
90
|
+
exit
|
|
91
|
+
when '--environment'
|
|
92
|
+
ENV['BUILDR_ENV'] = value
|
|
93
|
+
when '--require'
|
|
94
|
+
requires << value
|
|
95
|
+
when '--nosearch', '--quiet', '--trace'
|
|
96
|
+
super
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def command_line_options
|
|
101
|
+
OPTIONS.collect { |lst| lst[0..-2] }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def version
|
|
105
|
+
"Buildr #{Buildr::VERSION} #{RUBY_PLATFORM[/java/] && '(JRuby '+JRUBY_VERSION+')'}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def usage
|
|
109
|
+
puts version
|
|
110
|
+
puts
|
|
111
|
+
puts 'Usage:'
|
|
112
|
+
puts ' buildr [options] [tasks] [name=value]'
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def help
|
|
116
|
+
usage
|
|
117
|
+
puts
|
|
118
|
+
puts 'Options:'
|
|
119
|
+
OPTIONS.sort.each do |long, short, mode, desc|
|
|
120
|
+
if mode == GetoptLong::REQUIRED_ARGUMENT
|
|
121
|
+
if desc =~ /\b([A-Z]{2,})\b/
|
|
122
|
+
long = long + "=#{$1}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
printf " %-20s (%s)\n", long, short
|
|
126
|
+
printf " %s\n", desc
|
|
127
|
+
end
|
|
128
|
+
puts
|
|
129
|
+
puts 'For help with your buildfile:'
|
|
130
|
+
puts ' buildr help'
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,262 @@
|
|
|
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
|
+
require 'buildr/core/common'
|
|
19
|
+
require 'buildr/core/checks'
|
|
20
|
+
require 'buildr/core/environment'
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
module Buildr
|
|
24
|
+
|
|
25
|
+
class Options
|
|
26
|
+
|
|
27
|
+
# Runs the build in parallel when true (defaults to false). You can force a parallel build by
|
|
28
|
+
# setting this option directly, or by running the parallel task ahead of the build task.
|
|
29
|
+
#
|
|
30
|
+
# This option only affects recurvise tasks. For example:
|
|
31
|
+
# buildr parallel package
|
|
32
|
+
# will run all package tasks (from the sub-projects) in parallel, but each sub-project's package
|
|
33
|
+
# task runs its child tasks (prepare, compile, resources, etc) in sequence.
|
|
34
|
+
attr_accessor :parallel
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
task('parallel') { Buildr.options.parallel = true }
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
module Build
|
|
42
|
+
|
|
43
|
+
include Extension
|
|
44
|
+
|
|
45
|
+
first_time do
|
|
46
|
+
desc 'Build the project'
|
|
47
|
+
Project.local_task('build') { |name| "Building #{name}" }
|
|
48
|
+
desc 'Clean files generated during a build'
|
|
49
|
+
Project.local_task('clean') { |name| "Cleaning #{name}" }
|
|
50
|
+
|
|
51
|
+
desc 'The default task it build'
|
|
52
|
+
task 'default'=>'build'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
before_define do |project|
|
|
56
|
+
project.recursive_task 'build'
|
|
57
|
+
project.recursive_task 'clean'
|
|
58
|
+
project.clean do
|
|
59
|
+
verbose(true) do
|
|
60
|
+
rm_rf project.path_to(:target)
|
|
61
|
+
rm_rf project.path_to(:reports)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# *Deprecated:* Use +path_to(:target)+ instead.
|
|
68
|
+
def target
|
|
69
|
+
Buildr.application.deprecated 'Use path_to(:target) instead'
|
|
70
|
+
layout.expand(:target)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# *Deprecated:* Use Layout instead.
|
|
74
|
+
def target=(dir)
|
|
75
|
+
Buildr.application.deprecated 'Use Layout instead'
|
|
76
|
+
layout[:target] = _(dir)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# *Deprecated:* Use +path_to(:reports)+ instead.
|
|
80
|
+
def reports()
|
|
81
|
+
Buildr.application.deprecated 'Use path_to(:reports) instead'
|
|
82
|
+
layout.expand(:reports)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# *Deprecated:* Use Layout instead.
|
|
86
|
+
def reports=(dir)
|
|
87
|
+
Buildr.application.deprecated 'Use Layout instead'
|
|
88
|
+
layout[:reports] = _(dir)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# :call-seq:
|
|
92
|
+
# build(*prereqs) => task
|
|
93
|
+
# build { |task| .. } => task
|
|
94
|
+
#
|
|
95
|
+
# Returns the project's build task. With arguments or block, also enhances that task.
|
|
96
|
+
def build(*prereqs, &block)
|
|
97
|
+
task('build').enhance prereqs, &block
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# :call-seq:
|
|
101
|
+
# clean(*prereqs) => task
|
|
102
|
+
# clean { |task| .. } => task
|
|
103
|
+
#
|
|
104
|
+
# Returns the project's clean task. With arguments or block, also enhances that task.
|
|
105
|
+
def clean(*prereqs, &block)
|
|
106
|
+
task('clean').enhance prereqs, &block
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Release
|
|
113
|
+
|
|
114
|
+
THIS_VERSION_PATTERN = /THIS_VERSION|VERSION_NUMBER\s*=\s*(["'])(.*)\1/
|
|
115
|
+
NEXT_VERSION_PATTERN = /NEXT_VERSION\s*=\s*(["'])(.*)\1/
|
|
116
|
+
|
|
117
|
+
class << self
|
|
118
|
+
|
|
119
|
+
# :call-seq:
|
|
120
|
+
# make()
|
|
121
|
+
#
|
|
122
|
+
# Make a release.
|
|
123
|
+
def make()
|
|
124
|
+
check
|
|
125
|
+
version = with_next_version do |filename, version|
|
|
126
|
+
options = ['--buildfile', filename, 'DEBUG=no']
|
|
127
|
+
options << '--environment' << Buildr.environment unless Buildr.environment.to_s.empty?
|
|
128
|
+
sh "#{command} clean upload #{options.join(' ')}"
|
|
129
|
+
end
|
|
130
|
+
tag version
|
|
131
|
+
commit version + '-SNAPSHOT'
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
protected
|
|
135
|
+
|
|
136
|
+
def command() #:nodoc:
|
|
137
|
+
Config::CONFIG['arch'] =~ /dos|win32/i ? $PROGRAM_NAME.ext('cmd') : $PROGRAM_NAME
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# :call-seq:
|
|
141
|
+
# check()
|
|
142
|
+
#
|
|
143
|
+
# Check that we don't have any local changes in the working copy. Fails if it finds anything
|
|
144
|
+
# in the working copy that is not checked into source control.
|
|
145
|
+
def check()
|
|
146
|
+
fail "SVN URL must end with 'trunk' or 'branches/...'" unless svn_url =~ /(trunk)|(branches.*)$/
|
|
147
|
+
# Status check reveals modified file, but also SVN externals which we can safely ignore.
|
|
148
|
+
status = svn('status', '--ignore-externals').reject { |line| line =~ /^X\s/ }
|
|
149
|
+
fail "Uncommitted SVN files violate the First Principle Of Release!\n#{status}" unless
|
|
150
|
+
status.empty?
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# :call-seq:
|
|
154
|
+
# with_next_version() { |filename| ... } => version
|
|
155
|
+
#
|
|
156
|
+
# Yields to block with upgraded version number, before committing to use it. Returns the *new*
|
|
157
|
+
# current version number.
|
|
158
|
+
#
|
|
159
|
+
# We need a Buildfile with upgraded version numbers to run the build, but we don't want the
|
|
160
|
+
# Buildfile modified unless the build succeeds. So this method updates the version numbers in
|
|
161
|
+
# a separate (Buildfile.next) file, yields to the block with that filename, and if successful
|
|
162
|
+
# copies the new file over the existing one.
|
|
163
|
+
#
|
|
164
|
+
# Version numbers are updated as follows. The next release version becomes the current one,
|
|
165
|
+
# and the next version is upgraded by one to become the new next version. So:
|
|
166
|
+
# THIS_VERSION = 1.1.0
|
|
167
|
+
# NEXT_VERSION = 1.2.0
|
|
168
|
+
# becomes:
|
|
169
|
+
# THIS_VERSION = 1.2.0
|
|
170
|
+
# NEXT_VERSION = 1.2.1
|
|
171
|
+
# and the method will return 1.2.0.
|
|
172
|
+
def with_next_version()
|
|
173
|
+
new_filename = Buildr.application.buildfile + '.next'
|
|
174
|
+
modified = change_version do |this_version, next_version|
|
|
175
|
+
one_after = next_version.split('.')
|
|
176
|
+
one_after[-1] = one_after[-1].to_i + 1
|
|
177
|
+
[ next_version, one_after.join('.') ]
|
|
178
|
+
end
|
|
179
|
+
File.open(new_filename, 'w') { |file| file.write modified }
|
|
180
|
+
begin
|
|
181
|
+
yield new_filename
|
|
182
|
+
mv new_filename, Buildr.application.buildfile
|
|
183
|
+
ensure
|
|
184
|
+
rm new_filename rescue nil
|
|
185
|
+
end
|
|
186
|
+
File.read(Buildr.application.buildfile).scan(THIS_VERSION_PATTERN)[0][1]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# :call-seq:
|
|
190
|
+
# change_version() { |this, next| ... } => buildfile
|
|
191
|
+
#
|
|
192
|
+
# Change version numbers in the current Buildfile, but without writing a new file (yet).
|
|
193
|
+
# Returns the contents of the Buildfile with the modified version numbers.
|
|
194
|
+
#
|
|
195
|
+
# This method yields to the block with the current (this) and next version numbers and expects
|
|
196
|
+
# an array with the new this and next version numbers.
|
|
197
|
+
def change_version()
|
|
198
|
+
buildfile = File.read(Buildr.application.buildfile)
|
|
199
|
+
this_version = buildfile.scan(THIS_VERSION_PATTERN)[0][1] or
|
|
200
|
+
fail "Looking for THIS_VERSION = \"...\" in your Buildfile, none found"
|
|
201
|
+
next_version = buildfile.scan(NEXT_VERSION_PATTERN)[0][1] or
|
|
202
|
+
fail "Looking for NEXT_VERSION = \"...\" in your Buildfile, none found"
|
|
203
|
+
this_version, next_version = yield(this_version, next_version)
|
|
204
|
+
if verbose
|
|
205
|
+
puts 'Upgrading version numbers:'
|
|
206
|
+
puts " This: #{this_version}"
|
|
207
|
+
puts " Next: #{next_version}"
|
|
208
|
+
end
|
|
209
|
+
buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{this_version}"}) }.
|
|
210
|
+
gsub(NEXT_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{next_version}"}) }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# :call-seq:
|
|
214
|
+
# tag(version)
|
|
215
|
+
#
|
|
216
|
+
# Tags the current working copy with the release version number.
|
|
217
|
+
def tag(version)
|
|
218
|
+
url = svn_url.sub(/(trunk$)|(branches.*)$/, "tags/#{version}")
|
|
219
|
+
svn 'remove', url, '-m', 'Removing old copy' rescue nil
|
|
220
|
+
svn 'copy', Dir.pwd, url, '-m', "Release #{version}"
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# :call-seq:
|
|
224
|
+
# commit(version)
|
|
225
|
+
#
|
|
226
|
+
# Last, we commit what we currently have in the working copy.
|
|
227
|
+
def commit(version)
|
|
228
|
+
buildfile = File.read(Buildr.application.buildfile).
|
|
229
|
+
gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{version}"}) }
|
|
230
|
+
File.open(Buildr.application.buildfile, 'w') { |file| file.write buildfile }
|
|
231
|
+
svn 'commit', '-m', "Changed version number to #{version}", Buildr.application.buildfile
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# :call-seq:
|
|
235
|
+
# svn(*args)
|
|
236
|
+
#
|
|
237
|
+
# Executes SVN command and returns the output.
|
|
238
|
+
def svn(*args)
|
|
239
|
+
cmd = 'svn ' + args.map { |arg| arg[' '] ? %Q{"#{arg}"} : arg }.join(' ')
|
|
240
|
+
puts cmd if verbose
|
|
241
|
+
`#{cmd}`.tap { fail 'SVN command failed' unless $?.exitstatus == 0 }
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Return the current SVN URL
|
|
245
|
+
def svn_url
|
|
246
|
+
url = svn('info').scan(/URL: (.*)/)[0][0]
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
desc 'Make a release'
|
|
253
|
+
task 'release' do |task|
|
|
254
|
+
Release.make
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class Buildr::Project
|
|
261
|
+
include Buildr::Build
|
|
262
|
+
end
|
|
@@ -0,0 +1,382 @@
|
|
|
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
|
+
require 'buildr/packaging/zip'
|
|
19
|
+
require 'test/unit'
|
|
20
|
+
require 'spec/matchers'
|
|
21
|
+
require 'spec/expectations'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
module Buildr
|
|
25
|
+
# Methods added to Project to allow checking the build.
|
|
26
|
+
module Checks
|
|
27
|
+
|
|
28
|
+
module Matchers #:nodoc:
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
|
|
32
|
+
# Define matchers that operate by calling a method on the tested object.
|
|
33
|
+
# For example:
|
|
34
|
+
# foo.should contain(bar)
|
|
35
|
+
# calls:
|
|
36
|
+
# foo.contain(bar)
|
|
37
|
+
def match_using(*names)
|
|
38
|
+
names.each do |name|
|
|
39
|
+
matcher = Class.new do
|
|
40
|
+
# Initialize with expected arguments (i.e. contain(bar) initializes with bar).
|
|
41
|
+
define_method(:initialize) { |*args| @expects = args }
|
|
42
|
+
# Matches against actual value (i.e. foo.should exist called with foo).
|
|
43
|
+
define_method(:matches?) do |actual|
|
|
44
|
+
@actual = actual
|
|
45
|
+
return actual.send("#{name}?", *@expects) if actual.respond_to?("#{name}?")
|
|
46
|
+
return actual.send(name, *@expects) if actual.respond_to?(name)
|
|
47
|
+
raise "You can't check #{actual}, it doesn't respond to #{name}."
|
|
48
|
+
end
|
|
49
|
+
# Some matchers have arguments, others don't, treat appropriately.
|
|
50
|
+
define_method :failure_message do
|
|
51
|
+
args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
|
|
52
|
+
"Expected #{@actual} to #{name}#{args}"
|
|
53
|
+
end
|
|
54
|
+
define_method :negative_failure_message do
|
|
55
|
+
args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
|
|
56
|
+
"Expected #{@actual} to not #{name}#{args}"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
# Define method to create matcher.
|
|
60
|
+
define_method(name) { |*args| matcher.new(*args) }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Define delegate matchers for exist and contain methods.
|
|
67
|
+
match_using :exist, :contain
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# An expectation has subject, description and block. The expectation is validated by running the block,
|
|
73
|
+
# and can access the subject from the method #it. The description is used for reporting.
|
|
74
|
+
#
|
|
75
|
+
# The expectation is run by calling #run_against. You can share expectations by running them against
|
|
76
|
+
# different projects (or any other context for that matter).
|
|
77
|
+
#
|
|
78
|
+
# If the subject is missing, it is set to the argument of #run_against, typically the project itself.
|
|
79
|
+
# If the description is missing, it is set from the project. If the block is missing, the default behavior
|
|
80
|
+
# prints "Pending" followed by the description. You can use this to write place holders and fill them later.
|
|
81
|
+
class Expectation
|
|
82
|
+
|
|
83
|
+
attr_reader :description, :subject, :block
|
|
84
|
+
|
|
85
|
+
# :call-seq:
|
|
86
|
+
# initialize(subject, description?) { .... }
|
|
87
|
+
# initialize(description?) { .... }
|
|
88
|
+
#
|
|
89
|
+
# First argument is subject (returned from it method), second argument is description. If you omit the
|
|
90
|
+
# description, it will be set from the subject. If you omit the subject, it will be set from the object
|
|
91
|
+
# passed to run_against.
|
|
92
|
+
def initialize(*args, &block)
|
|
93
|
+
@description = args.pop if String === args.last
|
|
94
|
+
@subject = args.shift
|
|
95
|
+
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?
|
|
96
|
+
@block = block || lambda { puts "Pending: #{description}" if verbose }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# :call-seq:
|
|
100
|
+
# run_against(context)
|
|
101
|
+
#
|
|
102
|
+
# Runs this expectation against the context object. The context object is different from the subject,
|
|
103
|
+
# but used as the subject if no subject specified (i.e. returned from the it method).
|
|
104
|
+
#
|
|
105
|
+
# This method creates a new context object modeled after the context argument, but a separate object
|
|
106
|
+
# used strictly for running this expectation, and used only once. The context object will pass methods
|
|
107
|
+
# to the context argument, so you can call any method, e.g. package(:jar).
|
|
108
|
+
#
|
|
109
|
+
# It also adds all matchers defined in Buildr and RSpec, and two additional methods:
|
|
110
|
+
# * it() -- Returns the subject.
|
|
111
|
+
# * description() -- Returns the description.
|
|
112
|
+
def run_against(context)
|
|
113
|
+
subject = @subject || context
|
|
114
|
+
description = @description ? "#{subject} #{@description}" : subject.to_s
|
|
115
|
+
# Define anonymous class and load it with:
|
|
116
|
+
# - All instance methods defined in context, so we can pass method calls to the context.
|
|
117
|
+
# - it() method to return subject, description() method to return description.
|
|
118
|
+
# - All matchers defined by Buildr and RSpec.
|
|
119
|
+
klass = Class.new
|
|
120
|
+
klass.instance_eval do
|
|
121
|
+
context.class.instance_methods(false).each do |method|
|
|
122
|
+
define_method(method) { |*args| context.send(method, *args) }
|
|
123
|
+
end
|
|
124
|
+
define_method(:it) { subject }
|
|
125
|
+
define_method(:description) { description }
|
|
126
|
+
include Spec::Matchers
|
|
127
|
+
include Matchers
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Run the expectation. We only print the expectation name when tracing (to know they all ran),
|
|
131
|
+
# or when we get a failure.
|
|
132
|
+
begin
|
|
133
|
+
puts description if Buildr.application.options.trace
|
|
134
|
+
klass.new.instance_eval &@block
|
|
135
|
+
rescue Exception=>error
|
|
136
|
+
raise error.exception("#{description}\n#{error}").tap { |wrapped| wrapped.set_backtrace(error.backtrace) }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
include Extension
|
|
144
|
+
|
|
145
|
+
before_define do |project|
|
|
146
|
+
# The check task can do any sort of interesting things, but the most important is running expectations.
|
|
147
|
+
project.task("check") do |task|
|
|
148
|
+
project.expectations.inject(true) do |passed, expect|
|
|
149
|
+
begin
|
|
150
|
+
expect.run_against project
|
|
151
|
+
passed
|
|
152
|
+
rescue Exception=>error
|
|
153
|
+
if verbose
|
|
154
|
+
puts error.backtrace.detect { |line| line =~ /#{Buildr.application.buildfile}/ } || ""
|
|
155
|
+
puts error
|
|
156
|
+
end
|
|
157
|
+
false
|
|
158
|
+
end
|
|
159
|
+
end or fail "Checks failed for project #{project.name} (see errors above)."
|
|
160
|
+
end
|
|
161
|
+
project.task("package").enhance do |task|
|
|
162
|
+
# Run all actions before checks.
|
|
163
|
+
task.enhance { project.task("check").invoke }
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# :call-seq:
|
|
169
|
+
# check(description) { ... }
|
|
170
|
+
# check(subject, description) { ... }
|
|
171
|
+
#
|
|
172
|
+
# Adds an expectation. The expectation is run against the project by the check task, executed after packaging.
|
|
173
|
+
# You can access any package created by the project.
|
|
174
|
+
#
|
|
175
|
+
# An expectation is written using a subject, description and block to validate the expectation. For example:
|
|
176
|
+
#
|
|
177
|
+
# For example:
|
|
178
|
+
# check package(:jar), "should exist" do
|
|
179
|
+
# it.should exist
|
|
180
|
+
# end
|
|
181
|
+
# check package(:jar), "should contain a manifest" do
|
|
182
|
+
# it.should contain("META-INF/MANIFEST.MF")
|
|
183
|
+
# end
|
|
184
|
+
# check package(:jar).path("com/acme"), "should contain classes" do
|
|
185
|
+
# it.should_not be_empty
|
|
186
|
+
# end
|
|
187
|
+
# check package(:jar).entry("META-INF/MANIFEST"), "should be a recent license" do
|
|
188
|
+
# it.should contain(/Copyright (C) 2007/)
|
|
189
|
+
# end
|
|
190
|
+
#
|
|
191
|
+
# If you omit the subject, the project is used as the subject. If you omit the description, the subject is
|
|
192
|
+
# used as description.
|
|
193
|
+
#
|
|
194
|
+
# During development you can write placeholder expectations by omitting the block. This will simply report
|
|
195
|
+
# the expectation as pending.
|
|
196
|
+
def check(*args, &block)
|
|
197
|
+
expectations << Checks::Expectation.new(*args, &block)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# :call-seq:
|
|
201
|
+
# expectations() => Expectation*
|
|
202
|
+
#
|
|
203
|
+
# Returns a list of expectations (see #check).
|
|
204
|
+
def expectations()
|
|
205
|
+
@expectations ||= []
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
module Rake #:nodoc:
|
|
214
|
+
class FileTask
|
|
215
|
+
|
|
216
|
+
# :call-seq:
|
|
217
|
+
# exist?() => boolean
|
|
218
|
+
#
|
|
219
|
+
# Returns true if this file exists.
|
|
220
|
+
def exist?()
|
|
221
|
+
File.exist?(name)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# :call-seq:
|
|
225
|
+
# empty?() => boolean
|
|
226
|
+
#
|
|
227
|
+
# Returns true if file/directory is empty.
|
|
228
|
+
def empty?()
|
|
229
|
+
File.directory?(name) ? Dir.glob("#{name}/*").empty? : File.read(name).empty?
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# :call-seq:
|
|
233
|
+
# contain?(pattern*) => boolean
|
|
234
|
+
# contain?(file*) => boolean
|
|
235
|
+
#
|
|
236
|
+
# For a file, returns true if the file content matches against all the arguments. An argument may be
|
|
237
|
+
# a string or regular expression.
|
|
238
|
+
#
|
|
239
|
+
# For a directory, return true if the directory contains the specified files. You can use relative
|
|
240
|
+
# file names and glob patterns (using *, **, etc).
|
|
241
|
+
def contain?(*patterns)
|
|
242
|
+
if File.directory?(name)
|
|
243
|
+
patterns.map { |pattern| "#{name}/#{pattern}" }.all? { |pattern| !Dir[pattern].empty? }
|
|
244
|
+
else
|
|
245
|
+
contents = File.read(name)
|
|
246
|
+
patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
|
|
247
|
+
all? { |pattern| contents =~ pattern }
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
module Zip #:nodoc:
|
|
256
|
+
class ZipEntry
|
|
257
|
+
|
|
258
|
+
# :call-seq:
|
|
259
|
+
# exist() => boolean
|
|
260
|
+
#
|
|
261
|
+
# Returns true if this entry exists.
|
|
262
|
+
def exist?()
|
|
263
|
+
Zip::ZipFile.open(zipfile) { |zip| zip.file.exist?(@name) }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# :call-seq:
|
|
267
|
+
# empty?() => boolean
|
|
268
|
+
#
|
|
269
|
+
# Returns true if this entry is empty.
|
|
270
|
+
def empty?()
|
|
271
|
+
Zip::ZipFile.open(zipfile) { |zip| zip.file.read(@name) }.empty?
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# :call-seq:
|
|
275
|
+
# contain(patterns*) => boolean
|
|
276
|
+
#
|
|
277
|
+
# Returns true if this ZIP file entry matches against all the arguments. An argument may be
|
|
278
|
+
# a string or regular expression.
|
|
279
|
+
def contain?(*patterns)
|
|
280
|
+
content = Zip::ZipFile.open(zipfile) { |zip| zip.file.read(@name) }
|
|
281
|
+
patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
|
|
282
|
+
all? { |pattern| content =~ pattern }
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class Buildr::ArchiveTask
|
|
290
|
+
|
|
291
|
+
class Path #:nodoc:
|
|
292
|
+
|
|
293
|
+
# :call-seq:
|
|
294
|
+
# exist() => boolean
|
|
295
|
+
#
|
|
296
|
+
# Returns true if this path exists. This only works if the path has any entries in it,
|
|
297
|
+
# so exist on path happens to be the opposite of empty.
|
|
298
|
+
def exist?()
|
|
299
|
+
!entries.empty?
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# :call-seq:
|
|
303
|
+
# empty?() => boolean
|
|
304
|
+
#
|
|
305
|
+
# Returns true if this path is empty (has no other entries inside).
|
|
306
|
+
def empty?()
|
|
307
|
+
entries.all? { |entry| entry.empty? }
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# :call-seq:
|
|
311
|
+
# contain(file*) => boolean
|
|
312
|
+
#
|
|
313
|
+
# Returns true if this ZIP file path contains all the specified files. You can use relative
|
|
314
|
+
# file names and glob patterns (using *, **, etc).
|
|
315
|
+
def contain?(*files)
|
|
316
|
+
files.all? { |file| entries.detect { |entry| File.fnmatch(file, entry.to_s, File::FNM_PATHNAME) } }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# :call-seq:
|
|
320
|
+
# entry(name) => ZipEntry
|
|
321
|
+
#
|
|
322
|
+
# Returns a ZIP file entry. You can use this to check if the entry exists and its contents,
|
|
323
|
+
# for example:
|
|
324
|
+
# package(:jar).path("META-INF").entry("LICENSE").should contain(/Apache Software License/)
|
|
325
|
+
def entry(name)
|
|
326
|
+
root.entry("#{@path}#{name}")
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
protected
|
|
330
|
+
|
|
331
|
+
def entries() #:nodoc:
|
|
332
|
+
return root.entries unless @path
|
|
333
|
+
@entries ||= root.entries.inject([]) { |selected, entry|
|
|
334
|
+
selected << entry.name.sub(@path, "") if entry.name.index(@path) == 0
|
|
335
|
+
selected
|
|
336
|
+
}
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# :call-seq:
|
|
342
|
+
# empty?() => boolean
|
|
343
|
+
#
|
|
344
|
+
# Returns true if this ZIP file is empty (has no other entries inside).
|
|
345
|
+
def empty?()
|
|
346
|
+
path("").empty
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# :call-seq:
|
|
350
|
+
# contain(file*) => boolean
|
|
351
|
+
#
|
|
352
|
+
# Returns true if this ZIP file contains all the specified files. You can use absolute
|
|
353
|
+
# file names and glob patterns (using *, **, etc).
|
|
354
|
+
def contain?(*files)
|
|
355
|
+
path("").contain?(*files)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class Buildr::ZipTask #:nodoc:
|
|
362
|
+
|
|
363
|
+
# :call-seq:
|
|
364
|
+
# entry(name) => Entry
|
|
365
|
+
#
|
|
366
|
+
# Returns a ZIP file entry. You can use this to check if the entry exists and its contents,
|
|
367
|
+
# for example:
|
|
368
|
+
# package(:jar).entry("META-INF/LICENSE").should contain(/Apache Software License/)
|
|
369
|
+
def entry(entry_name)
|
|
370
|
+
::Zip::ZipEntry.new(name, entry_name)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def entries() #:nodoc:
|
|
374
|
+
@entries ||= Zip::ZipFile.open(name) { |zip| zip.entries }
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class Buildr::Project
|
|
381
|
+
include Buildr::Checks
|
|
382
|
+
end
|