ronin-repos 0.1.0.beta1
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 +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +7 -0
- data/Gemfile +32 -0
- data/README.md +159 -0
- data/Rakefile +34 -0
- data/bin/ronin-repos +35 -0
- data/data/templates/repo/README.md.erb +11 -0
- data/gemspec.yml +36 -0
- data/lib/ronin/repos/cache_dir.rb +267 -0
- data/lib/ronin/repos/class_dir.rb +150 -0
- data/lib/ronin/repos/cli/command.rb +63 -0
- data/lib/ronin/repos/cli/commands/install.rb +71 -0
- data/lib/ronin/repos/cli/commands/list.rb +80 -0
- data/lib/ronin/repos/cli/commands/new.rb +83 -0
- data/lib/ronin/repos/cli/commands/purge.rb +39 -0
- data/lib/ronin/repos/cli/commands/remove.rb +71 -0
- data/lib/ronin/repos/cli/commands/update.rb +91 -0
- data/lib/ronin/repos/cli.rb +45 -0
- data/lib/ronin/repos/exceptions.rb +33 -0
- data/lib/ronin/repos/repository.rb +343 -0
- data/lib/ronin/repos/root.rb +26 -0
- data/lib/ronin/repos/version.rb +24 -0
- data/lib/ronin/repos.rb +81 -0
- data/man/ronin-repos-install.1 +64 -0
- data/man/ronin-repos-install.1.md +49 -0
- data/man/ronin-repos-list.1 +54 -0
- data/man/ronin-repos-list.1.md +41 -0
- data/man/ronin-repos-new.1 +37 -0
- data/man/ronin-repos-purge.1 +54 -0
- data/man/ronin-repos-purge.1.md +41 -0
- data/man/ronin-repos-remove.1 +60 -0
- data/man/ronin-repos-remove.1.md +46 -0
- data/man/ronin-repos-update.1 +64 -0
- data/man/ronin-repos-update.1.md +49 -0
- data/man/ronin-repos.1 +49 -0
- data/man/ronin-repos.1.md +37 -0
- data/ronin-repos.gemspec +62 -0
- data/spec/cache_dir_spec.rb +272 -0
- data/spec/class_dir_spec.rb +97 -0
- data/spec/fixtures/cache/repo1/dir/file1.txt +0 -0
- data/spec/fixtures/cache/repo1/file1.txt +0 -0
- data/spec/fixtures/cache/repo1/file2.txt +0 -0
- data/spec/fixtures/cache/repo2/dir/file1.txt +0 -0
- data/spec/fixtures/cache/repo2/dir/file2.txt +0 -0
- data/spec/fixtures/cache/repo2/file1.txt +0 -0
- data/spec/fixtures/cache/repo2/file2.txt +0 -0
- data/spec/fixtures/cache/repo2/only-exists-in-repo2.txt +0 -0
- data/spec/fixtures/class_dir/file1.rb +0 -0
- data/spec/fixtures/class_dir/file2.rb +0 -0
- data/spec/fixtures/class_dir/only_in_class_dir.rb +0 -0
- data/spec/repos_spec.rb +67 -0
- data/spec/repository_spec.rb +415 -0
- data/spec/spec_helper.rb +6 -0
- metadata +143 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# ronin-repos 1 "2022-01-01" Ronin Repos "User Manuals"
|
2
|
+
|
3
|
+
## SYNOPSIS
|
4
|
+
|
5
|
+
`ronin-repos` [*options*] [*COMMAND*]
|
6
|
+
|
7
|
+
## DESCRIPTION
|
8
|
+
|
9
|
+
Allows downloading and managing git repositories. `ronin-repos` can install
|
10
|
+
and use any git repository containing Ruby code or other data.
|
11
|
+
|
12
|
+
## OPTIONS
|
13
|
+
|
14
|
+
`-h`, `--help`
|
15
|
+
Prints help information.
|
16
|
+
|
17
|
+
## FILES
|
18
|
+
|
19
|
+
*~/.cache/ronin-repos*
|
20
|
+
Installation directory for repositories.
|
21
|
+
|
22
|
+
## ENVIRONMENT
|
23
|
+
|
24
|
+
HOME
|
25
|
+
Specifies the home directory of the user. Ronin will search for the
|
26
|
+
*~/.cache/ronin-repos* cache directory within the home directory.
|
27
|
+
|
28
|
+
XDG_CACHE_HOME
|
29
|
+
Specifies the cache directory to use. Defaults to *$HOME/.cache*.
|
30
|
+
|
31
|
+
## AUTHOR
|
32
|
+
|
33
|
+
Postmodern <postmodern.mod3@gmail.com>
|
34
|
+
|
35
|
+
## SEE ALSO
|
36
|
+
|
37
|
+
ronin-repos-install(1) ronin-repos-list(1) ronin-repos-remove(1) ronin-repos-update(1) ronin-repos-purge(1)
|
data/ronin-repos.gemspec
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gemspec = YAML.load_file('gemspec.yml')
|
7
|
+
|
8
|
+
gem.name = gemspec.fetch('name')
|
9
|
+
gem.version = gemspec.fetch('version') do
|
10
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
|
+
|
13
|
+
require 'ronin/repos/version'
|
14
|
+
Ronin::Repos::VERSION
|
15
|
+
end
|
16
|
+
|
17
|
+
gem.summary = gemspec['summary']
|
18
|
+
gem.description = gemspec['description']
|
19
|
+
gem.licenses = Array(gemspec['license'])
|
20
|
+
gem.authors = Array(gemspec['authors'])
|
21
|
+
gem.email = gemspec['email']
|
22
|
+
gem.homepage = gemspec['homepage']
|
23
|
+
gem.metadata = gemspec['metadata'] if gemspec['metadata']
|
24
|
+
|
25
|
+
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
26
|
+
|
27
|
+
gem.files = `git ls-files`.split($/)
|
28
|
+
gem.files = glob[gemspec['files']] if gemspec['files']
|
29
|
+
gem.files += Array(gemspec['generated_files'])
|
30
|
+
|
31
|
+
gem.executables = gemspec.fetch('executables') do
|
32
|
+
glob['bin/*'].map { |path| File.basename(path) }
|
33
|
+
end
|
34
|
+
gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
|
35
|
+
|
36
|
+
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
37
|
+
gem.test_files = glob[gemspec['test_files'] || 'spec/{**/}*_spec.rb']
|
38
|
+
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
39
|
+
|
40
|
+
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
41
|
+
%w[ext lib].select { |dir| File.directory?(dir) }
|
42
|
+
})
|
43
|
+
|
44
|
+
gem.requirements = gemspec['requirements']
|
45
|
+
gem.required_ruby_version = gemspec['required_ruby_version']
|
46
|
+
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
47
|
+
gem.post_install_message = gemspec['post_install_message']
|
48
|
+
|
49
|
+
split = lambda { |string| string.split(/,\s*/) }
|
50
|
+
|
51
|
+
if gemspec['dependencies']
|
52
|
+
gemspec['dependencies'].each do |name,versions|
|
53
|
+
gem.add_dependency(name,split[versions])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if gemspec['development_dependencies']
|
58
|
+
gemspec['development_dependencies'].each do |name,versions|
|
59
|
+
gem.add_development_dependency(name,split[versions])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,272 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/repos/cache_dir'
|
3
|
+
|
4
|
+
describe Ronin::Repos::CacheDir do
|
5
|
+
let(:fixtures_dir) { File.expand_path(File.join(__dir__,'fixtures')) }
|
6
|
+
let(:cache_dir) { File.join(fixtures_dir,'cache') }
|
7
|
+
|
8
|
+
describe "PATH" do
|
9
|
+
subject { described_class::PATH }
|
10
|
+
|
11
|
+
it "must default to ~/.cache/ronin-repos" do
|
12
|
+
expect(subject).to eq(File.join(ENV['HOME'],'.cache','ronin-repos'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { described_class.new(cache_dir) }
|
17
|
+
|
18
|
+
describe "#initialize" do
|
19
|
+
context "when no arguments are given" do
|
20
|
+
subject { described_class.new }
|
21
|
+
|
22
|
+
it "must set #path to PATH" do
|
23
|
+
expect(subject.path).to eq(described_class::PATH)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when given a path argument" do
|
28
|
+
subject { described_class.new(cache_dir) }
|
29
|
+
|
30
|
+
it "must set #path" do
|
31
|
+
expect(subject.path).to eq(cache_dir)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#[]" do
|
37
|
+
context "when a repository with the given name exists in the cache dir" do
|
38
|
+
let(:name) { 'repo2' }
|
39
|
+
|
40
|
+
it "must return a Repository object with the matching name" do
|
41
|
+
repo = subject[name]
|
42
|
+
|
43
|
+
expect(repo).to be_kind_of(Repository)
|
44
|
+
expect(repo.name).to eq(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when given an unknown repository name" do
|
49
|
+
let(:name) { 'does_not_exist' }
|
50
|
+
|
51
|
+
it do
|
52
|
+
expect {
|
53
|
+
subject[name]
|
54
|
+
}.to raise_error(RepositoryNotFound,"repository not found: #{name.inspect}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#each" do
|
60
|
+
context "when given a block" do
|
61
|
+
it "must yield each Repository object" do
|
62
|
+
yielded_repos = []
|
63
|
+
|
64
|
+
subject.each do |repo|
|
65
|
+
yielded_repos << repo
|
66
|
+
end
|
67
|
+
|
68
|
+
expect(yielded_repos.length).to eq(2)
|
69
|
+
expect(yielded_repos[0]).to be_kind_of(Repository)
|
70
|
+
expect(yielded_repos[0].name).to eq("repo1")
|
71
|
+
|
72
|
+
expect(yielded_repos[1]).to be_kind_of(Repository)
|
73
|
+
expect(yielded_repos[1].name).to eq("repo2")
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when #path does not exist" do
|
77
|
+
subject { described_class.new('/does/not/exist') }
|
78
|
+
|
79
|
+
it "must not yield anything" do
|
80
|
+
expect { |b|
|
81
|
+
subject.each(&b)
|
82
|
+
}.to_not yield_control
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when no block is given" do
|
88
|
+
it "must return an Enumerator object" do
|
89
|
+
yielded_repos = subject.each.to_a
|
90
|
+
|
91
|
+
expect(yielded_repos.length).to eq(2)
|
92
|
+
expect(yielded_repos[0]).to be_kind_of(Repository)
|
93
|
+
expect(yielded_repos[0].name).to eq("repo1")
|
94
|
+
|
95
|
+
expect(yielded_repos[1]).to be_kind_of(Repository)
|
96
|
+
expect(yielded_repos[1].name).to eq("repo2")
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when #path does not exist" do
|
100
|
+
subject { described_class.new('/does/not/exist') }
|
101
|
+
|
102
|
+
it "the Enumerator must not return anything" do
|
103
|
+
expect(subject.each.to_a).to be_empty
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#install" do
|
110
|
+
let(:name) { 'new_repo' }
|
111
|
+
let(:uri) { "https://github.com/example/#{name}.git" }
|
112
|
+
let(:path) { File.join(cache_dir,name) }
|
113
|
+
|
114
|
+
let(:new_repo) { double('Repository') }
|
115
|
+
|
116
|
+
it "must `git clone` the given URI into the cache directory" do
|
117
|
+
expect(Repository).to receive(:system).with(
|
118
|
+
'git', 'clone', uri, path
|
119
|
+
).and_return(true)
|
120
|
+
|
121
|
+
expect(Repository).to receive(:new).and_return(new_repo)
|
122
|
+
|
123
|
+
expect(subject.install(uri)).to be(new_repo)
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when a custom name is given" do
|
127
|
+
let(:custom_name) { 'custom-repo' }
|
128
|
+
let(:path) { File.join(cache_dir,custom_name) }
|
129
|
+
|
130
|
+
it "must use the custom name instead of deriving the repository's name" do
|
131
|
+
expect(Repository).to receive(:system).with(
|
132
|
+
'git', 'clone', uri, path
|
133
|
+
).and_return(true)
|
134
|
+
|
135
|
+
expect(Repository).to receive(:new).and_return(new_repo)
|
136
|
+
|
137
|
+
expect(subject.install(uri,custom_name)).to be(new_repo)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#update" do
|
143
|
+
it "must call #update on each repository in the cache directory"
|
144
|
+
|
145
|
+
context "but system() returns nil" do
|
146
|
+
it do
|
147
|
+
expect_any_instance_of(Repository).to receive(:system).and_return(nil)
|
148
|
+
|
149
|
+
expect {
|
150
|
+
subject.update
|
151
|
+
}.to raise_error(CommandNotInstalled,"git is not installed")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "#remove" do
|
157
|
+
let(:name) { 'repo2' }
|
158
|
+
|
159
|
+
it "must call #delete on the Repository" do
|
160
|
+
expect_any_instance_of(Repository).to receive(:delete)
|
161
|
+
|
162
|
+
subject.remove(name)
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when given an unknown repository name" do
|
166
|
+
let(:name) { 'does-not-exist' }
|
167
|
+
|
168
|
+
it do
|
169
|
+
expect {
|
170
|
+
subject.remove(name)
|
171
|
+
}.to raise_error(RepositoryNotFound,"repository not found: #{name.inspect}")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "#purge" do
|
177
|
+
it "must call #delete on every repository in the cache directory" do
|
178
|
+
expect(FileUtils).to receive(:rm_rf).with(File.join(cache_dir,'repo1'))
|
179
|
+
expect(FileUtils).to receive(:rm_rf).with(File.join(cache_dir,'repo2'))
|
180
|
+
|
181
|
+
subject.purge
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#find_file" do
|
186
|
+
let(:relative_path) { 'only-exists-in-repo2.txt' }
|
187
|
+
|
188
|
+
it "must return the first file that matches the given relative path" do
|
189
|
+
expect(subject.find_file(relative_path)).to eq(
|
190
|
+
File.join(cache_dir,'repo2',relative_path)
|
191
|
+
)
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when the relative path does not exist within any repository" do
|
195
|
+
let(:relative_path) { 'does/not/exist.txt' }
|
196
|
+
|
197
|
+
it "must return nil" do
|
198
|
+
expect(subject.find_file(relative_path)).to be(nil)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#glob" do
|
204
|
+
context "when the pattern matches files within all repositories" do
|
205
|
+
let(:pattern) { 'dir/*.txt' }
|
206
|
+
|
207
|
+
let(:expected_paths) do
|
208
|
+
Dir[File.join(cache_dir,'*',pattern)]
|
209
|
+
end
|
210
|
+
|
211
|
+
it "must return the absolute paths that matches the pattern, in order" do
|
212
|
+
expect(subject.glob(pattern)).to eq(expected_paths.sort)
|
213
|
+
end
|
214
|
+
|
215
|
+
context "when a block is given" do
|
216
|
+
it "must yield the matching absolute paths" do
|
217
|
+
expect { |b|
|
218
|
+
subject.glob(pattern,&b)
|
219
|
+
}.to yield_successive_args(*expected_paths.sort)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context "when the relative path does not exist within any repository" do
|
225
|
+
let(:pattern) { 'does/not/exist/*.txt' }
|
226
|
+
|
227
|
+
it "must return []" do
|
228
|
+
expect(subject.glob(pattern)).to eq([])
|
229
|
+
end
|
230
|
+
|
231
|
+
context "when a block is given" do
|
232
|
+
it "must not yield" do
|
233
|
+
expect { |b|
|
234
|
+
subject.glob(pattern,&b)
|
235
|
+
}.to_not yield_control
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "#list_files" do
|
242
|
+
context "when given no arguments" do
|
243
|
+
it "must list every unique file within each repository" do
|
244
|
+
expect(subject.list_files).to eq(
|
245
|
+
Set.new(
|
246
|
+
%w[
|
247
|
+
dir/file1.txt
|
248
|
+
dir/file2.txt
|
249
|
+
file1.txt
|
250
|
+
file2.txt
|
251
|
+
only-exists-in-repo2.txt
|
252
|
+
]
|
253
|
+
)
|
254
|
+
)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "when given a glob pattern" do
|
259
|
+
it "must list only the files that match the glob pattern" do
|
260
|
+
expect(subject.list_files('dir/*.txt')).to eq(
|
261
|
+
Set.new(%w[dir/file1.txt dir/file2.txt])
|
262
|
+
)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "#to_s" do
|
268
|
+
it "must return the cache directory path" do
|
269
|
+
expect(subject.to_s).to eq(cache_dir)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/repos/class_dir'
|
3
|
+
|
4
|
+
describe Ronin::Repos::ClassDir do
|
5
|
+
let(:fixtures_dir) { File.expand_path(File.join(__dir__,'fixtures')) }
|
6
|
+
|
7
|
+
describe ".repo_class_dir" do
|
8
|
+
context "when a repo_class_dir has been defined" do
|
9
|
+
module TestClassDir
|
10
|
+
module WithReposClassDirSet
|
11
|
+
include Ronin::Repos::ClassDir
|
12
|
+
|
13
|
+
repo_class_dir "dir"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
subject { TestClassDir::WithReposClassDirSet }
|
18
|
+
|
19
|
+
it "must return the previously set .repo_class_dir" do
|
20
|
+
expect(subject.repo_class_dir).to eq("dir")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "but when no repo_class_dir has been defined" do
|
25
|
+
module TestReposDir
|
26
|
+
module WithoutReposDirSet
|
27
|
+
include Ronin::Repos::ClassDir
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
subject { TestReposDir::WithoutReposDirSet }
|
32
|
+
|
33
|
+
it do
|
34
|
+
expect {
|
35
|
+
subject.repo_class_dir
|
36
|
+
}.to raise_error(NotImplementedError,"#{subject} did not define a repo_class_dir")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module TestReposDir
|
42
|
+
module ExampleNamespace
|
43
|
+
include Ronin::Core::ClassRegistry
|
44
|
+
include Ronin::Repos::ClassDir
|
45
|
+
|
46
|
+
class_dir "#{__dir__}/fixtures/class_dir"
|
47
|
+
repo_class_dir 'dir'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
subject { TestReposDir::ExampleNamespace }
|
52
|
+
|
53
|
+
describe ".list_files" do
|
54
|
+
before do
|
55
|
+
expect(Ronin::Repos).to receive(:list_files).and_return(
|
56
|
+
Set.new(
|
57
|
+
%w[
|
58
|
+
file1.rb
|
59
|
+
file2.rb
|
60
|
+
]
|
61
|
+
)
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must list the modules in the .class_dir and in all .repo_class_dir" do
|
66
|
+
expect(subject.list_files).to eq(
|
67
|
+
%w[
|
68
|
+
file1
|
69
|
+
file2
|
70
|
+
only_in_class_dir
|
71
|
+
]
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe ".path_for" do
|
77
|
+
context "when the module name exists in the .class_dir" do
|
78
|
+
it "must return the path to the module file in .class_dir" do
|
79
|
+
expect(subject.path_for('only_in_class_dir')).to eq(
|
80
|
+
File.join(subject.class_dir,'only_in_class_dir.rb')
|
81
|
+
)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when the module name exists in one of the installed repos" do
|
86
|
+
it "must call Repos.find_file with the .repo_class_dir and module file name" do
|
87
|
+
expect(Ronin::Repos).to receive(:find_file).with(
|
88
|
+
File.join(subject.repo_class_dir,'file.rb')
|
89
|
+
).and_return("/path/to/#{subject.repo_class_dir}/file.rb")
|
90
|
+
|
91
|
+
expect(subject.path_for('file')).to eq(
|
92
|
+
"/path/to/#{subject.repo_class_dir}/file.rb"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/repos_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/repos'
|
3
|
+
|
4
|
+
describe Ronin::Repos do
|
5
|
+
it "should have a version" do
|
6
|
+
expect(subject.const_defined?('VERSION')).to be(true)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:cache_dir) { described_class.class_variable_get('@@cache_dir') }
|
10
|
+
|
11
|
+
describe "@@cache_dir" do
|
12
|
+
subject { cache_dir }
|
13
|
+
|
14
|
+
it "must be a CacheDir pointing to ~/.cache/ronin-repos" do
|
15
|
+
expect(subject).to be_kind_of(CacheDir)
|
16
|
+
expect(subject.path).to eq(File.expand_path("~/.cache/ronin-repos"))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".find_file" do
|
21
|
+
let(:relative_path) { 'file.txt' }
|
22
|
+
let(:matches) do
|
23
|
+
[
|
24
|
+
"/path/to/repo1/file.txt",
|
25
|
+
"/path/to/repo2/file.txt"
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "must call @@cache_dir.find_file" do
|
30
|
+
expect(cache_dir).to receive(:find_file).with(relative_path).and_return(matches)
|
31
|
+
|
32
|
+
expect(subject.find_file(relative_path)).to be(matches)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".glob" do
|
37
|
+
let(:pattern) { 'dir/*.txt' }
|
38
|
+
let(:matches) do
|
39
|
+
[
|
40
|
+
"/path/to/repo1/dir/file.txt",
|
41
|
+
"/path/to/repo2/dir/file.txt"
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "must call @@cache_dir.glob" do
|
46
|
+
expect(cache_dir).to receive(:glob).with(pattern).and_return(matches)
|
47
|
+
|
48
|
+
expect(subject.glob(pattern)).to be(matches)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".list_files" do
|
53
|
+
let(:pattern) { 'dir/*.txt' }
|
54
|
+
let(:files) do
|
55
|
+
Set[
|
56
|
+
"dir/file.txt",
|
57
|
+
"dir/file.txt"
|
58
|
+
]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "must call @@cache_dir.list_files" do
|
62
|
+
expect(cache_dir).to receive(:list_files).with(pattern).and_return(files)
|
63
|
+
|
64
|
+
expect(subject.list_files(pattern)).to be(files)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|