zip-container 2.2.0 → 4.0.2

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 (49) hide show
  1. checksums.yaml +5 -13
  2. data/Changes.rdoc +22 -0
  3. data/Gemfile +1 -1
  4. data/Licence.rdoc +1 -1
  5. data/Rakefile +15 -12
  6. data/ReadMe.rdoc +20 -8
  7. data/examples/create-zip-container +7 -8
  8. data/examples/zip-container-info +4 -4
  9. data/lib/zip-container/container.rb +49 -23
  10. data/lib/zip-container/dir.rb +8 -11
  11. data/lib/zip-container/entries/directory.rb +15 -11
  12. data/lib/zip-container/entries/entry.rb +38 -29
  13. data/lib/zip-container/entries/file.rb +19 -15
  14. data/lib/zip-container/entries/managed.rb +28 -16
  15. data/lib/zip-container/entries/reserved.rb +2 -2
  16. data/lib/zip-container/exceptions.rb +20 -13
  17. data/lib/zip-container/file.rb +16 -16
  18. data/lib/zip-container/util.rb +3 -3
  19. data/lib/zip-container/version.rb +4 -3
  20. data/version.yml +3 -3
  21. data/zip-container.gemspec +31 -28
  22. metadata +54 -95
  23. data/.gitignore +0 -9
  24. data/.ruby-env +0 -1
  25. data/.ruby-gemset +0 -2
  26. data/.ruby-version +0 -2
  27. data/.travis.yml +0 -17
  28. data/test/data/compressed_mimetype.container +0 -0
  29. data/test/data/dirs/dir-mimetype/mimetype/.gitkeep +0 -1
  30. data/test/data/dirs/empty/mimetype +0 -1
  31. data/test/data/dirs/managed/dir/.gitkeep +0 -0
  32. data/test/data/dirs/managed/greeting.txt +0 -1
  33. data/test/data/dirs/managed/mimetype +0 -1
  34. data/test/data/dirs/null/.gitkeep +0 -1
  35. data/test/data/empty.container +0 -0
  36. data/test/data/empty.zip +0 -0
  37. data/test/data/example.container +0 -0
  38. data/test/data/null.file +0 -0
  39. data/test/data/subclassed.container +0 -0
  40. data/test/helpers/entry_lists.rb +0 -35
  41. data/test/tc_create_dir.rb +0 -56
  42. data/test/tc_create_file.rb +0 -140
  43. data/test/tc_exceptions.rb +0 -56
  44. data/test/tc_managed_entries.rb +0 -399
  45. data/test/tc_read_dir.rb +0 -86
  46. data/test/tc_read_file.rb +0 -109
  47. data/test/tc_reserved_names.rb +0 -334
  48. data/test/tc_util.rb +0 -67
  49. data/test/ts_container.rb +0 -59
@@ -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) ? @name : "#{@parent.full_name}/#{@name}"
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) ? @hidden : @hidden || @parent.hidden?
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,54 +100,51 @@ module ZipContainer
87
100
  # Does this ManagedEntry exist in the Container?
88
101
  def exists?
89
102
  container.entries.each do |entry|
90
- test = (entry.ftype == :directory) ? "#{full_name}/" : full_name
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
110
+ # :call-seq:
111
+ # verify -> Array
112
+ #
113
+ # Verify this ManagedEntry returning a list of reasons why it fails if it
114
+ # does so. The empty list is returned if verification passes.
115
+ #
116
+ # Subclasses should override this method if they require more complex
117
+ # verification to be done.
118
+ def verify
119
+ if @required && !exists?
120
+ ["Entry '#{full_name}' is required but missing."]
121
+ else
122
+ []
123
+ end
102
124
  end
103
- # :startdoc:
104
125
 
105
126
  # :call-seq:
106
- # verify -> true or false
127
+ # verify? -> true or false
107
128
  #
108
129
  # Verify this ManagedEntry by checking that it exists if it is required
109
130
  # according to its Container specification and validating its contents if
110
131
  # necessary.
111
- def verify
112
- begin
113
- verify!
114
- rescue
115
- return false
116
- end
117
-
118
- true
132
+ def verify?
133
+ verify.empty?
119
134
  end
120
135
 
121
- protected
122
-
123
136
  # :call-seq:
124
137
  # verify!
125
138
  #
126
139
  # Verify this ManagedEntry raising a MalformedContainerError if it
127
140
  # fails.
128
- #
129
- # Subclasses should override this method if they require more complex
130
- # verification to be done.
131
141
  def verify!
