ro-crate 0.4.5 → 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78897fbce0fd01688c27516dceba600ed7cd984668fd16abde32a1713c0ba40f
4
- data.tar.gz: 3194d882e4b7f6cd347d652d5da38cb2fe02cfb18e36d84f50e012193a538a69
3
+ metadata.gz: cb6b4eba94b7190b7888cf3b1ddc8a8c6d0b464834ff48c45d9b50e6b13844ce
4
+ data.tar.gz: 70e0079caadfa3f17745e918f8109ec5908a8aa0c87d80aeaebfc55fdc03a9a8
5
5
  SHA512:
6
- metadata.gz: ddc2f5ffe217717299f2e5d76313b2a124fabfbc7b1e1800db18ca36d2f79c716ef249c6fcb8a6a8bfd4e0c5bba3b8a30d6ae3498ef8fd0068d7df08985c72f5
7
- data.tar.gz: 802bf935d2e911ce771e962d6faaf0821f682049424cf5ac893ec780b8fc89d22f844156a83dd38adbe045a31faa7e527b4d8406bcabe937bdf8a2e8afafcd93
6
+ metadata.gz: 62c9875be216987ceaca7e47f92112ba744109e4df9f8dcbba9023211ef3fc278f74f8ce7421523a0f443000f251627735eb01ce2357e9e526e36c23818bbba0
7
+ data.tar.gz: 0b5be2eedc7a045ccf25db4e3d800107f30d00b62e1e4b5bdb1deed1eed941897f46621bef9fa9a012891bc058857de82d6afebeb122153f8ffc944b8ca06a7a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ro-crate (0.4.5)
4
+ ro-crate (0.4.10)
5
5
  addressable (~> 2.7.0)
6
6
  rubyzip (~> 2.0.0)
7
7
 
@@ -3,21 +3,9 @@ module ROCrate
3
3
  # A class to represent a "Contextual Entity" within an RO-Crate.
4
4
  # Contextual Entities are used to describe and provide context to the Data Entities within the crate.
5
5
  class ContextualEntity < Entity
6
- def self.format_id(id)
6
+ def self.format_local_id(id)
7
7
  i = super
8
- begin
9
- uri = URI(id)
10
- rescue ArgumentError
11
- uri = nil
12
- end
13
-
14
- if uri&.absolute?
15
- i
16
- elsif i.start_with?('#')
17
- i
18
- else
19
- "##{i}"
20
- end
8
+ i.start_with?('#') ? i : "##{i}"
21
9
  end
22
10
 
23
11
  ##
@@ -8,6 +8,11 @@ module ROCrate
8
8
  properties(%w[name datePublished author license identifier distribution contactPoint publisher description url hasPart])
9
9
 
10
10
  def self.format_id(id)
11
+ i = super(id)
12
+ i.end_with?('/') ? i : "#{i}/"
13
+ end
14
+
15
+ def self.format_local_id(id)
11
16
  return id if id == IDENTIFIER
12
17
  super
13
18
  end
@@ -217,15 +222,19 @@ module ROCrate
217
222
 
218
223
  alias_method :own_entries, :entries
219
224
  ##
220
- # A map of all the files/directories contained in the RO-Crate, where the key is the destination path within the crate
221
- # and the value is an Entry where the source data can be read.
225
+ # # The RO-Crate's "payload" of the crate - a map of all the files/directories contained in the RO-Crate, where the
226
+ # key is the destination path within the crate and the value is an Entry where the source data can be read.
222
227
  #
223
228
  # @return [Hash{String => Entry}>]
224
229
  def entries
225
- entries = {}
226
-
227
- (default_entities | data_entities).each do |entity|
228
- (entity == self ? own_entries : entity.entries).each do |path, entry|
230
+ # Gather a map of entries, starting from the crate itself, then any directory data entities, then finally any
231
+ # file data entities. This ensures in the case of a conflict, the more "specific" data entities take priority.
232
+ entries = own_entries
233
+ non_self_entities = default_entities.reject { |e| e == self }
234
+ sorted_entities = (non_self_entities | data_entities).sort_by { |e| e.is_a?(ROCrate::Directory) ? 0 : 1 }
235
+
236
+ sorted_entities.each do |entity|
237
+ entity.entries.each do |path, entry|
229
238
  entries[path] = entry
