rom-distillery 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c93dc6ca08201ccc0ba94c522c397149ee26b5ce2419755c5411d008d62df25c
4
+ data.tar.gz: 3bc0071cf61768f4bfe946f3cb53e07919a81b7f1c73fdd68e102bd62b4705bc
5
+ SHA512:
6
+ metadata.gz: 9ccca87474a1cdb94e11f12b1898aa624b7d289880ff11fc732f0ba8cde4324ea899012c96783f820a155139ed433b75388766b975e1ba234f0a9ea5b33eb00f
7
+ data.tar.gz: 508208b41b94c7e4c1aadb6a132bc43e4a54de063a7ea88e3fe5e39c6541af9479b03c78341bc0d0607739d8db9c99bd891a7523059829152b74ae9600276092
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # -*- ruby -*-
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
data/LICENSE ADDED
@@ -0,0 +1,287 @@
1
+ EUROPEAN UNION PUBLIC LICENCE v. 1.2
2
+ EUPL © the European Union 2007, 2016
3
+
4
+ This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
5
+ below) which is provided under the terms of this Licence. Any use of the Work,
6
+ other than as authorised under this Licence is prohibited (to the extent such
7
+ use is covered by a right of the copyright holder of the Work).
8
+
9
+ The Work is provided under the terms of this Licence when the Licensor (as
10
+ defined below) has placed the following notice immediately following the
11
+ copyright notice for the Work:
12
+
13
+ Licensed under the EUPL
14
+
15
+ or has expressed by any other means his willingness to license under the EUPL.
16
+
17
+ 1. Definitions
18
+
19
+ In this Licence, the following terms have the following meaning:
20
+
21
+ - ‘The Licence’: this Licence.
22
+
23
+ - ‘The Original Work’: the work or software distributed or communicated by the
24
+ Licensor under this Licence, available as Source Code and also as Executable
25
+ Code as the case may be.
26
+
27
+ - ‘Derivative Works’: the works or software that could be created by the
28
+ Licensee, based upon the Original Work or modifications thereof. This Licence
29
+ does not define the extent of modification or dependence on the Original Work
30
+ required in order to classify a work as a Derivative Work; this extent is
31
+ determined by copyright law applicable in the country mentioned in Article 15.
32
+
33
+ - ‘The Work’: the Original Work or its Derivative Works.
34
+
35
+ - ‘The Source Code’: the human-readable form of the Work which is the most
36
+ convenient for people to study and modify.
37
+
38
+ - ‘The Executable Code’: any code which has generally been compiled and which is
39
+ meant to be interpreted by a computer as a program.
40
+
41
+ - ‘The Licensor’: the natural or legal person that distributes or communicates
42
+ the Work under the Licence.
43
+
44
+ - ‘Contributor(s)’: any natural or legal person who modifies the Work under the
45
+ Licence, or otherwise contributes to the creation of a Derivative Work.
46
+
47
+ - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
48
+ the Work under the terms of the Licence.
49
+
50
+ - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
51
+ renting, distributing, communicating, transmitting, or otherwise making
52
+ available, online or offline, copies of the Work or providing access to its
53
+ essential functionalities at the disposal of any other natural or legal
54
+ person.
55
+
56
+ 2. Scope of the rights granted by the Licence
57
+
58
+ The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
59
+ sublicensable licence to do the following, for the duration of copyright vested
60
+ in the Original Work:
61
+
62
+ - use the Work in any circumstance and for all usage,
63
+ - reproduce the Work,
64
+ - modify the Work, and make Derivative Works based upon the Work,
65
+ - communicate to the public, including the right to make available or display
66
+ the Work or copies thereof to the public and perform publicly, as the case may
67
+ be, the Work,
68
+ - distribute the Work or copies thereof,
69
+ - lend and rent the Work or copies thereof,
70
+ - sublicense rights in the Work or copies thereof.
71
+
72
+ Those rights can be exercised on any media, supports and formats, whether now
73
+ known or later invented, as far as the applicable law permits so.
74
+
75
+ In the countries where moral rights apply, the Licensor waives his right to
76
+ exercise his moral right to the extent allowed by law in order to make effective
77
+ the licence of the economic rights here above listed.
78
+
79
+ The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
80
+ any patents held by the Licensor, to the extent necessary to make use of the
81
+ rights granted on the Work under this Licence.
82
+
83
+ 3. Communication of the Source Code
84
+
85
+ The Licensor may provide the Work either in its Source Code form, or as
86
+ Executable Code. If the Work is provided as Executable Code, the Licensor
87
+ provides in addition a machine-readable copy of the Source Code of the Work
88
+ along with each copy of the Work that the Licensor distributes or indicates, in
89
+ a notice following the copyright notice attached to the Work, a repository where
90
+ the Source Code is easily and freely accessible for as long as the Licensor
91
+ continues to distribute or communicate the Work.
92
+
93
+ 4. Limitations on copyright
94
+
95
+ Nothing in this Licence is intended to deprive the Licensee of the benefits from
96
+ any exception or limitation to the exclusive rights of the rights owners in the
97
+ Work, of the exhaustion of those rights or of other applicable limitations
98
+ thereto.
99
+
100
+ 5. Obligations of the Licensee
101
+
102
+ The grant of the rights mentioned above is subject to some restrictions and
103
+ obligations imposed on the Licensee. Those obligations are the following:
104
+
105
+ Attribution right: The Licensee shall keep intact all copyright, patent or
106
+ trademarks notices and all notices that refer to the Licence and to the
107
+ disclaimer of warranties. The Licensee must include a copy of such notices and a
108
+ copy of the Licence with every copy of the Work he/she distributes or
109
+ communicates. The Licensee must cause any Derivative Work to carry prominent
110
+ notices stating that the Work has been modified and the date of modification.
111
+
112
+ Copyleft clause: If the Licensee distributes or communicates copies of the
113
+ Original Works or Derivative Works, this Distribution or Communication will be
114
+ done under the terms of this Licence or of a later version of this Licence
115
+ unless the Original Work is expressly distributed only under this version of the
116
+ Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
117
+ (becoming Licensor) cannot offer or impose any additional terms or conditions on
118
+ the Work or Derivative Work that alter or restrict the terms of the Licence.
119
+
120
+ Compatibility clause: If the Licensee Distributes or Communicates Derivative
121
+ Works or copies thereof based upon both the Work and another work licensed under
122
+ a Compatible Licence, this Distribution or Communication can be done under the
123
+ terms of this Compatible Licence. For the sake of this clause, ‘Compatible
124
+ Licence’ refers to the licences listed in the appendix attached to this Licence.
125
+ Should the Licensee's obligations under the Compatible Licence conflict with
126
+ his/her obligations under this Licence, the obligations of the Compatible
127
+ Licence shall prevail.
128
+
129
+ Provision of Source Code: When distributing or communicating copies of the Work,
130
+ the Licensee will provide a machine-readable copy of the Source Code or indicate
131
+ a repository where this Source will be easily and freely available for as long
132
+ as the Licensee continues to distribute or communicate the Work.
133
+
134
+ Legal Protection: This Licence does not grant permission to use the trade names,
135
+ trademarks, service marks, or names of the Licensor, except as required for
136
+ reasonable and customary use in describing the origin of the Work and
137
+ reproducing the content of the copyright notice.
138
+
139
+ 6. Chain of Authorship
140
+
141
+ The original Licensor warrants that the copyright in the Original Work granted
142
+ hereunder is owned by him/her or licensed to him/her and that he/she has the
143
+ power and authority to grant the Licence.
144
+
145
+ Each Contributor warrants that the copyright in the modifications he/she brings
146
+ to the Work are owned by him/her or licensed to him/her and that he/she has the
147
+ power and authority to grant the Licence.
148
+
149
+ Each time You accept the Licence, the original Licensor and subsequent
150
+ Contributors grant You a licence to their contributions to the Work, under the
151
+ terms of this Licence.
152
+
153
+ 7. Disclaimer of Warranty
154
+
155
+ The Work is a work in progress, which is continuously improved by numerous
156
+ Contributors. It is not a finished work and may therefore contain defects or
157
+ ‘bugs’ inherent to this type of development.
158
+
159
+ For the above reason, the Work is provided under the Licence on an ‘as is’ basis
160
+ and without warranties of any kind concerning the Work, including without
161
+ limitation merchantability, fitness for a particular purpose, absence of defects
162
+ or errors, accuracy, non-infringement of intellectual property rights other than
163
+ copyright as stated in Article 6 of this Licence.
164
+
165
+ This disclaimer of warranty is an essential part of the Licence and a condition
166
+ for the grant of any rights to the Work.
167
+
168
+ 8. Disclaimer of Liability
169
+
170
+ Except in the cases of wilful misconduct or damages directly caused to natural
171
+ persons, the Licensor will in no event be liable for any direct or indirect,
172
+ material or moral, damages of any kind, arising out of the Licence or of the use
173
+ of the Work, including without limitation, damages for loss of goodwill, work
174
+ stoppage, computer failure or malfunction, loss of data or any commercial
175
+ damage, even if the Licensor has been advised of the possibility of such damage.
176
+ However, the Licensor will be liable under statutory product liability laws as
177
+ far such laws apply to the Work.
178
+
179
+ 9. Additional agreements
180
+
181
+ While distributing the Work, You may choose to conclude an additional agreement,
182
+ defining obligations or services consistent with this Licence. However, if
183
+ accepting obligations, You may act only on your own behalf and on your sole
184
+ responsibility, not on behalf of the original Licensor or any other Contributor,
185
+ and only if You agree to indemnify, defend, and hold each Contributor harmless
186
+ for any liability incurred by, or claims asserted against such Contributor by
187
+ the fact You have accepted any warranty or additional liability.
188
+
189
+ 10. Acceptance of the Licence
190
+
191
+ The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
192
+ placed under the bottom of a window displaying the text of this Licence or by
193
+ affirming consent in any other similar way, in accordance with the rules of
194
+ applicable law. Clicking on that icon indicates your clear and irrevocable
195
+ acceptance of this Licence and all of its terms and conditions.
196
+
197
+ Similarly, you irrevocably accept this Licence and all of its terms and
198
+ conditions by exercising any rights granted to You by Article 2 of this Licence,
199
+ such as the use of the Work, the creation by You of a Derivative Work or the
200
+ Distribution or Communication by You of the Work or copies thereof.
201
+
202
+ 11. Information to the public
203
+
204
+ In case of any Distribution or Communication of the Work by means of electronic
205
+ communication by You (for example, by offering to download the Work from a
206
+ remote location) the distribution channel or media (for example, a website) must
207
+ at least provide to the public the information requested by the applicable law
208
+ regarding the Licensor, the Licence and the way it may be accessible, concluded,
209
+ stored and reproduced by the Licensee.
210
+
211
+ 12. Termination of the Licence
212
+
213
+ The Licence and the rights granted hereunder will terminate automatically upon
214
+ any breach by the Licensee of the terms of the Licence.
215
+
216
+ Such a termination will not terminate the licences of any person who has
217
+ received the Work from the Licensee under the Licence, provided such persons
218
+ remain in full compliance with the Licence.
219
+
220
+ 13. Miscellaneous
221
+
222
+ Without prejudice of Article 9 above, the Licence represents the complete
223
+ agreement between the Parties as to the Work.
224
+
225
+ If any provision of the Licence is invalid or unenforceable under applicable
226
+ law, this will not affect the validity or enforceability of the Licence as a
227
+ whole. Such provision will be construed or reformed so as necessary to make it
228
+ valid and enforceable.
229
+
230
+ The European Commission may publish other linguistic versions or new versions of
231
+ this Licence or updated versions of the Appendix, so far this is required and
232
+ reasonable, without reducing the scope of the rights granted by the Licence. New
233
+ versions of the Licence will be published with a unique version number.
234
+
235
+ All linguistic versions of this Licence, approved by the European Commission,
236
+ have identical value. Parties can take advantage of the linguistic version of
237
+ their choice.
238
+
239
+ 14. Jurisdiction
240
+
241
+ Without prejudice to specific agreement between parties,
242
+
243
+ - any litigation resulting from the interpretation of this License, arising
244
+ between the European Union institutions, bodies, offices or agencies, as a
245
+ Licensor, and any Licensee, will be subject to the jurisdiction of the Court
246
+ of Justice of the European Union, as laid down in article 272 of the Treaty on
247
+ the Functioning of the European Union,
248
+
249
+ - any litigation arising between other parties and resulting from the
250
+ interpretation of this License, will be subject to the exclusive jurisdiction
251
+ of the competent court where the Licensor resides or conducts its primary
252
+ business.
253
+
254
+ 15. Applicable Law
255
+
256
+ Without prejudice to specific agreement between parties,
257
+
258
+ - this Licence shall be governed by the law of the European Union Member State
259
+ where the Licensor has his seat, resides or has his registered office,
260
+
261
+ - this licence shall be governed by Belgian law if the Licensor has no seat,
262
+ residence or registered office inside a European Union Member State.
263
+
264
+ Appendix
265
+
266
+ ‘Compatible Licences’ according to Article 5 EUPL are:
267
+
268
+ - GNU General Public License (GPL) v. 2, v. 3
269
+ - GNU Affero General Public License (AGPL) v. 3
270
+ - Open Software License (OSL) v. 2.1, v. 3.0
271
+ - Eclipse Public License (EPL) v. 1.0
272
+ - CeCILL v. 2.0, v. 2.1
273
+ - Mozilla Public Licence (MPL) v. 2
274
+ - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
275
+ - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
276
+ works other than software
277
+ - European Union Public Licence (EUPL) v. 1.1, v. 1.2
278
+ - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
279
+ Reciprocity (LiLiQ-R+).
280
+
281
+ The European Commission may update this Appendix to later versions of the above
282
+ licences without producing a new version of the EUPL, as long as they provide
283
+ the rights granted in Article 2 of this Licence and protect the covered Source
284
+ Code from exclusive appropriation.
285
+
286
+ All other changes or additions to this Appendix require the production of a new
287
+ EUPL version.
@@ -0,0 +1,24 @@
1
+ Requirements
2
+ ============
3
+ * The 7z, zip, unzip programs
4
+
5
+
6
+ Usage
7
+ =====
8
+
9
+ ~~~sh
10
+ # Get help
11
+ rhum --help
12
+
13
+ # Validat ROMs against DAT file
14
+ rhum -D ${datfile} validate ${rom_directory}
15
+
16
+ # Repack archive using 7z format
17
+ rhum repack -F 7z ${rom_directory}
18
+
19
+ # Generate checksum index
20
+ rhum index ${rom_directory}
21
+
22
+ # Save ROM header to the specified directory
23
+ rhum -D ${header_dir} header ${rom_directory}
24
+ ~~~
@@ -0,0 +1,6 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'distillery'
4
+ require 'distillery/cli'
5
+
6
+ Distillery::CLI.run
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+ require "distillery/version"
4
+
5
+ # NOTE: 'distillery' name is taken but not used since 2012
6
+ # https://rubygems.org/gems/distillery
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = "rom-distillery"
10
+ s.version = Distillery::VERSION
11
+ s.platform = Gem::Platform::RUBY
12
+ s.licenses = [ 'EUPL-1.2' ]
13
+ s.summary = "ROM manager"
14
+ s.description = "Help organise emulation ROM using DAT file"
15
+
16
+ s.required_ruby_version = '>= 2.5'
17
+
18
+ s.authors = ["Stephane D'Alu"]
19
+ s.email = ["sdalu@sdalu.com"]
20
+ s.homepage = "http://github.com/sdalu/distillery"
21
+
22
+ s.add_dependency 'nokogiri'
23
+ s.add_dependency 'rubyzip'
24
+ s.add_dependency 'tty-screen'
25
+ s.add_dependency 'tty-logger'
26
+ s.add_dependency 'tty-spinner'
27
+ s.add_dependency 'tty-progressbar'
28
+
29
+ s.add_development_dependency "yard"
30
+ s.add_development_dependency "rake"
31
+
32
+ s.executables = [ 'rhum' ]
33
+ s.files = %w[ LICENSE README.md Gemfile distillery.gemspec ] +
34
+ Dir['lib/**/*.rb' ] +
35
+ Dir['lib/**/*.yaml']
36
+
37
+ end
38
+
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: EUPL-1.2
2
+
3
+ # ROM Manager
4
+ #
5
+ module Distillery
6
+ end
7
+
8
+ require_relative 'distillery/version'
9
+ require_relative 'distillery/datfile'
10
+ require_relative 'distillery/storage'
@@ -0,0 +1,372 @@
1
+ # coding: utf-8
2
+ # SPDX-License-Identifier: EUPL-1.2
3
+
4
+ require 'set'
5
+
6
+ require_relative 'archiver/archive'
7
+
8
+ module Distillery
9
+
10
+
11
+ # @abstract
12
+ # Allow processing of archives
13
+ #
14
+ class Archiver
15
+ include Enumerable
16
+
17
+ # Standard error for Archiver class and subclasses
18
+ class Error < StandardError
19
+ end
20
+
21
+ # Notification of not archiver found
22
+ class ArchiverNotFound < Error
23
+ end
24
+
25
+ # Excution error for external process
26
+ class ExecError < Error
27
+ end
28
+
29
+ # Processing error when dealing with archive
30
+ class ProcessingError < Error
31
+ end
32
+
33
+ # InputStream used by Archiver#reader
34
+ class InputStream
35
+ def initialize(io)
36
+ @io = io
37
+ end
38
+
39
+ # Read data
40
+ #
41
+ # @param length [Integer, nil] number of bytes to read,
42
+ # whole data if nil
43
+ #
44
+ # @return [String, nil] data or nil if end of stream
45
+ #
46
+ def read(length=nil)
47
+ @io.read(length)
48
+ end
49
+ end
50
+
51
+ # OutputStream used by Archiver#writer
52
+ class OutputStream
53
+ def initialize(io)
54
+ @io = io
55
+ end
56
+
57
+ # Write data
58
+ #
59
+ # @param data [String] date to write
60
+ #
61
+ # @return [Integer] number of bytes written
62
+ #
63
+ def write(data)
64
+ @io.write(data)
65
+ end
66
+ end
67
+
68
+
69
+ # @!visibility private
70
+ @@logger = nil
71
+
72
+ # @!visibility private
73
+ @@providers = []
74
+
75
+ # @!visibility private
76
+ @@archivers = Set.new
77
+
78
+ # @!visibility private
79
+ @@mimetypes = {}
80
+
81
+ # @!visibility private
82
+ @@extensions = {}
83
+
84
+
85
+
86
+ # Register a logger
87
+ #
88
+ # @param logger [Logger,nil] logger
89
+ #
90
+ # @return logger
91
+ #
92
+ def self.logger=(logger)
93
+ @@logger = logger
94
+ end
95
+
96
+
97
+ # Get the regisered logger
98
+ #
99
+ # @return [Logger,nil]
100
+ #
101
+ def self.logger
102
+ @@logger
103
+ end
104
+
105
+
106
+ # Add an archiver provider class
107
+ #
108
+ # @param provider [Class] archiver provider
109
+ #
110
+ # @return [self]
111
+ #
112
+ def self.add(provider)
113
+ @@providers << provider
114
+ self
115
+ end
116
+
117
+
118
+ # List of archivers' providers in loading order.
119
+ #
120
+ # @return [Array<Class>] Archiver class
121
+ #
122
+ def self.providers
123
+ # Could be done by looking at constants
124
+ # constants.lazy.map {|c| const_get(c) }.select {|k| k < self }.to_a
125
+ # But we want to keep loading order
126
+ @@providers
127
+ end
128
+
129
+
130
+ # Perform automatic registration of all the archive providers
131
+ #
132
+ # @return [self]
133
+ #
134
+ def self.registering
135
+ self.providers.each do |p|
136
+ p.registering
137
+ end
138
+ self
139
+ end
140
+
141
+
142
+
143
+ # Register an archiver.
144
+ #
145
+ # @param [Archiver] archiver Archiver to register
146
+ # @param [Boolean] warnings Emit warning when overriding
147
+ #
148
+ def self.register(archiver, warnings: true)
149
+ # Notifier
150
+ notify = if warnings
151
+ ->(type, key, old, new) {
152
+ oname = old.class.name.split('::').last
153
+ nname = new.class.name.split('::').last
154
+ Archiver.logger&.warn {
155
+ "#{self} overriding #{type} for #{key}" \
156
+ " [#{oname} -> #{nname}]"
157
+ }
158
+ }
159
+ end
160
+
161
+ # Add archiver
162
+ @@archivers.add(archiver)
163
+
164
+ # Register mimetypes
165
+ Array(archiver.mimetypes).each {|mt|
166
+ @@mimetypes.merge!(mt => archiver) {|key, old, new|
167
+ notify&.call("mimetype", key, old, new)
168
+ new
169
+ }
170
+ }
171
+ # Register extensions
172
+ Array(archiver.extensions).each {|ext|
173
+ @@extensions.merge!(ext.downcase => archiver) {|key, old, new|
174
+ notify&.call("extension", key, old, new)
175
+ new
176
+ }
177
+ }
178
+ # Return archiver
179
+ archiver
180
+ end
181
+
182
+
183
+ # List of registered archivers
184
+ #
185
+ # @return [Array<Archiver>]
186
+ #
187
+ def self.archivers
188
+ @@archivers.to_a
189
+ end
190
+
191
+
192
+ # Archiver able to process the selected mimetype
193
+ #
194
+ def self.for_mimetype(mimetype)
195
+ @@mimetypes[mimetype]
196
+ end
197
+
198
+
199
+ # Archiver able to process the selected extension
200
+ #
201
+ def self.for_extension(extension)
202
+ extension = extension[1..-1] if extension[0] == '.'
203
+ @@extensions[extension.downcase]
204
+ end
205
+
206
+
207
+ # Archiver able to process the selected file.
208
+ #
209
+ # @param [String] file archive file tpo consider
210
+ #
211
+ # @return [Archiver] archiver to use for processing file
212
+ # @return [nil] no matching archiver found
213
+ #
214
+ def self.for_file(file)
215
+ # Find by extension
216
+ parts = File.basename(file).split('.')
217
+ extlist = 1.upto(parts.size-1).map {|i| parts[i..-1].join('.') }
218
+ archiver = extlist.lazy.map {|ext| self.for_extension(ext) }
219
+ .find {|arc| ! arc.nil? }
220
+
221
+ # Find by mimetype if previously failed
222
+ archiver ||= if defined?(MimeMagic)
223
+ begin
224
+ File.open(file) {|io|
225
+ self.for_mimetype(MimeMagic.by_magic(io))
226
+ }
227
+ rescue Errno::ENOENT
228
+ end
229
+ end
230
+
231
+ # Return found archiver (or nil)
232
+ archiver
233
+ end
234
+
235
+
236
+ # Return an archive instance of the specified file, or invokes the block
237
+ # with the archive instance passed as parameter.
238
+ #
239
+ # @overload for(file)
240
+ # @param file [String] archive file
241
+ #
242
+ # @raise [ArchiverNotFound] an archiver able to process this file
243
+ # has not been found
244
+ #
245
+ # @return [Archive] archive instance
246
+ #
247
+ # @overload for(file)
248
+ # @param file [String] archive file
249
+ #
250
+ # @yieldparam archive [Archive] archive instance
251
+ #
252
+ # @raise [ArchiverNotFound] an archiver able to process this file
253
+ # has not been found
254
+ #
255
+ # @return [self]
256
+ #
257
+ def self.for(file)
258
+ archive = Archive.new(file)
259
+ if block_given?
260
+ yield(archive)
261
+ self
262
+ else
263
+ archive
264
+ end
265
+ end
266
+
267
+
268
+
269
+
270
+
271
+ def initialize
272
+ raise "abstract class"
273
+ end
274
+
275
+
276
+ # List of supported extensions
277
+ #
278
+ # @return [Array<String>]
279
+ #
280
+ def extensions
281
+ [ 'zip' ]
282
+ end
283
+
284
+
285
+ # List of supported mimetypes
286
+ #
287
+ # @return [Array<String>]
288
+ #
289
+ def mimetypes
290
+ [ 'application/zip' ]
291
+ end
292
+
293
+
294
+ # Iterate over each archive entry
295
+ #
296
+ # @param file [String] archive file
297
+ #
298
+ # @yieldparam entry [String]
299
+ # @yieldparam io [InputStream]
300
+ #
301
+ # @return [self,Enumerator]
302
+ #
303
+ def each(file, &block)
304
+ raise "abstract method"
305
+ end
306
+
307
+
308
+ # Check if the archive contains no entry
309
+ #
310
+ # @param file [String] archive file
311
+ #
312
+ # @return [Boolean]
313
+ #
314
+ def empty?(file)
315
+ ! each(file).any?
316
+ end
317
+
318
+
319
+ # List archive entries
320
+ #
321
+ # @param file [String] archive file
322
+ #
323
+ # @return [Array<String>]
324
+ #
325
+ def entries(file)
326
+ each(file).map {|a_entry, _| a_entry }
327
+ end
328
+
329
+
330
+ # Allow to perform read operation on an archive entry
331
+ #
332
+ # @param file [String] archive file
333
+ # @param entry [String] entry name
334
+ #
335
+ # @yieldparam io [InputStream] input stream for reading
336
+ #
337
+ # @return block value
338
+ #
339
+ def reader(file, entry, &block)
340
+ each(file) {|a_entry, a_io|
341
+ next unless a_entry == entry
342
+ return block.call(a_io)
343
+ }
344
+ end
345
+
346
+
347
+ # Allow to perform write operation on an archive entry
348
+ #
349
+ # @param file [String] archive file
350
+ # @param entry [String] entry name
351
+ #
352
+ # @yieldparam io [OutputStream] output stream for writing
353
+ #
354
+ # @return block value
355
+ #
356
+ def writer(file, entry, &block)
357
+ nil
358
+ end
359
+
360
+
361
+ # Delete the entry from the archive
362
+ #
363
+ # @param file [String] archive file
364
+ # @param entry [String] entry name
365
+ #
366
+ # @return [Boolean] operation status
367
+ #
368
+ def delete!(file, entry)
369
+ false
370
+ end
371
+ end
372
+ end