132
- unless !@required || exists?
133
- raise MalformedContainerError.new("Entry '#{full_name}' is required "\
134
- "but missing.")
135
- end
142
+ messages = verify
143
+ raise MalformedContainerError, messages unless messages.empty?
136
144
  end
137
145
 
146
+ protected
147
+
138
148
  # :call-seq:
139
149
  # container -> Container
140
150
  #
@@ -142,6 +152,5 @@ module ZipContainer
142
152
  def container
143
153
  @parent.is_a?(ZipContainer::Container) ? @parent : @parent.container
144
154
  end
145
-
146
155
  end
147
156
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2013 The University of Manchester, UK.
1
+ # Copyright (c) 2013-2015 The University of Manchester, UK.
2
2
  #
3
3
  # All rights reserved.
4
4
  #
@@ -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", :required => false,
61
- # :validation_proc => valid)
60
+ # ManagedFile.new("Surprize.txt", required: false,
61
+ # validation_proc: valid)
62
62
  def initialize(name, options = {})
63
63
  options = {
64
- :required => false,
65
- :hidden => false,
66
- :validation_proc => nil
64
+ required: false,
65
+ hidden: false,
66
+ validation_proc: nil
67
67
  }.merge(options)
68
68
 
69
69
  super(name, options[:required], options[:hidden])
@@ -73,18 +73,23 @@ module ZipContainer
73
73
  end
74
74
 
75
75
  # :call-seq:
76
- # verify!
76
+ # verify -> Array
77
77
  #
78
78
  # Verify this ManagedFile for correctness. The contents are validated if
79
79
  # required.
80
80
  #
81
- # A MalformedContainerError is raised if it does not pass verification.
82
- def verify!
83
- super
84
- unless (exists? ? validate : true)
85
- raise MalformedContainerError.new("The contents of file "\
86
- "'#{full_name}' do not pass validation.")
81
+ # If it does not pass verification a list of reasons why it fails is
82
+ # returned. The empty list is returned if verification passes.
83
+ def verify
84
+ messages = super
85
+
86
+ valid = exists? ? validate : true
87
+ unless valid
88
+ messages <<
89
+ "The contents of file '#{full_name}' do not pass validation."
87
90
  end
91
+
92
+ messages
88
93
  end
89
94
 
90
95
  protected
@@ -107,6 +112,5 @@ module ZipContainer
107
112
  def contents
108
113
  container.read(full_name)
109
114
  end
110
-
111
115
  end
112
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 { |d| d.full_name }
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 { |n| n.downcase }.include? name.downcase
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 ||= @files.values +
137
- @directories.values.map { |d| d.managed_files }.flatten
135
+ @managed_files ||=
136
+ @files.values +
137
+ @directories.values.map(&:managed_files).flatten
138
138
  end
139
139
 
140
140
  # :call-seq:
@@ -142,24 +142,36 @@ 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 { |f| f.full_name }
145
+ @managed_file_names ||= managed_files.map(&:full_name)
146
146
  end
147
147
 
148
148
  # :call-seq:
149
- # verify_managed_entries!
149
+ # verify_managed_entries -> Array
150
150
  #
151
151
  # All managed files and directories are checked to make sure that they
152
- # exist, if required.
153
- def verify_managed_entries!
152
+ # exist and validate, if required.
153
+ def verify_managed_entries
154
+ messages = []
155
+
154
156
  @directories.each_value do |dir|
155
- dir.verify!
157
+ messages += dir.verify
156
158
  end
157
159
 
158
160
  @files.each_value do |file|
159
- file.verify!
161
+ messages += file.verify
160
162
  end
161
163
 
162
- true
164
+ messages
165
+ end
166
+
167
+ # :call-seq:
168
+ # verify_managed_entries!
169
+ #
170
+ # All managed files and directories are checked to make sure that they
171
+ # exist and validate, if required.
172
+ def verify_managed_entries!
173
+ messages = verify_managed_entries
174
+ raise MalformedContainerError, messages unless messages.empty?
163
175
  end
164
176
 
165
177
  protected
@@ -193,8 +205,8 @@ module ZipContainer
193
205
  # managed files within it.
194
206
  def register_managed_entry(entry)
195
207
  unless entry.is_a?(ManagedDirectory) || entry.is_a?(ManagedFile)
196
- raise ArgumentError.new("The supplied entry must be of type "\
197
- "ManagedDirectory or ManagedFile or a subclass of either.")
208
+ raise ArgumentError, 'The supplied entry must be of type '\
209
+ 'ManagedDirectory or ManagedFile or a subclass of either.'
198
210
  end
