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,267 @@
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
+ require 'ronin/repos/repository'
21
+ require 'ronin/core/home'
22
+
23
+ require 'set'
24
+
25
+ module Ronin
26
+ module Repos
27
+ #
28
+ # Manages the `~/.cache/ronin-repos/` directory and the repositories
29
+ # contained within.
30
+ #
31
+ # @api private
32
+ #
33
+ class CacheDir
34
+
35
+ include Enumerable
36
+
37
+ # The ~/.cache/ronin-repos/ directory where all repos are stored.
38
+ PATH = Core::Home.cache_dir('ronin-repos')
39
+
40
+ # The path to the cache directory.
41
+ #
42
+ # @return [String]
43
+ attr_reader :path
44
+
45
+ #
46
+ # Initializes the repository cache.
47
+ #
48
+ # @param [String] path
49
+ # The path to the repository cache directory.
50
+ #
51
+ def initialize(path=PATH)
52
+ @path = path
53
+ end
54
+
55
+ #
56
+ # Accesses a repository from the cache directory.
57
+ #
58
+ # @param [String] name
59
+ # The name of the repository.
60
+ #
61
+ # @return [Repository]
62
+ # The repository from the cache.
63
+ #
64
+ # @raise [RepositoryNotFound]
65
+ # No repository exists with the given name in the cache directory.
66
+ #
67
+ def [](name)
68
+ path = File.join(@path,name.to_s)
69
+
70
+ unless File.directory?(path)
71
+ raise(RepositoryNotFound,"repository not found: #{name.inspect}")
72
+ end
73
+
74
+ return Repository.new(path)
75
+ end
76
+
77
+ #
78
+ # Enumerates through every repository in the cache directory.
79
+ #
80
+ # @yield [repo]
81
+ # The given block will be passed each repository.
82
+ #
83
+ # @yieldparam [Repository] repo
84
+ # A repository from the cache directory.
85
+ #
86
+ # @return [Enumerator]
87
+ # If no block is given, an Enumerator will be returned.
88
+ #
89
+ def each
90
+ return enum_for unless block_given?
91
+
92
+ each_child_directory do |path|
93
+ yield Repository.new(path)
94
+ end
95
+ end
96
+
97
+ #
98
+ # Clones and installs a repository into the cache directory.
99
+ #
100
+ # @param [String, URI::HTTPS] uri
101
+ # The URI to clone the repository from.
102
+ #
103
+ # @param [String, nil] name
104
+ # The explicit name of the repository to use. Defaults to the base-name
105
+ # of the URI's path, sans any `.git` extension.
106
+ #
107
+ # @return [Repository]
108
+ # The newly installed repository.
109
+ #
110
+ # @raise [CommandFailed]
111
+ # One of the `git` commands failed.
112
+ #
113
+ # @raise [CommandNotInstalled]
114
+ # The `git` command is not installed.
115
+ #
116
+ def install(uri,name=nil)
117
+ uri = uri.to_s
118
+ name ||= File.basename(uri,File.extname(uri))
119
+ path = File.join(@path,name)
120
+
121
+ return Repository.install(uri,path)
122
+ end
123
+
124
+ #
125
+ # Updates all repositories in the cache directory.
126
+ #
127
+ # @raise [CommandNotInstalled]
128
+ # The `git` command is not installed.
129
+ #
130
+ def update
131
+ each do |repo|
132
+ begin
133
+ repo.update
134
+ rescue CommandFailed
135
+ end
136
+ end
137
+ end
138
+
139
+ #
140
+ # Removes a repository from the cache directory.
141
+ #
142
+ # @param [String] name
143
+ # The repository name to find and delete.
144
+ #
145
+ # @raise [RepositoryNotFound]
146
+ # The repository with the given name does not exist in the cache
147
+ # directory.
148
+ #
149
+ def remove(name)
150
+ self[name].delete
151
+ end
152
+
153
+ #
154
+ # Deletes all repositories in the cache directory.
155
+ #
156
+ def purge
157
+ each(&:delete)
158
+ end
159
+
160
+ #
161
+ # Finds the first matching file.
162
+ #
163
+ # @param [String] path
164
+ # The relative path of the file.
165
+ #
166
+ # @return [String, nil]
167
+ # The absolute path of the matching file or `nil` if no matching file
168
+ # could be found.
169
+ #
170
+ # @example
171
+ # repos.find_file("wordlists/wordlist.txt")
172
+ # # => "/home/user/.cache/ronin-repos/foo-repo/wordlists/wordlist.txt"
173
+ #
174
+ def find_file(path)
175
+ each do |repo|
176
+ if (file = repo.find_file(path))
177
+ return file
178
+ end
179
+ end
180
+ end
181
+
182
+ #
183
+ # Finds all files in all repos that matches the glob pattern.
184
+ #
185
+ # @param [String] pattern
186
+ # The file glob pattern to search for.
187
+ #
188
+ # @return [Array<String>]
189
+ # The absolute paths to the files that match the glob pattern.
190
+ #
191
+ # @example
192
+ # repos.glob("wordlists/*.txt")
193
+ # # => ["/home/user/.cache/ronin-repos/foo-repo/wordlists/cities.txt",
194
+ # # "/home/user/.cache/ronin-repos/foo-repo/wordlists/states.txt",
195
+ # # "/home/user/.cache/ronin-repos/bar-repo/wordlists/bands.txt",
196
+ # # "/home/user/.cache/ronin-repos/bar-repo/wordlists/beers.txt"]
197
+ #
198
+ def glob(pattern,&block)
199
+ return enum_for(__method__,pattern).to_a unless block_given?
200
+
201
+ each do |repo|
202
+ repo.glob(pattern,&block)
203
+ end
204
+ end
205
+
206
+ #
207
+ # Lists all files across all repos installed in the cache directory.
208
+ #
209
+ # @param [String] pattern
210
+ # The optional glob pattern to use to list specific files.
211
+ #
212
+ # @return [Set<String>]
213
+ # The matching paths within the repository.
214
+ #
215
+ # @example
216
+ # repos.list_files('exploits/{**/}*.rb')
217
+ # # => #<Set: {"exploits/exploit1.rb", "exploits/exploit2.rb"}>
218
+ #
219
+ def list_files(pattern='{**/}*.*')
220
+ each_with_object(Set.new) do |repo,files|
221
+ files.merge(repo.list_files(pattern))
222
+ end
223
+ end
224
+
225
+ #
226
+ # Converts the cache directory to a String.
227
+ #
228
+ # @return [String]
229
+ # The path to the cache directory.
230
+ #
231
+ def to_s
232
+ @path
233
+ end
234
+
235
+ private
236
+
237
+ #
238
+ # Enumerates over each directory in the cache directory.
239
+ #
240
+ # @yield [dir]
241
+ # The given block will be passed each repository's directory path.
242
+ #
243
+ # @yieldparam [String] dir
244
+ # A path to a repository directory within the cache directory.
245
+ #
246
+ # @return [Enumerator]
247
+ # If no block is given, an Enumerator will be returned.
248
+ #
249
+ def each_child_directory
250
+ return enum_for(__method__) unless block_given?
251
+
252
+ if File.directory?(@path)
253
+ Dir.children(@path).sort.each do |name|
254
+ path = File.join(@path,name)
255
+
256
+ if File.directory?(path)
257
+ yield path
258
+ end
259
+ end
260
+ end
261
+
262
+ return nil
263
+ end
264
+
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,150 @@
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'
20
+ require 'ronin/core/class_registry'
21
+
22
+ require 'set'
23
+
24
+ module Ronin
25
+ module Repos
26
+ #
27
+ # Adds the ability to load classes from directories within installed
28
+ # repositories.
29
+ #
30
+ # ## Example
31
+ #
32
+ # `lib/ronin/exploits.rb`:
33
+ #
34
+ # require 'ronin/core/module_registry'
35
+ # require 'ronin/repos/class_dir'
36
+ #
37
+ # module Ronin
38
+ # module Exploits
39
+ # include Ronin::Core::ClassRegistry
40
+ # include Ronin::Repos::ClassDir
41
+ #
42
+ # class_dir "#{__dir__}/classes"
43
+ # repo_class_dir "exploits"
44
+ # end
45
+ # end
46
+ #
47
+ # `lib/ronin/exploits/exploit.rb`:
48
+ #
49
+ # module Ronin
50
+ # module Exploits
51
+ # class Exploit
52
+ #
53
+ # def self.register(name)
54
+ # Exploits.register(name,self)
55
+ # end
56
+ #
57
+ # end
58
+ # end
59
+ # end
60
+ #
61
+ # `~/.cache/ronin-repos/repo1/exploits/my_exploit.rb`:
62
+ #
63
+ # require 'ronin/exploits/exploit'
64
+ #
65
+ # module Ronin
66
+ # module Exploits
67
+ # class MyExploit < Exploit
68
+ #
69
+ # register 'my_exploit'
70
+ #
71
+ # end
72
+ # end
73
+ # end
74
+ #
75
+ # @api semipublic
76
+ #
77
+ module ClassDir
78
+ #
79
+ # Includes `Ronin::Core::ClassRegistry` and adds {ClassMethods}.
80
+ #
81
+ # @param [Module] namespace
82
+ # The module that is including {ClassDir}.
83
+ #
84
+ # @api private
85
+ #
86
+ def self.included(namespace)
87
+ namespace.send :include, Core::ClassRegistry
88
+ namespace.extend ClassMethods
89
+ end
90
+
91
+ module ClassMethods
92
+ #
93
+ # Gets or sets the repository module directory name.
94
+ #
95
+ # @param [String, nil] new_dir
96
+ # The new module directory path.
97
+ #
98
+ # @return [String]
99
+ # The repository module directory name.
100
+ #
101
+ # @raise [NotImplementedError]
102
+ # The `repo_class_dir` method was not defined in the module.
103
+ #
104
+ # @example
105
+ # repo_class_dir "exploits"
106
+ #
107
+ def repo_class_dir(new_dir=nil)
108
+ if new_dir
109
+ @repo_class_dir = new_dir
110
+ else
111
+ @repo_class_dir || raise(NotImplementedError,"#{self} did not define a repo_class_dir")
112
+ end
113
+ end
114
+
115
+ #
116
+ # List the module names within the `class_dir` and within
117
+ # {#repo_class_dir} across all installed repositories.
118
+ #
119
+ # @return [Array<String>]
120
+ #
121
+ def list_files
122
+ modules = Set.new(super)
123
+ pattern = File.join(repo_class_dir,"{**/}*.rb")
124
+
125
+ Repos.list_files(pattern).each do |path|
126
+ modules << path.chomp('.rb')
127
+ end
128
+
129
+ return modules.to_a
130
+ end
131
+
132
+ #
133
+ # Finds a module within `class_dir` or within `repo_class_dir`
134
+ # in one of the installed repositories.
135
+ #
136
+ # @param [String] name
137
+ # The module name to lookup.
138
+ #
139
+ # @return [String, nil]
140
+ # The path to the module or `nil` if the module could not be found
141
+ # in `class_dir` or any of the installed repositories.
142
+ #
143
+ def path_for(name)
144
+ super(name) ||
145
+ Repos.find_file(File.join(repo_class_dir,"#{name}.rb"))
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,63 @@
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/root'
20
+ require 'ronin/repos/cache_dir'
21
+
22
+ require 'ronin/core/cli/command'
23
+
24
+ module Ronin
25
+ module Repos
26
+ class CLI
27
+ class Command < Core::CLI::Command
28
+
29
+ man_dir File.join(ROOT,'man')
30
+
31
+ bug_report_url 'https://github.com/ronin-rb/ronin-repos/issues/new'
32
+
33
+ option :cache_dir, short: '-C',
34
+ value: {
35
+ type: String,
36
+ usage: 'DIR'
37
+ },
38
+ desc: 'Overrides the default cache directory' do |dir|
39
+ @cache_dir = CacheDir.new(dir)
40
+ end
41
+
42
+
43
+ # The ronin-repos cache directory.
44
+ #
45
+ # @return [CacheDir]
46
+ attr_reader :cache_dir
47
+
48
+ #
49
+ # Initializes the command.
50
+ #
51
+ # @param [Hash{Symbol => Object}] kwargs
52
+ # Additional keyword arguments for `initialize`.
53
+ #
54
+ def initialize(**kwargs)
55
+ super(**kwargs)
56
+
57
+ @cache_dir = CacheDir.new
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ 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
+ # Installs a git repository into the cache directory.
27
+ #
28
+ # ## Usage
29
+ #
30
+ # ronin-repos install [options] [REPO]
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
+ # URI URI of the git repository
40
+ #
41
+ class Install < Command
42
+
43
+ usage '[options] URI'
44
+
45
+ argument :uri, required: true,
46
+ usage: 'URI',
47
+ desc: 'URI of the git repository'
48
+
49
+ description 'Installs a git repository into the cache directory'
50
+
51
+ man_page 'ronin-repos-install.1'
52
+
53
+ #
54
+ # Runs the `ronin-repos install` command.
55
+ #
56
+ # @param [String] uri
57
+ # The repository's git URI to install from.
58
+ #
59
+ def run(uri)
60
+ log_info "Installing repository from #{uri} ..."
61
+ cache_dir.download(uri)
62
+ rescue CommandFailed => 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,80 @@
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
+ # Lists all repositories in the cache directory.
27
+ #
28
+ # ## Usage
29
+ #
30
+ # ronin-repos list [options] [REPO]
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] Optional repository name to list
40
+ #
41
+ class List < Command
42
+
43
+ usage '[options] [REPO]'
44
+
45
+ argument :name, required: false,
46
+ usage: 'REPO',
47
+ desc: 'Optional repository name to list'
48
+
49
+ description 'Lists all repositories in the cache directory'
50
+
51
+ man_page 'ronin-repos-list.1'
52
+
53
+ #
54
+ # Runs the `ronin-repos list` command.
55
+ #
56
+ # @param [String, nil] name
57
+ # The optional repo name to list.
58
+ #
59
+ def run(name=nil)
60
+ if name
61
+ begin
62
+ repo = cache_dir[name]
63
+
64
+ puts " #{repo}"
65
+ rescue RepositoryNotFound => error
66
+ print_error(error.message)
67
+ exit(-1)
68
+ end
69
+ else
70
+ cache_dir.each do |repo|
71
+ puts " #{repo}"
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,83 @@
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
+ require 'ronin/repos/root'
21
+
22
+ require 'ronin/core/cli/generator'
23
+ require 'ronin/core/git'
24
+
25
+ module Ronin
26
+ module Repos
27
+ class CLI
28
+ module Commands
29
+ #
30
+ # Creates a new git repository.
31
+ #
32
+ # ## Usage
33
+ #
34
+ # ronin-repos new [options] PATH
35
+ #
36
+ # ## Options
37
+ #
38
+ # -C, --cache-dir DIR Overrides the default cache directory
39
+ # -h, --help Print help information
40
+ #
41
+ # ## Arguments
42
+ #
43
+ # PATH The path to the new repository
44
+ #
45
+ class New < Command
46
+
47
+ include Core::CLI::Generator
48
+
49
+ template_dir File.join(ROOT,'data','templates','repo')
50
+
51
+ usage '[options] PATH'
52
+
53
+ argument :path, desc: 'The path to the new repository'
54
+
55
+ description 'Creates a new git repository'
56
+
57
+ man_page 'ronin-repos.1'
58
+
59
+ #
60
+ # Runs the `ronin-repos new` command.
61
+ #
62
+ # @param [String] path
63
+ # The path to the new repo directory to create.
64
+ #
65
+ def run(path)
66
+ @name = File.basename(path)
67
+ @github_user = Core::Git.github_user || ENV['USER']
68
+
69
+ mkdir path
70
+ erb 'README.md.erb', File.join(path,'README.md')
71
+
72
+ Dir.chdir(path) do
73
+ sh 'git', 'init', '-q', '-b', 'main'
74
+ sh 'git', 'add', 'README.md'
75
+ sh 'git', 'commit', '-q', '-m', 'Initial commit.'
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end