stashify 3.1.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek.yml +4 -3
- data/.rubocop.yml +0 -3
- data/Gemfile +2 -0
- data/Gemfile.lock +5 -1
- data/README.md +94 -6
- data/lib/stashify/directory/local.rb +7 -1
- data/lib/stashify/directory.rb +113 -8
- data/lib/stashify/file/local.rb +4 -0
- data/lib/stashify/file.rb +67 -2
- data/lib/stashify/version.rb +1 -1
- data/lib/stashify.rb +2 -0
- data/stashify.gemspec +37 -0
- metadata +3 -3
- data/lib/stashify/local.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 035b4f42412c865a6fcabf7944cd6a49169034b974054e20a8eb67ea1f06a4a4
|
4
|
+
data.tar.gz: 4a393454a48b04bc1769fe29a3ea21fe5e4ce501c3443f903e777c7a44b8478e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f3f849fff674adea33a49fbd2c9495cda7d21a64690cf09a828800acfaea5e70cd223ba3400a785e7e8f44f8e1daa3fa5047a44a3de9c0bfe936b91a7099c91
|
7
|
+
data.tar.gz: a13e678a94cdf0844d3d537310af37a0f21e9b55075600cfe47ce186cabee8c52c3ff3981459a630ca7163c1e3d7664aa6b36d0390afe1cfd02df3fd8ed04e37
|
data/.reek.yml
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
detectors:
|
2
|
-
IrresponsibleModule:
|
3
|
-
enabled: false
|
4
|
-
|
5
2
|
TooManyStatements:
|
6
3
|
exclude:
|
7
4
|
- properties
|
@@ -19,3 +16,7 @@ detectors:
|
|
19
16
|
ControlParameter:
|
20
17
|
exclude:
|
21
18
|
- Stashify::Directory#initialize
|
19
|
+
|
20
|
+
NilCheck:
|
21
|
+
exclude:
|
22
|
+
- Stashify::File#exists?
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
stashify (3.1
|
4
|
+
stashify (3.2.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -93,6 +93,9 @@ GEM
|
|
93
93
|
rspec (~> 3.0)
|
94
94
|
thor (1.2.1)
|
95
95
|
unicode-display_width (2.4.2)
|
96
|
+
webrick (1.7.0)
|
97
|
+
yard (0.9.28)
|
98
|
+
webrick (~> 1.7.0)
|
96
99
|
|
97
100
|
PLATFORMS
|
98
101
|
x86_64-linux
|
@@ -109,6 +112,7 @@ DEPENDENCIES
|
|
109
112
|
rubocop (~> 1.21)
|
110
113
|
stashify!
|
111
114
|
stashify-contract
|
115
|
+
yard
|
112
116
|
|
113
117
|
BUNDLED WITH
|
114
118
|
2.2.33
|
data/README.md
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
# Stashify
|
2
2
|
|
3
|
-
|
3
|
+
Stashify is a common abstraction to interact with several different storage mediums in a uniform way. Provided in this gem is an implementation of the local filesystem, but other gems provide other implementations.
|
4
4
|
|
5
|
-
|
5
|
+
* [Google Cloud Storage](https://github.com/Lambda-Null/stashify-google-cloud-storage)
|
6
|
+
* [AWS S3](https://github.com/Lambda-Null/stashify-aws-s3)
|
7
|
+
* [Azure Blob Storage](https://github.com/Lambda-Null/stashify-microsoft-azure-storage-blob)
|
8
|
+
|
9
|
+
The uniform nature of these implementations allows results from one be passed to others. This not only affords you flexibility in your implementation and testing, but a simple way of transferring information from one storage provider to another.
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
9
13
|
Add this line to your application's Gemfile:
|
10
14
|
|
11
|
-
|
12
|
-
gem 'stashify'
|
13
|
-
```
|
15
|
+
gem 'stashify'
|
14
16
|
|
15
17
|
And then execute:
|
16
18
|
|
@@ -22,7 +24,91 @@ Or install it yourself as:
|
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
|
-
|
27
|
+
Provided in this gem is an implementation of local storage. Here is an example of how to use that implementation:
|
28
|
+
|
29
|
+
> require "stashify/file/local"
|
30
|
+
=> true
|
31
|
+
> file = Stashify::File::Local.new(path: "/tmp/foo")
|
32
|
+
=> #<Stashify::File::Local:0x000055a2a62f53c0 @contents="", @name="foo", @path="/tmp/foo">
|
33
|
+
> file.contents
|
34
|
+
=> "1\n"
|
35
|
+
> file.delete
|
36
|
+
=> true
|
37
|
+
> file.write("100")
|
38
|
+
=> 3
|
39
|
+
> file.contents
|
40
|
+
=> "100"
|
41
|
+
> file.delete
|
42
|
+
=> 1
|
43
|
+
> file.exists?
|
44
|
+
=> false
|
45
|
+
> require "stashify/directory/local"
|
46
|
+
> dir = Stashify::Directory::Local.new(path: "/tmp")
|
47
|
+
> file2 = dir.find("bar")
|
48
|
+
=> #<Stashify::File::Local:0x000055a2a62ff000 @contents="", @name="bar", @path="/tmp/bar">
|
49
|
+
> file2.contents
|
50
|
+
=> "2\n"
|
51
|
+
> dir.exists?(file.name)
|
52
|
+
=> false
|
53
|
+
> dir.write(Stashify::File.new(name: "foo", contents: "1"))
|
54
|
+
> dir.exists?("foo")
|
55
|
+
=> true
|
56
|
+
> dir.find("foo").contents
|
57
|
+
=> "1"
|
58
|
+
> dir.exists?("bar")
|
59
|
+
=> true
|
60
|
+
> dir.delete("bar")
|
61
|
+
=> 1
|
62
|
+
> dir.exists?("bar")
|
63
|
+
=> false
|
64
|
+
> subdir = dir.find("foobar")
|
65
|
+
=>
|
66
|
+
#<Stashify::Directory::Local:0x000055a2a5ffb660
|
67
|
+
...
|
68
|
+
> subdir.files.map(&:name)
|
69
|
+
=> ["baz"]
|
70
|
+
> subfile = subdir.files.first
|
71
|
+
=>
|
72
|
+
#<Stashify::File::Local:0x000055a2a62937b0
|
73
|
+
...
|
74
|
+
> subfile.name
|
75
|
+
=> "baz"
|
76
|
+
> subfile.contents
|
77
|
+
=> "3\n"
|
78
|
+
|
79
|
+
To interact with `Stashify::File` implementations is through `exists?`, `contents`, `write` and `delete`. To interact with `Stashify::Directory` implementations, use the methods `exists?`, `find`, `write`, `delete` and `files`. Regardless of the implementation of `Stashify::Directory`, `find` will return and `write` will take implementations of `Stashify::File`.
|
80
|
+
|
81
|
+
This consistency allows a lot of portability. For instance, pulling in a couple [other](https://github.com/Lambda-Null/stashify-google-cloud-storage) [gems](https://github.com/Lambda-Null/stashify-aws-s3) allows you to do cool things like this:
|
82
|
+
|
83
|
+
> require "stashify/directory/local"
|
84
|
+
=> true
|
85
|
+
> dir = Stashify::Directory::Local.new(path: "/tmp/foobar")
|
86
|
+
=>
|
87
|
+
#<Stashify::Directory::Local:0x0000564d9e8f9f48
|
88
|
+
...
|
89
|
+
> dir.files.map(&:name)
|
90
|
+
=> ["baz"]
|
91
|
+
> require "stashify/directory/google/cloud/storage"
|
92
|
+
=> true
|
93
|
+
> gdir = Stashify::Directory::Google::Cloud::Storage.new(bucket: bucket, path
|
94
|
+
: "")
|
95
|
+
=>
|
96
|
+
#<Stashify::Directory::Google::Cloud::Storage:0x0000564d9ee87140
|
97
|
+
...
|
98
|
+
> gdir.write(dir)
|
99
|
+
> gdir.files.map(&:name)
|
100
|
+
=> ["foobar"]
|
101
|
+
> require "stashify/directory/aws/s3"
|
102
|
+
=> true
|
103
|
+
> adir = Stashify::Directory::AWS::S3.new(bucket: bucket, path: "")
|
104
|
+
=>
|
105
|
+
#<Stashify::Directory::AWS::S3:0x0000564da0851580
|
106
|
+
...
|
107
|
+
> adir.write(gdir)
|
108
|
+
> adir.files.map(&:name)
|
109
|
+
=> ["baz"]
|
110
|
+
|
111
|
+
As you can see in the above examples, `Stashify::File` and `Stashify::Directory` can be created directly to define in-memory objects. This helps avoid the need to do silly things like write files to disk in order to get them to the desired destination.
|
26
112
|
|
27
113
|
## Development
|
28
114
|
|
@@ -34,6 +120,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
34
120
|
|
35
121
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/stashify. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/stashify/blob/master/CODE_OF_CONDUCT.md).
|
36
122
|
|
123
|
+
If you wish to create an implementation for a new provider, the gem [stashify-contract](https://github.com/Lambda-Null/stashify-contract) provides shared examples which verifies the consistency which maintains portability. To have your gem included in the list above, it must implement these examples in the way documented in that gem.
|
124
|
+
|
37
125
|
## License
|
38
126
|
|
39
127
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -5,7 +5,13 @@ require "stashify/directory"
|
|
5
5
|
|
6
6
|
module Stashify
|
7
7
|
class Directory
|
8
|
+
# An implementation for interacting with local directories. The
|
9
|
+
# constructor needs no information on top of what is included
|
10
|
+
# {Stashify::Directory#initialize}, although it's important to
|
11
|
+
# note that setting the files parameter will not do anything.
|
8
12
|
class Local < Stashify::Directory
|
13
|
+
# Mostly uses the default implementaiton, but needs to create
|
14
|
+
# the directory first so it has a valid destination.
|
9
15
|
def write_directory(directory)
|
10
16
|
FileUtils.mkdir(path_of(directory.name))
|
11
17
|
super
|
@@ -21,7 +27,7 @@ module Stashify
|
|
21
27
|
|
22
28
|
def files
|
23
29
|
Dir.entries(path).grep_v(/^[.][.]?$/).map do |file_name|
|
24
|
-
find(
|
30
|
+
find(file_name)
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
data/lib/stashify/directory.rb
CHANGED
@@ -1,9 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Stashify
|
4
|
+
# A common abstraction for interacting with directories. All methods
|
5
|
+
# that need to interact with directories are assumed to adhere to
|
6
|
+
# the public methods defined here. Specifically, the methods
|
7
|
+
# {#find}, {#write}, {#delete}, and {#files} are guaranteed to exist
|
8
|
+
# and behave in a way that is consistent across all gems. Unless
|
9
|
+
# called out separately, documentation for those methods here will
|
10
|
+
# hold true of any implementations of this class.
|
4
11
|
class Directory
|
5
|
-
|
12
|
+
# Provides the files and subdirectories of this directory. In the
|
13
|
+
# base class, this is implemented as an attribute which defaults
|
14
|
+
# to an empty list, but most implementations will override this
|
15
|
+
# with a method. In most implementations, the performance cost of
|
16
|
+
# reading all of thie names in a directory to construct these
|
17
|
+
# objects is high enough that we only want to pay it if it's
|
18
|
+
# actually needed.
|
19
|
+
#
|
20
|
+
# @return [Array<Stashify::File and Stashify::Directory>] Returns
|
21
|
+
# an Enumerable of Stashify::File and Stashify::Directory
|
22
|
+
# objects.
|
23
|
+
attr_reader :files
|
6
24
|
|
25
|
+
# The name of the directory. It is everything that follows the
|
26
|
+
# final "/" in the {#path}. This is always guaranteed to be
|
27
|
+
# populated.
|
28
|
+
attr_reader :name
|
29
|
+
|
30
|
+
# The full path to the directory this represents. Anything after the
|
31
|
+
# final "/" will also be returned from {#name}. This is not
|
32
|
+
# necessarily guaranteed to be populated, but usually will be.
|
33
|
+
attr_reader :path
|
34
|
+
|
35
|
+
# Basic information associated with a directory that is necessary
|
36
|
+
# to enable memory-based interactions.
|
37
|
+
#
|
38
|
+
# @param name [String not containing a "/"] The name of the file. Either this or path must be defined.
|
39
|
+
# @param path [String] The path of the file, will populate name with everything following the final "/".
|
40
|
+
# @param files An array of Stashify::File and Stashify::Directory
|
41
|
+
# objects representing the contents of this directory.
|
7
42
|
def initialize(name: nil, path: nil, files: [])
|
8
43
|
raise StandardError, "name or path must be defined" unless name || path
|
9
44
|
|
@@ -12,6 +47,19 @@ module Stashify
|
|
12
47
|
@files = files
|
13
48
|
end
|
14
49
|
|
50
|
+
# Look up the item in this directory represented by the provided
|
51
|
+
# name.
|
52
|
+
#
|
53
|
+
# For those looking to implement this method, it's typically more
|
54
|
+
# effective to override {#directory?}, {#directory}, {#exists?}
|
55
|
+
# and {#file}. Unless there are performance concerns with calling
|
56
|
+
# those, the default implementation will work pretty well.
|
57
|
+
#
|
58
|
+
# @param name [String with no "/"] The name of the desired item in
|
59
|
+
# this directory.
|
60
|
+
#
|
61
|
+
# @return Either a Stashify::File or Stashify::Directory object,
|
62
|
+
# depending on what that name represents.
|
15
63
|
def find(name)
|
16
64
|
if directory?(name)
|
17
65
|
directory(name)
|
@@ -20,23 +68,59 @@ module Stashify
|
|
20
68
|
end
|
21
69
|
end
|
22
70
|
|
23
|
-
|
24
|
-
|
25
|
-
|
71
|
+
# Write the provided item into the directory. If the item is a
|
72
|
+
# directory itself, then all of the contents will be copied.
|
73
|
+
#
|
74
|
+
# For those looking to implement this method, it's typically
|
75
|
+
# easier to implement {#write_file} and {#write_directory}. This
|
76
|
+
# helps you avoid having to know what type of object you're
|
77
|
+
# dealing with.
|
78
|
+
#
|
79
|
+
# @param item Either a Stashify::File or Stashify::Directory
|
80
|
+
# object. Note that these can be any implementation of these
|
81
|
+
# base classes, it's not limited to the classes from the same
|
82
|
+
# provider.
|
83
|
+
def write(item)
|
84
|
+
if item.is_a?(Stashify::Directory)
|
85
|
+
write_directory(item)
|
26
86
|
else
|
27
|
-
write_file(
|
87
|
+
write_file(item)
|
28
88
|
end
|
29
89
|
end
|
30
90
|
|
91
|
+
# Writes the provided directory. Typically you will want to
|
92
|
+
# interact with this functionality through {#write} rather than
|
93
|
+
# directly, as it protects you from errors related to accidentally
|
94
|
+
# passing a Stashify::File value in. It is primarily implemented
|
95
|
+
# separately to give a more specific hook for various
|
96
|
+
# implementations.
|
97
|
+
#
|
98
|
+
# The default implementation might work for you, as it iterates
|
99
|
+
# through {#files} and writes them to the new subdirectory.
|
31
100
|
def write_directory(directory)
|
32
101
|
subdir = self.directory(directory.name)
|
33
102
|
directory.files.each { |file| subdir.write(file) }
|
34
103
|
end
|
35
104
|
|
105
|
+
# Writes the provided file. Typically you will want to interact
|
106
|
+
# with this functionality through {#write} rather than directly,
|
107
|
+
# as it protects you from errors related to accidentally passing a
|
108
|
+
# Stashify::Directory value in. It is primarily implemented
|
109
|
+
# separately to give a more specific hook for various
|
110
|
+
# implementations.
|
36
111
|
def write_file(file)
|
37
112
|
file(file.name).write(file.contents)
|
38
113
|
end
|
39
114
|
|
115
|
+
# Delete provided name from the directory. If the item is a
|
116
|
+
# directory itself, then all of the contents will be copied.
|
117
|
+
#
|
118
|
+
# For those looking to implement this method, it's typically
|
119
|
+
# easier to implement {#directory?}, {#delete_directory} and
|
120
|
+
# {#delete_file}. The primary reason to override this method would
|
121
|
+
# be for performance reasons.
|
122
|
+
#
|
123
|
+
# @param name [String] Name of the item to be deleted.
|
40
124
|
def delete(name)
|
41
125
|
if directory?(name)
|
42
126
|
delete_directory(name)
|
@@ -45,27 +129,48 @@ module Stashify
|
|
45
129
|
end
|
46
130
|
end
|
47
131
|
|
132
|
+
# Deletes the provided directory name. Typically you will want to
|
133
|
+
# interact with this functionality through {#delete} rather than
|
134
|
+
# directly, as it protects you from errors related to accidentally
|
135
|
+
# asking to delete a file as a directory.
|
48
136
|
def delete_directory(name)
|
49
137
|
subdir = directory(name)
|
50
138
|
subdir.files.each { |file| subdir.delete(file.name) }
|
51
139
|
end
|
52
140
|
|
141
|
+
# Deletes the provided file name. Typically you will want to
|
142
|
+
# interact with this functionality through {#delete} rather than
|
143
|
+
# directly, as it protects you from errors related to accidentally
|
144
|
+
# asking to delete a directory as a file.
|
53
145
|
def delete_file(name)
|
54
146
|
file(name).delete
|
55
147
|
end
|
56
148
|
|
149
|
+
# Two directories are equal if their files are equal. This is
|
150
|
+
# distinct from being the same directory, which is served by the
|
151
|
+
# {#eql?} method.
|
57
152
|
def ==(other)
|
58
153
|
files == other.files
|
59
154
|
end
|
60
155
|
|
156
|
+
# This answers if the two directories are the same, which is
|
157
|
+
# usually more specific than you want. If you wish to determine if
|
158
|
+
# all of the files are equal, consider {#==} instead..
|
61
159
|
def eql?(other)
|
62
160
|
self.class == other.class && name == other.name && path == other.path
|
63
161
|
end
|
64
162
|
|
65
|
-
|
163
|
+
# @return [Stashify::File] Return an object representing a single
|
164
|
+
# file in this directory.
|
165
|
+
def file(name)
|
166
|
+
Stashify::File.new(path: path_of(name))
|
167
|
+
end
|
66
168
|
|
67
|
-
|
68
|
-
|
169
|
+
# The full path to the item in this directory provided by the
|
170
|
+
# names. Any number of names can be provided, allowing arbitrarily
|
171
|
+
# deep paths to be constructed below this directory.
|
172
|
+
def path_of(*names)
|
173
|
+
::File.join(path, *names)
|
69
174
|
end
|
70
175
|
end
|
71
176
|
end
|
data/lib/stashify/file/local.rb
CHANGED
@@ -4,6 +4,10 @@ require "stashify/file"
|
|
4
4
|
|
5
5
|
module Stashify
|
6
6
|
class File
|
7
|
+
# An implementation for interacting with local files. The
|
8
|
+
# constructor needs no information on top of what is included
|
9
|
+
# {Stashify::File#initialize}, although it's important to note
|
10
|
+
# that setting the contents parameter will not do anything.
|
7
11
|
class Local < Stashify::File
|
8
12
|
def contents
|
9
13
|
::File.read(path)
|
data/lib/stashify/file.rb
CHANGED
@@ -3,10 +3,38 @@
|
|
3
3
|
require "stashify"
|
4
4
|
|
5
5
|
module Stashify
|
6
|
+
# A common abstraction for interacting with files. All methods that
|
7
|
+
# need to interact with files are assumed to adhere to the methods
|
8
|
+
# defined here. Specifically the methods {#write}, {#delete},
|
9
|
+
# {#contents} and {#exists?} are guaranteed to exist and behave in a
|
10
|
+
# way that is consistent across all gems. Unless called out
|
11
|
+
# separately, documentation for those methods here will hold true of
|
12
|
+
# any implementations of this class.
|
6
13
|
class File
|
7
|
-
|
14
|
+
# Provides the contents of this file. In the base class, this is
|
15
|
+
# implemented as an attribute, but most implementations will
|
16
|
+
# override this with a method. In most implementations, the
|
17
|
+
# performance cost of reading the file is high enough that we only
|
18
|
+
# want to pay it if it's actually needed.
|
19
|
+
attr_reader :contents
|
8
20
|
|
9
|
-
|
21
|
+
# The name of the file is the actual filename in a directory. In
|
22
|
+
# other words, it is everything that follows the final "/" in the
|
23
|
+
# {#path}. This is always guaranteed to be populated.
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# The full path to the file this represents. Anything after the
|
27
|
+
# final "/" will also be returned from {#name}. This is not
|
28
|
+
# necessarily guaranteed to be populated, but usually will be.
|
29
|
+
attr_reader :path
|
30
|
+
|
31
|
+
# Basic information associated with a file that is necessary to
|
32
|
+
# enable memory-based interactions.
|
33
|
+
#
|
34
|
+
# @param name [String not containing a "/"] The name of the file. Either this or path must be defined.
|
35
|
+
# @param path [String] The path of the file, will populate name with everything following the final "/".
|
36
|
+
# @param contents [String] The contents of the file, if nil this object will mimic a missing file.
|
37
|
+
def initialize(name: nil, path: nil, contents: nil)
|
10
38
|
raise StandardError, "name or path must be defined" unless name || path
|
11
39
|
raise Stashify::InvalidFile, "Name '#{name}' contains a /" if name && name =~ %r{/}
|
12
40
|
|
@@ -15,14 +43,51 @@ module Stashify
|
|
15
43
|
@contents = contents
|
16
44
|
end
|
17
45
|
|
46
|
+
# Persists the provided contents into {#path}. If that file does
|
47
|
+
# not exist, it creates it in the process. Otherwise it updates
|
48
|
+
# the existing file.
|
49
|
+
#
|
50
|
+
# In general, if {#exists?} returns false before this is called it
|
51
|
+
# will return true after this is called.
|
52
|
+
#
|
53
|
+
# @note For the base implementation, it will assign something to
|
54
|
+
# @contents. The value of this instance variable should not be
|
55
|
+
# relied upon outside of the base implementation though, every
|
56
|
+
# other implementation so far overrides to an action more
|
57
|
+
# appropriate to its storage medium.
|
58
|
+
#
|
59
|
+
# @param contents [String] A String describing the contents of the file.
|
60
|
+
# @return No guarantees are made as to the return value of this method,
|
61
|
+
# it will largely depend on the implementation of the implementing class.
|
18
62
|
def write(contents)
|
19
63
|
@contents = contents
|
20
64
|
end
|
21
65
|
|
66
|
+
# Deletes the underlying file.
|
67
|
+
#
|
68
|
+
# In general, if {#exists?} returns true prior to this method
|
69
|
+
# being called, it will no longer return true after this method is
|
70
|
+
# called.
|
71
|
+
#
|
72
|
+
# @return No guarantees are made as to the return value of this method,
|
73
|
+
# it will largely depend on the implementation of the implementing class.
|
22
74
|
def delete
|
23
75
|
@contents = nil
|
24
76
|
end
|
25
77
|
|
78
|
+
# Answers if the file exists. In general, it will always return
|
79
|
+
# true after {#write} is called and always return false after
|
80
|
+
# {#delete} is called.
|
81
|
+
#
|
82
|
+
# @note The base class checks if {#contents} returns nil, but this
|
83
|
+
# is extremely unlikely for other implementations.
|
84
|
+
def exists?
|
85
|
+
!contents.nil?
|
86
|
+
end
|
87
|
+
|
88
|
+
# Two files are considered equal if they have the same name and
|
89
|
+
# contents. This means that equality holds between files in two
|
90
|
+
# separate directories.
|
26
91
|
def ==(other)
|
27
92
|
name == other.name && contents == other.contents
|
28
93
|
end
|
data/lib/stashify/version.rb
CHANGED
data/lib/stashify.rb
CHANGED
data/stashify.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/stashify/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "stashify"
|
7
|
+
spec.version = Stashify::VERSION
|
8
|
+
spec.authors = ["Lambda Null"]
|
9
|
+
spec.email = ["lambda.null.42@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Common abstraction for storing files"
|
12
|
+
spec.description = "Provides an abstraction to various services (local filesystem, S3, etc)"
|
13
|
+
spec.homepage = "https://github.com/Lambda-Null/stashify"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
24
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
# Uncomment to register a new dependency of your gem
|
32
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
33
|
+
|
34
|
+
# For more information and examples about making a new gem, checkout our
|
35
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
36
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
37
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stashify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lambda Null
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Provides an abstraction to various services (local filesystem, S3, etc)
|
14
14
|
email:
|
@@ -35,9 +35,9 @@ files:
|
|
35
35
|
- lib/stashify/directory/local.rb
|
36
36
|
- lib/stashify/file.rb
|
37
37
|
- lib/stashify/file/local.rb
|
38
|
-
- lib/stashify/local.rb
|
39
38
|
- lib/stashify/version.rb
|
40
39
|
- sig/stashify.rbs
|
40
|
+
- stashify.gemspec
|
41
41
|
homepage: https://github.com/Lambda-Null/stashify
|
42
42
|
licenses:
|
43
43
|
- MIT
|