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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15c432cdab53f9a20369203af0e05bb8157413a622655ae28d4c36131f318a8b
4
- data.tar.gz: 5e2d87b9a660825c36d4140fa1a5c30b1a5e10573edc34df7fb6cbcff7e5f802
3
+ metadata.gz: 035b4f42412c865a6fcabf7944cd6a49169034b974054e20a8eb67ea1f06a4a4
4
+ data.tar.gz: 4a393454a48b04bc1769fe29a3ea21fe5e4ce501c3443f903e777c7a44b8478e
5
5
  SHA512:
6
- metadata.gz: 73612ebce48eaf45c396d4277ea4e73a591ffb976589049101dc28c6cd8b4fbbd3ad376852db2a8e5deb0a8864982e10071821da47a2ca19e05b443e0054613a
7
- data.tar.gz: a897048fb68343a37408a5bdc43bcf93f629621fea1d21235896f32b0800e643ab791feac51d32b17df73ed2fcc3141652e43fd4bc85deac757abd78c1410080
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
@@ -2,9 +2,6 @@ AllCops:
2
2
  TargetRubyVersion: 2.6
3
3
  NewCops: enable
4
4
 
5
- Style/Documentation:
6
- Enabled: false
7
-
8
5
  Style/StringLiterals:
9
6
  Enabled: true
10
7
  EnforcedStyle: double_quotes
data/Gemfile CHANGED
@@ -18,3 +18,5 @@ gem "guard-rubocop"
18
18
 
19
19
  gem "byebug"
20
20
  gem "stashify-contract"
21
+
22
+ gem "yard"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stashify (3.1.0)
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/stashify`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
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
- ```ruby
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
- TODO: Write usage instructions here
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(::File.basename(file_name))
30
+ find(file_name)
25
31
  end
26
32
  end
27
33
 
@@ -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
- attr_reader :name, :files, :path
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
- def write(file)
24
- if file.is_a?(Stashify::Directory)
25
- write_directory(file)
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(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
- private
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
- def path_of(*name)
68
- ::File.join(path, *name)
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
@@ -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
- attr_reader :name, :path, :contents
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
- def initialize(name: nil, path: nil, contents: "")
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stashify
4
- VERSION = "3.1.0"
4
+ VERSION = "3.2.1"
5
5
  end
data/lib/stashify.rb CHANGED
@@ -3,5 +3,7 @@
3
3
  require_relative "stashify/version"
4
4
 
5
5
  module Stashify
6
+ # Error raised when the filename given is invalid. This most likely
7
+ # means the name parameter contains a "/".
6
8
  class InvalidFile < StandardError; end
7
9
  end
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.0
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-01 00:00:00.000000000 Z
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
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Stashify
4
- class Local
5
- def initialize(path)
6
- @path = path
7
- end
8
- end
9
- end