valkyrie-shrine 1.0.0 → 1.1.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/README.md +16 -3
- data/circle.yml +1 -0
- data/lib/valkyrie/shrine/storage/s3.rb +64 -0
- data/lib/valkyrie/shrine/version.rb +1 -1
- data/lib/valkyrie/shrine.rb +2 -0
- data/lib/valkyrie/storage/shrine.rb +33 -11
- data/lib/valkyrie/storage/versioned_shrine.rb +181 -0
- data/valkyrie-shrine.gemspec +1 -1
- metadata +19 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3422215c665f0b4a25b59b9d62537318f364e1c5522bd8b352de0f92e7c1a03
|
|
4
|
+
data.tar.gz: e5e537adc20cb7c9f5ca8f1382148263c9631935136de7ac5f9a5998051c7ee2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba9e4ac128bb0cf59ea04cd825dac307decda1b1ad97b21f4fb46e8373d0714d91be79f31f511cb5bb680db126b2ea28117f62d243510d6bcec1c85e8df6fb77
|
|
7
|
+
data.tar.gz: 5a6a6d9e534cbf4ef8ec561a2a3c569e93862f9b64d2c9f7236ab54428e0a73b2609862c27b05a9fbf340ef714f28facf11d76a74024753873b7247b9f5ede22
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[Shrine](http://shrinerb.com/) storage adapter for [Valkyrie](https://github.com/samvera-labs/valkyrie).
|
|
4
4
|
|
|
5
5
|
[](https://circleci.com/gh/samvera-labs/valkyrie-shrine)
|
|
6
|
-
|
|
6
|
+

|
|
7
7
|
|
|
8
8
|
## Installation
|
|
9
9
|
|
|
@@ -21,8 +21,9 @@ Follow the Valkyrie [README](https://github.com/samvera-labs/valkyrie) to get a
|
|
|
21
21
|
# config/initializers/valkyrie.rb
|
|
22
22
|
require 'shrine/storage/s3'
|
|
23
23
|
require 'shrine/storage/file_system'
|
|
24
|
-
require 'valkyrie/
|
|
25
|
-
require 'valkyrie/
|
|
24
|
+
require 'valkyrie/shrine/checksum/s3'
|
|
25
|
+
require 'valkyrie/shrine/checksum/file_system'
|
|
26
|
+
require 'valkyrie/shrine/storage/s3'
|
|
26
27
|
|
|
27
28
|
Shrine.storages = {
|
|
28
29
|
file: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),
|
|
@@ -36,6 +37,18 @@ Follow the Valkyrie [README](https://github.com/samvera-labs/valkyrie) to get a
|
|
|
36
37
|
Valkyrie::StorageAdapter.register(
|
|
37
38
|
Valkyrie::Storage::Shrine.new(Shrine.storages[:file]), :disk
|
|
38
39
|
)
|
|
40
|
+
|
|
41
|
+
s3_options = {
|
|
42
|
+
access_key_id: s3_access_key,
|
|
43
|
+
bucket: s3_bucket,
|
|
44
|
+
endpoint: s3_endpoint,
|
|
45
|
+
force_path_style: force_path_style,
|
|
46
|
+
region: s3_region,
|
|
47
|
+
secret_access_key: s3_secret_key
|
|
48
|
+
}
|
|
49
|
+
Valkyrie::StorageAdapter.register(
|
|
50
|
+
Valkyrie::Storage::VersionedShrine.new(Valkyrie::Shrine::Storage::S3.new(**s3_options)), :versioned_s3
|
|
51
|
+
)
|
|
39
52
|
```
|
|
40
53
|
|
|
41
54
|
Then proceed to configure your application following the [Valkyrie documentation](https://github.com/samvera-labs/valkyrie#sample-configuration-configvalkyrieyml)
|
data/circle.yml
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "shrine/storage/s3"
|
|
4
|
+
|
|
5
|
+
module Valkyrie
|
|
6
|
+
module Shrine
|
|
7
|
+
module Storage
|
|
8
|
+
class S3 < ::Shrine::Storage::S3
|
|
9
|
+
# List objects that are starting with a given prefix.
|
|
10
|
+
# This is helpful for versioned files that have a common file identifier.
|
|
11
|
+
# Need to make sure to combine with storage prefix.
|
|
12
|
+
# list_objects(id_prefix: "some/object/id")
|
|
13
|
+
# @param id_prefix [String] - object's id that starts with
|
|
14
|
+
# @return [Array(Aws::S3::Object)]
|
|
15
|
+
def list_objects(id_prefix:)
|
|
16
|
+
aws_prefix = [*prefix, id_prefix].join("/")
|
|
17
|
+
bucket.objects(prefix: aws_prefix)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# List objects id's that are starting with a given prefix.
|
|
21
|
+
# This is helpful for versioned files that have a common file identifier.
|
|
22
|
+
# Need to make sure to combine with storage prefix.
|
|
23
|
+
# list_object_ids(id_prefix: "some/object/id")
|
|
24
|
+
# @param id_prefix [String] - object's id that starts with
|
|
25
|
+
# @return [Array(String)]
|
|
26
|
+
def list_object_ids(id_prefix:)
|
|
27
|
+
objects = list_objects(id_prefix: id_prefix)
|
|
28
|
+
object_ids_for(objects)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Move a file to a another location.
|
|
32
|
+
# @param id [String] - the id of the source file
|
|
33
|
+
# @param destination_id [String] - the id of the destination file
|
|
34
|
+
# @param destination_bucket [String] - the bucket name of the destination
|
|
35
|
+
# @return [String]
|
|
36
|
+
def move_to(id:, destination_id:, destination_bucket: bucket.name)
|
|
37
|
+
source_object = Aws::S3::Object.new(bucket.name, object_key(id), client: client)
|
|
38
|
+
destination_key = "#{destination_bucket}/#{object_key(destination_id)}"
|
|
39
|
+
source_object.move_to(destination_key)
|
|
40
|
+
destination_key
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Deletes all objects in fewest requests possible.
|
|
44
|
+
# @see +super#delete_objects(objects)+.
|
|
45
|
+
# @return [Array(string)] List of object id's that are deleted
|
|
46
|
+
def delete_objects(objects)
|
|
47
|
+
super
|
|
48
|
+
object_ids_for(objects)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# @ return list of object id's
|
|
54
|
+
# @param objects [Array(Aws::S3::Object)]
|
|
55
|
+
def object_ids_for(objects)
|
|
56
|
+
keys = objects.map(&:key)
|
|
57
|
+
return keys if prefix.blank?
|
|
58
|
+
|
|
59
|
+
keys.map { |k| k.delete_prefix("#{prefix}/") }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/valkyrie/shrine.rb
CHANGED
|
@@ -5,6 +5,8 @@ require 'valkyrie/storage/shrine'
|
|
|
5
5
|
require 'valkyrie/shrine/checksum/base'
|
|
6
6
|
require 'valkyrie/shrine/checksum/file_system'
|
|
7
7
|
require 'valkyrie/shrine/checksum/s3'
|
|
8
|
+
require 'valkyrie/shrine/storage/s3'
|
|
9
|
+
require 'valkyrie/storage/versioned_shrine'
|
|
8
10
|
|
|
9
11
|
module Valkyrie
|
|
10
12
|
module Shrine
|
|
@@ -69,16 +69,9 @@ module Valkyrie
|
|
|
69
69
|
# @raise Valkyrie::Shrine::IntegrityError if #verify_checksum is defined
|
|
70
70
|
# on the shrine object and the file and result digests do not match
|
|
71
71
|
def upload(file:, original_filename:, resource:, **upload_options)
|
|
72
|
-
# S3 adapter validates options, so we have to remove this one used in
|
|
73
|
-
# the shared specs.
|
|
74
|
-
upload_options.delete(:fake_upload_argument)
|
|
75
72
|
identifier = path_generator.generate(resource: resource, file: file, original_filename: original_filename).to_s
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if verifier
|
|
79
|
-
raise Valkyrie::Shrine::IntegrityError unless verifier.verify_checksum(file, result)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
73
|
+
|
|
74
|
+
upload_file(file: file, identifier: identifier, **upload_options)
|
|
82
75
|
end
|
|
83
76
|
|
|
84
77
|
# Return the file associated with the given identifier
|
|
@@ -88,8 +81,6 @@ module Valkyrie
|
|
|
88
81
|
def find_by(id:)
|
|
89
82
|
raise Valkyrie::StorageAdapter::FileNotFound unless shrine.exists?(shrine_id_for(id))
|
|
90
83
|
Valkyrie::StorageAdapter::StreamFile.new(id: Valkyrie::ID.new(id.to_s), io: DelayedDownload.new(shrine, shrine_id_for(id)))
|
|
91
|
-
rescue Aws::S3::Errors::NoSuchKey
|
|
92
|
-
raise Valkyrie::StorageAdapter::FileNotFound
|
|
93
84
|
end
|
|
94
85
|
|
|
95
86
|
# @param id [Valkyrie::ID]
|
|
@@ -104,8 +95,39 @@ module Valkyrie
|
|
|
104
95
|
shrine.delete(shrine_id_for(id))
|
|
105
96
|
end
|
|
106
97
|
|
|
98
|
+
# @param _feature [Symbol] Feature to test for.
|
|
99
|
+
# @return [Boolean] true if the adapter supports the given feature
|
|
100
|
+
def supports?(_feature)
|
|
101
|
+
false
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @return [String] identifier prefix
|
|
105
|
+
def protocol
|
|
106
|
+
protocol_with_prefix
|
|
107
|
+
end
|
|
108
|
+
|
|
107
109
|
private
|
|
108
110
|
|
|
111
|
+
# Upload file with a given shrine object idenfifier (without prefix #protocol_with_prefix)
|
|
112
|
+
# @param file [IO]
|
|
113
|
+
# @param original_filename [String]
|
|
114
|
+
# @param resource [Valkyrie::Resource]
|
|
115
|
+
# @return [Valkyrie::StorageAdapter::StreamFile]
|
|
116
|
+
# @raise Valkyrie::Shrine::IntegrityError if #verify_checksum is defined
|
|
117
|
+
# on the shrine object and the file and result digests do not match
|
|
118
|
+
def upload_file(file:, identifier:, **upload_options)
|
|
119
|
+
# S3 adapter validates options, so we have to remove this one used in
|
|
120
|
+
# the shared specs.
|
|
121
|
+
upload_options.delete(:fake_upload_argument)
|
|
122
|
+
|
|
123
|
+
shrine.upload(file, identifier, **upload_options)
|
|
124
|
+
find_by(id: "#{protocol_with_prefix}#{identifier}").tap do |result|
|
|
125
|
+
if verifier
|
|
126
|
+
raise Valkyrie::Shrine::IntegrityError unless verifier.verify_checksum(file, result)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
109
131
|
def try_to_find_verifier
|
|
110
132
|
class_const = shrine.class.name.split(/::/).last.to_sym
|
|
111
133
|
@verifier = Valkyrie::Shrine::Checksum.const_get(class_const).new if Valkyrie::Shrine::Checksum.const_defined?(class_const)
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Valkyrie
|
|
4
|
+
module Storage
|
|
5
|
+
# The VersionedShrine adapter implements versioned storage on S3 that manages versions
|
|
6
|
+
# through Shrine object id with a timestamp like shrine://[resource_id]/[UUID]/v-[timestamp].
|
|
7
|
+
#
|
|
8
|
+
# Example to use VersionedShrine storage adapter:
|
|
9
|
+
# shrine_s3_options = {
|
|
10
|
+
# access_key_id: s3_access_key,
|
|
11
|
+
# bucket: s3_bucket,
|
|
12
|
+
# endpoint: s3_endpoint,
|
|
13
|
+
# force_path_style: force_path_style,
|
|
14
|
+
# region: s3_region,
|
|
15
|
+
# secret_access_key: s3_secret_key
|
|
16
|
+
# }
|
|
17
|
+
# Valkyrie::StorageAdapter.register(
|
|
18
|
+
# Valkyrie::Storage::VersionedShrine.new(Valkyrie::Shrine::Storage::S3.new(**shrine_s3_options)),
|
|
19
|
+
# :s3_repository
|
|
20
|
+
# )
|
|
21
|
+
class VersionedShrine < Shrine
|
|
22
|
+
# @param feature [Symbol] Feature to test for.
|
|
23
|
+
# @return [Boolean] true if the adapter supports the given feature
|
|
24
|
+
def supports?(feature)
|
|
25
|
+
feature == :versions || feature == :version_deletion
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Retireve all files versions with no deletion marker that are associated from S3.
|
|
29
|
+
# @param id [Valkyrie::ID]
|
|
30
|
+
# @return [Array(Valkyrie::StorageAdapter::StreamFile)]
|
|
31
|
+
def find_versions(id:)
|
|
32
|
+
version_files(id: id).map { |f| find_by(id: f) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Retireve all file versions associated with the given identifier from S3
|
|
36
|
+
# @param id [Valkyrie::ID]
|
|
37
|
+
# @return [Array(Valkyrie::ID)] - list of file identifiers
|
|
38
|
+
def version_files(id:)
|
|
39
|
+
shrine.list_object_ids(id_prefix: shrine_id_for(id))
|
|
40
|
+
.sort
|
|
41
|
+
.reverse
|
|
42
|
+
.map { |v| Valkyrie::ID.new(protocol_with_prefix + v) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Upload a file via the VersionedShrine storage adapter with a version id assigned.
|
|
46
|
+
# @param file [IO]
|
|
47
|
+
# @param original_filename [String]
|
|
48
|
+
# @param resource [Valkyrie::Resource]
|
|
49
|
+
# @return [Valkyrie::StorageAdapter::StreamFile]
|
|
50
|
+
# @raise Valkyrie::Shrine::IntegrityError if #verify_checksum is defined
|
|
51
|
+
# on the shrine object and the file and result digests do not match
|
|
52
|
+
def upload(file:, original_filename:, resource:, **upload_options)
|
|
53
|
+
identifier = path_generator.generate(resource: resource, file: file, original_filename: original_filename)
|
|
54
|
+
perform_upload(id: "#{protocol_with_prefix}#{identifier}", file: file, **upload_options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Upload a new version file
|
|
58
|
+
# @param id [Valkyrie::ID] ID of the Valkyrie::StorageAdapter::File to version.
|
|
59
|
+
# @param file [IO]
|
|
60
|
+
def upload_version(id:, file:, **upload_options)
|
|
61
|
+
# For backward compatablity with files ingested in the past and we don't have to migrate it to versioned fies.
|
|
62
|
+
# If there is a file associated with the given identifier that is not a versioned file,
|
|
63
|
+
# simply convert it to a versioned file basing on last_modified time to keep all versioned files consistent.
|
|
64
|
+
migrate_to_versioned(id: id) if shrine.exists?(shrine_id_for(id))
|
|
65
|
+
|
|
66
|
+
perform_upload(id: id, file: file, **upload_options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Upload a file with a version id assigned.
|
|
70
|
+
# @param id [Valkyrie::ID] ID of the Valkyrie::StorageAdapter::File to version.
|
|
71
|
+
# @param file [IO]
|
|
72
|
+
# @return [Valkyrie::StorageAdapter::StreamFile]
|
|
73
|
+
# @raise Valkyrie::Shrine::IntegrityError if #verify_checksum is defined
|
|
74
|
+
def perform_upload(id:, file:, **upload_options)
|
|
75
|
+
shrine_id = shrine_id_for(VersionId.new(id).new_version)
|
|
76
|
+
upload_file(file: file, identifier: shrine_id, **upload_options)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Delete the versioned file or delete all versions in S3 associated with the given identifier.
|
|
80
|
+
# @param id [Valkyrie::ID]
|
|
81
|
+
# @return [Array(Valkyrie::ID)] - file id's that are deleted.
|
|
82
|
+
# @raise Valkyrie::StorageAdapter::FileNotFound if nothing is found
|
|
83
|
+
def delete(id:)
|
|
84
|
+
objects = objects_to_delete(id)
|
|
85
|
+
raise Valkyrie::StorageAdapter::FileNotFound if objects.blank?
|
|
86
|
+
|
|
87
|
+
shrine.delete_objects(objects)
|
|
88
|
+
.map { |obj_id| Valkyrie::ID.new(protocol_with_prefix + obj_id) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Find the file associated with the given version identifier
|
|
92
|
+
#
|
|
93
|
+
# Note: we need override it to use the latest version
|
|
94
|
+
# so that file characterization and derivative creation can use the latest file uploaded
|
|
95
|
+
# @param id [Valkyrie::ID]
|
|
96
|
+
# @return [Valkyrie::StorageAdapter::StreamFile]
|
|
97
|
+
# @raise Valkyrie::StorageAdapter::FileNotFound if nothing is found
|
|
98
|
+
def find_by(id:)
|
|
99
|
+
version_id = resolve_current(id)
|
|
100
|
+
|
|
101
|
+
raise Valkyrie::StorageAdapter::FileNotFound unless version_id && shrine.exists?(shrine_id_for(version_id.id))
|
|
102
|
+
Valkyrie::StorageAdapter::StreamFile.new(id: Valkyrie::ID.new(version_id.base_identifier),
|
|
103
|
+
io: DelayedDownload.new(shrine, shrine_id_for(version_id.id)),
|
|
104
|
+
version_id: version_id.id)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @return VersionId A VersionId value that's resolved to a current version,
|
|
108
|
+
# so we can access the latest version with a base identifier that is not a version.
|
|
109
|
+
def resolve_current(id)
|
|
110
|
+
version_id = VersionId.new(id)
|
|
111
|
+
return version_id if version_id.versioned?
|
|
112
|
+
version_files = version_files(id: Valkyrie::ID.new(version_id.base_identifier))
|
|
113
|
+
return nil if version_files.blank?
|
|
114
|
+
VersionId.new(Valkyrie::ID.new(version_files.first))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @param id [Valkyrie::ID]
|
|
118
|
+
# @return [Array(Aws::S3::Object)] list of objects
|
|
119
|
+
def objects_to_delete(id)
|
|
120
|
+
shrine_id = shrine_id_for(id)
|
|
121
|
+
version_id = VersionId.new(id)
|
|
122
|
+
return shrine.list_objects(id_prefix: shrine_id).to_a unless version_id.versioned?
|
|
123
|
+
|
|
124
|
+
shrine.exists?(shrine_id) ? [shrine.object(shrine_id)] : []
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Convert a non-versioned file to a version file basing on its last_modified time.
|
|
128
|
+
# @param id [Valkyrie::ID]
|
|
129
|
+
# @return [VerrsionId]
|
|
130
|
+
def migrate_to_versioned(id:)
|
|
131
|
+
shrine_id = shrine_id_for(id)
|
|
132
|
+
last_modified = shrine.object(shrine_id).last_modified
|
|
133
|
+
version_id = VersionId.new(id).new_version(timestamp: last_modified)
|
|
134
|
+
shrine.move_to(id: shrine_id, destination_id: shrine_id_for(version_id))
|
|
135
|
+
version_id
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# A class that holds a version id and methods for knowing things about it.
|
|
139
|
+
# Examples of version ids in this adapter:
|
|
140
|
+
# * shrine://[resource_id]/[uuid]/v-20250429142441274
|
|
141
|
+
#
|
|
142
|
+
# @note With '/' as path delimiter for versions like '/v-', there is an issue with MinIO
|
|
143
|
+
# that fails to list the version files if a file with a base identifier
|
|
144
|
+
# that is not a version exisits along with other versioned files associated with the base identifier.
|
|
145
|
+
class VersionId
|
|
146
|
+
VERSION_DELIMITER = "/v-"
|
|
147
|
+
|
|
148
|
+
attr_reader :id
|
|
149
|
+
def initialize(id)
|
|
150
|
+
@id = id
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Create new version identifier basing on the given identifier, which could be the original file identifier like
|
|
154
|
+
# shrine://[resource_id]/[uuid], or a version identifier like shrine://[resource_id]/[uuid]/v-20250429142441274.
|
|
155
|
+
# @param timestamp [Time]
|
|
156
|
+
# @return [String]
|
|
157
|
+
def new_version(timestamp: nil)
|
|
158
|
+
version_timestamp = (timestamp&.utc || Time.now.utc).strftime("%Y%m%d%H%M%S%L")
|
|
159
|
+
versioned? ? string_id.gsub(version, version_timestamp) : string_id + VERSION_DELIMITER + version_timestamp
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def versioned?
|
|
163
|
+
string_id.include?(VERSION_DELIMITER)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def version
|
|
167
|
+
string_id.split(VERSION_DELIMITER).last
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @return [String] The base identifier that is not a version
|
|
171
|
+
def base_identifier
|
|
172
|
+
string_id.split(VERSION_DELIMITER).first
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def string_id
|
|
176
|
+
id.to_s
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
data/valkyrie-shrine.gemspec
CHANGED
|
@@ -29,11 +29,11 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
|
|
30
30
|
spec.add_development_dependency 'bixby', '~> 2.0.0.pre.beta1'
|
|
31
31
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
32
|
-
spec.add_development_dependency 'coveralls', '~> 0.8.3'
|
|
33
32
|
spec.add_development_dependency 'pry'
|
|
34
33
|
spec.add_development_dependency 'pry-byebug'
|
|
35
34
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
|
36
35
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
37
36
|
spec.add_development_dependency 'simplecov'
|
|
38
37
|
spec.add_development_dependency 'actionpack'
|
|
38
|
+
spec.add_development_dependency 'webmock'
|
|
39
39
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: valkyrie-shrine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brendan Quinn
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-11-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-s3
|
|
@@ -86,20 +86,6 @@ dependencies:
|
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
88
|
version: '2.0'
|
|
89
|
-
- !ruby/object:Gem::Dependency
|
|
90
|
-
name: coveralls
|
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - "~>"
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: 0.8.3
|
|
96
|
-
type: :development
|
|
97
|
-
prerelease: false
|
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - "~>"
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: 0.8.3
|
|
103
89
|
- !ruby/object:Gem::Dependency
|
|
104
90
|
name: pry
|
|
105
91
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -184,6 +170,20 @@ dependencies:
|
|
|
184
170
|
- - ">="
|
|
185
171
|
- !ruby/object:Gem::Version
|
|
186
172
|
version: '0'
|
|
173
|
+
- !ruby/object:Gem::Dependency
|
|
174
|
+
name: webmock
|
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - ">="
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '0'
|
|
180
|
+
type: :development
|
|
181
|
+
prerelease: false
|
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - ">="
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '0'
|
|
187
187
|
description:
|
|
188
188
|
email:
|
|
189
189
|
- brendan-quinn@northwestern.edu
|
|
@@ -206,8 +206,10 @@ files:
|
|
|
206
206
|
- lib/valkyrie/shrine/checksum/base.rb
|
|
207
207
|
- lib/valkyrie/shrine/checksum/file_system.rb
|
|
208
208
|
- lib/valkyrie/shrine/checksum/s3.rb
|
|
209
|
+
- lib/valkyrie/shrine/storage/s3.rb
|
|
209
210
|
- lib/valkyrie/shrine/version.rb
|
|
210
211
|
- lib/valkyrie/storage/shrine.rb
|
|
212
|
+
- lib/valkyrie/storage/versioned_shrine.rb
|
|
211
213
|
- valkyrie-shrine.gemspec
|
|
212
214
|
homepage: https://github.com/samvera-labs/valkyrie-shrine
|
|
213
215
|
licenses:
|
|
@@ -228,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
228
230
|
- !ruby/object:Gem::Version
|
|
229
231
|
version: '0'
|
|
230
232
|
requirements: []
|
|
231
|
-
rubygems_version: 3.1
|
|
233
|
+
rubygems_version: 3.4.1
|
|
232
234
|
signing_key:
|
|
233
235
|
specification_version: 4
|
|
234
236
|
summary: Shrine storage adapter for Valkyrie
|