zip-container 2.2.0 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
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