zip-container 3.0.2 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -1
- data/Licence.rdoc +1 -1
- data/Rakefile +15 -12
- data/examples/create-zip-container +7 -8
- data/examples/zip-container-info +4 -4
- data/lib/zip-container/container.rb +5 -7
- data/lib/zip-container/dir.rb +8 -11
- data/lib/zip-container/entries/directory.rb +5 -5
- data/lib/zip-container/entries/entry.rb +19 -15
- data/lib/zip-container/entries/file.rb +10 -9
- data/lib/zip-container/entries/managed.rb +11 -11
- data/lib/zip-container/entries/reserved.rb +2 -2
- data/lib/zip-container/exceptions.rb +4 -2
- data/lib/zip-container/file.rb +16 -16
- data/lib/zip-container/util.rb +3 -3
- data/lib/zip-container/version.rb +4 -3
- data/version.yml +2 -2
- data/zip-container.gemspec +30 -27
- metadata +41 -83
- data/.gitignore +0 -9
- data/.ruby-env +0 -1
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -19
- data/test/data/compressed_mimetype.container +0 -0
- data/test/data/dirs/dir-mimetype/mimetype/.gitkeep +0 -1
- data/test/data/dirs/empty/mimetype +0 -1
- data/test/data/dirs/managed/dir/.gitkeep +0 -0
- data/test/data/dirs/managed/greeting.txt +0 -1
- data/test/data/dirs/managed/mimetype +0 -1
- data/test/data/dirs/null/.gitkeep +0 -1
- data/test/data/empty.container +0 -0
- data/test/data/empty.zip +0 -0
- data/test/data/example.container +0 -0
- data/test/data/null.file +0 -0
- data/test/data/subclassed.container +0 -0
- data/test/helpers/entry_lists.rb +0 -35
- data/test/tc_create_dir.rb +0 -56
- data/test/tc_create_file.rb +0 -140
- data/test/tc_exceptions.rb +0 -105
- data/test/tc_managed_entries.rb +0 -446
- data/test/tc_read_dir.rb +0 -90
- data/test/tc_read_file.rb +0 -118
- data/test/tc_reserved_names.rb +0 -334
- data/test/tc_util.rb +0 -67
- data/test/ts_container.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 40f261a3985bb13d5eef74340722d167ce5b2addcd0754756ddb00f120bf817e
|
4
|
+
data.tar.gz: 027d0a9ec9fe5372be16f3a4e1016625c5bb1e471d3951e7906707eba44c0cbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63b164f87290014a514377e2be895ef1c00e8154a668ec977b88a19b1d353046bb39cb6e7d34709107da8a3846e1caf92a787b2ebb8d15c454ddc152c0ad8924
|
7
|
+
data.tar.gz: 05450730a60b22f18759a457d942de14c8d8fd571b048e47843beb14a02e075c4db083bd779ee7e6cc4130069ef83f6a54c3ea3d6b09b2172df5f88150ffd2c7
|
data/Gemfile
CHANGED
data/Licence.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2013
|
1
|
+
# Copyright (c) 2013-2018 The University of Manchester, UK.
|
2
2
|
#
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
@@ -30,24 +30,27 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
33
|
+
require 'bundler/gem_tasks'
|
34
|
+
require 'rake/testtask'
|
35
|
+
require 'rdoc/task'
|
36
|
+
require 'rubocop/rake_task'
|
36
37
|
|
37
|
-
task :
|
38
|
+
task default: :test
|
38
39
|
|
39
40
|
Rake::TestTask.new do |t|
|
40
|
-
t.libs <<
|
41
|
+
t.libs << 'test'
|
41
42
|
t.test_files = FileList['test/ts_container.rb']
|
42
43
|
t.verbose = true
|
43
44
|
end
|
44
45
|
|
45
46
|
RDoc::Task.new do |r|
|
46
|
-
r.main =
|
47
|
-
lib = Dir.glob(
|
48
|
-
r.rdoc_files.include(
|
49
|
-
r.options <<
|
47
|
+
r.main = 'ReadMe.rdoc'
|
48
|
+
lib = Dir.glob('lib/**/*.rb')
|
49
|
+
r.rdoc_files.include('ReadMe.rdoc', 'Licence.rdoc', 'Changes.rdoc', lib)
|
50
|
+
r.options << '-t ZIP Container Format Ruby Library version ' \
|
50
51
|
"#{ZipContainer::Version::STRING}"
|
51
|
-
r.options <<
|
52
|
-
r.options <<
|
52
|
+
r.options << '-N'
|
53
|
+
r.options << '--tab-width=2'
|
53
54
|
end
|
55
|
+
|
56
|
+
RuboCop::RakeTask.new
|
@@ -43,27 +43,26 @@ usage unless ARGV.length == 1
|
|
43
43
|
|
44
44
|
container_file = ARGV[0]
|
45
45
|
|
46
|
-
if File.
|
46
|
+
if File.exist?(container_file)
|
47
47
|
puts "File '#{container_file}' already exists. Exiting."
|
48
48
|
exit 1
|
49
49
|
end
|
50
50
|
|
51
51
|
begin
|
52
|
-
ZipContainer::File.create(container_file,
|
53
|
-
|
52
|
+
ZipContainer::File.create(container_file, 'application/epub+zip') do |c|
|
54
53
|
# Add a cheery greeting file from a string.
|
55
|
-
c.file.open(
|
56
|
-
f.puts
|
54
|
+
c.file.open('greeting.txt', 'w') do |f|
|
55
|
+
f.puts 'Hello, World!'
|
57
56
|
end
|
58
57
|
|
59
58
|
# Create a subdirectory.
|
60
|
-
c.dir.mkdir(
|
59
|
+
c.dir.mkdir('dir')
|
61
60
|
|
62
61
|
# Copy this example code in straight from a file.
|
63
|
-
c.add(
|
62
|
+
c.add('dir/code.rb', __FILE__)
|
64
63
|
|
65
64
|
# Add a explanation of this file.
|
66
|
-
c.comment =
|
65
|
+
c.comment = 'This is an example Container file!'
|
67
66
|
end
|
68
67
|
rescue ZipContainer::MalformedContainerError, ZipContainer::ZipError => err
|
69
68
|
puts err.to_s
|
data/examples/zip-container-info
CHANGED
@@ -50,7 +50,7 @@ rescue ZipContainer::MalformedContainerError, ZipContainer::ZipError => err
|
|
50
50
|
exit 1
|
51
51
|
end
|
52
52
|
|
53
|
-
puts "Archive: #{container
|
53
|
+
puts "Archive: #{container}"
|
54
54
|
puts "Container file size: #{File.size(container_file)} bytes, "\
|
55
55
|
"number of entries: #{container.size}"
|
56
56
|
|
@@ -60,11 +60,11 @@ total_comp = 0
|
|
60
60
|
container.each do |entry|
|
61
61
|
total_size += entry.size
|
62
62
|
total_comp += entry.compressed_size
|
63
|
-
comp = entry.compression_method
|
63
|
+
comp = entry.compression_method.zero? ? 'stor' : 'defN'
|
64
64
|
size = entry.size.to_s.rjust(8)
|
65
65
|
puts "#{size} #{comp} #{entry.time} #{entry.name}"
|
66
66
|
end
|
67
67
|
|
68
68
|
ratio = ((total_size - total_comp) / total_size.to_f) * 100
|
69
|
-
puts "
|
70
|
-
|
69
|
+
puts "#{container.size} files, #{total_size} bytes uncompressed, "\
|
70
|
+
"#{total_comp} bytes compressed: #{ratio.round(1)}%"
|
@@ -30,13 +30,14 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
33
|
+
##
|
34
34
|
module ZipContainer
|
35
35
|
|
36
36
|
# The superclass of anything that represents a Zip Container. That
|
37
37
|
# representation could be as a Zip file (most commonly), as a directory or
|
38
38
|
# something else.
|
39
39
|
class Container
|
40
|
+
|
40
41
|
include ReservedNames
|
41
42
|
include ManagedEntries
|
42
43
|
|
@@ -47,7 +48,7 @@ module ZipContainer
|
|
47
48
|
|
48
49
|
# :stopdoc:
|
49
50
|
# The reserved mimetype file name for standard ZipContainers.
|
50
|
-
MIMETYPE_FILE =
|
51
|
+
MIMETYPE_FILE = 'mimetype'.freeze
|
51
52
|
|
52
53
|
def initialize(location)
|
53
54
|
@container = open_container(location)
|
@@ -69,7 +70,7 @@ module ZipContainer
|
|
69
70
|
#
|
70
71
|
# Open an existing ZipContainer. It will be checked for conformance upon
|
71
72
|
# first access.
|
72
|
-
def self.open(filename
|
73
|
+
def self.open(filename)
|
73
74
|
c = new(filename)
|
74
75
|
|
75
76
|
if block_given?
|
@@ -147,13 +148,10 @@ module ZipContainer
|
|
147
148
|
# This method raises a MalformedContainerError if there are any problems
|
148
149
|
# with the container.
|
149
150
|
def verify!
|
150
|
-
unless @mimetype_error.nil?
|
151
|
-
raise MalformedContainerError.new(@mimetype_error)
|
152
|
-
end
|
151
|
+
raise MalformedContainerError, @mimetype_error unless @mimetype_error.nil?
|
153
152
|
|
154
153
|
verify_managed_entries!
|
155
154
|
end
|
156
|
-
|
157
155
|
end
|
158
156
|
|
159
157
|
end
|
data/lib/zip-container/dir.rb
CHANGED
@@ -49,7 +49,7 @@ module ZipContainer
|
|
49
49
|
|
50
50
|
extend Forwardable
|
51
51
|
def_delegators :@container, :close, :each, :path, :pos, :pos=, :rewind,
|
52
|
-
|
52
|
+
:seek, :tell
|
53
53
|
|
54
54
|
private_class_method :new
|
55
55
|
|
@@ -65,7 +65,7 @@ module ZipContainer
|
|
65
65
|
#
|
66
66
|
# Create a new (or convert an existing) directory as a ZipContainer with
|
67
67
|
# the specified mimetype.
|
68
|
-
def self.create(pathname, mimetype
|
68
|
+
def self.create(pathname, mimetype)
|
69
69
|
::Dir.mkdir(pathname) unless ::File.directory?(pathname)
|
70
70
|
::File.write(::File.join(pathname, MIMETYPE_FILE), mimetype)
|
71
71
|
|
@@ -108,7 +108,8 @@ module ZipContainer
|
|
108
108
|
Entries.new(@container)
|
109
109
|
end
|
110
110
|
|
111
|
-
class Entries
|
111
|
+
class Entries # :nodoc:
|
112
|
+
|
112
113
|
include Enumerable
|
113
114
|
|
114
115
|
Entry = Struct.new(:name, :ftype)
|
@@ -122,7 +123,7 @@ module ZipContainer
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
125
|
-
def each
|
126
|
+
def each
|
126
127
|
@entries.each do |entry|
|
127
128
|
yield entry
|
128
129
|
end
|
@@ -145,12 +146,9 @@ module ZipContainer
|
|
145
146
|
|
146
147
|
def verify_mimetype
|
147
148
|
mime_path = full_path(MIMETYPE_FILE)
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
else
|
152
|
-
return "'mimetype' file is missing."
|
153
|
-
end
|
149
|
+
return "'mimetype' file is missing." unless ::File.exist?(mime_path)
|
150
|
+
return "'mimetype' is not a regular file" unless ::File.file?(mime_path)
|
151
|
+
return "'mimetype' is not readable." unless ::File.readable?(mime_path)
|
154
152
|
end
|
155
153
|
|
156
154
|
def read_mimetype
|
@@ -225,7 +223,6 @@ module ZipContainer
|
|
225
223
|
#
|
226
224
|
# Equal to
|
227
225
|
# {::Dir.tell}[http://ruby-doc.org/core-1.9.3/Dir.html#method-i-tell]
|
228
|
-
|
229
226
|
end
|
230
227
|
|
231
228
|
end
|
@@ -30,7 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
33
|
+
##
|
34
34
|
module ZipContainer
|
35
35
|
|
36
36
|
# A ManagedDirectory acts as the interface to a set of (possibly) managed
|
@@ -40,6 +40,7 @@ module ZipContainer
|
|
40
40
|
# Once a ManagedDirectory is registered in a Container then only it can be
|
41
41
|
# used to write to its contents.
|
42
42
|
class ManagedDirectory < ManagedEntry
|
43
|
+
|
43
44
|
include ReservedNames
|
44
45
|
include ManagedEntries
|
45
46
|
|
@@ -55,9 +56,9 @@ module ZipContainer
|
|
55
56
|
# that are within this directory (default []).
|
56
57
|
def initialize(name, options = {})
|
57
58
|
options = {
|
58
|
-
:
|
59
|
-
:
|
60
|
-
:
|
59
|
+
required: false,
|
60
|
+
hidden: false,
|
61
|
+
entries: []
|
61
62
|
}.merge(options)
|
62
63
|
|
63
64
|
super(name, options[:required], options[:hidden])
|
@@ -80,6 +81,5 @@ module ZipContainer
|
|
80
81
|
|
81
82
|
messages
|
82
83
|
end
|
83
|
-
|
84
84
|
end
|
85
85
|
end
|
@@ -30,18 +30,23 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
33
|
+
##
|
34
34
|
module ZipContainer
|
35
35
|
|
36
36
|
# ManagedEntry is the superclass of ManagedDirectory and ManagedFile. It
|
37
37
|
# should not be used directly but may be subclassed if necessary.
|
38
38
|
class ManagedEntry
|
39
|
+
|
39
40
|
include Util
|
40
41
|
|
41
42
|
# The name of the ManagedEntry. For the full path name of this entry use
|
42
43
|
# full_name.
|
43
44
|
attr_reader :name
|
44
45
|
|
46
|
+
# Allows the object in which this entry has been registered to tell it
|
47
|
+
# who it is.
|
48
|
+
attr_writer :parent # :nodoc:
|
49
|
+
|
45
50
|
# :call-seq:
|
46
51
|
# new(name, required) -> ManagedEntry
|
47
52
|
#
|
@@ -60,7 +65,11 @@ module ZipContainer
|
|
60
65
|
#
|
61
66
|
# The fully qualified name of this ManagedEntry.
|
62
67
|
def full_name
|
63
|
-
@parent.is_a?(ZipContainer::Container)
|
68
|
+
if @parent.is_a?(ZipContainer::Container)
|
69
|
+
@name
|
70
|
+
else
|
71
|
+
"#{@parent.full_name}/#{@name}"
|
72
|
+
end
|
64
73
|
end
|
65
74
|
|
66
75
|
# :call-seq:
|
@@ -78,7 +87,11 @@ module ZipContainer
|
|
78
87
|
# Is this ManagedEntry hidden for normal operations?
|
79
88
|
def hidden?
|
80
89
|
# An entry is hidden if its parent is hidden.
|
81
|
-
@parent.is_a?(ZipContainer::Container)
|
90
|
+
if @parent.is_a?(ZipContainer::Container)
|
91
|
+
@hidden
|
92
|
+
else
|
93
|
+
@hidden || @parent.hidden?
|
94
|
+
end
|
82
95
|
end
|
83
96
|
|
84
97
|
# :call-seq:
|
@@ -87,21 +100,13 @@ module ZipContainer
|
|
87
100
|
# Does this ManagedEntry exist in the Container?
|
88
101
|
def exists?
|
89
102
|
container.entries.each do |entry|
|
90
|
-
test =
|
103
|
+
test = entry.ftype == :directory ? "#{full_name}/" : full_name
|
91
104
|
return true if entry.name == test
|
92
105
|
end
|
93
106
|
|
94
107
|
false
|
95
108
|
end
|
96
109
|
|
97
|
-
# :stopdoc:
|
98
|
-
# Allows the object in which this entry has been registered in to tell it
|
99
|
-
# who it is.
|
100
|
-
def parent=(parent)
|
101
|
-
@parent = parent
|
102
|
-
end
|
103
|
-
# :startdoc:
|
104
|
-
|
105
110
|
# :call-seq:
|
106
111
|
# verify -> Array
|
107
112
|
#
|
@@ -111,7 +116,7 @@ module ZipContainer
|
|
111
116
|
# Subclasses should override this method if they require more complex
|
112
117
|
# verification to be done.
|
113
118
|
def verify
|
114
|
-
|
119
|
+
if @required && !exists?
|
115
120
|
["Entry '#{full_name}' is required but missing."]
|
116
121
|
else
|
117
122
|
[]
|
@@ -135,7 +140,7 @@ module ZipContainer
|
|
135
140
|
# fails.
|
136
141
|
def verify!
|
137
142
|
messages = verify
|
138
|
-
raise MalformedContainerError
|
143
|
+
raise MalformedContainerError, messages unless messages.empty?
|
139
144
|
end
|
140
145
|
|
141
146
|
protected
|
@@ -147,6 +152,5 @@ module ZipContainer
|
|
147
152
|
def container
|
148
153
|
@parent.is_a?(ZipContainer::Container) ? @parent : @parent.container
|
149
154
|
end
|
150
|
-
|
151
155
|
end
|
152
156
|
end
|
@@ -30,7 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
33
|
+
##
|
34
34
|
module ZipContainer
|
35
35
|
|
36
36
|
# A ManagedFile is used to reserve a filename in a Container namespace.
|
@@ -57,13 +57,13 @@ module ZipContainer
|
|
57
57
|
# word "Boo!".
|
58
58
|
#
|
59
59
|
# valid = Proc.new { |contents| contents == "Boo!" }
|
60
|
-
# ManagedFile.new("Surprize.txt", :
|
61
|
-
# :
|
60
|
+
# ManagedFile.new("Surprize.txt", required: false,
|
61
|
+
# validation_proc: valid)
|
62
62
|
def initialize(name, options = {})
|
63
63
|
options = {
|
64
|
-
:
|
65
|
-
:
|
66
|
-
:
|
64
|
+
required: false,
|
65
|
+
hidden: false,
|
66
|
+
validation_proc: nil
|
67
67
|
}.merge(options)
|
68
68
|
|
69
69
|
super(name, options[:required], options[:hidden])
|
@@ -83,8 +83,10 @@ module ZipContainer
|
|
83
83
|
def verify
|
84
84
|
messages = super
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
valid = exists? ? validate : true
|
87
|
+
unless valid
|
88
|
+
messages <<
|
89
|
+
"The contents of file '#{full_name}' do not pass validation."
|
88
90
|
end
|
89
91
|
|
90
92
|
messages
|
@@ -110,6 +112,5 @@ module ZipContainer
|
|
110
112
|
def contents
|
111
113
|
container.read(full_name)
|
112
114
|
end
|
113
|
-
|
114
115
|
end
|
115
116
|
end
|
@@ -30,7 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
33
|
+
##
|
34
34
|
module ZipContainer
|
35
35
|
|
36
36
|
# This module provides support for managed file and directory entries.
|
@@ -49,8 +49,7 @@ module ZipContainer
|
|
49
49
|
return @managed_directories if @managed_directories
|
50
50
|
|
51
51
|
dirs = @directories.values
|
52
|
-
@managed_directories = dirs +
|
53
|
-
dirs.map { |d| d.managed_directories }.flatten
|
52
|
+
@managed_directories = dirs + dirs.map(&:managed_directories).flatten
|
54
53
|
end
|
55
54
|
|
56
55
|
# :call-seq:
|
@@ -58,7 +57,7 @@ module ZipContainer
|
|
58
57
|
#
|
59
58
|
# Return the list of managed directory names.
|
60
59
|
def managed_directory_names
|
61
|
-
@managed_directory_names ||= managed_directories.map
|
60
|
+
@managed_directory_names ||= managed_directories.map(&:full_name)
|
62
61
|
end
|
63
62
|
|
64
63
|
# :call-seq:
|
@@ -91,7 +90,7 @@ module ZipContainer
|
|
91
90
|
# Is the supplied entry/name a managed entry?
|
92
91
|
def managed_entry?(entry, list = managed_entry_names)
|
93
92
|
name = entry_name(entry)
|
94
|
-
list.map
|
93
|
+
list.map(&:downcase).include? name.downcase
|
95
94
|
end
|
96
95
|
|
97
96
|
# :call-seq:
|
@@ -133,8 +132,9 @@ module ZipContainer
|
|
133
132
|
#
|
134
133
|
# Return the list of managed files.
|
135
134
|
def managed_files
|
136
|
-
@managed_files ||=
|
137
|
-
@
|
135
|
+
@managed_files ||=
|
136
|
+
@files.values +
|
137
|
+
@directories.values.map(&:managed_files).flatten
|
138
138
|
end
|
139
139
|
|
140
140
|
# :call-seq:
|
@@ -142,7 +142,7 @@ module ZipContainer
|
|
142
142
|
#
|
143
143
|
# Return the list of managed file names.
|
144
144
|
def managed_file_names
|
145
|
-
@managed_file_names ||= managed_files.map
|
145
|
+
@managed_file_names ||= managed_files.map(&:full_name)
|
146
146
|
end
|
147
147
|
|
148
148
|
# :call-seq:
|
@@ -171,7 +171,7 @@ module ZipContainer
|
|
171
171
|
# exist and validate, if required.
|
172
172
|
def verify_managed_entries!
|
173
173
|
messages = verify_managed_entries
|
174
|
-
raise MalformedContainerError
|
174
|
+
raise MalformedContainerError, messages unless messages.empty?
|
175
175
|
end
|
176
176
|
|
177
177
|
protected
|
@@ -205,8 +205,8 @@ module ZipContainer
|
|
205
205
|
# managed files within it.
|
206
206
|
def register_managed_entry(entry)
|
207
207
|
unless entry.is_a?(ManagedDirectory) || entry.is_a?(ManagedFile)
|
208
|
-
raise ArgumentError
|
209
|
-
|
208
|
+
raise ArgumentError, 'The supplied entry must be of type '\
|
209
|
+
'ManagedDirectory or ManagedFile or a subclass of either.'
|
210
210
|
end
|
211
211
|
|
212
212
|
entry.parent = self
|