230
239
  end
231
240
  end
@@ -3,7 +3,7 @@ module ROCrate
3
3
  # A class to represent a "Data Entity" within an RO-Crate.
4
4
  # Data Entities are the actual physical files and directories within the Crate.
5
5
  class DataEntity < Entity
6
- def self.format_id(id)
6
+ def self.format_local_id(id)
7
7
  super.chomp('/')
8
8
  end
9
9
 
@@ -4,7 +4,7 @@ module ROCrate
4
4
  class Directory < DataEntity
5
5
  properties(%w[name contentSize dateModified encodingFormat identifier sameAs])
6
6
 
7
- def self.format_id(id)
7
+ def self.format_local_id(id)
8
8
  super + '/'
9
9
  end
10
10
 
@@ -30,8 +30,8 @@ module ROCrate
30
30
  end
31
31
 
32
32
  ##
33
- # A map of all the files/directories under this directory, where the key is the destination path within the crate
34
- # and the value is an Entry where the source data can be read.
33
+ # The "payload" of this directory - a map of all the files/directories, where the key is the destination path
34
+ # within the crate and the value is an Entry where the source data can be read.
35
35
  #
36
36
  # @return [Hash{String => Entry}>]
37
37
  def entries
@@ -29,12 +29,34 @@ module ROCrate
29
29
  end
30
30
 
31
31
  ##
32
- # Format the given ID with rules appropriate for this type.
32
+ # Format the given ID with rules appropriate for this type if it is local/relative, leave as-is if absolute.
33
+ #
34
+ # @param id [String] The candidate ID to be formatted.
35
+ # @return [String] The formatted ID.
36
+ def self.format_id(id)
37
+ begin
38
+ uri = URI(id)
39
+ rescue ArgumentError, URI::InvalidURIError
40
+ uri = nil
41
+ end
42
+
43
+ if uri&.absolute?
44
+ id
45
+ else
46
+ format_local_id(id)
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Format the given local ID with rules appropriate for this type.
33
52
  # For example:
34
53
  # * contextual entities MUST be absolute URIs, or begin with: #
35
54
  # * files MUST NOT begin with ./
36
55
  # * directories MUST NOT begin with ./ (except for the crate itself), and MUST end with /