199
211
 
200
212
  entry.parent = self
@@ -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 reserved names.
@@ -70,7 +70,7 @@ module ZipContainer
70
70
  # Zip::Entry object can be passed in here.
71
71
  def reserved_entry?(entry)
72
72
  name = entry_name(entry)
73
- reserved_names.map { |n| n.downcase }.include? name.downcase
73
+ reserved_names.map(&:downcase).include? name.downcase
74
74
  end
75
75
 
76
76
  protected
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2013, 2014 The University of Manchester, UK.
1
+ # Copyright (c) 2013-2015 The University of Manchester, UK.
2
2
  #
3
3
  # All rights reserved.
4
4
  #
@@ -30,31 +30,37 @@
30
30
  #
31
31
  # Author: Robert Haines
32
32
 
33
- #
33
+ ##
34
34
  module ZipContainer
35
35
 
36
36
  # The base of all exceptions raised by this library.
37
- module ContainerError
37
+ module Error
38
38
  end
39
39
 
40
40
  # Shadow Zip::Error so the rubyzip API doesn't leak out.
41
41
  ZipError = ::Zip::Error
42
- ZipError.send(:include, ContainerError)
42
+ ZipError.send(:include, Error)
43
43
 
44
44
  # This exception is raised when a bad Container is detected.
45
45
  class MalformedContainerError < RuntimeError
46
- include ContainerError
46
+
47
+ include Error
47
48
 
48
49
  # :call-seq:
49
- # new(reason = "")
50
+ # new
51
+ # new(reason)
52
+ # new(reason_list)
50
53
  #
51
- # Create a new MalformedContainerError with an optional reason for why
52
- # the Container file is malformed.
54
+ # Create a new MalformedContainerError with an optional reason or list of
55
+ # reasons for why the Container is malformed.
53
56
  def initialize(reason = nil)
54
- if reason.nil?
55
- super("Malformed Container File.")
57
+ if reason.nil? || reason.empty?
58
+ super('Malformed Container.')
59
+ elsif reason.is_a?(Array)
60
+ reasons = reason.map { |r| " * #{r}\n" }
61
+ super("Malformed Container:\n#{reasons}")
56
62
  else
57
- super("Malformed Container File: #{reason}")
63
+ super("Malformed Container: #{reason}")
58
64
  end
59
65
  end
60
66
  end
@@ -62,14 +68,15 @@ module ZipContainer
62
68
  # This exception is raised when a clash occurs with a reserved or managed
63
69
  # name.
64
70
  class ReservedNameClashError < RuntimeError
65
- include ContainerError
71
+
72
+ include Error
66
73
 
67
74
  # :call-seq:
68
75
  # new(name)
69
76
  #
70
77
  # Create a new ReservedNameClashError with the name of the clash supplied.
71
78
  def initialize(name)
72
- super("'#{name}' is reserved for internal use in this ZipContainer file.")
79
+ super("'#{name}' is reserved for internal use in this ZipContainer.")
73
80
  end
74
81
  end
75
82
 
@@ -49,7 +49,7 @@ module ZipContainer
49
49
 
50
50
  extend Forwardable
51
51
  def_delegators :@container, :comment, :comment=, :commit_required?, :each,
52
- :entries, :extract, :get_input_stream, :name, :read, :size
52
+ :entries, :extract, :get_input_stream, :name, :read, :size
53
53
 
54
54
  private_class_method :new
55
55
 
@@ -74,7 +74,7 @@ module ZipContainer
74
74
  # File.create(filename, mimetype) {|container| ...}
75
75
  #
76
76
  # Create a new ZipContainer file on disk with the specified mimetype.
77
- def self.create(filename, mimetype, &block)
77
+ def self.create(filename, mimetype)
78
78
  ::Zip::OutputStream.open(filename) do |stream|
79
79
  stream.put_next_entry(MIMETYPE_FILE, nil, nil, ::Zip::Entry::STORED)
80
80
  stream.write mimetype
@@ -127,7 +127,7 @@ module ZipContainer
127
127
  # +continue_on_exists_proc+ parameter.
128
128
  def add(entry, src_path, &continue_on_exists_proc)
129
129
  if reserved_entry?(entry) || managed_directory?(entry)
130
- raise ReservedNameClashError.new(entry.to_s)
130
+ raise ReservedNameClashError, entry.to_s
131
131
  end
132
132
 
133
133
  @container.add(entry, src_path, &continue_on_exists_proc)
