ronin-repos 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +27 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +165 -0
  9. data/ChangeLog.md +7 -0
  10. data/Gemfile +32 -0
  11. data/README.md +159 -0
  12. data/Rakefile +34 -0
  13. data/bin/ronin-repos +35 -0
  14. data/data/templates/repo/README.md.erb +11 -0
  15. data/gemspec.yml +36 -0
  16. data/lib/ronin/repos/cache_dir.rb +267 -0
  17. data/lib/ronin/repos/class_dir.rb +150 -0
  18. data/lib/ronin/repos/cli/command.rb +63 -0
  19. data/lib/ronin/repos/cli/commands/install.rb +71 -0
  20. data/lib/ronin/repos/cli/commands/list.rb +80 -0
  21. data/lib/ronin/repos/cli/commands/new.rb +83 -0
  22. data/lib/ronin/repos/cli/commands/purge.rb +39 -0
  23. data/lib/ronin/repos/cli/commands/remove.rb +71 -0
  24. data/lib/ronin/repos/cli/commands/update.rb +91 -0
  25. data/lib/ronin/repos/cli.rb +45 -0
  26. data/lib/ronin/repos/exceptions.rb +33 -0
  27. data/lib/ronin/repos/repository.rb +343 -0
  28. data/lib/ronin/repos/root.rb +26 -0
  29. data/lib/ronin/repos/version.rb +24 -0
  30. data/lib/ronin/repos.rb +81 -0
  31. data/man/ronin-repos-install.1 +64 -0
  32. data/man/ronin-repos-install.1.md +49 -0
  33. data/man/ronin-repos-list.1 +54 -0
  34. data/man/ronin-repos-list.1.md +41 -0
  35. data/man/ronin-repos-new.1 +37 -0
  36. data/man/ronin-repos-purge.1 +54 -0
  37. data/man/ronin-repos-purge.1.md +41 -0
  38. data/man/ronin-repos-remove.1 +60 -0
  39. data/man/ronin-repos-remove.1.md +46 -0
  40. data/man/ronin-repos-update.1 +64 -0
  41. data/man/ronin-repos-update.1.md +49 -0
  42. data/man/ronin-repos.1 +49 -0
  43. data/man/ronin-repos.1.md +37 -0
  44. data/ronin-repos.gemspec +62 -0
  45. data/spec/cache_dir_spec.rb +272 -0
  46. data/spec/class_dir_spec.rb +97 -0
  47. data/spec/fixtures/cache/repo1/dir/file1.txt +0 -0
  48. data/spec/fixtures/cache/repo1/file1.txt +0 -0
  49. data/spec/fixtures/cache/repo1/file2.txt +0 -0
  50. data/spec/fixtures/cache/repo2/dir/file1.txt +0 -0
  51. data/spec/fixtures/cache/repo2/dir/file2.txt +0 -0
  52. data/spec/fixtures/cache/repo2/file1.txt +0 -0
  53. data/spec/fixtures/cache/repo2/file2.txt +0 -0
  54. data/spec/fixtures/cache/repo2/only-exists-in-repo2.txt +0 -0
  55. data/spec/fixtures/class_dir/file1.rb +0 -0
  56. data/spec/fixtures/class_dir/file2.rb +0 -0
  57. data/spec/fixtures/class_dir/only_in_class_dir.rb +0 -0
  58. data/spec/repos_spec.rb +67 -0
  59. data/spec/repository_spec.rb +415 -0
  60. data/spec/spec_helper.rb +6 -0
  61. metadata +143 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/repos/cli/command'
