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.
Files changed (186) hide show
  1. data/CHANGELOG +998 -0
  2. data/LICENSE +176 -0
  3. data/NOTICE +26 -0
  4. data/README.rdoc +134 -0
  5. data/Rakefile +45 -0
  6. data/_buildr +29 -0
  7. data/_jbuildr +29 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +22 -0
  10. data/addon/buildr/drb.rb +281 -0
  11. data/addon/buildr/emma.rb +22 -0
  12. data/addon/buildr/hibernate.rb +142 -0
  13. data/addon/buildr/javacc.rb +85 -0
  14. data/addon/buildr/jdepend.rb +60 -0
  15. data/addon/buildr/jetty.rb +248 -0
  16. data/addon/buildr/jibx.rb +86 -0
  17. data/addon/buildr/nailgun.rb +221 -0
  18. data/addon/buildr/openjpa.rb +90 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  21. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  25. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  26. data/addon/buildr/xmlbeans.rb +93 -0
  27. data/bin/buildr +19 -0
  28. data/buildr.buildfile +58 -0
  29. data/buildr.gemspec +65 -0
  30. data/doc/_config.yml +1 -0
  31. data/doc/_layouts/default.html +88 -0
  32. data/doc/_layouts/preface.html +22 -0
  33. data/doc/artifacts.textile +211 -0
  34. data/doc/building.textile +244 -0
  35. data/doc/contributing.textile +252 -0
  36. data/doc/css/default.css +236 -0
  37. data/doc/css/print.css +101 -0
  38. data/doc/css/syntax.css +23 -0
  39. data/doc/download.textile +79 -0
  40. data/doc/extending.textile +186 -0
  41. data/doc/images/1442160941-frontcover.jpg +0 -0
  42. data/doc/images/asf-logo.gif +0 -0
  43. data/doc/images/asf-logo.png +0 -0
  44. data/doc/images/buildr-hires.png +0 -0
  45. data/doc/images/buildr.png +0 -0
  46. data/doc/images/favicon.png +0 -0
  47. data/doc/images/growl-icon.tiff +0 -0
  48. data/doc/images/note.png +0 -0
  49. data/doc/images/project-structure.png +0 -0
  50. data/doc/images/tip.png +0 -0
  51. data/doc/images/zbuildr.png +0 -0
  52. data/doc/images/zbuildr.tif +0 -0
  53. data/doc/index.textile +69 -0
  54. data/doc/installing.textile +266 -0
  55. data/doc/languages.textile +459 -0
  56. data/doc/mailing_lists.textile +25 -0
  57. data/doc/more_stuff.textile +457 -0
  58. data/doc/packaging.textile +430 -0
  59. data/doc/preface.textile +54 -0
  60. data/doc/projects.textile +271 -0
  61. data/doc/quick_start.textile +210 -0
  62. data/doc/scripts/buildr-git.rb +512 -0
  63. data/doc/scripts/gitflow.rb +296 -0
  64. data/doc/scripts/install-jruby.sh +44 -0
  65. data/doc/scripts/install-linux.sh +72 -0
  66. data/doc/scripts/install-osx.sh +52 -0
  67. data/doc/settings_profiles.textile +280 -0
  68. data/doc/testing.textile +222 -0
  69. data/etc/KEYS +151 -0
  70. data/lib/buildr.rb +36 -0
  71. data/lib/buildr/core.rb +35 -0
  72. data/lib/buildr/core/application.rb +656 -0
  73. data/lib/buildr/core/build.rb +452 -0
  74. data/lib/buildr/core/checks.rb +254 -0
  75. data/lib/buildr/core/common.rb +150 -0
  76. data/lib/buildr/core/compile.rb +608 -0
  77. data/lib/buildr/core/environment.rb +129 -0
  78. data/lib/buildr/core/filter.rb +362 -0
  79. data/lib/buildr/core/generate.rb +195 -0
  80. data/lib/buildr/core/help.rb +119 -0
  81. data/lib/buildr/core/osx.rb +46 -0
  82. data/lib/buildr/core/progressbar.rb +156 -0
  83. data/lib/buildr/core/project.rb +866 -0
  84. data/lib/buildr/core/shell.rb +198 -0
  85. data/lib/buildr/core/test.rb +723 -0
  86. data/lib/buildr/core/transports.rb +559 -0
  87. data/lib/buildr/core/util.rb +449 -0
  88. data/lib/buildr/groovy.rb +19 -0
  89. data/lib/buildr/groovy/bdd.rb +106 -0
  90. data/lib/buildr/groovy/compiler.rb +138 -0
  91. data/lib/buildr/groovy/shell.rb +48 -0
  92. data/lib/buildr/ide.rb +19 -0
  93. data/lib/buildr/ide/eclipse.rb +334 -0
  94. data/lib/buildr/ide/eclipse/java.rb +53 -0
  95. data/lib/buildr/ide/eclipse/plugin.rb +68 -0
  96. data/lib/buildr/ide/eclipse/scala.rb +66 -0
  97. data/lib/buildr/ide/idea.ipr.template +300 -0
  98. data/lib/buildr/ide/idea.rb +190 -0
  99. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  100. data/lib/buildr/ide/idea7x.rb +212 -0
  101. data/lib/buildr/java.rb +23 -0
  102. data/lib/buildr/java/ant.rb +94 -0
  103. data/lib/buildr/java/bdd.rb +459 -0
  104. data/lib/buildr/java/cobertura.rb +274 -0
  105. data/lib/buildr/java/commands.rb +213 -0
  106. data/lib/buildr/java/compiler.rb +349 -0
  107. data/lib/buildr/java/deprecated.rb +141 -0
  108. data/lib/buildr/java/emma.rb +244 -0
  109. data/lib/buildr/java/jruby.rb +117 -0
  110. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  111. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  112. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +137 -0
  113. data/lib/buildr/java/packaging.rb +716 -0
  114. data/lib/buildr/java/pom.rb +174 -0
  115. data/lib/buildr/java/rjb.rb +155 -0
  116. data/lib/buildr/java/test_result.rb +353 -0
  117. data/lib/buildr/java/tests.rb +333 -0
  118. data/lib/buildr/java/version_requirement.rb +172 -0
  119. data/lib/buildr/packaging.rb +24 -0
  120. data/lib/buildr/packaging/archive.rb +488 -0
  121. data/lib/buildr/packaging/artifact.rb +749 -0
  122. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  123. data/lib/buildr/packaging/artifact_search.rb +140 -0
  124. data/lib/buildr/packaging/gems.rb +102 -0
  125. data/lib/buildr/packaging/package.rb +238 -0
  126. data/lib/buildr/packaging/tar.rb +186 -0
  127. data/lib/buildr/packaging/version_requirement.rb +172 -0
  128. data/lib/buildr/packaging/zip.rb +73 -0
  129. data/lib/buildr/packaging/ziptask.rb +316 -0
  130. data/lib/buildr/resources/buildr.icns +0 -0
  131. data/lib/buildr/scala.rb +25 -0
  132. data/lib/buildr/scala/bdd.rb +109 -0
  133. data/lib/buildr/scala/compiler.rb +195 -0
  134. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner$.class +0 -0
  135. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
  136. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.scala +35 -0
  137. data/lib/buildr/scala/shell.rb +55 -0
  138. data/lib/buildr/scala/tests.rb +157 -0
  139. data/lib/buildr/shell.rb +180 -0
  140. data/rakelib/checks.rake +57 -0
  141. data/rakelib/doc.rake +92 -0
  142. data/rakelib/jekylltask.rb +120 -0
  143. data/rakelib/package.rake +73 -0
  144. data/rakelib/release.rake +149 -0
  145. data/rakelib/rspec.rake +73 -0
  146. data/rakelib/setup.rake +54 -0
  147. data/rakelib/stage.rake +213 -0
  148. data/rakelib/stage.rake~ +213 -0
  149. data/spec/addon/drb_spec.rb +328 -0
  150. data/spec/core/application_spec.rb +502 -0
  151. data/spec/core/build_spec.rb +677 -0
  152. data/spec/core/checks_spec.rb +519 -0
  153. data/spec/core/common_spec.rb +670 -0
  154. data/spec/core/compile_spec.rb +583 -0
  155. data/spec/core/extension_spec.rb +93 -0
  156. data/spec/core/generate_spec.rb +33 -0
  157. data/spec/core/project_spec.rb +762 -0
  158. data/spec/core/test_spec.rb +1098 -0
  159. data/spec/core/transport_spec.rb +537 -0
  160. data/spec/core/util_spec.rb +67 -0
  161. data/spec/groovy/bdd_spec.rb +80 -0
  162. data/spec/groovy/compiler_spec.rb +240 -0
  163. data/spec/ide/eclipse_spec.rb +501 -0
  164. data/spec/ide/idea7x_spec.rb +84 -0
  165. data/spec/java/ant_spec.rb +33 -0
  166. data/spec/java/bdd_spec.rb +382 -0
  167. data/spec/java/cobertura_spec.rb +85 -0
  168. data/spec/java/compiler_spec.rb +446 -0
  169. data/spec/java/emma_spec.rb +119 -0
  170. data/spec/java/java_spec.rb +124 -0
  171. data/spec/java/packaging_spec.rb +1134 -0
  172. data/spec/java/test_coverage_helper.rb +257 -0
  173. data/spec/java/tests_spec.rb +493 -0
  174. data/spec/packaging/archive_spec.rb +527 -0
  175. data/spec/packaging/artifact_namespace_spec.rb +654 -0
  176. data/spec/packaging/artifact_spec.rb +795 -0
  177. data/spec/packaging/packaging_helper.rb +63 -0
  178. data/spec/packaging/packaging_spec.rb +684 -0
  179. data/spec/sandbox.rb +142 -0
  180. data/spec/scala/bdd_spec.rb +119 -0
  181. data/spec/scala/compiler_spec.rb +284 -0
  182. data/spec/scala/scala.rb +38 -0
  183. data/spec/scala/tests_spec.rb +261 -0
  184. data/spec/spec_helpers.rb +340 -0
  185. data/spec/version_requirement_spec.rb +129 -0
  186. 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