shrine-content_addressable 0.2.0 → 0.3.0

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
  SHA1:
3
- metadata.gz: 0a2e3d00b3be4739f5fcc1484c838bdedebef812
4
- data.tar.gz: eab756297c29f2e9b8f2232d944d4948a19479a9
3
+ metadata.gz: 48b7c5d303fd33194e6bf893237f6116c6e79a1e
4
+ data.tar.gz: a5cd20d76d9136773685b54861050012c1195950
5
5
  SHA512:
6
- metadata.gz: 6df1452483522aebedae8598595518af88f48f8f7ddbdb0ae53d5b4b3c32cd0105ba5c4e5fb12e0be838c84acc64bd7ba8d2b4987b878d1899d80b2124d97c40
7
- data.tar.gz: 0df1cb9d5688ac5d8385df5ed586c08567be451556d69e2f402f9aa0de2d21e59eddcae84184eecebd98f3cff90221c91920d2170a73e2cad7dacfa4eb002ddb
6
+ metadata.gz: f680433393ec5f045caff471e3fcdd89646f1c90bfdb0f3c4ed87ef5c4790e03e5b6b7d2b20347c8b8c47475f6006b9b581238a1338e580afefffdd1b5f44592
7
+ data.tar.gz: 81544f628c4899516449924a5f79aa70e426ab400b6bcac0c0c046bed5f3393c0172b4208c6399f8a3947690dad71a750d287d6b2050fc571fcdac79e0ab8967
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0
4
+
5
+ - Add read only (no mass deletion) for `ContentAddressableFile`.
6
+ - Add `#digest` and related functionality
7
+
3
8
  ## 0.2.0
4
9
  Add `ContentAddressableFile` for easy lookup
5
10
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # shrine-content_addressable
2
2
  [![Build Status](https://travis-ci.com/SleeplessByte/shrine-content_addressable.svg?branch=master)](https://travis-ci.com/SleeplessByte/content_addressable)
3
- [![Gem Version](https://badge.fury.io/rb/shrine-content_addressable.svg)](https://badge.fury.io/rb/content_addressable)
3
+ [![Gem Version](https://badge.fury.io/rb/shrine-content_addressable.svg)](https://badge.fury.io/rb/shrine-content_addressable)
4
4
  [![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
5
5
 
6
6
  Generate content addressable locations for shrine uploads.
@@ -55,6 +55,9 @@ require 'content_addressable_file'
55
55
  # You currently need to register the storages
56
56
  ContentAddressableFile.register_storage(lookup, lookup, lookup)
57
57
 
58
+ # You can disallow deletion using
59
+ ContentAddressableFile.register_read_only_storage(lookup, lookup, lookup)
60
+
58
61
  file = ContentAddressableFile.new(content_addressable_hash)
59
62
 
60
63
  # => file methods like open, rewind, read, close and eof? are available
@@ -1,17 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'English'
4
+ require 'multihashes'
5
+ require 'forwardable'
6
+
7
+ class ReadOnlyStorage
8
+ extend Forwardable
9
+ def_delegators :@storage, :exists?, :download, :url
10
+
11
+ def initialize(storage)
12
+ @storage = storage
13
+ end
14
+ end
4
15
 
5
16
  class ContentAddressableFile
6
17
 
7
18
  class << self
8
19
  attr_accessor :storages
9
20
 
21
+ # Registers a storage to be used with content-addressable file. All shrine
22
+ # storages are supported by default, as is any duck type that responds to
23
+ # Storage#open(content-addressable-hash) and Storage#exists?(hash).
24
+ #
25
+ # Additional functionality needs Storage#url(hash), Storage#delete(hash)
26
+ # and Storage#download(hash).
27
+ #
28
+ # When a content-addressable file is deleted, it's deleted from all
29
+ # registered storages. use #register_read_only_storage to prevent deletion.
30
+ #
10
31
  def register_storage(*storage)
11
32
  self.storages = Array(storages).push(*storage)
12
33
  self
13
34
  end
14
35
 
36
+ # Same as #register_storage, but only forwards read only methods.
37
+ def register_read_only_storage(*storage)
38
+ read_only = Array(storage).map { |s| ReadOnlyStorage.new(s) }
39
+ self.storages = Array(storages).push(*read_only)
40
+ self
41
+ end
42
+
43
+ # Removes all registered storages
15
44
  def reset
16
45
  self.storages = []
17
46
  self
@@ -20,10 +49,38 @@ class ContentAddressableFile
20
49
 
21
50
  attr_reader :id
22
51
 
52
+ # Creates a new content-addressable file wrapper that uses the given id as
53
+ # content hash, assuming that it is a content addressable multihash
54
+ #
55
+ # @param [String] id the multihash that is the content-addressable
56
+ #
23
57
  def initialize(id)
24
58
  self.id = id
25
59
  end
26
60
 
61
+ # Tries to decode the multihash. This is a good check to see if the given id
62
+ # is actually a content-addressable, but also easy to "fake", as the only way
63
+ # to be certain that the id is a content addressable is actually getting the
64
+ # file and hashing it again.
65
+ def decode
66
+ @decode ||= Multihashes.decode id
67
+ end
68
+
69
+ # The #deocode digest as a byte array
70
+ def digest
71
+ decode[:digest]
72
+ end
73
+
74
+ # The #decode digest length
75
+ def digest_length
76
+ decode[:length]
77
+ end
78
+
79
+ # The #decode hash function
80
+ def digest_hash_function
81
+ decode[:hash_function]
82
+ end
83
+
27
84
  # Calls `#open` on the storages to open the uploaded file for reading.
28
85
  # Most storages will return a lazy IO object which dynamically
29
86
  # retrieves file content from the storage as the object is being read.
@@ -34,6 +91,8 @@ class ContentAddressableFile
34
91
  #
35
92
  # If no block is given, the opened IO object is returned.
36
93
  #
94
+ # @example
95
+ #
37
96
  # content_addressable.open #=> IO object returned by the storage
38
97
  # content_addressable.read #=> "..."
39
98
  # content_addressable.close
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'shrine-content_addressable'
8
- spec.version = '0.2.0'
8
+ spec.version = '0.3.0'
9
9
  spec.authors = ['Derk-Jan Karrenbeld']
10
10
  spec.email = ['derk-jan+github@karrenbeld.info']
11
11
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine-content_addressable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derk-Jan Karrenbeld