37
- def self.format_id(id)
56
+ #
57
+ # @param id [String] The candidate local ID to be formatted.
58
+ # @return [String] The formatted local ID.
59
+ def self.format_local_id(id)
38
60
  Addressable::URI.escape(id.sub(/\A\.\//, '')) # Remove initial ./ if present
39
61
  end
40
62
 
@@ -52,7 +52,9 @@ module ROCrate
52
52
  end
53
53
 
54
54
  ##
55
- # A map of all the files/directories associated with this File. Should only be a single key and value.
55
+ # The "payload". A map with a single key and value, of the relative filepath within the crate, to the source on disk
56
+ # where the actual bytes of the file can be read. Blank if remote.
57
+ #
56
58
  # (for compatibility with Directory#entries)
57
59
  #
58
60
  # @return [Hash{String => Entry}>] The key is the location within the crate, and the value is an Entry.
@@ -3,29 +3,67 @@ module ROCrate
3
3
  # A class to handle reading of RO-Crates from Zip files or directories.
4
4
  class Reader
5
5
  ##
6
- # Reads an RO-Crate from a directory of zip file.
6
+ # Reads an RO-Crate from a directory or zip file.
7
7
  #
8
- # @param source [String, ::File, Pathname] The source location for the crate.
8
+ # @param source [String, ::File, Pathname, #read] The location of the zip or directory, or an IO-like object containing a zip.
9
9
  # @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped (if its a Zip file).
10
10
  # @return [Crate] The RO-Crate.
11
11
  def self.read(source, target_dir: Dir.mktmpdir)
12
12
  raise "Not a directory!" unless ::File.directory?(target_dir)
13
- if ::File.directory?(source)
13
+ begin
14
+ is_dir = ::File.directory?(source)
15
+ rescue TypeError
16
+ is_dir = false
17
+ end
18
+
19
+ if is_dir
14
20
  read_directory(source)
15
21
  else
16
22
  read_zip(source, target_dir: target_dir)
17
23
  end
18
24
  end
19
25
 
26
+ ##
27
+ # Extract the contents of the given Zip file/data to the given directory.
28
+ #
29
+ # @param source [String, ::File, Pathname, #read] The location of the zip file, or an IO-like object.
30
+ # @param target [String, ::File, Pathname] The target directory where the file should be unzipped.
31
+ def self.unzip_to(source, target)
32
+ source = Pathname.new(::File.expand_path(source)) if source.is_a?(String)
33
+
34
+ if source.is_a?(Pathname) || source.respond_to?(:path)
35
+ unzip_file_to(source, target)
36
+ else
37
+ unzip_io_to(source, target)
38
+ end
39
+ end
40
+
41
+ ##
42
+ # Extract the given Zip file data to the given directory.
43
+ #
44
+ # @param source [#read] An IO-like object containing a Zip file.
45
+ # @param target [String, ::File, Pathname] The target directory where the file should be unzipped.
46
+ def self.unzip_io_to(io, target)
47
+ Dir.chdir(target) do
48
+ Zip::InputStream.open(io) do |input|
49
+ while (entry = input.get_next_entry)
50
+ unless ::File.exist?(entry.name) || entry.name_is_directory?
51
+ FileUtils::mkdir_p(::File.dirname(entry.name))
52
+ ::File.binwrite(entry.name, input.read)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
20
59
  ##
21
60
  # Extract the contents of the given Zip file to the given directory.
22
61
  #
23
62
  # @param source [String, ::File, Pathname] The location of the zip file.
24
63
  # @param target [String, ::File, Pathname] The target directory where the file should be unzipped.
25
- def self.unzip_to(source, target)
26
- source = ::File.expand_path(source)
64
+ def self.unzip_file_to(file_or_path, target)
27
65
  Dir.chdir(target) do
28
- Zip::File.open(source) do |zipfile|
66
+ Zip::File.open(file_or_path) do |zipfile|
29
67
  zipfile.each do |entry|
30
68
  unless ::File.exist?(entry.name)
31
69
  FileUtils::mkdir_p(::File.dirname(entry.name))
@@ -40,13 +78,16 @@ module ROCrate
40
78
  # Reads an RO-Crate from a zip file. It first extracts the Zip file to a temporary directory, and then calls
41
79
  # #read_directory.
42
80
  #
43
- # @param source [String, ::File, Pathname] The location of the zip file.
81
+ # @param source [String, ::File, Pathname, #read] The location of the zip file, or an IO-like object.
44
82
  # @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped.
45
83
  # @return [Crate] The RO-Crate.
46
84
  def self.read_zip(source, target_dir: Dir.mktmpdir)
47
85
  unzip_to(source, target_dir)
48
86
 
49
- read_directory(target_dir)
87
+ # Traverse the unzipped directory to try and find the crate's root
88
+ root_dir = detect_root_directory(target_dir)
89
+
90
+ read_directory(root_dir)
50
91
  end
51
92
 
52
93
  ##
@@ -55,6 +96,8 @@ module ROCrate
55
96
  # @param source [String, ::File, Pathname] The location of the directory.
56
97
  # @return [Crate] The RO-Crate.
57
98
  def self.read_directory(source)
99
+ raise "Not a directory!" unless ::File.directory?(source)
100
+
58
101
  source = ::File.expand_path(source)
59
102
  metadata_file = Dir.entries(source).detect { |entry| entry == ROCrate::Metadata::IDENTIFIER ||
60
103
  entry == ROCrate::Metadata::IDENTIFIER_1_0 }
@@ -107,6 +150,7 @@ module ROCrate
107
150
  crate.metadata.properties = entity_hash.delete(ROCrate::Metadata::IDENTIFIER)
108
151
  preview_properties = entity_hash.delete(ROCrate::Preview::IDENTIFIER)
109
152
  crate.preview.properties = preview_properties if preview_properties
153
+ crate.add_all(source, false)
110
154
  extract_data_entities(crate, source, entity_hash).each do |entity|
111
155
  crate.add_data_entity(entity)
112
156
  end
@@ -211,5 +255,23 @@ module ROCrate
211
255
  raise "Metadata entity does not reference any root entity" unless root_id
212
256
  entities.delete(root_id)
213
257
  end
258
+
259
+ ##
260
+ # Finds an RO-Crate's root directory (where `ro-crate-metdata.json` is located) within a given directory.
261
+ #
262
+ # @param source [String, ::File, Pathname] The location of the directory.
263
+ # @return [Pathname, nil] The path to the root, or nil if not found.
264
+ def self.detect_root_directory(source)
265
+ Pathname(source).find do |entry|
266
+ if entry.file?
267
+ name = entry.basename.to_s
268
+ if name == ROCrate::Metadata::IDENTIFIER || name == ROCrate::Metadata::IDENTIFIER_1_0
269
+ return entry.parent
270
+ end
271
+ end
272
+ end
273
+
274
+ nil
275
+ end
214
276
  end
215
277
  end
data/ro_crate.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ro-crate'
3
- s.version = '0.4.5'
3
+ s.version = '0.4.10'
4
4
  s.summary = 'Create, manipulate, read RO-Crates.'
5
5
  s.authors = ['Finn Bacall']
6
6
  s.email = 'finn.bacall@manchester.ac.uk'
data/test/entity_test.rb CHANGED
@@ -70,4 +70,25 @@ class EntityTest < Test::Unit::TestCase
70
70
  assert_equal({ '@id' => '#fred' }, person.reference)
71
71
  assert_equal(person.canonical_id, crate.author.canonical_id)
72
72
  end
73
+
74
+ test 'format various IDs' do
75
+ assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('#Hello World/Goodbye World')
76
+ assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('Hello World/Goodbye World')
77
+ assert_equal "#%F0%9F%98%8A", ROCrate::ContextualEntity.format_id("😊")
78
+
79
+ assert_equal "test123/hello.txt", ROCrate::File.format_id('./test123/hello.txt')
80
+ assert_equal "test123/hello.txt", ROCrate::File.format_id('./test123/hello.txt/')
81
+ assert_equal "http://www.data.com/my%20data.txt", ROCrate::File.format_id('http://www.data.com/my%20data.txt')
82
+ assert_equal "http://www.data.com/my%20data.txt/", ROCrate::File.format_id('http://www.data.com/my%20data.txt/'), 'Should not modify absolute URI for DataEntity'
83
+
84
+ assert_equal "my%20directory/", ROCrate::Directory.format_id('my directory')
85
+ assert_equal "my%20directory/", ROCrate::Directory.format_id('my directory/')
86
+ assert_equal 'http://www.data.com/my%20directory', ROCrate::Directory.format_id('http://www.data.com/my%20directory'), 'Should not modify absolute URI for DataEntity'
87
+ assert_equal 'http://www.data.com/my%20directory/', ROCrate::Directory.format_id('http://www.data.com/my%20directory/'), 'Should not modify absolute URI for DataEntity'
88
+
89
+ assert_equal "./", ROCrate::Crate.format_id('./')
90
+ assert_equal "cool%20crate/", ROCrate::Crate.format_id('./cool crate')
91
+ assert_equal "http://www.data.com/my%20crate/", ROCrate::Crate.format_id('http://www.data.com/my%20crate'), 'Crate ID should end with /'
92
+ assert_equal "http://www.data.com/my%20crate/", ROCrate::Crate.format_id('http://www.data.com/my%20crate/')
93
+ end
73
94
  end
Binary file
@@ -0,0 +1 @@
1
+ I'm at the root
@@ -0,0 +1,32 @@
1
+ {
2
+ "@context": "https://w3id.org/ro/crate/1.0/context",
3
+ "@graph": [
4
+ {
5
+ "@id": "ro-crate-metadata.jsonld",
6
+ "@type": "CreativeWork",
7
+ "about": {
8
+ "@id": "./"
9
+ }
10
+ },
11
+ {
12
+ "@id": "ro-crate-preview.html",
13
+ "@type": "CreativeWork",
14
+ "about": {
15
+ "@id": "./"
16
+ }
17
+ },
18
+ {
19
+ "@id": "./",
20
+ "@type": "Dataset",
21
+ "hasPart": [
22
+ {
23
+ "@id": "listed_file.txt"
24
+ }
25
+ ]
26
+ },
27
+ {
28
+ "@id": "listed_file.txt",
29
+ "@type": "File"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>New RO-Crate</title>
5
+ <script type="application/ld+json">{
6
+ "@context": "https://w3id.org/ro/crate/1.1/context",
7
+ "@graph": [
8
+ {
9
+ "@id": "ro-crate-metadata.jsonld",
10
+ "@type": "CreativeWork",
11
+ "about": {
12
+ "@id": "./"
13
+ }
14
+ },
15
+ {
16
+ "@id": "ro-crate-preview.html",
17
+ "@type": "CreativeWork",
18
+ "about": {
19
+ "@id": "./"
20
+ }
21
+ },
22
+ {
23
+ "@id": "./",
24
+ "@type": "Dataset",
25
+ "hasPart": [
26
+ {
27
+ "@id": "fish/"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "@id": "fish/",
33
+ "@type": "Dataset"
34
+ }
35
+ ]
36
+ }</script>
37
+ <meta name="generator" content="https://github.com/fbacall/ro-crate-ruby">
38
+ <meta name="keywords" content="RO-Crate">
39
+ </head>
40
+ <body>
41
+ <h1>New RO-Crate</h1>
42
+
43
+ <p>
44
+
45
+ </p>
46
+ <dl>
47
+
48
+
49
+
50
+
51
+ </dl>
52
+
53
+ <h2>Contents</h2>
54
+ <ul>
55
+
56
+ <li id="__data_entity_fish/">
57
+
58
+ <strong>fish/</strong>
59
+
60
+
61
+
62
+ </li>
63
+
64
+ </ul>
65
+ </body>
66
+ </html>
data/test/reader_test.rb CHANGED
@@ -163,4 +163,68 @@ class ReaderTest < Test::Unit::TestCase
163
163
  assert_equal 'http://example.com/external_ref.txt', ext_file.id
164
164
  assert_equal 'file contents', ext_file.source.read
165
165
  end
166
+
167
+ test 'reading from directory with unlisted files' do
168
+ crate = ROCrate::Reader.read_directory(fixture_file('sparse_directory_crate').path)
169
+
170
+ assert_equal 11, crate.entries.count
171
+ assert crate.entries['listed_file.txt']
172
+ assert crate.entries['unlisted_file.txt']
173
+ assert crate.entries['fish']
174
+ assert_equal '1234', crate.entries['fish/info.txt'].source.read.chomp
175
+ refute crate.entries['fish/root.txt'].directory?
176
+ assert crate.entries['fish/data'].directory?
177
+ assert crate.entries['fish/data/info.txt']
178
+ refute crate.entries['fish/data/nested.txt'].remote?
179
+ assert crate.entries['fish/data/binary.jpg']
180
+ assert_equal ['./', 'listed_file.txt', 'ro-crate-metadata.jsonld', 'ro-crate-preview.html'], crate.entities.map(&:id).sort
181
+ end
182
+
183
+ test 'reading from a zip with unlisted files' do
184
+ crate = ROCrate::Reader.read_zip(fixture_file('sparse_directory_crate.zip').path)
185
+
186
+ assert_equal 11, crate.entries.count
187
+ assert crate.entries['listed_file.txt']
188
+ assert crate.entries['unlisted_file.txt']
189
+ assert crate.entries['fish']
190
+ assert_equal '1234', crate.entries['fish/info.txt'].source.read.chomp
191
+ refute crate.entries['fish/root.txt'].directory?
192
+ assert crate.entries['fish/data'].directory?
193
+ assert crate.entries['fish/data/info.txt']
194
+ refute crate.entries['fish/data/nested.txt'].remote?
195
+ assert crate.entries['fish/data/binary.jpg']
196
+ assert_equal ['./', 'listed_file.txt', 'ro-crate-metadata.jsonld', 'ro-crate-preview.html'], crate.entities.map(&:id).sort
197
+ end
198
+
199
+ test 'reading a zip from various object types' do
200
+ string_io = StringIO.new
201
+ string_io.write(::File.read(fixture_file('sparse_directory_crate.zip').path))
202
+ string_io.rewind
203
+ assert string_io.is_a?(StringIO)
204
+ assert_equal 11, ROCrate::Reader.read_zip(string_io).entries.count
205
+
206
+ path = Pathname.new(fixture_file('sparse_directory_crate.zip').path)
207
+ assert path.is_a?(Pathname)
208
+ assert_equal 11, ROCrate::Reader.read_zip(path).entries.count
209
+
210
+ file = ::File.open(fixture_file('sparse_directory_crate.zip').path)
211
+ assert file.is_a?(::File)
212
+ assert_equal 11, ROCrate::Reader.read_zip(file).entries.count
213
+
214
+ string = fixture_file('sparse_directory_crate.zip').path
215
+ assert string.is_a?(String)
216
+ assert_equal 11, ROCrate::Reader.read_zip(string).entries.count
217
+ end
218
+
219
+ test 'reading from zip where the crate root is nested somewhere within' do
220
+ crate = ROCrate::Reader.read_zip(fixture_file('nested_directory.zip'))
221
+
222
+ assert crate.entries['fish/info.txt']
223
+ assert_equal '1234', crate.entries['fish/info.txt'].source.read.chomp
224
+ assert crate.entries['fish/root.txt']
225
+ assert crate.entries['fish/data/info.txt']
226
+ assert crate.entries['fish/data/nested.txt']
227
+ assert crate.entries['fish/data/binary.jpg']
228
+ assert_equal ['./', 'fish/', 'ro-crate-metadata.json', 'ro-crate-preview.html'], crate.entities.map(&:id).sort
229
+ end
166
230
  end
data/test/writer_test.rb CHANGED
@@ -112,4 +112,24 @@ class WriterTest < Test::Unit::TestCase
112
112
  assert_equal 2529, ::File.size(::File.join(dir, 'data', 'binary.jpg'))
113
113
  end
114
114
  end
115
+
116
+ test 'reading and writing out a directory crate produces an identical crate' do
117
+ fixture = fixture_file('sparse_directory_crate').path
118
+ Dir.mktmpdir do |dir|
119
+ dir = ::File.join(dir, 'new_directory')
120
+ crate = ROCrate::Reader.read(fixture)
121
+
122
+ ROCrate::Writer.new(crate).write(dir)
123
+ expected_files = Dir.chdir(fixture) { Dir.glob('**/*') }
124
+ actual_files = Dir.chdir(dir) { Dir.glob('**/*') }
125
+ assert_equal expected_files, actual_files
126
+ expected_files.each do |file|
127
+ next if file == 'ro-crate-metadata.jsonld' # Expected context gets updated.
128
+ next if file == 'ro-crate-preview.html' # RO-Crate preview format changed
129
+ abs_file_path = ::File.join(fixture, file)
130
+ next if ::File.directory?(abs_file_path)
131
+ assert_equal ::File.read(abs_file_path), ::File.read(::File.join(dir, file)), "#{file} didn't match"
132
+ end
133
+ end
134
+ end
115
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ro-crate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Finn Bacall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-24 00:00:00.000000000 Z
11
+ date: 2021-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -165,8 +165,19 @@ files:
165
165
  - test/fixtures/directory_crate/ro-crate-preview.html
166
166
  - test/fixtures/file with spaces.txt
167
167
  - test/fixtures/info.txt
168
+ - test/fixtures/nested_directory.zip
168
169
  - test/fixtures/spaces/file with spaces.txt
169
170
  - test/fixtures/spaces/ro-crate-metadata.jsonld
171
+ - test/fixtures/sparse_directory_crate.zip
172
+ - test/fixtures/sparse_directory_crate/fish/data/binary.jpg
173
+ - test/fixtures/sparse_directory_crate/fish/data/info.txt
174
+ - test/fixtures/sparse_directory_crate/fish/data/nested.txt
175
+ - test/fixtures/sparse_directory_crate/fish/info.txt
176
+ - test/fixtures/sparse_directory_crate/fish/root.txt
177
+ - test/fixtures/sparse_directory_crate/listed_file.txt
178
+ - test/fixtures/sparse_directory_crate/ro-crate-metadata.jsonld
179
+ - test/fixtures/sparse_directory_crate/ro-crate-preview.html
180
+ - test/fixtures/sparse_directory_crate/unlisted_file.txt
170
181
  - test/fixtures/workflow-0.2.0.zip
171
182
  - test/fixtures/workflow-0.2.0/Dockerfile
172
183
  - test/fixtures/workflow-0.2.0/README.md