stashify 3.2.0 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek.yml +0 -3
- data/.rubocop.yml +0 -3
- data/Gemfile.lock +1 -1
- data/README.md +2 -0
- data/lib/stashify/directory/local.rb +7 -1
- data/lib/stashify/directory.rb +110 -7
- data/lib/stashify/file/local.rb +4 -0
- data/lib/stashify/file.rb +63 -2
- data/lib/stashify/version.rb +1 -1
- data/lib/stashify.rb +2 -0
- data/stashify.gemspec +1 -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: 5e8d4b251e21c2a89ba19ab2088a822517c0715e78c4060f1cfdeadb85cca5a3
|
4
|
+
data.tar.gz: 94853f51dafda043120f9d9e56423fd07f223380647b5c3387b29050dd0aa130
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98c3c6e6cda965e3015f5c7fbb17e1b0e90935089b90fc7aaa2f1eb6b9ad289b30819c17465de8be99bd95daad78d30d3e144b62a8c057a9b895fde2711e2a82
|
7
|
+
data.tar.gz: b8d4d0c1b7f445f8f9a8977e10f294249d8661d302b99bb39e3980e8e733cbf83ba2939867c86ef2a45ff729d9ab671bc13f75c3a86cc514bd53a871606844e8
|
data/.reek.yml
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -108,6 +108,8 @@ This consistency allows a lot of portability. For instance, pulling in a couple
|
|
108
108
|
> adir.files.map(&:name)
|
109
109
|
=> ["baz"]
|
110
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.
|
112
|
+
|
111
113
|
## Development
|
112
114
|
|
113
115
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -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,29 +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
|
|
163
|
+
# @return [Stashify::File] Return an object representing a single
|
164
|
+
# file in this directory.
|
65
165
|
def file(name)
|
66
166
|
Stashify::File.new(path: path_of(name))
|
67
167
|
end
|
68
168
|
|
69
|
-
|
70
|
-
|
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)
|
71
174
|
end
|
72
175
|
end
|
73
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,18 +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.
|
26
84
|
def exists?
|
27
85
|
!contents.nil?
|
28
86
|
end
|
29
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.
|
30
91
|
def ==(other)
|
31
92
|
name == other.name && contents == other.contents
|
32
93
|
end
|
data/lib/stashify/version.rb
CHANGED
data/lib/stashify.rb
CHANGED
data/stashify.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/stashify"
|
19
20
|
|
20
21
|
# Specify which files should be added to the gem when it is released.
|
21
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
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.2.
|
4
|
+
version: 3.2.2
|
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-
|
11
|
+
date: 2023-07-13 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,7 +35,6 @@ 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
|
41
40
|
- stashify.gemspec
|
@@ -45,6 +44,7 @@ licenses:
|
|
45
44
|
metadata:
|
46
45
|
homepage_uri: https://github.com/Lambda-Null/stashify
|
47
46
|
source_code_uri: https://github.com/Lambda-Null/stashify
|
47
|
+
documentation_uri: https://rubydoc.info/gems/stashify
|
48
48
|
rubygems_mfa_required: 'true'
|
49
49
|
post_install_message:
|
50
50
|
rdoc_options: []
|