@@ -143,12 +143,10 @@ module ZipContainer
143
143
  def commit
144
144
  return false unless commit_required?
145
145
 
146
- if on_disk?
147
- @container.commit
148
- end
146
+ @container.commit if on_disk?
149
147
  end
150
148
 
151
- alias :close :commit
149
+ alias close commit
152
150
 
153
151
  # :call-seq:
154
152
  # dir -> Zip::ZipFsDir
@@ -182,7 +180,7 @@ module ZipContainer
182
180
  # can specify <tt>:include_hidden => true</tt> to include hidden entries
183
181
  # in the search.
184
182
  def find_entry(entry_name, options = {})
185
- options = {:include_hidden => false}.merge(options)
183
+ options = { include_hidden: false }.merge(options)
186
184
 
187
185
  unless options[:include_hidden]
188
186
  return if hidden_entry?(entry_name)
@@ -199,7 +197,7 @@ module ZipContainer
199
197
  # can specify <tt>:include_hidden => true</tt> to include hidden entries
200
198
  # in the search.
201
199
  def get_entry(entry, options = {})
202
- options = {:include_hidden => false}.merge(options)
200
+ options = { include_hidden: false }.merge(options)
203
201
 
204
202
  unless options[:include_hidden]
205
203
  raise Errno::ENOENT, entry if hidden_entry?(entry)
@@ -220,7 +218,7 @@ module ZipContainer
220
218
  # parameter.
221
219
  def get_output_stream(entry, permission = nil, &block)
222
220
  if reserved_entry?(entry) || managed_directory?(entry)
223
- raise ReservedNameClashError.new(entry.to_s)
221
+ raise ReservedNameClashError, entry.to_s
224
222
  end
225
223
 
226
224
  @container.get_output_stream(entry, permission, &block)
@@ -240,9 +238,9 @@ module ZipContainer
240
238
  # <tt>::File::FNM_PATHNAME | ::File::FNM_DOTMATCH</tt>
241
239
  # * +options+ - <tt>:include_hidden => true</tt> will include hidden
242
240
  # entries in the search.
243
- def glob(pattern, *params, &block)
241
+ def glob(pattern, *params)
244
242
  flags = ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH
245
- options = { :include_hidden => false }
243
+ options = { include_hidden: false }
246
244
 
247
245
  params.each do |param|
248
246
  case param
@@ -256,6 +254,7 @@ module ZipContainer
256
254
  entries.map do |entry|
257
255
  next if !options[:include_hidden] && hidden_entry?(entry)
258
256
  next unless ::File.fnmatch(pattern, entry.name.chomp('/'), flags)
257
+
259
258
  yield(entry) if block_given?
260
259
  entry
261
260
  end.compact
@@ -279,9 +278,9 @@ module ZipContainer
279
278
  # The new directory will be created with the supplied unix-style
280
279
  # permissions. The default (+0755+) is owner read, write and list; group
281
280
  # read and list; and world read and list.
282
- def mkdir(name, permission = 0755)
281
+ def mkdir(name, permission = 0o0755)
283
282
  if reserved_entry?(name) || managed_file?(name)
284
- raise ReservedNameClashError.new(name)
283
+ raise ReservedNameClashError, name
285
284
  end
286
285
 
287
286
  @container.mkdir(name, permission)
@@ -303,6 +302,7 @@ module ZipContainer
303
302
  # method will do nothing.
304
303
  def remove(entry)
305
304
  return if reserved_entry?(entry)
305
+
306
306
  @container.remove(entry)
307
307
  end
308
308
 
@@ -318,7 +318,7 @@ module ZipContainer
318
318
  # +continue_on_exists_proc+ parameter.
319
319
  def rename(entry, new_name, &continue_on_exists_proc)
320
320
  return if reserved_entry?(entry)
321
- raise ReservedNameClashError.new(new_name) if reserved_entry?(new_name)
321
+ raise ReservedNameClashError, new_name if reserved_entry?(new_name)
322
322
 
323
323
  @container.rename(entry, new_name, &continue_on_exists_proc)
324
324
  end
@@ -332,6 +332,7 @@ module ZipContainer
332
332
  # nothing.
333
333
  def replace(entry, src_path)
334
334
  return if reserved_entry?(entry)
335
+
335
336
  @container.replace(entry, src_path)
336
337
  end
337
338
 
@@ -479,6 +480,5 @@ module ZipContainer
479
480
  # size -> int
480
481
  #
481
482
  # Returns the number of entries in the ZipContainer file.
482
-
483
483
  end
484
484
  end