zip-container 3.0.2 → 4.0.1
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.
- 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
|