20
+
21
+ module Ronin
22
+ module Repos
23
+ class CLI
24
+ module Commands
25
+ class Purge < Command
26
+
27
+ description 'Removes all git repository from the cache directory'
28
+
29
+ man_page 'ronin-repos-download.1'
30
+
31
+ def run
32
+ cache_dir.purge
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/repos/cli/command'
20
+
21
+ module Ronin
22
+ module Repos
23
+ class CLI
24
+ module Commands
25
+ #
26
+ # Deletes a repository from the cache directory.
27
+ #
28
+ # ## Usage
29
+ #
30
+ # ronin-repos remove [options] NAME
31
+ #
32
+ # ## Options
33
+ #
34
+ # -C, --cache-dir DIR Overrides the default cache directory
35
+ # -h, --help Print help information
36
+ #
37
+ # ## Arguments
38
+ #
39
+ # REPO URI of the git repository
40
+ #
41
+ class Remove < Command
42
+
43
+ usage '[options] NAME'
44
+
45
+ argument :name, required: true,
46
+ usage: 'REPO',
47
+ desc: 'URI of the git repository'
48
+
49
+ description 'Deletes a repository from the cache directory'
50
+
51
+ man_page 'ronin-repos-remove.1'
52
+
53
+ #
54
+ # Runs the `ronin-repos remove` command.
55
+ #
56
+ # @param [String] name
57
+ # The repository name to remove.
58
+ #
59
+ def run(name)
60
+ repo = cache_dir[name]
61
+ repo.delete
62
+ rescue RepositoryNotFound => error
63
+ print_error(error.message)
64
+ exit(-1)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/repos/cli/command'
20
+
21
+ require 'ronin/core/cli/logging'
22
+
23
+ module Ronin
24
+ module Repos
25
+ class CLI
26
+ module Commands
27
+ #
28
+ # Updates all or one repository from the cache directory.
29
+ #
30
+ # ## Usage
31
+ #
32
+ # ronin-repos update [options] [REPO]
33
+ #
34
+ # ## Options
35
+ #
36
+ # -C, --cache-dir DIR Overrides the default cache directory
37
+ # -h, --help Print help information
38
+ #
39
+ # ## Arguments
40
+ #
41
+ # [REPO] The repository to update
42
+ #
43
+ class Update < Command
44
+
45
+ include Core::CLI::Logging
46
+
47
+ usage '[options] [REPO]'
48
+
49
+ argument :name, required: false,
50
+ usage: 'REPO',
51
+ desc: 'The repository to update'
52
+
53
+ description 'Updates all or one repository from the cache directory'
54
+
55
+ man_page 'ronin-repos-update.1'
56
+
57
+ #
58
+ # Runs the `ronin-repos update` command.
59
+ #
60
+ # @param [String, nil] name
61
+ # The optional repository name to update.
62
+ #
63
+ def run(name=nil)
64
+ if name
65
+ begin
66
+ repo = cache_dir[name]
67
+
68
+ log_info "Updating repository #{repo} ..."
69
+ repo.update
70
+ rescue RepositoryNotFound, CommandFailed => error
71
+ log_error(error.message)
72
+ exit(-1)
73
+ end
74
+ else
75
+ cache_dir.each do |repo|
76
+ log_info "Updating repository #{repo} ..."
77
+
78
+ begin
79
+ repo.update
80
+ rescue CommandFailed => error
81
+ log_error("failed to update repository #{repo}: #{error.message}")
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'command_kit/commands'
20
+ require 'command_kit/commands/auto_load'
21
+
22
+ module Ronin
23
+ module Repos
24
+ #
25
+ # The `ronin-repos` command-line interface (CLI).
26
+ #
27
+ # @api private
28
+ #
29
+ class CLI
30
+
31
+ include CommandKit::Commands
32
+ include CommandKit::Commands::AutoLoad.new(
33
+ dir: "#{__dir__}/cli/commands",
34
+ namespace: "#{self}::Commands"
35
+ )
36
+
37
+ command_name 'ronin-repos'
38
+
39
+ command_aliases['ls'] = 'list'
40
+ command_aliases['up'] = 'update'
41
+ command_aliases['rm'] = 'remove'
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ module Ronin
20
+ module Repos
21
+ class Exception < RuntimeError
22
+ end
23
+
24
+ class RepositoryNotFound < Exception
25
+ end
26
+
27
+ class CommandNotInstalled < Exception
28
+ end
29
+
30
+ class CommandFailed < Exception
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,343 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/repos/exceptions'
20
+
21
+ require 'fileutils'
22
+
23
+ module Ronin
24
+ module Repos
25
+ #
26
+ # Represents an installed repository.
27
+ #
28
+ # @api private
29
+ #
30
+ class Repository
31
+
32
+ # The path to the repository's directory.
33
+ #
34
+ # @return [String]
35
+ attr_reader :path
36
+
37
+ # The name of the repository.
38
+ #
39
+ # @return [String]
40
+ attr_reader :name
41
+
42
+ #
43
+ # Initializes the repository.
44
+ #
45
+ # @param [String] path
46
+ # The path to the repository.
47
+ #
48
+ # @raise [RepositoryNotFound]
49
+ # The path does not exist or does not point to a directory.
50
+ #
51
+ def initialize(path)
52
+ @path = File.expand_path(path)
53
+
54
+ unless File.exist?(@path)
55
+ raise(RepositoryNotFound,"repository does not exist: #{@path.inspect}")
56
+ end
57
+
58
+ unless File.directory?(@path)
59
+ raise(RepositoryNotFound,"path is not a directory: #{@path.inspect}")
60
+ end
61
+
62
+ @name = File.basename(@path)
63
+ end
64
+
65
+ #
66
+ # Clones a repository.
67
+ #
68
+ # @param [String, URI::HTTPS] uri
69
+ # The `https://` or `git@HOST:PATH` SSH URI
70
+ #
71
+ # @param [String] path
72
+ # The path to where the repository will be cloned to.
73
+ #
74
+ # @param [Integer, nil] depth
75
+ # The number of commits to clone.
76
+ #
77
+ # @return [Repository]
78
+ # The newly cloned repository.
79
+ #
80
+ # @raise [CommandFailed]
81
+ # The `git` command failed.
82
+ #
83
+ # @raise [CommandNotFailed]
84
+ # The `git` command is not installed.
85
+ #
86
+ def self.clone(uri,path, depth: nil)
87
+ path = path.to_s
88
+ args = []
89
+
90
+ if depth
91
+ args << '--depth' << depth.to_s
92
+ end
93
+
94
+ args << uri.to_s
95
+ args << path.to_s
96
+
97
+ case system('git','clone',*args)
98
+ when nil
99
+ raise(CommandNotInstalled,"git is not installed")
100
+ when false
101
+ raise(CommandFailed,"command failed: git clone #{args.join(' ')}")
102
+ end
103
+
104
+ return new(path)
105
+ end
106
+
107
+ #
108
+ # Clones and installs a repository from the URI and to the destination
109
+ # path.
110
+ #
111
+ # @param [String, URI::HTTPS] uri
112
+ # The `https://` or `git@HOST:PATH` SSH URI
113
+ #
114
+ # @param [String] path
115
+ # The path to where the repository will be cloned to.
116
+ #
117
+ # @param [String, nil] branch
118
+ # The git branch to pull.
119
+ #
120
+ # @param [Boolean] tag
121
+ # Controls whether to pull git tags in addition to the git commits.
122
+ #
123
+ # @param [Hash{Symbol => Object}] kwargs
124
+ # Additional keyword arguments for {clone}.
125
+ #
126
+ # @return [Repository]
127
+ # The newly cloned repository.
128
+ #
129
+ # @raise [CommandFailed]
130
+ #
131
+ def self.install(uri,path, branch: nil, tag: nil, **kwargs)
132
+ repo = clone(uri,path, **kwargs)
133
+
134
+ if branch || tag
135
+ repo.checkout(branch || tag)
136
+ end
137
+
138
+ return repo
139
+ end
140
+
141
+ #
142
+ # Pulls down new git commits.
143
+ #
144
+ # @param [String] remote
145
+ # The git remote to pull from.
146
+ #
147
+ # @param [String, nil] branch
148
+ # The git branch to pull.
149
+ #
150
+ # @param [Boolean] tags
151
+ # Controls whether to pull git tags in addition to the git commits.
152
+ #
153
+ # @return [true]
154
+ # Indicates that the `git` command executed successfully.
155
+ #
156
+ # @raise [CommandFailed]
157
+ #
158
+ def pull(remote: 'origin', branch: nil, tags: nil)
159
+ args = []
160
+ args << '--tags' if tags
161
+
162
+ args << remote.to_s
163
+ args << branch.to_s if branch
164
+
165
+ Dir.chdir(@path) do
166
+ case system('git','pull',*args)
167
+ when nil
168
+ raise(CommandNotInstalled,"git is not installed")
169
+ when false
170
+ raise(CommandFailed,"command failed: git pull #{args.join(' ')}")
171
+ end
172
+ end
173
+ end
174
+
175
+ #
176
+ # Checks out the git branch or tag.
177
+ #
178
+ # @param [String] branch_or_tag
179
+ # The branch or tag name to checkout.
180
+ #
181
+ # @return [true]
182
+ # Indicates that the `git` command executed successfully.
183
+ #
184
+ # @raise [CommandFailed]
185
+ #
186
+ def checkout(branch_or_tag)
187
+ Dir.chdir(@path) do
188
+ case system('git','checkout',branch_or_tag)
189
+ when nil
190
+ raise(CommandNotInstalled,"git is not installed")
191
+ when false
192
+ raise(CommandFailed,"command failed: git checkout #{branch_or_tag}")
193
+ end
194
+ end
195
+ end
196
+
197
+ #
198
+ # Updates the repository.
199
+ #
200
+ # @param [String, nil] branch
201
+ # The optional git branch to update from.
202
+ #
203
+ # @param [String, nil] tag
204
+ # The optional git tag to update to.
205
+ #
206
+ # @param [Hash{Symbol => Object}] kwargs
207
+ # Additional keyword arguments for {#pull}.
208
+ #
209
+ # @return [true]
210
+ # Indicates that the `git` commands executed successfully.
211
+ #
212
+ # @raise [CommandFailed]
213
+ # One of the `git` commands failed.
214
+ #
215
+ def update(branch: nil, tag: nil, **kwargs)
216
+ pull(branch: branch, tags: branch.nil?, **kwargs)
217
+
218
+ if branch || tag
219
+ checkout(branch || tag)
220
+ end
221
+ end
222
+
223
+ #
224
+ # Deletes the repository directory.
225
+ #
226
+ def delete
227
+ FileUtils.rm_rf(@path)
228
+ end
229
+
230
+ #
231
+ # Converts a relative path to an absolute path.
232
+ #
233
+ # @param [String] relative_path
234
+ # The relative path of the file.
235
+ #
236
+ # @return [String]
237
+ # The absolute path with respect to the repository.
238
+ #
239
+ def join(relative_path)
240
+ File.join(@path,relative_path)
241
+ end
242
+
243
+ #
244
+ # Determines if the repository contains the file.
245
+ #
246
+ # @param [String] relative_path
247
+ # The relative path of the file.
248
+ #
249
+ # @return [Boolean]
250
+ # Indicates whether the repository contains the file or not.
251
+ #
252
+ def has_file?(relative_path)
253
+ File.file?(join(relative_path))
254
+ end
255
+
256
+ #
257
+ # Determines if the repository contains the directory.
258
+ #
259
+ # @param [String] relative_path
260
+ # The relative path of the directory.
261
+ #
262
+ # @return [Boolean]
263
+ # Indicates whether the repository contains the directory or not.
264
+ #
265
+ def has_directory?(relative_path)
266
+ File.directory?(join(relative_path))
267
+ end
268
+
269
+ #
270
+ # Finds a file within the repository.
271
+ #
272
+ # @param [String] relative_path
273
+ # The relative path of the file.
274
+ #
275
+ # @return [String, nil]
276
+ # The absolute path of the matching file or `nil` if no matching file
277
+ # could be found.
278
+ #
279
+ # @example
280
+ # repo.find_file("wordlists/wordlist.txt")
281
+ # # => "/home/user/.cache/ronin-repos/foo-repo/wordlists/wordlist.txt"
282
+ #
283
+ def find_file(relative_path)
284
+ path = join(relative_path)
285
+
286
+ if File.file?(path)
287
+ return path
288
+ end
289
+ end
290
+
291
+ #
292
+ # Finds all files in the repository that matches the glob pattern.
293
+ #
294
+ # @param [String] pattern
295
+ # The file glob pattern to search for.
296
+ #
297
+ # @return [Array<String>]
298
+ # The absolute paths to the files that match the glob pattern.
299
+ #
300
+ # @example
301
+ # repo.glob("wordlists/*.txt")
302
+ # # => ["/home/user/.cache/ronin-repos/foo-repo/wordlists/cities.txt",
303
+ # # "/home/user/.cache/ronin-repos/foo-repo/wordlists/states.txt"]
304
+ #
305
+ def glob(pattern,&block)
306
+ path = join(pattern)
307
+ matches = Dir.glob(path).sort
308
+
309
+ if block then matches.each(&block)
310
+ else matches
311
+ end
312
+ end
313
+
314
+ #
315
+ # Lists the paths within the repository.
316
+ #
317
+ # @param [String] pattern
318
+ # The optional glob pattern to use to list specific files.
319
+ #
320
+ # @return [Array<String>]
321
+ # The matching paths within the repository.
322
+ #
323
+ # @example
324
+ # repo.list_files('exploits/{**/}*.rb')
325
+ # # => ["exploits/exploit1.rb", "exploits/exploit2.rb"]
326
+ #
327
+ def list_files(pattern='{**/}*.*')
328
+ Dir.glob(pattern, base: @path)
329
+ end
330
+
331
+ #
332
+ # Converts the repository to a String.
333
+ #
334
+ # @return [String]
335
+ # The name of the repository.
336
+ #
337
+ def to_s
338
+ @name
339
+ end
340
+
341
+ end
342
+ end
343
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ module Ronin
20
+ module Repos
21
+ # Path to `ronin-repos` root directory.
22
+ #
23
+ # @api private
24
+ ROOT = File.expand_path(File.join(__dir__,'..','..','..'))
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-repos is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-repos is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-repos. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ module Ronin
20
+ module Repos
21
+ # ronin-repos version
22
+ VERSION = '0.1.0.beta1'
23
+ end
24
+ end