buildr 1.3.5-x86-mswin32
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 +998 -0
- data/LICENSE +176 -0
- data/NOTICE +26 -0
- data/README.rdoc +134 -0
- data/Rakefile +45 -0
- data/_buildr +29 -0
- data/_jbuildr +29 -0
- data/addon/buildr/antlr.rb +65 -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 +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/jibx.rb +86 -0
- data/addon/buildr/nailgun.rb +221 -0
- data/addon/buildr/openjpa.rb +90 -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/xmlbeans.rb +93 -0
- data/bin/buildr +19 -0
- data/buildr.buildfile +58 -0
- data/buildr.gemspec +65 -0
- data/doc/_config.yml +1 -0
- data/doc/_layouts/default.html +88 -0
- data/doc/_layouts/preface.html +22 -0
- data/doc/artifacts.textile +211 -0
- data/doc/building.textile +244 -0
- data/doc/contributing.textile +252 -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 +79 -0
- data/doc/extending.textile +186 -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 +69 -0
- data/doc/installing.textile +266 -0
- data/doc/languages.textile +459 -0
- data/doc/mailing_lists.textile +25 -0
- data/doc/more_stuff.textile +457 -0
- data/doc/packaging.textile +430 -0
- data/doc/preface.textile +54 -0
- data/doc/projects.textile +271 -0
- data/doc/quick_start.textile +210 -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 +72 -0
- data/doc/scripts/install-osx.sh +52 -0
- data/doc/settings_profiles.textile +280 -0
- data/doc/testing.textile +222 -0
- data/etc/KEYS +151 -0
- data/lib/buildr.rb +36 -0
- data/lib/buildr/core.rb +35 -0
- data/lib/buildr/core/application.rb +656 -0
- data/lib/buildr/core/build.rb +452 -0
- data/lib/buildr/core/checks.rb +254 -0
- data/lib/buildr/core/common.rb +150 -0
- data/lib/buildr/core/compile.rb +608 -0
- data/lib/buildr/core/environment.rb +129 -0
- data/lib/buildr/core/filter.rb +362 -0
- data/lib/buildr/core/generate.rb +195 -0
- data/lib/buildr/core/help.rb +119 -0
- data/lib/buildr/core/osx.rb +46 -0
- data/lib/buildr/core/progressbar.rb +156 -0
- data/lib/buildr/core/project.rb +866 -0
- data/lib/buildr/core/shell.rb +198 -0
- data/lib/buildr/core/test.rb +723 -0
- data/lib/buildr/core/transports.rb +559 -0
- data/lib/buildr/core/util.rb +449 -0
- data/lib/buildr/groovy.rb +19 -0
- data/lib/buildr/groovy/bdd.rb +106 -0
- data/lib/buildr/groovy/compiler.rb +138 -0
- data/lib/buildr/groovy/shell.rb +48 -0
- data/lib/buildr/ide.rb +19 -0
- data/lib/buildr/ide/eclipse.rb +334 -0
- data/lib/buildr/ide/eclipse/java.rb +53 -0
- data/lib/buildr/ide/eclipse/plugin.rb +68 -0
- data/lib/buildr/ide/eclipse/scala.rb +66 -0
- data/lib/buildr/ide/idea.ipr.template +300 -0
- data/lib/buildr/ide/idea.rb +190 -0
- data/lib/buildr/ide/idea7x.ipr.template +290 -0
- data/lib/buildr/ide/idea7x.rb +212 -0
- data/lib/buildr/java.rb +23 -0
- data/lib/buildr/java/ant.rb +94 -0
- data/lib/buildr/java/bdd.rb +459 -0
- data/lib/buildr/java/cobertura.rb +274 -0
- data/lib/buildr/java/commands.rb +213 -0
- data/lib/buildr/java/compiler.rb +349 -0
- data/lib/buildr/java/deprecated.rb +141 -0
- data/lib/buildr/java/emma.rb +244 -0
- data/lib/buildr/java/jruby.rb +117 -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 +137 -0
- data/lib/buildr/java/packaging.rb +716 -0
- data/lib/buildr/java/pom.rb +174 -0
- data/lib/buildr/java/rjb.rb +155 -0
- data/lib/buildr/java/test_result.rb +353 -0
- data/lib/buildr/java/tests.rb +333 -0
- data/lib/buildr/java/version_requirement.rb +172 -0
- data/lib/buildr/packaging.rb +24 -0
- data/lib/buildr/packaging/archive.rb +488 -0
- data/lib/buildr/packaging/artifact.rb +749 -0
- data/lib/buildr/packaging/artifact_namespace.rb +972 -0
- data/lib/buildr/packaging/artifact_search.rb +140 -0
- data/lib/buildr/packaging/gems.rb +102 -0
- data/lib/buildr/packaging/package.rb +238 -0
- data/lib/buildr/packaging/tar.rb +186 -0
- data/lib/buildr/packaging/version_requirement.rb +172 -0
- data/lib/buildr/packaging/zip.rb +73 -0
- data/lib/buildr/packaging/ziptask.rb +316 -0
- data/lib/buildr/resources/buildr.icns +0 -0
- data/lib/buildr/scala.rb +25 -0
- data/lib/buildr/scala/bdd.rb +109 -0
- data/lib/buildr/scala/compiler.rb +195 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner$.class +0 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.scala +35 -0
- data/lib/buildr/scala/shell.rb +55 -0
- data/lib/buildr/scala/tests.rb +157 -0
- data/lib/buildr/shell.rb +180 -0
- data/rakelib/checks.rake +57 -0
- data/rakelib/doc.rake +92 -0
- data/rakelib/jekylltask.rb +120 -0
- data/rakelib/package.rake +73 -0
- data/rakelib/release.rake +149 -0
- data/rakelib/rspec.rake +73 -0
- data/rakelib/setup.rake +54 -0
- data/rakelib/stage.rake +213 -0
- data/rakelib/stage.rake~ +213 -0
- data/spec/addon/drb_spec.rb +328 -0
- data/spec/core/application_spec.rb +502 -0
- data/spec/core/build_spec.rb +677 -0
- data/spec/core/checks_spec.rb +519 -0
- data/spec/core/common_spec.rb +670 -0
- data/spec/core/compile_spec.rb +583 -0
- data/spec/core/extension_spec.rb +93 -0
- data/spec/core/generate_spec.rb +33 -0
- data/spec/core/project_spec.rb +762 -0
- data/spec/core/test_spec.rb +1098 -0
- data/spec/core/transport_spec.rb +537 -0
- data/spec/core/util_spec.rb +67 -0
- data/spec/groovy/bdd_spec.rb +80 -0
- data/spec/groovy/compiler_spec.rb +240 -0
- data/spec/ide/eclipse_spec.rb +501 -0
- data/spec/ide/idea7x_spec.rb +84 -0
- data/spec/java/ant_spec.rb +33 -0
- data/spec/java/bdd_spec.rb +382 -0
- data/spec/java/cobertura_spec.rb +85 -0
- data/spec/java/compiler_spec.rb +446 -0
- data/spec/java/emma_spec.rb +119 -0
- data/spec/java/java_spec.rb +124 -0
- data/spec/java/packaging_spec.rb +1134 -0
- data/spec/java/test_coverage_helper.rb +257 -0
- data/spec/java/tests_spec.rb +493 -0
- data/spec/packaging/archive_spec.rb +527 -0
- data/spec/packaging/artifact_namespace_spec.rb +654 -0
- data/spec/packaging/artifact_spec.rb +795 -0
- data/spec/packaging/packaging_helper.rb +63 -0
- data/spec/packaging/packaging_spec.rb +684 -0
- data/spec/sandbox.rb +142 -0
- data/spec/scala/bdd_spec.rb +119 -0
- data/spec/scala/compiler_spec.rb +284 -0
- data/spec/scala/scala.rb +38 -0
- data/spec/scala/tests_spec.rb +261 -0
- data/spec/spec_helpers.rb +340 -0
- data/spec/version_requirement_spec.rb +129 -0
- metadata +383 -0
@@ -0,0 +1,186 @@
|
|
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/packaging/archive'
|
18
|
+
gem 'archive-tar-minitar' ; autoload :Archive, 'archive/tar/minitar'
|
19
|
+
|
20
|
+
|
21
|
+
module Buildr
|
22
|
+
|
23
|
+
# The TarTask creates a new Tar file. You can include any number of files and and directories,
|
24
|
+
# use exclusion patterns, and include files into specific directories.
|
25
|
+
#
|
26
|
+
# To create a GZipped Tar, either set the gzip option to true, or use the .tgz or .gz suffix.
|
27
|
+
#
|
28
|
+
# For example:
|
29
|
+
# tar("test.tgz").tap do |task|
|
30
|
+
# task.include "srcs"
|
31
|
+
# task.include "README", "LICENSE"
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# See Buildr#tar and ArchiveTask.
|
35
|
+
class TarTask < ArchiveTask
|
36
|
+
|
37
|
+
# To create a GZipped Tar, either set this option to true, or use the .tgz/.gz suffix.
|
38
|
+
attr_accessor :gzip
|
39
|
+
# Permission mode for files contained in the Tar. Defaults to 0755.
|
40
|
+
attr_accessor :mode
|
41
|
+
|
42
|
+
def initialize(*args, &block) #:nodoc:
|
43
|
+
super
|
44
|
+
self.gzip = name =~ /\.[t?]gz$/
|
45
|
+
self.mode = '0755'
|
46
|
+
end
|
47
|
+
|
48
|
+
# :call-seq:
|
49
|
+
# entry(name) => Entry
|
50
|
+
#
|
51
|
+
# Returns a Tar file entry. You can use this to check if the entry exists and its contents,
|
52
|
+
# for example:
|
53
|
+
# package(:tar).entry("src/LICENSE").should contain(/Apache Software License/)
|
54
|
+
def entry(entry_name)
|
55
|
+
Buildr::TarEntry.new(self, entry_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def entries() #:nodoc:
|
59
|
+
tar_entries = nil
|
60
|
+
with_uncompressed_tar { |tar| tar_entries = tar.entries }
|
61
|
+
tar_entries
|
62
|
+
end
|
63
|
+
|
64
|
+
# :call-seq:
|
65
|
+
# with_uncompressed_tar { |tar_entries| ... }
|
66
|
+
#
|
67
|
+
# Yields an Archive::Tar::Minitar::Input object to the provided block.
|
68
|
+
# Opening, closing and Gzip-decompressing is automatically taken care of.
|
69
|
+
def with_uncompressed_tar &block
|
70
|
+
if gzip
|
71
|
+
Zlib::GzipReader.open(name) { |tar| Archive::Tar::Minitar.open(tar, &block) }
|
72
|
+
else
|
73
|
+
Archive::Tar::Minitar.open(name, &block)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def create_from(file_map)
|
80
|
+
if gzip
|
81
|
+
StringIO.new.tap do |io|
|
82
|
+
create_tar io, file_map
|
83
|
+
io.seek 0
|
84
|
+
Zlib::GzipWriter.open(name) { |gzip| gzip.write io.read }
|
85
|
+
end
|
86
|
+
else
|
87
|
+
File.open(name, 'wb') { |file| create_tar file, file_map }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_tar(out, file_map)
|
92
|
+
Archive::Tar::Minitar::Writer.open(out) do |tar|
|
93
|
+
options = { :mode=>mode || '0755', :mtime=>Time.now }
|
94
|
+
|
95
|
+
file_map.each do |path, content|
|
96
|
+
if content.respond_to?(:call)
|
97
|
+
tar.add_file(path, options) { |os, opts| content.call os }
|
98
|
+
elsif content.nil? || File.directory?(content.to_s)
|
99
|
+
else
|
100
|
+
File.open content.to_s, 'rb' do |is|
|
101
|
+
tar.add_file path, options.merge(:mode=>is.stat.mode, :mtime=>is.stat.mtime, :uid=>is.stat.uid, :gid=>is.stat.gid) do |os, opts|
|
102
|
+
while data = is.read(4096)
|
103
|
+
os.write(data)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
class TarEntry #:nodoc:
|
116
|
+
|
117
|
+
def initialize(tar_task, entry_name)
|
118
|
+
@tar_task = tar_task
|
119
|
+
@entry_name = entry_name
|
120
|
+
end
|
121
|
+
|
122
|
+
# :call-seq:
|
123
|
+
# contain?(*patterns) => boolean
|
124
|
+
#
|
125
|
+
# Returns true if this Tar file entry matches against all the arguments. An argument may be
|
126
|
+
# a string or regular expression.
|
127
|
+
def contain?(*patterns)
|
128
|
+
content = read_content_from_tar
|
129
|
+
patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
|
130
|
+
all? { |pattern| content =~ pattern }
|
131
|
+
end
|
132
|
+
|
133
|
+
# :call-seq:
|
134
|
+
# empty?() => boolean
|
135
|
+
#
|
136
|
+
# Returns true if this entry is empty.
|
137
|
+
def empty?()
|
138
|
+
read_content_from_tar.nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
# :call-seq:
|
142
|
+
# exist() => boolean
|
143
|
+
#
|
144
|
+
# Returns true if this entry exists.
|
145
|
+
def exist?()
|
146
|
+
exist = false
|
147
|
+
@tar_task.with_uncompressed_tar { |tar| exist = tar.any? { |entry| entry.name == @entry_name } }
|
148
|
+
exist
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_s #:nodoc:
|
152
|
+
@entry_name
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def read_content_from_tar
|
158
|
+
content = Errno::ENOENT.new("No such file or directory - #{@entry_name}")
|
159
|
+
@tar_task.with_uncompressed_tar do |tar|
|
160
|
+
content = tar.inject(content) { |content, entry| entry.name == @entry_name ? entry.read : content }
|
161
|
+
end
|
162
|
+
raise content if Exception === content
|
163
|
+
content
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# :call-seq:
|
171
|
+
# tar(file) => TarTask
|
172
|
+
#
|
173
|
+
# The TarTask creates a new Tar file. You can include any number of files and
|
174
|
+
# and directories, use exclusion patterns, and include files into specific
|
175
|
+
# directories.
|
176
|
+
#
|
177
|
+
# To create a GZipped Tar, either set the gzip option to true, or use the .tgz or .gz suffix.
|
178
|
+
#
|
179
|
+
# For example:
|
180
|
+
# tar("test.tgz").tap do |tgz|
|
181
|
+
# tgz.include "srcs"
|
182
|
+
# tgz.include "README", "LICENSE"
|
183
|
+
# end
|
184
|
+
def tar(file)
|
185
|
+
TarTask.define_task(file)
|
186
|
+
end
|
@@ -0,0 +1,172 @@
|
|
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
|
+
module Buildr
|
18
|
+
|
19
|
+
#
|
20
|
+
# See ArtifactNamespace#need
|
21
|
+
class VersionRequirement
|
22
|
+
|
23
|
+
CMP_PROCS = Gem::Requirement::OPS.dup
|
24
|
+
CMP_REGEX = Gem::Requirement::OP_RE.dup
|
25
|
+
CMP_CHARS = CMP_PROCS.keys.join
|
26
|
+
BOOL_CHARS = '\|\&\!'
|
27
|
+
VER_CHARS = '\w\.\-'
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# is +str+ a version string?
|
31
|
+
def version?(str)
|
32
|
+
/^\s*[#{VER_CHARS}]+\s*$/ === str
|
33
|
+
end
|
34
|
+
|
35
|
+
# is +str+ a version requirement?
|
36
|
+
def requirement?(str)
|
37
|
+
/[#{BOOL_CHARS}#{CMP_CHARS}\(\)]/ === str
|
38
|
+
end
|
39
|
+
|
40
|
+
# :call-seq:
|
41
|
+
# VersionRequirement.create(" >1 <2 !(1.5) ") -> requirement
|
42
|
+
#
|
43
|
+
# parse the +str+ requirement
|
44
|
+
def create(str)
|
45
|
+
instance_eval normalize(str)
|
46
|
+
rescue StandardError => e
|
47
|
+
raise "Failed to parse #{str.inspect} due to: #{e}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def requirement(req)
|
52
|
+
unless req =~ /^\s*(#{CMP_REGEX})?\s*([#{VER_CHARS}]+)\s*$/
|
53
|
+
raise "Invalid requirement string: #{req}"
|
54
|
+
end
|
55
|
+
comparator, version = $1, $2
|
56
|
+
version = Gem::Version.new(0).tap { |v| v.version = version }
|
57
|
+
VersionRequirement.new(nil, [$1, version])
|
58
|
+
end
|
59
|
+
|
60
|
+
def negate(vreq)
|
61
|
+
vreq.negative = !vreq.negative
|
62
|
+
vreq
|
63
|
+
end
|
64
|
+
|
65
|
+
def normalize(str)
|
66
|
+
str = str.strip
|
67
|
+
if str[/[^\s\(\)#{BOOL_CHARS + VER_CHARS + CMP_CHARS}]/]
|
68
|
+
raise "version string #{str.inspect} contains invalid characters"
|
69
|
+
end
|
70
|
+
str.gsub!(/\s+(and|\&\&)\s+/, ' & ')
|
71
|
+
str.gsub!(/\s+(or|\|\|)\s+/, ' | ')
|
72
|
+
str.gsub!(/(^|\s*)not\s+/, ' ! ')
|
73
|
+
pattern = /(#{CMP_REGEX})?\s*[#{VER_CHARS}]+/
|
74
|
+
left_pattern = /[#{VER_CHARS}\)]$/
|
75
|
+
right_pattern = /^(#{pattern}|\()/
|
76
|
+
str = str.split.inject([]) do |ary, i|
|
77
|
+
ary << '&' if ary.last =~ left_pattern && i =~ right_pattern
|
78
|
+
ary << i
|
79
|
+
end
|
80
|
+
str = str.join(' ')
|
81
|
+
str.gsub!(/!([^=])?/, ' negate \1')
|
82
|
+
str.gsub!(pattern) do |expr|
|
83
|
+
case expr.strip
|
84
|
+
when 'not', 'negate' then 'negate '
|
85
|
+
else 'requirement("' + expr + '")'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
str.gsub!(/negate\s+\(/, 'negate(')
|
89
|
+
str
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize(op, *requirements) #:nodoc:
|
94
|
+
@op, @requirements = op, requirements
|
95
|
+
end
|
96
|
+
|
97
|
+
# Is this object a composed requirement?
|
98
|
+
# VersionRequirement.create('1').composed? -> false
|
99
|
+
# VersionRequirement.create('1 | 2').composed? -> true
|
100
|
+
# VersionRequirement.create('1 & 2').composed? -> true
|
101
|
+
def composed?
|
102
|
+
requirements.size > 1
|
103
|
+
end
|
104
|
+
|
105
|
+
# Return the last requirement on this object having an = operator.
|
106
|
+
def default
|
107
|
+
default = nil
|
108
|
+
requirements.reverse.find do |r|
|
109
|
+
if Array === r
|
110
|
+
if !negative && (r.first.nil? || r.first.include?('='))
|
111
|
+
default = r.last.to_s
|
112
|
+
end
|
113
|
+
else
|
114
|
+
default = r.default
|
115
|
+
end
|
116
|
+
end
|
117
|
+
default
|
118
|
+
end
|
119
|
+
|
120
|
+
# Test if this requirement can be satisfied by +version+
|
121
|
+
def satisfied_by?(version)
|
122
|
+
return false unless version
|
123
|
+
unless version.kind_of?(Gem::Version)
|
124
|
+
raise "Invalid version: #{version.inspect}" unless self.class.version?(version)
|
125
|
+
version = Gem::Version.new(0).tap { |v| v.version = version.strip }
|
126
|
+
end
|
127
|
+
message = op == :| ? :any? : :all?
|
128
|
+
result = requirements.send message do |req|
|
129
|
+
if Array === req
|
130
|
+
cmp, rv = *req
|
131
|
+
CMP_PROCS[cmp || '='].call(version, rv)
|
132
|
+
else
|
133
|
+
req.satisfied_by?(version)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
negative ? !result : result
|
137
|
+
end
|
138
|
+
|
139
|
+
# Either modify the current requirement (if it's already an or operation)
|
140
|
+
# or create a new requirement
|
141
|
+
def |(other)
|
142
|
+
operation(:|, other)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Either modify the current requirement (if it's already an and operation)
|
146
|
+
# or create a new requirement
|
147
|
+
def &(other)
|
148
|
+
operation(:&, other)
|
149
|
+
end
|
150
|
+
|
151
|
+
# return the parsed expression
|
152
|
+
def to_s
|
153
|
+
str = requirements.map(&:to_s).join(" " + @op.to_s + " ").to_s
|
154
|
+
str = "( " + str + " )" if negative || requirements.size > 1
|
155
|
+
str = "!" + str if negative
|
156
|
+
str
|
157
|
+
end
|
158
|
+
|
159
|
+
attr_accessor :negative
|
160
|
+
protected
|
161
|
+
attr_reader :requirements, :op
|
162
|
+
def operation(op, other)
|
163
|
+
@op ||= op
|
164
|
+
if negative == other.negative && @op == op && other.requirements.size == 1
|
165
|
+
@requirements << other.requirements.first
|
166
|
+
self
|
167
|
+
else
|
168
|
+
self.class.new(op, self, other)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end # VersionRequirement
|
172
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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
|
+
if RUBY_VERSION >= '1.9.0' # Required to properly load RubyZip under Ruby 1.9
|
18
|
+
$LOADED_FEATURES.unshift 'ftools'
|
19
|
+
require 'fileutils'
|
20
|
+
def File.move(source, dest)
|
21
|
+
FileUtils.move source, dest
|
22
|
+
end
|
23
|
+
def File.rm_rf(path)
|
24
|
+
FileUtils.rm_rf path
|
25
|
+
end
|
26
|
+
end
|
27
|
+
require 'zip/zip'
|
28
|
+
require 'zip/zipfilesystem'
|
29
|
+
|
30
|
+
|
31
|
+
module Zip #:nodoc:
|
32
|
+
|
33
|
+
class ZipCentralDirectory #:nodoc:
|
34
|
+
# Patch to add entries in alphabetical order.
|
35
|
+
def write_to_stream(io)
|
36
|
+
offset = io.tell
|
37
|
+
@entrySet.sort { |a,b| a.name <=> b.name }.each { |entry| entry.write_c_dir_entry(io) }
|
38
|
+
write_e_o_c_d(io, offset)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class ZipEntry
|
44
|
+
|
45
|
+
# :call-seq:
|
46
|
+
# exist() => boolean
|
47
|
+
#
|
48
|
+
# Returns true if this entry exists.
|
49
|
+
def exist?()
|
50
|
+
Zip::ZipFile.open(zipfile) { |zip| zip.file.exist?(@name) }
|
51
|
+
end
|
52
|
+
|
53
|
+
# :call-seq:
|
54
|
+
# empty?() => boolean
|
55
|
+
#
|
56
|
+
# Returns true if this entry is empty.
|
57
|
+
def empty?()
|
58
|
+
Zip::ZipFile.open(zipfile) { |zip| zip.file.read(@name) }.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
# :call-seq:
|
62
|
+
# contain(patterns*) => boolean
|
63
|
+
#
|
64
|
+
# Returns true if this ZIP file entry matches against all the arguments. An argument may be
|
65
|
+
# a string or regular expression.
|
66
|
+
def contain?(*patterns)
|
67
|
+
content = Zip::ZipFile.open(zipfile) { |zip| zip.file.read(@name) }
|
68
|
+
patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
|
69
|
+
all? { |pattern| content =~ pattern }
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,316 @@
|
|
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/packaging/archive'
|
18
|
+
|
19
|
+
|
20
|
+
module Buildr
|
21
|
+
|
22
|
+
# The ZipTask creates a new Zip file. You can include any number of files and and directories,
|
23
|
+
# use exclusion patterns, and include files into specific directories.
|
24
|
+
#
|
25
|
+
# For example:
|
26
|
+
# zip('test.zip').tap do |task|
|
27
|
+
# task.include 'srcs'
|
28
|
+
# task.include 'README', 'LICENSE'
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# See Buildr#zip and ArchiveTask.
|
32
|
+
class ZipTask < ArchiveTask
|
33
|
+
|
34
|
+
# Compression leve for this Zip.
|
35
|
+
attr_accessor :compression_level
|
36
|
+
|
37
|
+
def initialize(*args) #:nodoc:
|
38
|
+
self.compression_level = Zlib::DEFAULT_COMPRESSION
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
# :call-seq:
|
43
|
+
# entry(name) => Entry
|
44
|
+
#
|
45
|
+
# Returns a ZIP file entry. You can use this to check if the entry exists and its contents,
|
46
|
+
# for example:
|
47
|
+
# package(:jar).entry("META-INF/LICENSE").should contain(/Apache Software License/)
|
48
|
+
def entry(entry_name)
|
49
|
+
::Zip::ZipEntry.new(name, entry_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def entries #:nodoc:
|
53
|
+
@entries ||= Zip::ZipFile.open(name) { |zip| zip.entries }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def create_from(file_map)
|
59
|
+
Zip::ZipOutputStream.open name do |zip|
|
60
|
+
seen = {}
|
61
|
+
mkpath = lambda do |dir|
|
62
|
+
unless dir == '.' || seen[dir]
|
63
|
+
mkpath.call File.dirname(dir)
|
64
|
+
zip.put_next_entry(dir + '/', compression_level)
|
65
|
+
seen[dir] = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
file_map.each do |path, content|
|
70
|
+
mkpath.call File.dirname(path)
|
71
|
+
if content.respond_to?(:call)
|
72
|
+
zip.put_next_entry(path, compression_level)
|
73
|
+
content.call zip
|
74
|
+
elsif content.nil? || File.directory?(content.to_s)
|
75
|
+
mkpath.call path
|
76
|
+
else
|
77
|
+
entry = zip.put_next_entry(path, compression_level)
|
78
|
+
File.open content.to_s, 'rb' do |is|
|
79
|
+
entry.unix_perms = is.stat.mode & 07777
|
80
|
+
while data = is.read(4096)
|
81
|
+
zip << data
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
# :call-seq:
|
93
|
+
# zip(file) => ZipTask
|
94
|
+
#
|
95
|
+
# The ZipTask creates a new Zip file. You can include any number of files and
|
96
|
+
# and directories, use exclusion patterns, and include files into specific
|
97
|
+
# directories.
|
98
|
+
#
|
99
|
+
# For example:
|
100
|
+
# zip('test.zip').tap do |task|
|
101
|
+
# task.include 'srcs'
|
102
|
+
# task.include 'README', 'LICENSE'
|
103
|
+
# end
|
104
|
+
def zip(file)
|
105
|
+
ZipTask.define_task(file)
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# An object for unzipping a file into a target directory. You can tell it to include
|
110
|
+
# or exclude only specific files and directories, and also to map files from particular
|
111
|
+
# paths inside the zip file into the target directory. Once ready, call #extract.
|
112
|
+
#
|
113
|
+
# Usually it is more convenient to create a file task for extracting the zip file
|
114
|
+
# (see #unzip) and pass this object as a prerequisite to other tasks.
|
115
|
+
#
|
116
|
+
# See Buildr#unzip.
|
117
|
+
class Unzip
|
118
|
+
|
119
|
+
# The zip file to extract.
|
120
|
+
attr_accessor :zip_file
|
121
|
+
# The target directory to extract to.
|
122
|
+
attr_accessor :target
|
123
|
+
|
124
|
+
# Initialize with hash argument of the form target=>zip_file.
|
125
|
+
def initialize(args)
|
126
|
+
@target, arg_names, zip_file = Buildr.application.resolve_args([args])
|
127
|
+
@zip_file = zip_file.first
|
128
|
+
@paths = {}
|
129
|
+
end
|
130
|
+
|
131
|
+
# :call-seq:
|
132
|
+
# extract
|
133
|
+
#
|
134
|
+
# Extract the zip file into the target directory.
|
135
|
+
#
|
136
|
+
# You can call this method directly. However, if you are using the #unzip method,
|
137
|
+
# it creates a file task for the target directory: use that task instead as a
|
138
|
+
# prerequisite. For example:
|
139
|
+
# build unzip(dir=>zip_file)
|
140
|
+
# Or:
|
141
|
+
# unzip(dir=>zip_file).target.invoke
|
142
|
+
def extract
|
143
|
+
# If no paths specified, then no include/exclude patterns
|
144
|
+
# specified. Nothing will happen unless we include all files.
|
145
|
+
if @paths.empty?
|
146
|
+
@paths[nil] = FromPath.new(self, nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Otherwise, empty unzip creates target as a file when touching.
|
150
|
+
mkpath target.to_s
|
151
|
+
Zip::ZipFile.open(zip_file.to_s) do |zip|
|
152
|
+
entries = zip.collect
|
153
|
+
@paths.each do |path, patterns|
|
154
|
+
patterns.map(entries).each do |dest, entry|
|
155
|
+
next if entry.directory?
|
156
|
+
dest = File.expand_path(dest, target.to_s)
|
157
|
+
trace "Extracting #{dest}"
|
158
|
+
mkpath File.dirname(dest) rescue nil
|
159
|
+
entry.restore_permissions = true
|
160
|
+
entry.extract(dest) { true }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
# Let other tasks know we updated the target directory.
|
165
|
+
touch target.to_s
|
166
|
+
end
|
167
|
+
|
168
|
+
# :call-seq:
|
169
|
+
# include(*files) => self
|
170
|
+
# include(*files, :path=>name) => self
|
171
|
+
#
|
172
|
+
# Include all files that match the patterns and returns self.
|
173
|
+
#
|
174
|
+
# Use include if you only want to unzip some of the files, by specifying
|
175
|
+
# them instead of using exclusion. You can use #include in combination
|
176
|
+
# with #exclude.
|
177
|
+
def include(*files)
|
178
|
+
if Hash === files.last
|
179
|
+
from_path(files.pop[:path]).include *files
|
180
|
+
else
|
181
|
+
from_path(nil).include *files
|
182
|
+
end
|
183
|
+
self
|
184
|
+
end
|
185
|
+
alias :add :include
|
186
|
+
|
187
|
+
# :call-seq:
|
188
|
+
# exclude(*files) => self
|
189
|
+
#
|
190
|
+
# Exclude all files that match the patterns and return self.
|
191
|
+
#
|
192
|
+
# Use exclude to unzip all files except those that match the pattern.
|
193
|
+
# You can use #exclude in combination with #include.
|
194
|
+
def exclude(*files)
|
195
|
+
if Hash === files.last
|
196
|
+
from_path(files.pop[:path]).exclude *files
|
197
|
+
else
|
198
|
+
from_path(nil).exclude *files
|
199
|
+
end
|
200
|
+
self
|
201
|
+
end
|
202
|
+
|
203
|
+
# :call-seq:
|
204
|
+
# from_path(name) => Path
|
205
|
+
#
|
206
|
+
# Allows you to unzip from a path. Returns an object you can use to
|
207
|
+
# specify which files to include/exclude relative to that path.
|
208
|
+
# Expands the file relative to that path.
|
209
|
+
#
|
210
|
+
# For example:
|
211
|
+
# unzip(Dir.pwd=>'test.jar').from_path('etc').include('LICENSE')
|
212
|
+
# will unzip etc/LICENSE into ./LICENSE.
|
213
|
+
#
|
214
|
+
# This is different from:
|
215
|
+
# unzip(Dir.pwd=>'test.jar').include('etc/LICENSE')
|
216
|
+
# which unzips etc/LICENSE into ./etc/LICENSE.
|
217
|
+
def from_path(name)
|
218
|
+
@paths[name] ||= FromPath.new(self, name)
|
219
|
+
end
|
220
|
+
alias :path :from_path
|
221
|
+
|
222
|
+
# :call-seq:
|
223
|
+
# root => Unzip
|
224
|
+
#
|
225
|
+
# Returns the root path, essentially the Unzip object itself. In case you are wondering
|
226
|
+
# down paths and want to go back.
|
227
|
+
def root
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
# Returns the path to the target directory.
|
232
|
+
def to_s
|
233
|
+
target.to_s
|
234
|
+
end
|
235
|
+
|
236
|
+
class FromPath #:nodoc:
|
237
|
+
|
238
|
+
def initialize(unzip, path)
|
239
|
+
@unzip = unzip
|
240
|
+
if path
|
241
|
+
@path = path[-1] == ?/ ? path : path + '/'
|
242
|
+
else
|
243
|
+
@path = ''
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# See UnzipTask#include
|
248
|
+
def include(*files) #:doc:
|
249
|
+
@include ||= []
|
250
|
+
@include |= files
|
251
|
+
self
|
252
|
+
end
|
253
|
+
|
254
|
+
# See UnzipTask#exclude
|
255
|
+
def exclude(*files) #:doc:
|
256
|
+
@exclude ||= []
|
257
|
+
@exclude |= files
|
258
|
+
self
|
259
|
+
end
|
260
|
+
|
261
|
+
def map(entries)
|
262
|
+
includes = @include || ['*']
|
263
|
+
excludes = @exclude || []
|
264
|
+
entries.inject({}) do |map, entry|
|
265
|
+
if entry.name =~ /^#{@path}/
|
266
|
+
short = entry.name.sub(@path, '')
|
267
|
+
if includes.any? { |pat| File.fnmatch(pat, short) } &&
|
268
|
+
!excludes.any? { |pat| File.fnmatch(pat, short) }
|
269
|
+
map[short] = entry
|
270
|
+
end
|
271
|
+
end
|
272
|
+
map
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Documented in Unzip.
|
277
|
+
def root
|
278
|
+
@unzip
|
279
|
+
end
|
280
|
+
|
281
|
+
# The target directory to extract to.
|
282
|
+
def target
|
283
|
+
@unzip.target
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
# :call-seq:
|
291
|
+
# unzip(to_dir=>zip_file) => Zip
|
292
|
+
#
|
293
|
+
# Creates a task that will unzip a file into the target directory. The task name
|
294
|
+
# is the target directory, the prerequisite is the file to unzip.
|
295
|
+
#
|
296
|
+
# This method creates a file task to expand the zip file. It returns an Unzip object
|
297
|
+
# that specifies how the file will be extracted. You can include or exclude specific
|
298
|
+
# files from within the zip, and map to different paths.
|
299
|
+
#
|
300
|
+
# The Unzip object's to_s method return the path to the target directory, so you can
|
301
|
+
# use it as a prerequisite. By keeping the Unzip object separate from the file task,
|
302
|
+
# you overlay additional work on top of the file task.
|
303
|
+
#
|
304
|
+
# For example:
|
305
|
+
# unzip('all'=>'test.zip')
|
306
|
+
# unzip('src'=>'test.zip').include('README', 'LICENSE')
|
307
|
+
# unzip('libs'=>'test.zip').from_path('libs')
|
308
|
+
def unzip(args)
|
309
|
+
target, arg_names, zip_file = Buildr.application.resolve_args([args])
|
310
|
+
task = file(File.expand_path(target.to_s)=>zip_file)
|
311
|
+
Unzip.new(task=>zip_file).tap do |setup|
|
312
|
+
task.enhance { setup.extract }
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|