ro-crate 0.5.3 → 0.7.0
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 +4 -4
- data/.github/workflows/docs.yml +1 -1
- data/.github/workflows/tests.yml +2 -2
- data/.ruby-version +1 -1
- data/README.md +3 -3
- data/Rakefile +0 -9
- data/lib/ro_crate/model/crate.rb +9 -2
- data/lib/ro_crate/model/directory.rb +2 -3
- data/lib/ro_crate/model/metadata.rb +38 -5
- data/lib/ro_crate/reader.rb +70 -22
- data/lib/ro_crate/writer.rb +1 -1
- data/ro_crate.gemspec +7 -6
- data/test/crate_test.rb +29 -0
- data/test/fixtures/crate-spec1.2/file with spaces.txt +1 -0
- data/test/fixtures/crate-spec1.2/ro-crate-metadata.json +42 -0
- data/test/fixtures/crate-spec1.2/ro-crate-preview.html +82 -0
- data/test/fixtures/crate-spec1.3/file with spaces.txt +1 -0
- data/test/fixtures/crate-spec1.3/ro-crate-metadata.json +42 -0
- data/test/fixtures/crate-spec1.3/ro-crate-preview.html +82 -0
- data/test/fixtures/just_a_zip.zip +0 -0
- data/test/fixtures/unsafe/absolute1.zip +0 -0
- data/test/fixtures/unsafe/relative0.zip +0 -0
- data/test/reader_test.rb +93 -8
- data/test/test_helper.rb +28 -1
- metadata +31 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eee42ff56abf6a19d3a0e3575957c338b79a87c5609566618c032ca302ccab8d
|
|
4
|
+
data.tar.gz: 7d36b9517a344a2d2f9559a11229e8a51e2a2e4b02c5ada951d8b86b82051900
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 82917f083837b091d304e61188dbcb06cbe9a306676e3c17e4c56d662cb3a65d90bb7f41b5c09503caaf457a0740d30a9011a4f4edc64fe2bf78556a6e9f078e
|
|
7
|
+
data.tar.gz: 430857f30551fb3f4e2c82fce71babfd9574cf4a039ece9dd26318766d054ff4ac9725b3fa6bab134d8e0a5ad5eed01905324aeadbdaf0053730716b57e97eca
|
data/.github/workflows/docs.yml
CHANGED
|
@@ -7,7 +7,7 @@ jobs:
|
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
9
|
- name: Checkout
|
|
10
|
-
uses: actions/checkout@
|
|
10
|
+
uses: actions/checkout@v6
|
|
11
11
|
with:
|
|
12
12
|
persist-credentials: false
|
|
13
13
|
- name: Setup Ruby
|
data/.github/workflows/tests.yml
CHANGED
|
@@ -5,11 +5,11 @@ jobs:
|
|
|
5
5
|
runs-on: ubuntu-latest
|
|
6
6
|
strategy:
|
|
7
7
|
matrix:
|
|
8
|
-
ruby: ['2.
|
|
8
|
+
ruby: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4', '4.0']
|
|
9
9
|
fail-fast: false
|
|
10
10
|
steps:
|
|
11
11
|
- name: Checkout
|
|
12
|
-
uses: actions/checkout@
|
|
12
|
+
uses: actions/checkout@v6
|
|
13
13
|
with:
|
|
14
14
|
persist-credentials: false
|
|
15
15
|
- name: Setup Ruby
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-3.
|
|
1
|
+
ruby-3.4.9
|
data/README.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
This is a WIP gem for creating, manipulating and reading RO-Crates (conforming to version 1.
|
|
5
|
+
This is a WIP gem for creating, manipulating and reading RO-Crates (conforming to version 1.3 of the specification). RO-Crates produced by older versions (1.0, 1.1, 1.2) of the spec can still be read.
|
|
6
6
|
|
|
7
|
-
* RO-Crate - https://researchobject.
|
|
8
|
-
* RO-Crate spec (1.
|
|
7
|
+
* RO-Crate - https://www.researchobject.org/ro-crate/
|
|
8
|
+
* RO-Crate spec (1.3) - https://www.researchobject.org/ro-crate/specification/1.3/
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
data/Rakefile
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require 'bundler/gem_tasks'
|
|
2
2
|
require 'rake/testtask'
|
|
3
|
-
require 'rdoc/task'
|
|
4
3
|
|
|
5
4
|
desc 'Default: run unit tests.'
|
|
6
5
|
task default: :test
|
|
@@ -13,14 +12,6 @@ Rake::TestTask.new(:test) do |t|
|
|
|
13
12
|
t.warning = false
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
17
|
-
rdoc.rdoc_dir = 'rdoc'
|
|
18
|
-
rdoc.title = 'Devise'
|
|
19
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
|
20
|
-
rdoc.rdoc_files.include('README.md')
|
|
21
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
22
|
-
end
|
|
23
|
-
|
|
24
15
|
task :console do
|
|
25
16
|
require 'irb'
|
|
26
17
|
require 'irb/completion'
|
data/lib/ro_crate/model/crate.rb
CHANGED
|
@@ -21,9 +21,16 @@ module ROCrate
|
|
|
21
21
|
|
|
22
22
|
##
|
|
23
23
|
# Initialize an empty RO-Crate.
|
|
24
|
-
|
|
24
|
+
#
|
|
25
|
+
# @param id [String] The crate's identifier.
|
|
26
|
+
# @param properties [Hash] Initial properties for the root data entity.
|
|
27
|
+
# @param version [String] RO-Crate spec version to declare (default: ROCrate::Metadata::DEFAULT_VERSION).
|
|
28
|
+
# Must be one of ROCrate::Metadata::SUPPORTED_VERSIONS.
|
|
29
|
+
def initialize(id = IDENTIFIER, properties = {}, version: ROCrate::Metadata::DEFAULT_VERSION)
|
|
30
|
+
ROCrate::Metadata.warn_unrecognized_version(version)
|
|
25
31
|
@data_entities = Set.new
|
|
26
32
|
@contextual_entities = Set.new
|
|
33
|
+
@metadata_version = version
|
|
27
34
|
super(self, nil, id, properties)
|
|
28
35
|
end
|
|
29
36
|
|
|
@@ -168,7 +175,7 @@ module ROCrate
|
|
|
168
175
|
#
|
|
169
176
|
# @return [Metadata]
|
|
170
177
|
def metadata
|
|
171
|
-
@metadata ||= ROCrate::Metadata.new(self)
|
|
178
|
+
@metadata ||= ROCrate::Metadata.new(self, {}, version: @metadata_version || ROCrate::Metadata::DEFAULT_VERSION)
|
|
172
179
|
end
|
|
173
180
|
|
|
174
181
|
##
|
|
@@ -74,9 +74,8 @@ module ROCrate
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def list_all_files(source_directory, include_hidden: false)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
Dir.chdir(source_directory) { Dir.glob(*args) }.reject do |path|
|
|
77
|
+
flags = include_hidden ? ::File::FNM_DOTMATCH : 0
|
|
78
|
+
Dir.glob('**/*', flags, base: source_directory).reject do |path|
|
|
80
79
|
path == '.' || path == '..' || path.end_with?('/.')
|
|
81
80
|
end
|
|
82
81
|
end
|
|
@@ -5,13 +5,46 @@ module ROCrate
|
|
|
5
5
|
IDENTIFIER = 'ro-crate-metadata.json'.freeze
|
|
6
6
|
IDENTIFIER_1_0 = 'ro-crate-metadata.jsonld'.freeze # 1.0 spec identifier
|
|
7
7
|
RO_CRATE_BASE = 'https://w3id.org/ro/crate/'
|
|
8
|
-
CONTEXT = "#{RO_CRATE_BASE}1.1/context".freeze
|
|
9
|
-
SPEC = "#{RO_CRATE_BASE}1.1".freeze
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
SUPPORTED_VERSIONS = %w[1.0 1.0-DRAFT 1.1 1.1-DRAFT 1.2 1.2-DRAFT 1.3].freeze
|
|
10
|
+
DEFAULT_VERSION = '1.3'.freeze
|
|
11
|
+
|
|
12
|
+
CONTEXT = "#{RO_CRATE_BASE}#{DEFAULT_VERSION}/context".freeze
|
|
13
|
+
SPEC = "#{RO_CRATE_BASE}#{DEFAULT_VERSION}".freeze
|
|
14
|
+
|
|
15
|
+
attr_reader :version
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Emit a warning if the given version is not in SUPPORTED_VERSIONS.
|
|
19
|
+
# Does not raise — unrecognized versions are still accepted so the library
|
|
20
|
+
# stays forward-compatible with future spec versions that need no changes.
|
|
21
|
+
def self.warn_unrecognized_version(v)
|
|
22
|
+
return if SUPPORTED_VERSIONS.include?(v)
|
|
23
|
+
warn "Unrecognized RO-Crate version: #{v.inspect}. Known versions: #{SUPPORTED_VERSIONS.join(', ')}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(crate, properties = {}, version: DEFAULT_VERSION)
|
|
27
|
+
self.class.warn_unrecognized_version(version)
|
|
28
|
+
@version = version
|
|
12
29
|
super(crate, nil, IDENTIFIER, properties)
|
|
13
30
|
end
|
|
14
31
|
|
|
32
|
+
##
|
|
33
|
+
# Update the spec version this metadata declares.
|
|
34
|
+
# Used by the Reader to preserve the version of a parsed crate.
|
|
35
|
+
def version=(v)
|
|
36
|
+
self.class.warn_unrecognized_version(v)
|
|
37
|
+
@version = v
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def context_url
|
|
41
|
+
"#{RO_CRATE_BASE}#{@version}/context"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def spec_url
|
|
45
|
+
"#{RO_CRATE_BASE}#{@version}"
|
|
46
|
+
end
|
|
47
|
+
|
|
15
48
|
##
|
|
16
49
|
# Generate the crate's `ro-crate-metadata.jsonld`.
|
|
17
50
|
# @return [String] The rendered JSON-LD as a "prettified" string.
|
|
@@ -21,7 +54,7 @@ module ROCrate
|
|
|
21
54
|
end
|
|
22
55
|
|
|
23
56
|
def context
|
|
24
|
-
@context ||
|
|
57
|
+
@context || context_url
|
|
25
58
|
end
|
|
26
59
|
|
|
27
60
|
def context= c
|
|
@@ -39,7 +72,7 @@ module ROCrate
|
|
|
39
72
|
'@id' => IDENTIFIER,
|
|
40
73
|
'@type' => 'CreativeWork',
|
|
41
74
|
'about' => { '@id' => crate.id },
|
|
42
|
-
'conformsTo' => { '@id' =>
|
|
75
|
+
'conformsTo' => { '@id' => spec_url }
|
|
43
76
|
}
|
|
44
77
|
end
|
|
45
78
|
end
|
data/lib/ro_crate/reader.rb
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
require 'zip/version'
|
|
2
|
+
|
|
1
3
|
module ROCrate
|
|
2
4
|
##
|
|
3
5
|
# A class to handle reading of RO-Crates from Zip files or directories.
|
|
4
6
|
class Reader
|
|
7
|
+
LEGACY_EXTRACT = Zip::VERSION.start_with?('2.').freeze
|
|
8
|
+
|
|
5
9
|
##
|
|
6
10
|
# Reads an RO-Crate from a directory or zip file.
|
|
7
11
|
#
|
|
@@ -42,15 +46,15 @@ module ROCrate
|
|
|
42
46
|
#
|
|
43
47
|
# @param source [#read] An IO-like object containing a Zip file.
|
|
44
48
|
# @param target [String, ::File, Pathname] The target directory where the file should be unzipped.
|
|
45
|
-
def self.unzip_io_to(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
def self.unzip_io_to(source, target)
|
|
50
|
+
target_path = Pathname(target)
|
|
51
|
+
Zip::InputStream.open(source) do |input|
|
|
52
|
+
while (entry = input.get_next_entry)
|
|
53
|
+
next if entry.name_is_directory?
|
|
54
|
+
dest = safe_join(target_path, entry.name)
|
|
55
|
+
next if dest.exist?
|
|
56
|
+
FileUtils.mkdir_p(dest.dirname)
|
|
57
|
+
::File.binwrite(dest, input.read)
|
|
54
58
|
end
|
|
55
59
|
end
|
|
56
60
|
end
|
|
@@ -60,15 +64,14 @@ module ROCrate
|
|
|
60
64
|
#
|
|
61
65
|
# @param source [String, ::File, Pathname] The location of the zip file.
|
|
62
66
|
# @param target [String, ::File, Pathname] The target directory where the file should be unzipped.
|
|
63
|
-
def self.unzip_file_to(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
67
|
+
def self.unzip_file_to(source, target)
|
|
68
|
+
target_path = Pathname(target)
|
|
69
|
+
Zip::File.open(source) do |zipfile|
|
|
70
|
+
zipfile.each do |entry|
|
|
71
|
+
dest = safe_join(target_path, entry.name)
|
|
72
|
+
next if dest.exist?
|
|
73
|
+
FileUtils.mkdir_p(dest.dirname)
|
|
74
|
+
LEGACY_EXTRACT ? entry.extract(dest) : entry.extract(entry.name, destination_directory: target_path)
|
|
72
75
|
end
|
|
73
76
|
end
|
|
74
77
|
end
|
|
@@ -87,6 +90,7 @@ module ROCrate
|
|
|
87
90
|
|
|
88
91
|
# Traverse the unzipped directory to try and find the crate's root
|
|
89
92
|
root_dir = detect_root_directory(target_dir)
|
|
93
|
+
raise ROCrate::ReadException, "No metadata found!" unless root_dir
|
|
90
94
|
|
|
91
95
|
read_directory(root_dir)
|
|
92
96
|
end
|
|
@@ -184,7 +188,10 @@ module ROCrate
|
|
|
184
188
|
def self.initialize_crate(entity_hash, source, crate_class: ROCrate::Crate, context:)
|
|
185
189
|
crate_class.new.tap do |crate|
|
|
186
190
|
crate.properties = entity_hash.delete(ROCrate::Crate::IDENTIFIER)
|
|
187
|
-
|
|
191
|
+
metadata_props = entity_hash.delete(ROCrate::Metadata::IDENTIFIER)
|
|
192
|
+
crate.metadata.properties = metadata_props
|
|
193
|
+
parsed_version = extract_version(metadata_props)
|
|
194
|
+
crate.metadata.version = parsed_version if parsed_version
|
|
188
195
|
crate.metadata.context = context
|
|
189
196
|
preview_properties = entity_hash.delete(ROCrate::Preview::IDENTIFIER)
|
|
190
197
|
preview_path = ::File.join(source, ROCrate::Preview::IDENTIFIER)
|
|
@@ -265,7 +272,7 @@ module ROCrate
|
|
|
265
272
|
|
|
266
273
|
##
|
|
267
274
|
# Extract the metadata entity from the entity hash, according to the rules defined here:
|
|
268
|
-
# https://www.researchobject.org/ro-crate/1.
|
|
275
|
+
# https://www.researchobject.org/ro-crate/specification/1.2/root-data-entity.html#finding-the-root-data-entity
|
|
269
276
|
# @return [nil, Hash{String => Hash}] A Hash containing (hopefully) one value, the metadata entity's properties
|
|
270
277
|
# mapped by its @id, or nil if nothing is found.
|
|
271
278
|
def self.extract_metadata_entity(entities)
|
|
@@ -284,6 +291,24 @@ module ROCrate
|
|
|
284
291
|
entities.delete(ROCrate::Metadata::IDENTIFIER_1_0))
|
|
285
292
|
end
|
|
286
293
|
|
|
294
|
+
##
|
|
295
|
+
# Extract the spec version from the metadata entity's `conformsTo`.
|
|
296
|
+
# Looks for an `@id` matching `https://w3id.org/ro/crate/<version>` and returns `<version>`.
|
|
297
|
+
# @param metadata_props [Hash, nil] The metadata entity's properties.
|
|
298
|
+
# @return [String, nil] The parsed version string, or nil if not found.
|
|
299
|
+
def self.extract_version(metadata_props)
|
|
300
|
+
return nil unless metadata_props
|
|
301
|
+
conforms = metadata_props['conformsTo']
|
|
302
|
+
conforms = [conforms] unless conforms.is_a?(Array)
|
|
303
|
+
conforms.compact.each do |c|
|
|
304
|
+
id = c.is_a?(Hash) ? c['@id'] : c
|
|
305
|
+
next unless id&.start_with?(ROCrate::Metadata::RO_CRATE_BASE)
|
|
306
|
+
version = id.sub(ROCrate::Metadata::RO_CRATE_BASE, '').split('/').first
|
|
307
|
+
return version if version && !version.empty?
|
|
308
|
+
end
|
|
309
|
+
nil
|
|
310
|
+
end
|
|
311
|
+
|
|
287
312
|
##
|
|
288
313
|
# Extract the ro-crate-preview entity from the entity hash.
|
|
289
314
|
# @return [Hash{String => Hash}] A Hash containing the preview entity's properties mapped by its @id, or nil if nothing is found.
|
|
@@ -293,7 +318,7 @@ module ROCrate
|
|
|
293
318
|
|
|
294
319
|
##
|
|
295
320
|
# Extract the root entity from the entity hash, according to the rules defined here:
|
|
296
|
-
# https://www.researchobject.org/ro-crate/1.
|
|
321
|
+
# https://www.researchobject.org/ro-crate/specification/1.2/root-data-entity.html#finding-the-root-data-entity
|
|
297
322
|
# @return [Hash{String => Hash}] A Hash containing (hopefully) one value, the root entity's properties,
|
|
298
323
|
# mapped by its @id.
|
|
299
324
|
def self.extract_root_entity(entities)
|
|
@@ -303,7 +328,7 @@ module ROCrate
|
|
|
303
328
|
end
|
|
304
329
|
|
|
305
330
|
##
|
|
306
|
-
# Finds an RO-Crate's root directory (where `ro-crate-
|
|
331
|
+
# Finds an RO-Crate's root directory (where `ro-crate-metadata.json` is located) within a given directory.
|
|
307
332
|
#
|
|
308
333
|
# @param source [String, ::File, Pathname] The location of the directory.
|
|
309
334
|
# @return [Pathname, nil] The path to the root, or nil if not found.
|
|
@@ -323,5 +348,28 @@ module ROCrate
|
|
|
323
348
|
|
|
324
349
|
nil
|
|
325
350
|
end
|
|
351
|
+
|
|
352
|
+
##
|
|
353
|
+
# Safely joins a desired file path onto a base directory, raising an exception if the path attempts to traverse
|
|
354
|
+
# outside it.
|
|
355
|
+
#
|
|
356
|
+
# @param base [Pathname] The base directory where the file will go.
|
|
357
|
+
# @param path [String] The desired file path.
|
|
358
|
+
#
|
|
359
|
+
# @raise [ROCrate::ReadException] Raised if an unsafe path is given.
|
|
360
|
+
#
|
|
361
|
+
# @return [Pathname] The safely joined base + path.
|
|
362
|
+
def self.safe_join(base, path)
|
|
363
|
+
dest = base.join(path)
|
|
364
|
+
# Guard against zip-slip attacks.
|
|
365
|
+
begin
|
|
366
|
+
unsafe = dest.expand_path.relative_path_from(base.expand_path).each_filename.first == '..'
|
|
367
|
+
rescue ArgumentError # Handle unjoinable paths, e.g. on different drives.
|
|
368
|
+
unsafe = true
|
|
369
|
+
end
|
|
370
|
+
raise ROCrate::ReadException, "Unsafe path in zip entry: #{path}" if unsafe
|
|
371
|
+
|
|
372
|
+
dest
|
|
373
|
+
end
|
|
326
374
|
end
|
|
327
375
|
end
|
data/lib/ro_crate/writer.rb
CHANGED
|
@@ -44,7 +44,7 @@ module ROCrate
|
|
|
44
44
|
# @param destination [String, ::File] The destination where to write the RO-Crate zip.
|
|
45
45
|
# @param skip_preview [Boolean] Whether or not to skip generation of the RO-Crate preview HTML file.
|
|
46
46
|
def write_zip(destination, skip_preview: false)
|
|
47
|
-
Zip::File.open(destination,
|
|
47
|
+
Zip::File.open(destination, create: true) do |zip|
|
|
48
48
|
@crate.payload.each do |path, entry|
|
|
49
49
|
next if entry.directory?
|
|
50
50
|
next if skip_preview && entry&.source.is_a?(ROCrate::PreviewGenerator)
|
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.
|
|
3
|
+
s.version = '0.7.0'
|
|
4
4
|
s.summary = 'Create, manipulate, read RO-Crates.'
|
|
5
5
|
s.authors = ['Finn Bacall']
|
|
6
6
|
s.email = 'finn.bacall@manchester.ac.uk'
|
|
@@ -8,12 +8,13 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.homepage = 'https://github.com/ResearchObject/ro-crate-ruby'
|
|
9
9
|
s.require_paths = ['lib']
|
|
10
10
|
s.licenses = ['MIT']
|
|
11
|
-
s.
|
|
12
|
-
s.add_runtime_dependency '
|
|
13
|
-
s.
|
|
11
|
+
s.required_ruby_version = '>= 2.7.0'
|
|
12
|
+
s.add_runtime_dependency 'addressable', '>= 2.7', '< 3'
|
|
13
|
+
s.add_runtime_dependency 'rubyzip', '>= 2.3', '< 4'
|
|
14
|
+
s.add_development_dependency 'rake', '~> 13.4.2'
|
|
14
15
|
s.add_development_dependency 'test-unit', '~> 3.5.3'
|
|
15
16
|
s.add_development_dependency 'simplecov', '~> 0.21.2'
|
|
16
17
|
s.add_development_dependency 'yard', '~> 0.9.25'
|
|
17
|
-
s.add_development_dependency 'webmock', '~> 3.
|
|
18
|
-
s.add_development_dependency 'rexml', '~> 3.
|
|
18
|
+
s.add_development_dependency 'webmock', '~> 3.26.2'
|
|
19
|
+
s.add_development_dependency 'rexml', '~> 3.4.4'
|
|
19
20
|
end
|
data/test/crate_test.rb
CHANGED
|
@@ -377,4 +377,33 @@ class CrateTest < Test::Unit::TestCase
|
|
|
377
377
|
assert_nil crate.get('#joe')
|
|
378
378
|
assert crate.get('#joehouse')
|
|
379
379
|
end
|
|
380
|
+
|
|
381
|
+
test 'defaults to RO-Crate spec 1.3' do
|
|
382
|
+
crate = ROCrate::Crate.new
|
|
383
|
+
assert_equal '1.3', crate.metadata.version
|
|
384
|
+
assert_equal 'https://w3id.org/ro/crate/1.3/context', crate.metadata.context
|
|
385
|
+
assert_equal 'https://w3id.org/ro/crate/1.3', crate.metadata.spec_url
|
|
386
|
+
assert_equal({ '@id' => 'https://w3id.org/ro/crate/1.3' }, crate.metadata.properties['conformsTo'])
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
test 'can write older spec version' do
|
|
390
|
+
crate = ROCrate::Crate.new(ROCrate::Crate::IDENTIFIER, {}, version: '1.1')
|
|
391
|
+
assert_equal '1.1', crate.metadata.version
|
|
392
|
+
assert_equal 'https://w3id.org/ro/crate/1.1/context', crate.metadata.context
|
|
393
|
+
assert_equal({ '@id' => 'https://w3id.org/ro/crate/1.1' }, crate.metadata.properties['conformsTo'])
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
test 'warns but accepts unrecognized spec version' do
|
|
397
|
+
original_stderr = $stderr
|
|
398
|
+
begin
|
|
399
|
+
$stderr = StringIO.new
|
|
400
|
+
crate = ROCrate::Crate.new(ROCrate::Crate::IDENTIFIER, {}, version: '1.5')
|
|
401
|
+
err = $stderr.string
|
|
402
|
+
assert_match(/Unrecognized RO-Crate version/, err)
|
|
403
|
+
assert_equal '1.5', crate.metadata.version
|
|
404
|
+
assert_equal 'https://w3id.org/ro/crate/1.5', crate.metadata.spec_url
|
|
405
|
+
ensure
|
|
406
|
+
$stderr = original_stderr
|
|
407
|
+
end
|
|
408
|
+
end
|
|
380
409
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I have spaces in my name
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://w3id.org/ro/crate/1.2/context",
|
|
3
|
+
"@graph": [
|
|
4
|
+
{
|
|
5
|
+
"@id": "ro-crate-metadata.json",
|
|
6
|
+
"@type": "CreativeWork",
|
|
7
|
+
"about": {
|
|
8
|
+
"@id": "./"
|
|
9
|
+
},
|
|
10
|
+
"conformsTo": {
|
|
11
|
+
"@id": "https://w3id.org/ro/crate/1.2"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"@id": "ro-crate-preview.html",
|
|
16
|
+
"@type": "CreativeWork",
|
|
17
|
+
"about": {
|
|
18
|
+
"@id": "./"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"@id": "./",
|
|
23
|
+
"@type": "Dataset",
|
|
24
|
+
"hasPart": [
|
|
25
|
+
{
|
|
26
|
+
"@id": "http://example.com/external_ref.txt"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"@id": "file%20with%20spaces.txt"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"@id": "http://example.com/external_ref.txt",
|
|
35
|
+
"@type": "File"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"@id": "file%20with%20spaces.txt",
|
|
39
|
+
"@type": "File"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<title>New RO-Crate</title>
|
|
6
|
+
<script type="application/ld+json">{
|
|
7
|
+
"@context": "https://w3id.org/ro/crate/1.2/context",
|
|
8
|
+
"@graph": [
|
|
9
|
+
{
|
|
10
|
+
"@id": "ro-crate-metadata.json",
|
|
11
|
+
"@type": "CreativeWork",
|
|
12
|
+
"about": {
|
|
13
|
+
"@id": "./"
|
|
14
|
+
},
|
|
15
|
+
"conformsTo": {
|
|
16
|
+
"@id": "https://w3id.org/ro/crate/1.2"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"@id": "ro-crate-preview.html",
|
|
21
|
+
"@type": "CreativeWork",
|
|
22
|
+
"about": {
|
|
23
|
+
"@id": "./"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"@id": "./",
|
|
28
|
+
"@type": "Dataset",
|
|
29
|
+
"hasPart": [
|
|
30
|
+
{
|
|
31
|
+
"@id": "http://example.com/external_ref.txt"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"@id": "file%20with%20spaces.txt"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"@id": "http://example.com/external_ref.txt",
|
|
40
|
+
"@type": "File"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"@id": "file%20with%20spaces.txt",
|
|
44
|
+
"@type": "File"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}</script>
|
|
48
|
+
<meta name="generator" content="https://github.com/ResearchObject/ro-crate-ruby">
|
|
49
|
+
<meta name="keywords" content="RO-Crate">
|
|
50
|
+
<meta charset="utf-8">
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<h1>New RO-Crate</h1>
|
|
54
|
+
|
|
55
|
+
<p>
|
|
56
|
+
|
|
57
|
+
</p>
|
|
58
|
+
<dl>
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
</dl>
|
|
64
|
+
|
|
65
|
+
<h2>Contents</h2>
|
|
66
|
+
<ul>
|
|
67
|
+
|
|
68
|
+
<li>
|
|
69
|
+
<strong><a href="http://example.com/external_ref.txt" target="_blank">http://example.com/external_ref.txt</a></strong>
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
</li>
|
|
73
|
+
|
|
74
|
+
<li>
|
|
75
|
+
<strong>file%20with%20spaces.txt</strong>
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
</li>
|
|
79
|
+
|
|
80
|
+
</ul>
|
|
81
|
+
</body>
|
|
82
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I have spaces in my name
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://w3id.org/ro/crate/1.3/context",
|
|
3
|
+
"@graph": [
|
|
4
|
+
{
|
|
5
|
+
"@id": "ro-crate-metadata.json",
|
|
6
|
+
"@type": "CreativeWork",
|
|
7
|
+
"about": {
|
|
8
|
+
"@id": "./"
|
|
9
|
+
},
|
|
10
|
+
"conformsTo": {
|
|
11
|
+
"@id": "https://w3id.org/ro/crate/1.3"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"@id": "ro-crate-preview.html",
|
|
16
|
+
"@type": "CreativeWork",
|
|
17
|
+
"about": {
|
|
18
|
+
"@id": "./"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"@id": "./",
|
|
23
|
+
"@type": "Dataset",
|
|
24
|
+
"hasPart": [
|
|
25
|
+
{
|
|
26
|
+
"@id": "http://example.com/external_ref.txt"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"@id": "file%20with%20spaces.txt"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"@id": "http://example.com/external_ref.txt",
|
|
35
|
+
"@type": "File"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"@id": "file%20with%20spaces.txt",
|
|
39
|
+
"@type": "File"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<title>New RO-Crate</title>
|
|
6
|
+
<script type="application/ld+json">{
|
|
7
|
+
"@context": "https://w3id.org/ro/crate/1.3/context",
|
|
8
|
+
"@graph": [
|
|
9
|
+
{
|
|
10
|
+
"@id": "ro-crate-metadata.json",
|
|
11
|
+
"@type": "CreativeWork",
|
|
12
|
+
"about": {
|
|
13
|
+
"@id": "./"
|
|
14
|
+
},
|
|
15
|
+
"conformsTo": {
|
|
16
|
+
"@id": "https://w3id.org/ro/crate/1.3"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"@id": "ro-crate-preview.html",
|
|
21
|
+
"@type": "CreativeWork",
|
|
22
|
+
"about": {
|
|
23
|
+
"@id": "./"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"@id": "./",
|
|
28
|
+
"@type": "Dataset",
|
|
29
|
+
"hasPart": [
|
|
30
|
+
{
|
|
31
|
+
"@id": "http://example.com/external_ref.txt"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"@id": "file%20with%20spaces.txt"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"@id": "http://example.com/external_ref.txt",
|
|
40
|
+
"@type": "File"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"@id": "file%20with%20spaces.txt",
|
|
44
|
+
"@type": "File"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}</script>
|
|
48
|
+
<meta name="generator" content="https://github.com/ResearchObject/ro-crate-ruby">
|
|
49
|
+
<meta name="keywords" content="RO-Crate">
|
|
50
|
+
<meta charset="utf-8">
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<h1>New RO-Crate</h1>
|
|
54
|
+
|
|
55
|
+
<p>
|
|
56
|
+
|
|
57
|
+
</p>
|
|
58
|
+
<dl>
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
</dl>
|
|
64
|
+
|
|
65
|
+
<h2>Contents</h2>
|
|
66
|
+
<ul>
|
|
67
|
+
|
|
68
|
+
<li>
|
|
69
|
+
<strong><a href="http://example.com/external_ref.txt" target="_blank">http://example.com/external_ref.txt</a></strong>
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
</li>
|
|
73
|
+
|
|
74
|
+
<li>
|
|
75
|
+
<strong>file%20with%20spaces.txt</strong>
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
</li>
|
|
79
|
+
|
|
80
|
+
</ul>
|
|
81
|
+
</body>
|
|
82
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/test/reader_test.rb
CHANGED
|
@@ -188,6 +188,48 @@ class ReaderTest < Test::Unit::TestCase
|
|
|
188
188
|
assert crate.preview.source.source.is_a?(ROCrate::PreviewGenerator)
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
+
test 'can read a 1.2 spec crate' do
|
|
192
|
+
stub_request(:get, "http://example.com/external_ref.txt").to_return(status: 200, body: 'file contents')
|
|
193
|
+
|
|
194
|
+
crate = ROCrate::Reader.read_directory(fixture_file('crate-spec1.2').path)
|
|
195
|
+
file = crate.dereference('file with spaces.txt')
|
|
196
|
+
assert file
|
|
197
|
+
assert file.is_a?(ROCrate::File)
|
|
198
|
+
refute file.remote?
|
|
199
|
+
assert file.source.is_a?(ROCrate::Entry)
|
|
200
|
+
assert_equal 'file%20with%20spaces.txt', file.id
|
|
201
|
+
|
|
202
|
+
ext_file = crate.dereference('http://example.com/external_ref.txt')
|
|
203
|
+
assert ext_file
|
|
204
|
+
assert ext_file.is_a?(ROCrate::File)
|
|
205
|
+
assert ext_file.remote?
|
|
206
|
+
assert ext_file.source.is_a?(ROCrate::RemoteEntry)
|
|
207
|
+
assert_equal 'http://example.com/external_ref.txt', ext_file.id
|
|
208
|
+
assert_equal 'file contents', ext_file.source.read
|
|
209
|
+
assert crate.preview.source.source.is_a?(Pathname)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
test 'can read a 1.3 spec crate' do
|
|
213
|
+
stub_request(:get, "http://example.com/external_ref.txt").to_return(status: 200, body: 'file contents')
|
|
214
|
+
|
|
215
|
+
crate = ROCrate::Reader.read_directory(fixture_file('crate-spec1.3').path)
|
|
216
|
+
file = crate.dereference('file with spaces.txt')
|
|
217
|
+
assert file
|
|
218
|
+
assert file.is_a?(ROCrate::File)
|
|
219
|
+
refute file.remote?
|
|
220
|
+
assert file.source.is_a?(ROCrate::Entry)
|
|
221
|
+
assert_equal 'file%20with%20spaces.txt', file.id
|
|
222
|
+
|
|
223
|
+
ext_file = crate.dereference('http://example.com/external_ref.txt')
|
|
224
|
+
assert ext_file
|
|
225
|
+
assert ext_file.is_a?(ROCrate::File)
|
|
226
|
+
assert ext_file.remote?
|
|
227
|
+
assert ext_file.source.is_a?(ROCrate::RemoteEntry)
|
|
228
|
+
assert_equal 'http://example.com/external_ref.txt', ext_file.id
|
|
229
|
+
assert_equal 'file contents', ext_file.source.read
|
|
230
|
+
assert crate.preview.source.source.is_a?(Pathname)
|
|
231
|
+
end
|
|
232
|
+
|
|
191
233
|
test 'reading from directory with unlisted files' do
|
|
192
234
|
crate = ROCrate::Reader.read_directory(fixture_file('sparse_directory_crate').path)
|
|
193
235
|
|
|
@@ -358,6 +400,11 @@ class ReaderTest < Test::Unit::TestCase
|
|
|
358
400
|
ROCrate::Reader.read(fixture_file('broken/missing_file'))
|
|
359
401
|
end
|
|
360
402
|
assert_include e.message, 'not found in crate: file1.txt'
|
|
403
|
+
|
|
404
|
+
e = check_exception(ROCrate::ReadException) do
|
|
405
|
+
ROCrate::Reader.read(fixture_file('just_a_zip.zip').path)
|
|
406
|
+
end
|
|
407
|
+
assert_include e.message, 'No metadata found'
|
|
361
408
|
end
|
|
362
409
|
|
|
363
410
|
test 'tolerates arcp identifier on root data entity (and missing hasPart)' do
|
|
@@ -381,18 +428,56 @@ class ReaderTest < Test::Unit::TestCase
|
|
|
381
428
|
assert_equal 'a_file', data.first.name
|
|
382
429
|
end
|
|
383
430
|
|
|
384
|
-
|
|
431
|
+
test 'protect against zip-slip' do
|
|
432
|
+
Dir.mktmpdir do |dir|
|
|
433
|
+
subdir = ::File.join(dir, 'subdir')
|
|
434
|
+
::Dir.mkdir(subdir)
|
|
435
|
+
|
|
436
|
+
# Relative
|
|
437
|
+
e = check_exception(ROCrate::ReadException) do
|
|
438
|
+
ROCrate::Reader.unzip_file_to(fixture_file('unsafe/relative0.zip').path, subdir)
|
|
439
|
+
end
|
|
440
|
+
assert_include e.message, 'Unsafe path in zip entry: ../moo'
|
|
441
|
+
refute ::File.exist?(::File.join(dir, 'moo'))
|
|
442
|
+
|
|
443
|
+
e = check_exception(ROCrate::ReadException) do
|
|
444
|
+
ROCrate::Reader.unzip_io_to(fixture_file('unsafe/relative0.zip'), subdir)
|
|
445
|
+
end
|
|
446
|
+
assert_include e.message, 'Unsafe path in zip entry: ../moo'
|
|
447
|
+
refute ::File.exist?(::File.join(dir, 'moo'))
|
|
448
|
+
|
|
449
|
+
# Absolute
|
|
450
|
+
e = check_exception(ROCrate::ReadException) do
|
|
451
|
+
ROCrate::Reader.unzip_file_to(fixture_file('unsafe/absolute1.zip').path, subdir)
|
|
452
|
+
end
|
|
453
|
+
assert_include e.message, 'Unsafe path in zip entry: /tmp/moo'
|
|
385
454
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
455
|
+
e = check_exception(ROCrate::ReadException) do
|
|
456
|
+
ROCrate::Reader.unzip_io_to(fixture_file('unsafe/absolute1.zip'), subdir)
|
|
457
|
+
end
|
|
458
|
+
assert_include e.message, 'Unsafe path in zip entry: /tmp/moo'
|
|
459
|
+
|
|
460
|
+
# Simulate ArgumentError in safe_join
|
|
389
461
|
begin
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
462
|
+
original_expand_path = Pathname.instance_method(:expand_path)
|
|
463
|
+
Pathname.define_method(:expand_path) do |*args|
|
|
464
|
+
raise ArgumentError, 'Oh no'
|
|
465
|
+
end
|
|
466
|
+
e = check_exception(ROCrate::ReadException) do
|
|
467
|
+
ROCrate::Reader.unzip_file_to(fixture_file('unsafe/absolute1.zip').path, subdir)
|
|
468
|
+
end
|
|
469
|
+
assert_include e.message, 'Unsafe path in zip entry: /tmp/moo'
|
|
470
|
+
ensure
|
|
471
|
+
Pathname.define_method(:expand_path, original_expand_path)
|
|
393
472
|
end
|
|
394
473
|
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
test 'reads spec 1.1 RO-Crate and preserves version' do
|
|
477
|
+
crate = ROCrate::Reader.read(fixture_file('crate-spec1.1').path)
|
|
395
478
|
|
|
396
|
-
|
|
479
|
+
assert_equal '1.1', crate.metadata.version
|
|
480
|
+
assert_equal 'https://w3id.org/ro/crate/1.1', crate.metadata.spec_url
|
|
481
|
+
assert_equal 'https://w3id.org/ro/crate/1.1/context', crate.metadata.context_url
|
|
397
482
|
end
|
|
398
483
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -5,10 +5,37 @@ require 'test/unit'
|
|
|
5
5
|
require 'ro_crate'
|
|
6
6
|
require 'webmock/test_unit'
|
|
7
7
|
|
|
8
|
+
class Test::Unit::TestCase
|
|
9
|
+
def teardown
|
|
10
|
+
self._opened_files.each do |f|
|
|
11
|
+
f.close unless f.closed?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def _opened_files
|
|
16
|
+
@opened_files ||= []
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
def fixture_file(name, *args)
|
|
9
|
-
::File.open(::File.join(fixture_dir, name), *args)
|
|
21
|
+
f = ::File.open(::File.join(fixture_dir, name), *args)
|
|
22
|
+
self._opened_files << f
|
|
23
|
+
f
|
|
10
24
|
end
|
|
11
25
|
|
|
12
26
|
def fixture_dir
|
|
13
27
|
::File.join(::File.dirname(__FILE__), 'fixtures')
|
|
14
28
|
end
|
|
29
|
+
|
|
30
|
+
def check_exception(exception_class)
|
|
31
|
+
e = nil
|
|
32
|
+
assert_raise(exception_class) do
|
|
33
|
+
begin
|
|
34
|
+
yield
|
|
35
|
+
rescue exception_class => e
|
|
36
|
+
raise e
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
e
|
|
41
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ro-crate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Finn Bacall
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: addressable
|
|
@@ -19,7 +18,7 @@ dependencies:
|
|
|
19
18
|
version: '2.7'
|
|
20
19
|
- - "<"
|
|
21
20
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '
|
|
21
|
+
version: '3'
|
|
23
22
|
type: :runtime
|
|
24
23
|
prerelease: false
|
|
25
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -29,35 +28,41 @@ dependencies:
|
|
|
29
28
|
version: '2.7'
|
|
30
29
|
- - "<"
|
|
31
30
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
31
|
+
version: '3'
|
|
33
32
|
- !ruby/object:Gem::Dependency
|
|
34
33
|
name: rubyzip
|
|
35
34
|
requirement: !ruby/object:Gem::Requirement
|
|
36
35
|
requirements:
|
|
37
|
-
- - "
|
|
36
|
+
- - ">="
|
|
38
37
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 2.
|
|
38
|
+
version: '2.3'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '4'
|
|
40
42
|
type: :runtime
|
|
41
43
|
prerelease: false
|
|
42
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
45
|
requirements:
|
|
44
|
-
- - "
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '2.3'
|
|
49
|
+
- - "<"
|
|
45
50
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
51
|
+
version: '4'
|
|
47
52
|
- !ruby/object:Gem::Dependency
|
|
48
53
|
name: rake
|
|
49
54
|
requirement: !ruby/object:Gem::Requirement
|
|
50
55
|
requirements:
|
|
51
56
|
- - "~>"
|
|
52
57
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 13.
|
|
58
|
+
version: 13.4.2
|
|
54
59
|
type: :development
|
|
55
60
|
prerelease: false
|
|
56
61
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
62
|
requirements:
|
|
58
63
|
- - "~>"
|
|
59
64
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 13.
|
|
65
|
+
version: 13.4.2
|
|
61
66
|
- !ruby/object:Gem::Dependency
|
|
62
67
|
name: test-unit
|
|
63
68
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -106,29 +111,28 @@ dependencies:
|
|
|
106
111
|
requirements:
|
|
107
112
|
- - "~>"
|
|
108
113
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 3.
|
|
114
|
+
version: 3.26.2
|
|
110
115
|
type: :development
|
|
111
116
|
prerelease: false
|
|
112
117
|
version_requirements: !ruby/object:Gem::Requirement
|
|
113
118
|
requirements:
|
|
114
119
|
- - "~>"
|
|
115
120
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: 3.
|
|
121
|
+
version: 3.26.2
|
|
117
122
|
- !ruby/object:Gem::Dependency
|
|
118
123
|
name: rexml
|
|
119
124
|
requirement: !ruby/object:Gem::Requirement
|
|
120
125
|
requirements:
|
|
121
126
|
- - "~>"
|
|
122
127
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: 3.
|
|
128
|
+
version: 3.4.4
|
|
124
129
|
type: :development
|
|
125
130
|
prerelease: false
|
|
126
131
|
version_requirements: !ruby/object:Gem::Requirement
|
|
127
132
|
requirements:
|
|
128
133
|
- - "~>"
|
|
129
134
|
- !ruby/object:Gem::Version
|
|
130
|
-
version: 3.
|
|
131
|
-
description:
|
|
135
|
+
version: 3.4.4
|
|
132
136
|
email: finn.bacall@manchester.ac.uk
|
|
133
137
|
executables: []
|
|
134
138
|
extensions: []
|
|
@@ -181,6 +185,12 @@ files:
|
|
|
181
185
|
- test/fixtures/conflicting_data_directory/nested.txt
|
|
182
186
|
- test/fixtures/crate-spec1.1/file with spaces.txt
|
|
183
187
|
- test/fixtures/crate-spec1.1/ro-crate-metadata.json
|
|
188
|
+
- test/fixtures/crate-spec1.2/file with spaces.txt
|
|
189
|
+
- test/fixtures/crate-spec1.2/ro-crate-metadata.json
|
|
190
|
+
- test/fixtures/crate-spec1.2/ro-crate-preview.html
|
|
191
|
+
- test/fixtures/crate-spec1.3/file with spaces.txt
|
|
192
|
+
- test/fixtures/crate-spec1.3/ro-crate-metadata.json
|
|
193
|
+
- test/fixtures/crate-spec1.3/ro-crate-preview.html
|
|
184
194
|
- test/fixtures/data.csv
|
|
185
195
|
- test/fixtures/dir_symlink
|
|
186
196
|
- test/fixtures/directory.zip
|
|
@@ -200,6 +210,7 @@ files:
|
|
|
200
210
|
- test/fixtures/directory_crate/ro-crate-preview.html
|
|
201
211
|
- test/fixtures/file with spaces.txt
|
|
202
212
|
- test/fixtures/info.txt
|
|
213
|
+
- test/fixtures/just_a_zip.zip
|
|
203
214
|
- test/fixtures/misc_data_entity_crate/ro-crate-metadata.json
|
|
204
215
|
- test/fixtures/multi_metadata_crate.crate.zip
|
|
205
216
|
- test/fixtures/nested_directory.zip
|
|
@@ -232,6 +243,8 @@ files:
|
|
|
232
243
|
- test/fixtures/unlinked_entity_crate/test/test1/input.bed
|
|
233
244
|
- test/fixtures/unlinked_entity_crate/test/test1/output_exp.bed
|
|
234
245
|
- test/fixtures/unlinked_entity_crate/test/test1/sort-and-change-case-test.yml
|
|
246
|
+
- test/fixtures/unsafe/absolute1.zip
|
|
247
|
+
- test/fixtures/unsafe/relative0.zip
|
|
235
248
|
- test/fixtures/uri_heavy_crate/main.nf
|
|
236
249
|
- test/fixtures/uri_heavy_crate/ro-crate-metadata.json
|
|
237
250
|
- test/fixtures/uri_heavy_crate/ro-crate-preview.html
|
|
@@ -2473,7 +2486,6 @@ homepage: https://github.com/ResearchObject/ro-crate-ruby
|
|
|
2473
2486
|
licenses:
|
|
2474
2487
|
- MIT
|
|
2475
2488
|
metadata: {}
|
|
2476
|
-
post_install_message:
|
|
2477
2489
|
rdoc_options: []
|
|
2478
2490
|
require_paths:
|
|
2479
2491
|
- lib
|
|
@@ -2481,15 +2493,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
2481
2493
|
requirements:
|
|
2482
2494
|
- - ">="
|
|
2483
2495
|
- !ruby/object:Gem::Version
|
|
2484
|
-
version:
|
|
2496
|
+
version: 2.7.0
|
|
2485
2497
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
2486
2498
|
requirements:
|
|
2487
2499
|
- - ">="
|
|
2488
2500
|
- !ruby/object:Gem::Version
|
|
2489
2501
|
version: '0'
|
|
2490
2502
|
requirements: []
|
|
2491
|
-
rubygems_version: 3.
|
|
2492
|
-
signing_key:
|
|
2503
|
+
rubygems_version: 3.6.9
|
|
2493
2504
|
specification_version: 4
|
|
2494
2505
|
summary: Create, manipulate, read RO-Crates.
|
|
2495
2506
|
test_files: []
|