nugem 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +91 -0
- data/CHANGELOG.md +12 -0
- data/README.md +317 -0
- data/Rakefile +40 -0
- data/lib/nugem/cli/cli_gem.rb +61 -0
- data/lib/nugem/cli/cli_jekyll.rb +192 -0
- data/lib/nugem/cli/cli_rails.rb +60 -0
- data/lib/nugem/cli/jekyll_demo.rb +60 -0
- data/lib/nugem/cli.rb +90 -0
- data/lib/nugem/git.rb +81 -0
- data/lib/nugem/repository.rb +53 -0
- data/lib/nugem/version.rb +3 -0
- data/lib/nugem.rb +31 -0
- data/lib/util.rb +11 -0
- data/nugem.gemspec +23 -0
- data/spec/jekyll_tag_spec.rb +89 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/status_persistence.txt +0 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8bd31585552b513ce66b36f8902a1a06bcc9e508ad45d98cd6ad327b593bc3c5
|
4
|
+
data.tar.gz: bf467fb473d869fbd29d648688822226f6c02cc8b63bb9de9123f2c7e2d83ded
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5fbe5a7757e4986a7b4992dbe67797a9d1a488e300e0d4611ad39daaddba91b04cc590317555f73747532aece87288e320d98312f272d80e8509c0c03a4176fe
|
7
|
+
data.tar.gz: b8373ad340266e1837890c29d8730f277fdfcc3e3610183a572d5e4593dff7314ecaff214c98be7a9ab7ed4ebc99e382746c9cceae6d67030aac6d6a150d44d5
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require:
|
2
|
+
# - rubocop-jekyll
|
3
|
+
- rubocop-md
|
4
|
+
- rubocop-performance
|
5
|
+
- rubocop-rake
|
6
|
+
- rubocop-rspec
|
7
|
+
|
8
|
+
AllCops:
|
9
|
+
Exclude:
|
10
|
+
- binstub/**/*
|
11
|
+
- exe/**/*
|
12
|
+
- generated/**/binstub/*
|
13
|
+
- generated/**/exe/**/*
|
14
|
+
- vendor/**/*
|
15
|
+
- Gemfile*
|
16
|
+
- Rakefile
|
17
|
+
- README.md
|
18
|
+
NewCops: enable
|
19
|
+
TargetRubyVersion: 3.1.3
|
20
|
+
|
21
|
+
Gemspec/DeprecatedAttributeAssignment:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Gemspec/RequireMFA:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Layout/ArgumentAlignment:
|
28
|
+
EnforcedStyle: with_fixed_indentation
|
29
|
+
|
30
|
+
Layout/HashAlignment:
|
31
|
+
EnforcedColonStyle: table
|
32
|
+
EnforcedHashRocketStyle: table
|
33
|
+
|
34
|
+
Layout/LineLength:
|
35
|
+
Max: 150
|
36
|
+
|
37
|
+
Layout/MultilineMethodCallIndentation:
|
38
|
+
EnforcedStyle: indented_relative_to_receiver
|
39
|
+
|
40
|
+
Metrics/AbcSize:
|
41
|
+
Max: 45
|
42
|
+
|
43
|
+
Metrics/BlockLength:
|
44
|
+
Exclude:
|
45
|
+
- nugem.gemspec
|
46
|
+
Max: 30
|
47
|
+
|
48
|
+
Metrics/ClassLength:
|
49
|
+
Exclude:
|
50
|
+
- spec/*.rb
|
51
|
+
|
52
|
+
Metrics/CyclomaticComplexity:
|
53
|
+
Max: 20
|
54
|
+
|
55
|
+
Metrics/MethodLength:
|
56
|
+
Max: 40
|
57
|
+
|
58
|
+
Metrics/ModuleLength:
|
59
|
+
Enabled: false
|
60
|
+
|
61
|
+
Metrics/PerceivedComplexity:
|
62
|
+
Max: 15
|
63
|
+
|
64
|
+
Naming/FileName:
|
65
|
+
Exclude:
|
66
|
+
- Rakefile
|
67
|
+
|
68
|
+
Style/Documentation:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
Style/FrozenStringLiteralComment:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Style/StringConcatenation:
|
75
|
+
Mode: conservative
|
76
|
+
|
77
|
+
Style/TrailingCommaInHashLiteral:
|
78
|
+
EnforcedStyleForMultiline: comma
|
79
|
+
|
80
|
+
Style/TrailingCommaInArrayLiteral:
|
81
|
+
EnforcedStyleForMultiline: comma
|
82
|
+
|
83
|
+
RSpec/FilePath:
|
84
|
+
IgnoreMethods: true
|
85
|
+
SpecSuffixOnly: true
|
86
|
+
|
87
|
+
RSpec/ExampleLength:
|
88
|
+
Enabled: false
|
89
|
+
|
90
|
+
RSpec/MultipleExpectations:
|
91
|
+
Max: 15
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
## 0.8.0
|
2
|
+
* Updated dependencies and `README`.
|
3
|
+
* Renamed the `gem` subcommand to `plain`.
|
4
|
+
* Renamed the `plugin` subcommand to `rails`.
|
5
|
+
* Added `CHANGELOG`, `.rspec`, `.rubocop` and `.vscode/`.
|
6
|
+
* Added `binstubs/`.
|
7
|
+
* Using `require_relative` where appropriate.
|
8
|
+
* Changed the default for including an executable to `false`.
|
9
|
+
* Added the `--quiet` and `--todos` options, common to the `plain`, `jekyll` and `rails` subcommands.
|
10
|
+
|
11
|
+
## 0.7.4
|
12
|
+
* Last release was 7 years prior without a change history.
|
data/README.md
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
# `Nugem` [![Gem Version](https://badge.fury.io/rb/nugem.svg)](https://badge.fury.io/rb/nugem)
|
2
|
+
|
3
|
+
## WORK IN PROGRESS
|
4
|
+
|
5
|
+
`Nugem` creates a scaffold project for a new gem in a new git repository.
|
6
|
+
After you add your special code to the gem scaffold,
|
7
|
+
the project is ready to be released to a public or private gem server.
|
8
|
+
|
9
|
+
This gem generates a scaffold with all files you need to start,
|
10
|
+
with the following features:
|
11
|
+
|
12
|
+
- Generates a README with badges.
|
13
|
+
- Automatically creates local and remote git repositories (on GitHub, BitBucket or Geminabox) for your new gem.
|
14
|
+
- Remote repositories can be private or public.
|
15
|
+
- Can include a [Thor-based executable](https://github.com/rails/thor).
|
16
|
+
- Creates a test infrastructure based on `rspec` or `minitest` and `minitest-reporters`.
|
17
|
+
- Ready to publicly release to `rubygems.org` or to a private Geminabox gem server.
|
18
|
+
- Optionally create the gem as:
|
19
|
+
- A Rails plugin, possibly with a mountable engine.
|
20
|
+
- A Jekyll plugin (tag, block tag, filter, generator, or hooks).
|
21
|
+
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
```shell
|
26
|
+
$ gem install nugem
|
27
|
+
```
|
28
|
+
|
29
|
+
To update the program:
|
30
|
+
|
31
|
+
```shell
|
32
|
+
$ gem update nugem
|
33
|
+
```
|
34
|
+
|
35
|
+
|
36
|
+
## Subcommands and Options
|
37
|
+
|
38
|
+
`Nugem` has 4 subcommands `plain`, `jekyll`, `help` and `rails`:
|
39
|
+
|
40
|
+
### `help` Subcommand
|
41
|
+
|
42
|
+
The following lists the available subcommands:
|
43
|
+
|
44
|
+
```shell
|
45
|
+
$ nugem help
|
46
|
+
```
|
47
|
+
|
48
|
+
The following provides detailed help for the specified subcommand:
|
49
|
+
|
50
|
+
```shell
|
51
|
+
$ nugem help [SUBCOMMAND]
|
52
|
+
```
|
53
|
+
|
54
|
+
|
55
|
+
### Common Options
|
56
|
+
|
57
|
+
The `plain`, `jekyll` and `rails` subcommands have common options.
|
58
|
+
|
59
|
+
The default option values assume that:
|
60
|
+
|
61
|
+
- You do not want an executable for your gem scaffold
|
62
|
+
- The gem project will be hosted on a public GitHub git repository
|
63
|
+
- The gem will be released to `rubygems.org`
|
64
|
+
|
65
|
+
Common options for the `plain`, `jekyll` and `rails` subcommands are:
|
66
|
+
|
67
|
+
<dl>
|
68
|
+
<dt><code>--executable</code></dt>
|
69
|
+
<dd>add an executable based on Thor.</dd>
|
70
|
+
|
71
|
+
<dt><code>--host</code></dt>
|
72
|
+
<dd>
|
73
|
+
specifies the git host; possible values are <code>bitbucket</code>, <code>github</code> and <code>geminabox</code>.
|
74
|
+
</dd>
|
75
|
+
|
76
|
+
<dt><code>--private</code></dt>
|
77
|
+
<dd>the remote repository is made private,
|
78
|
+
and on release the gem will be pushed to a private Geminabox server.
|
79
|
+
</dd>
|
80
|
+
|
81
|
+
<dt><code>--quiet</code></dt>
|
82
|
+
<dd>reduces verbosity.</dd>
|
83
|
+
|
84
|
+
<dt><code>--no-todos</code></dt>
|
85
|
+
<dd>do not generate `TODO:` strings in generated code.</dd>
|
86
|
+
</dl>
|
87
|
+
|
88
|
+
|
89
|
+
### Common Behavior
|
90
|
+
|
91
|
+
The `plain`, `jekyll` and `rails` subcommands have common behavior.
|
92
|
+
|
93
|
+
Gem scaffolds are created within the `generated/` directory.
|
94
|
+
|
95
|
+
If your user name is not already stored in your git global config,
|
96
|
+
you will be asked for your GitHub or BitBucket user name.
|
97
|
+
You will also be asked to enter your GitHub or BitBucket password when the remote repository is created for you.
|
98
|
+
|
99
|
+
After you create the gem, edit the `gemspec` and change the summary and the description.
|
100
|
+
Then commit the changes to git and invoke `rake release`,
|
101
|
+
and your gem will be published.
|
102
|
+
|
103
|
+
|
104
|
+
### `plain` Subcommand
|
105
|
+
|
106
|
+
```shell
|
107
|
+
$ nugem plain NAME [COMMON_OPTIONS] [--test-framework=minitest|rspec]
|
108
|
+
```
|
109
|
+
|
110
|
+
`NAME` is the name of the gem to be generated.
|
111
|
+
|
112
|
+
The default test framework for the `plain` subcommand is `rspec`,
|
113
|
+
but you can specify `minitest` instead like this:
|
114
|
+
|
115
|
+
```shell
|
116
|
+
$ nugem plain my_gem --test-framework=minitest
|
117
|
+
```
|
118
|
+
|
119
|
+
|
120
|
+
### `jekyll` Subcommand
|
121
|
+
|
122
|
+
The `jekyll` subcommand extends the `plain` subcommand and creates a new Jekyll plugin with the given NAME:
|
123
|
+
|
124
|
+
```shell
|
125
|
+
$ nugem jekyll NAME [OPTIONS]
|
126
|
+
```
|
127
|
+
|
128
|
+
`NAME` is the name of the Jekyll plugin gem to be generated.
|
129
|
+
|
130
|
+
In addition to the common options, the `jekyll`-specific `OPTIONS` are:
|
131
|
+
|
132
|
+
`--block`, `--blockn`, `--filter`, `--hooks`, `--tag`, and `--tagn`.
|
133
|
+
|
134
|
+
Each of these options causes `nugem` to prompt the user for additional input.
|
135
|
+
|
136
|
+
The test framework for `jekyll` plugins is `rspec`.
|
137
|
+
|
138
|
+
All of the above options can be specified more than once,
|
139
|
+
except the `--hooks` option.
|
140
|
+
For example:
|
141
|
+
|
142
|
+
```shell
|
143
|
+
$ nugem jekyll test_tags --tag my_tag1 --tag my_tag2
|
144
|
+
```
|
145
|
+
|
146
|
+
The above creates a Jekyll plugin called `test_tags`,
|
147
|
+
which defines Jekyll tags called `my_tag1` and `my_tag2`.
|
148
|
+
You might use these tags in an HTML document like this:
|
149
|
+
|
150
|
+
```html
|
151
|
+
<pre>
|
152
|
+
my_tag1 usage: {% my_tag1 %}
|
153
|
+
my_tag2 usage: {% my_tag2 %}
|
154
|
+
</pre>
|
155
|
+
```
|
156
|
+
|
157
|
+
For more information, type
|
158
|
+
|
159
|
+
```shell
|
160
|
+
$ nugem help jekyll
|
161
|
+
```
|
162
|
+
|
163
|
+
|
164
|
+
### `rails` Subcommand
|
165
|
+
|
166
|
+
The `rails` subcommand extends the `plain` subcommand and creates a new Rails plugin with the given NAME:
|
167
|
+
|
168
|
+
```shell
|
169
|
+
$ nugem rails NAME [OPTIONS]
|
170
|
+
```
|
171
|
+
|
172
|
+
`NAME` is the name of the Ruby on Rails plugin gem to be generated.
|
173
|
+
|
174
|
+
In addition to the common options, `rails` `OPTIONS` are
|
175
|
+
`--engine` and `--mountable`.
|
176
|
+
|
177
|
+
You can specify if the plugin should be an engine (`--engine`) or a mountable engine (`--mountable`).
|
178
|
+
|
179
|
+
Each of these options causes `nugem` to prompt the user for additional input.
|
180
|
+
|
181
|
+
The test framework for `rails` gems is `minitest`.
|
182
|
+
|
183
|
+
For more information, type
|
184
|
+
|
185
|
+
```shell
|
186
|
+
$ nugem help rails
|
187
|
+
```
|
188
|
+
|
189
|
+
|
190
|
+
## Did It Work?
|
191
|
+
|
192
|
+
The following shows all files that were committed to the newly created git repository,
|
193
|
+
after `nugem jekyll` finished making two tag blocks:
|
194
|
+
|
195
|
+
```shell
|
196
|
+
$ git ls-tree --name-only --full-tree -r HEAD
|
197
|
+
.envrc
|
198
|
+
.gitignore
|
199
|
+
.rspec
|
200
|
+
.rubocop.yml
|
201
|
+
.simplecov
|
202
|
+
.travis.yml
|
203
|
+
.vscode/extensions.json
|
204
|
+
.vscode/launch.json
|
205
|
+
.vscode/settings.json
|
206
|
+
CHANGELOG.md
|
207
|
+
Gemfile
|
208
|
+
LICENCE.txt
|
209
|
+
README.md
|
210
|
+
Rakefile
|
211
|
+
bin/attach
|
212
|
+
bin/console
|
213
|
+
bin/rake
|
214
|
+
bin/setup
|
215
|
+
demo/Gemfile
|
216
|
+
demo/_bin/debug
|
217
|
+
demo/_config.yml
|
218
|
+
demo/_drafts/2022/2022-05-01-test2.html
|
219
|
+
demo/_includes/block_tag_template_wrapper
|
220
|
+
demo/_layouts/default.html
|
221
|
+
demo/_posts/2022/2022-01-02-redact-test.html
|
222
|
+
demo/assets/css/style.css
|
223
|
+
demo/assets/images/404-error.png
|
224
|
+
demo/assets/images/404-error.webp
|
225
|
+
demo/assets/images/favicon.png
|
226
|
+
demo/assets/images/jekyll.png
|
227
|
+
demo/assets/images/jekyll.webp
|
228
|
+
demo/assets/js/clipboard.min.js
|
229
|
+
demo/assets/js/jquery-3.4.1.min.js
|
230
|
+
demo/blog/blogsByDate.html
|
231
|
+
demo/blog/index.html
|
232
|
+
demo/index.html
|
233
|
+
jekyll_test.code-workspace
|
234
|
+
jekyll_test.gemspec
|
235
|
+
lib/jekyll_test.rb
|
236
|
+
lib/jekyll_test/version.rb
|
237
|
+
lib/my_block1.rb
|
238
|
+
lib/my_block2.rb
|
239
|
+
spec/jekyll_test_spec.rb
|
240
|
+
spec/spec_helper.rb
|
241
|
+
test/jekyll_test_test.rb
|
242
|
+
test/test_helper.rb
|
243
|
+
```
|
244
|
+
|
245
|
+
|
246
|
+
## Visual Studio Code Support
|
247
|
+
|
248
|
+
### Nugem Project
|
249
|
+
|
250
|
+
#### Plugins
|
251
|
+
|
252
|
+
If you have not installed the
|
253
|
+
[Snippets](https://marketplace.visualstudio.com/items?itemName=devonray.snippet) extension,
|
254
|
+
Visual Studio Code will suggest that you do so the first time you open this project with Visual Studio Code.
|
255
|
+
You can also review the list of suggested extensions of with the <kbd>Ctrl</kbd>-<kbd>P</kbd>
|
256
|
+
`Extensions: Show Recommended Extensions` command.
|
257
|
+
|
258
|
+
#### Snippets
|
259
|
+
|
260
|
+
The predefined snippets for `nugem` are defined in
|
261
|
+
[`.vscode/nugem.json.code-snippets`](.vscode/nugem.json.code-snippets).
|
262
|
+
These snippets are focused on maintaining `nugem` itself.
|
263
|
+
|
264
|
+
#### File Associations
|
265
|
+
|
266
|
+
`.vscode/settings.json` defines file associations for various flavors of Thor templates in the `"files.associations"` section.
|
267
|
+
You can disable them by commenting some or all of those definitions.
|
268
|
+
|
269
|
+
|
270
|
+
### Generated Projects
|
271
|
+
|
272
|
+
|
273
|
+
#### Plugins
|
274
|
+
|
275
|
+
Similarly, for each gem project generated by `nugem`, Visual Studio Code will suggest
|
276
|
+
the user install missing extensions the first time those projects are opened.
|
277
|
+
|
278
|
+
|
279
|
+
#### Snippets
|
280
|
+
|
281
|
+
The predefined snippets for gem projects generated by `nugem` are defined in
|
282
|
+
their `.vscode/gem.json.code-snippets` file.
|
283
|
+
These snippets are focused on writing Jekyll plugins.
|
284
|
+
|
285
|
+
|
286
|
+
## Development
|
287
|
+
|
288
|
+
After checking out the repository, run `bin/setup` to install dependencies.
|
289
|
+
Then, run `rake test` to run the tests.
|
290
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
291
|
+
|
292
|
+
To install this gem onto your local machine, run
|
293
|
+
|
294
|
+
```shell
|
295
|
+
$ bundle exec rake install
|
296
|
+
```
|
297
|
+
|
298
|
+
To release a new version, run:
|
299
|
+
|
300
|
+
```shell
|
301
|
+
$ bundle exec rake release
|
302
|
+
```
|
303
|
+
|
304
|
+
The above will create a git tag for the version, push git commits and tags,
|
305
|
+
and push the `.gem` file to https://rubygems.org.
|
306
|
+
|
307
|
+
|
308
|
+
## Contributing
|
309
|
+
|
310
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/mslinn/nugem.
|
311
|
+
|
312
|
+
|
313
|
+
## See Also
|
314
|
+
|
315
|
+
- [`gem-release`](https://rubygems.org/gems/gem-release)
|
316
|
+
- [`bundle gem`](https://bundler.io/v2.4/man/bundle-gem.1.html)
|
317
|
+
- [Deveoping a RubyGem using Bundler](https://bundler.io/guides/creating_gem.html)
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << 'test'
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Bump patch'
|
11
|
+
task :patch do
|
12
|
+
system 'gem bump --tag'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Bump minor'
|
16
|
+
task :minor do
|
17
|
+
system 'gem bump --version minor --tag'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Bump major'
|
21
|
+
task :major do
|
22
|
+
system 'gem bump --version major --tag'
|
23
|
+
end
|
24
|
+
|
25
|
+
task publish: [:build] do
|
26
|
+
$VERBOSE = nil
|
27
|
+
load 'nugem/version.rb'
|
28
|
+
system "gem push pkg/nugem-#{Nugem::VERSION}.gem"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Bump patch version, create git tag, build the gem and release to geminabox (default)'
|
32
|
+
task release_patch: %i[test patch publish]
|
33
|
+
|
34
|
+
desc 'Bump minor version, create git tag, build the gem and release to geminabox'
|
35
|
+
task release_minor: %i[test minor publish]
|
36
|
+
|
37
|
+
desc 'Bump major version, create git tag, build the gem and release to geminabox'
|
38
|
+
task release_major: %i[test major publish]
|
39
|
+
|
40
|
+
task default: :test
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
# Nugem::Cli is a Thor class that is invoked when a user runs a nugem executable
|
4
|
+
require_relative '../cli'
|
5
|
+
|
6
|
+
module Nugem
|
7
|
+
class Cli < Thor
|
8
|
+
include Thor::Actions
|
9
|
+
include Nugem::Git
|
10
|
+
|
11
|
+
desc 'plain NAME', 'Creates a new plain gem scaffold.'
|
12
|
+
|
13
|
+
long_desc <<~END_DESC
|
14
|
+
Creates a new plain gem scaffold with the given NAME,
|
15
|
+
by default hosted by GitHub and published on RubyGems.
|
16
|
+
END_DESC
|
17
|
+
|
18
|
+
method_option :host, type: :string, default: 'github',
|
19
|
+
enum: %w[bitbucket github], desc: 'Repository host.'
|
20
|
+
|
21
|
+
method_option :private, type: :boolean, default: false,
|
22
|
+
desc: 'Publish the gem in a private repository.'
|
23
|
+
|
24
|
+
def plain(gem_name)
|
25
|
+
@dir = Nugem.dest_root gem_name
|
26
|
+
|
27
|
+
@host = options['host']
|
28
|
+
@private = options['private']
|
29
|
+
@test_framework = options['test_framework']
|
30
|
+
|
31
|
+
create_plain_scaffold gem_name
|
32
|
+
initialize_repository gem_name
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Defines globals for templates
|
38
|
+
def create_plain_scaffold(gem_name)
|
39
|
+
@gem_name = gem_name
|
40
|
+
say "Creating a scaffold for a new plain Ruby gem named #{@gem_name} in #{@dir}.", :green
|
41
|
+
@class_name = Nugem.camel_case @gem_name
|
42
|
+
@executable = options[:executable]
|
43
|
+
@host = options[:bitbucket] ? :bitbucket : :github
|
44
|
+
@private = options[:private]
|
45
|
+
@repository = Nugem::Repository.new(
|
46
|
+
host: @host,
|
47
|
+
user: git_repository_user_name(@host),
|
48
|
+
name: @gem_name,
|
49
|
+
gem_server_url: gem_server_url(@private),
|
50
|
+
private: @private
|
51
|
+
)
|
52
|
+
exclude_pattern = case @test_framework
|
53
|
+
when 'minitest' then /spec.*/
|
54
|
+
when 'rspec' then /test.*/
|
55
|
+
end
|
56
|
+
directory 'common/gem_scaffold', @dir, force: true, mode: :preserve, exclude_pattern: exclude_pattern
|
57
|
+
directory 'common/executable_scaffold', @dir, force: true, mode: :preserve if @executable
|
58
|
+
template 'common/LICENCE.txt', "#{@dir}/LICENCE.txt", force: true if @repository.public?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require_relative '../cli'
|
2
|
+
require_relative 'jekyll_demo'
|
3
|
+
|
4
|
+
module Nugem
|
5
|
+
class Cli < Thor # rubocop:disable Metrics/ClassLength
|
6
|
+
include Thor::Actions
|
7
|
+
include Nugem::Git
|
8
|
+
|
9
|
+
attr_accessor :class_name, :filter_params, :trailing_args, :trailing_dump, :trailing_params
|
10
|
+
|
11
|
+
desc 'jekyll NAME', 'Creates a new Jekyll plugin scaffold.'
|
12
|
+
|
13
|
+
long_desc <<~END_DESC
|
14
|
+
Creates a new Jekyll plugin scaffold with the given NAME,
|
15
|
+
by default hosted by GitHub and published on RubyGems.
|
16
|
+
END_DESC
|
17
|
+
|
18
|
+
method_option :block, type: :string, repeatable: true,
|
19
|
+
desc: 'Specifies the name of a Jekyll block tag.'
|
20
|
+
|
21
|
+
method_option :blockn, type: :string, repeatable: true,
|
22
|
+
desc: 'Specifies the name of a Jekyll no-arg block tag.'
|
23
|
+
|
24
|
+
method_option :filter, type: :string, repeatable: true,
|
25
|
+
desc: 'Specifies the name of a Jekyll/Liquid filter module.'
|
26
|
+
|
27
|
+
method_option :generator, type: :string, repeatable: true,
|
28
|
+
desc: 'Specifies a Jekyll generator.'
|
29
|
+
|
30
|
+
method_option :hooks, type: :string,
|
31
|
+
desc: 'Specifies Jekyll hooks.'
|
32
|
+
|
33
|
+
method_option :tag, name: :string, repeatable: true,
|
34
|
+
desc: 'Specifies the name of a Jekyll tag.'
|
35
|
+
|
36
|
+
method_option :tagn, name: :string, repeatable: true,
|
37
|
+
desc: 'Specifies the name of a Jekyll no-arg tag.'
|
38
|
+
|
39
|
+
test_option 'rspec'
|
40
|
+
|
41
|
+
def jekyll(gem_name)
|
42
|
+
@gem_name = gem_name
|
43
|
+
@dir = Nugem.dest_root @gem_name
|
44
|
+
@class_name = Nugem.camel_case @gem_name
|
45
|
+
@jekyll = true
|
46
|
+
@rspec = true
|
47
|
+
|
48
|
+
@host = options['host']
|
49
|
+
@private = options['private']
|
50
|
+
@test_framework = options['test_framework']
|
51
|
+
@todos = options['todos']
|
52
|
+
|
53
|
+
create_plain_scaffold @gem_name
|
54
|
+
create_jekyll_scaffold
|
55
|
+
options.each do |option|
|
56
|
+
case option.first
|
57
|
+
when 'block' then option[1].each { |name| create_jekyll_block_scaffold name }
|
58
|
+
when 'blockn' then option[1].each { |name| create_jekyll_block_no_arg_scaffold name }
|
59
|
+
when 'filter' then option[1].each { |name| create_jekyll_filter_scaffold name }
|
60
|
+
when 'generator' then option[1].each { |name| create_jekyll_generator_scaffold name }
|
61
|
+
when 'tag' then option[1].each { |name| create_jekyll_tag_scaffold name }
|
62
|
+
when 'tagn' then option[1].each { |name| create_jekyll_tag_no_arg_scaffold name }
|
63
|
+
when 'hooks' then create_jekyll_hooks_scaffold option[1]
|
64
|
+
when 'host', 'executable', 'private', 'test_framework', 'todos', 'quiet' then next
|
65
|
+
else puts "Warning: Unrecognized option: #{option}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
initialize_repository @gem_name
|
70
|
+
end
|
71
|
+
|
72
|
+
no_commands do
|
73
|
+
# Invoked by directory action when processing Jekyll tags and block tags
|
74
|
+
def parse_jekyll_parameters
|
75
|
+
content = @jekyll_parameter_names_types.map do |name, _type|
|
76
|
+
"@#{name} = @helper.parameter_specified? '#{name}' # Obtain the value of parameter #{name}"
|
77
|
+
end
|
78
|
+
content.join "\n "
|
79
|
+
end
|
80
|
+
|
81
|
+
# Invoked by directory action when processing Jekyll tags and block tags
|
82
|
+
def dump_jekyll_parameters
|
83
|
+
content = @jekyll_parameter_names_types.map do |name, _type|
|
84
|
+
"@#{name}='\#{@#{name}}'"
|
85
|
+
end
|
86
|
+
content.join "\n "
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Sets @jekyll_parameter_names_types, which contains a
|
93
|
+
# list of pairs that describe each Jekyll/Liquid tag invocation option:
|
94
|
+
# [[name1, type1], ... [nameN, typeN]]
|
95
|
+
def ask_option_names_types(tag)
|
96
|
+
names = ask("Please list the names of the options for the #{tag} Jekyll/Liquid tag:").split(/[ ,\t]/)
|
97
|
+
types = names.reject(&:empty?).map do |name|
|
98
|
+
ask "What is the type of #{name}? (tab autocompletes)", default: 'string', limited_to: %w[boolean string numeric]
|
99
|
+
end
|
100
|
+
@jekyll_parameter_names_types = names.zip types
|
101
|
+
@jekyll_parameter_names_types
|
102
|
+
end
|
103
|
+
|
104
|
+
def create_jekyll_scaffold
|
105
|
+
say "Creating a Jekyll scaffold for a new gem named #{@gem_name} in #{@dir}", :green
|
106
|
+
@mute = true
|
107
|
+
directory 'jekyll/common_scaffold', @dir, force: true, mode: :preserve
|
108
|
+
directory 'jekyll/demo', @dir, force: true, mode: :preserve
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_jekyll_block_scaffold(block_name)
|
112
|
+
@block_name = block_name
|
113
|
+
@jekyll_class_name = Nugem.camel_case block_name
|
114
|
+
ask_option_names_types block_name # Defines @jekyll_parameter_names_types, which is a nested array of name/value pairs:
|
115
|
+
# [["opt1", "string"], ["opt2", "boolean"]]
|
116
|
+
say "Creating Jekyll block tag #{@block_name} scaffold within #{@jekyll_class_name}", :green
|
117
|
+
@mute = true
|
118
|
+
directory 'jekyll/block_scaffold', @dir, force: true, mode: :preserve
|
119
|
+
append_to_file "#{Nugem.dest_root gem_name}/demo/index.html", Cli.add_demo_example(block_name, @jekyll_parameter_names_types, :block)
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_jekyll_block_no_arg_scaffold(block_name)
|
123
|
+
@block_name = block_name
|
124
|
+
@jekyll_class_name = Nugem.camel_case block_name
|
125
|
+
say "Creating Jekyll block tag no_arg #{@block_name} scaffold within #{@jekyll_class_name}", :green
|
126
|
+
@mute = true
|
127
|
+
directory 'jekyll/block_no_arg_scaffold', @dir, force: true, mode: :preserve
|
128
|
+
append_to_file "#{Nugem.dest_root gem_name}/demo/index.html", Cli.add_demo_example(block_name, @jekyll_parameter_names_types, :block)
|
129
|
+
end
|
130
|
+
|
131
|
+
def create_jekyll_filter_scaffold(filter_name)
|
132
|
+
# rubocop:disable Style/StringConcatenation
|
133
|
+
@filter_name = filter_name
|
134
|
+
@jekyll_class_name = Nugem.camel_case filter_name
|
135
|
+
@filter_params = ask('Jekyll filters have at least one input. ' \
|
136
|
+
"What are the names of additional inputs for #{filter_name}, if any?")
|
137
|
+
.split(/[ ,\t]/)
|
138
|
+
.reject(&:empty?)
|
139
|
+
unless @filter_params.empty?
|
140
|
+
@trailing_args = ', ' + @filter_params.join(', ')
|
141
|
+
@trailing_params = ': ' + @filter_params.join(', ')
|
142
|
+
@trailing_dump1 = @filter_params.map { |arg| "#{@class_name}.logger.debug { \"#{arg} = \#{#{arg}}\" }" }.join "\n "
|
143
|
+
lspace = "\n "
|
144
|
+
@trailing_dump2 = lspace + @filter_params.map { |arg| "#{arg} = \#{#{arg}}" }.join(lspace) unless @filter_params.empty?
|
145
|
+
end
|
146
|
+
say "Creating a new Jekyll filter method scaffold #{@filter_name}", :green
|
147
|
+
@mute = true
|
148
|
+
directory 'jekyll/filter_scaffold', @dir, force: true, mode: :preserve
|
149
|
+
|
150
|
+
tp = ': ' + @filter_params.map { |x| "'#{x}_value'" }.join(', ') unless @filter_params.empty?
|
151
|
+
append_to_file "#{Nugem.dest_root gem_name}/demo/index.html", Cli.add_filter_example(filter_name, tp)
|
152
|
+
# rubocop:enable Style/StringConcatenation
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_jekyll_generator_scaffold(generator_name)
|
156
|
+
@generator_name = generator_name
|
157
|
+
@jekyll_class_name = Nugem.camel_case generator_name
|
158
|
+
say "Creating a new Jekyll generator class scaffold #{@jekyll_class_name}", :green
|
159
|
+
@mute = true
|
160
|
+
directory 'jekyll/generator_scaffold', @dir, force: true, mode: :preserve
|
161
|
+
end
|
162
|
+
|
163
|
+
def create_jekyll_hooks_scaffold(plugin_name)
|
164
|
+
@plugin_name = plugin_name
|
165
|
+
@jekyll_class_name = Nugem.camel_case plugin_name
|
166
|
+
say 'Creating a new Jekyll hook scaffold', :green
|
167
|
+
@mute = true
|
168
|
+
directory 'jekyll/hooks_scaffold', @dir, force: true, mode: :preserve
|
169
|
+
end
|
170
|
+
|
171
|
+
def create_jekyll_tag_no_arg_scaffold(tag_name)
|
172
|
+
@tag_name = tag_name
|
173
|
+
@jekyll_class_name = Nugem.camel_case @tag_name
|
174
|
+
say "Creating Jekyll tag no_arg #{@tag_name} scaffold within #{@jekyll_class_name}", :green
|
175
|
+
@mute = true
|
176
|
+
directory 'jekyll/tag_no_arg_scaffold', @dir, force: true, mode: :preserve
|
177
|
+
append_to_file "#{Nugem.dest_root gem_name}/demo/index.html", Cli.add_demo_example(tag_name, @jekyll_parameter_names_types, :tag)
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_jekyll_tag_scaffold(tag_name)
|
181
|
+
@tag_name = tag_name
|
182
|
+
@jekyll_class_name = Nugem.camel_case @tag_name
|
183
|
+
ask_option_names_types tag_name # Defines @jekyll_parameter_names_types, which is a nested array of name/value pairs:
|
184
|
+
# [["opt1", "string"], ["opt2", "boolean"]]
|
185
|
+
say "Creating Jekyll tag #{@tag_name} scaffold within #{@jekyll_class_name}", :green
|
186
|
+
@mute = true
|
187
|
+
# puts set_color("@jekyll_parameter_names_types=#{@jekyll_parameter_names_types}", :yellow)
|
188
|
+
directory 'jekyll/tag_scaffold', @dir, force: true, mode: :preserve
|
189
|
+
append_to_file "#{Nugem.dest_root gem_name}/demo/index.html", Cli.add_demo_example(tag_name, @jekyll_parameter_names_types, :tag)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative '../cli'
|
2
|
+
|
3
|
+
module Nugem
|
4
|
+
class Cli < Thor
|
5
|
+
include Thor::Actions
|
6
|
+
include Nugem::Git
|
7
|
+
|
8
|
+
desc 'rails NAME', 'Creates a new Rails rails scaffold.'
|
9
|
+
|
10
|
+
long_desc <<~END_DESC
|
11
|
+
Creates a new Rails rails scaffold with the given NAME,
|
12
|
+
by default hosted by GitHub and published on RubyGems.
|
13
|
+
END_DESC
|
14
|
+
|
15
|
+
method_option :engine, type: :boolean, default: false,
|
16
|
+
desc: 'Create a gem containing a Rails engine.'
|
17
|
+
|
18
|
+
test_option 'minitest'
|
19
|
+
|
20
|
+
method_option :mountable, type: :boolean, default: false,
|
21
|
+
desc: 'Create a gem containing a mountable Rails engine.'
|
22
|
+
|
23
|
+
def rails(gem_name)
|
24
|
+
@host = options['host']
|
25
|
+
@mountable = options['mountable']
|
26
|
+
@private = options['private']
|
27
|
+
@test_framework = options['test_framework']
|
28
|
+
|
29
|
+
@dir = Nugem.dest_root gem_name
|
30
|
+
@engine = @host || @mountable
|
31
|
+
@rails = true
|
32
|
+
|
33
|
+
create_plain_scaffold gem_name
|
34
|
+
create_rails_scaffold gem_name
|
35
|
+
create_engine_scaffold gem_name if @engine
|
36
|
+
create_mountable_scaffold gem_name if @mountable
|
37
|
+
initialize_repository gem_name
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def create_engine_scaffold(gem_name)
|
43
|
+
say "Creating a new Rails engine scaffold for a new gem named #{gem_name} in #{@dir}", :green
|
44
|
+
directory 'rails/engine_scaffold', @dir, force: true, mode: :preserve
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_mountable_scaffold(gem_name)
|
48
|
+
say "Creating a mountable Rails engine scaffold for a new gem named #{gem_name} in #{@dir}", :green
|
49
|
+
directory 'rails/mountable_scaffold', @dir, force: true, mode: :preserve
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_rails_scaffold(gem_name)
|
53
|
+
say "Creating a new Rails plugin scaffold as a gem named #{gem_name} in #{@dir}", :green
|
54
|
+
directory 'rails/rails_scaffold', @dir, force: true, mode: :preserve
|
55
|
+
Dir.chdir @dir do
|
56
|
+
run 'chmod +x test/dummy/bin/*' # TODO: fix me
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Nugem
|
2
|
+
class Cli < Thor
|
3
|
+
include Thor::Actions
|
4
|
+
|
5
|
+
def self.combinations(params)
|
6
|
+
(0..params.length).flat_map do |n|
|
7
|
+
params.combination(n).map do |param|
|
8
|
+
next [] if param.empty?
|
9
|
+
|
10
|
+
param.flat_map do |p|
|
11
|
+
name = p.first
|
12
|
+
type = p[1]
|
13
|
+
case type
|
14
|
+
when 'boolean' then name
|
15
|
+
when 'string' then "#{name}='somevalue'"
|
16
|
+
when 'numeric' then "#{name}=1234"
|
17
|
+
else "#{name} has unknown type: #{type}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.add_demo_example(tag, params, tag_type = :tag)
|
25
|
+
last_tag = ''
|
26
|
+
examples = combinations(params).map do |option|
|
27
|
+
options = option.join ' '
|
28
|
+
label = options.empty? ? ' (invoked without parameters)' : options
|
29
|
+
close_tag = case tag_type
|
30
|
+
when :tag then ''
|
31
|
+
when :block then <<~END_BLOCK
|
32
|
+
\nThis is line 1 of the block content.<br>
|
33
|
+
This is line 2.
|
34
|
+
{% end#{tag} %}
|
35
|
+
END_BLOCK
|
36
|
+
end
|
37
|
+
example = <<~END_EX
|
38
|
+
<!-- #region #{tag} #{label} -->
|
39
|
+
<h3 id="#{tag}" class="code">#{tag} #{label}</h3>
|
40
|
+
{% #{tag} #{options} %}#{close_tag}
|
41
|
+
<!-- endregion -->
|
42
|
+
END_EX
|
43
|
+
if tag == last_tag
|
44
|
+
example
|
45
|
+
else
|
46
|
+
last_tag = tag
|
47
|
+
"<h2 id=\"tag_#{tag}\" class='code'>#{tag}</h2>\n" + example
|
48
|
+
end
|
49
|
+
end
|
50
|
+
examples.join("\n\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.add_filter_example(filter_name, trailing_params)
|
54
|
+
<<~END_EX
|
55
|
+
<h2 id="filter_#{filter_name}" class='code'>#{filter_name}</h2>
|
56
|
+
{{ "TODO: Provide filter input here" | #{filter_name}#{trailing_params} }}
|
57
|
+
END_EX
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/nugem/cli.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rugged'
|
3
|
+
require_relative '../nugem'
|
4
|
+
|
5
|
+
# Nugem::Cli is a Thor class that is invoked when a user runs a nugem executable.
|
6
|
+
# This file defines the common aspects of the Thor class.
|
7
|
+
# The cli/ directory contains class extensions specific to each Thor subcommand.
|
8
|
+
module Nugem
|
9
|
+
class Cli < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
include Nugem::Git
|
12
|
+
|
13
|
+
class_option :executable, type: :boolean, default: false,
|
14
|
+
desc: 'Include an executable for the gem.'
|
15
|
+
|
16
|
+
class_option :host, type: :string, default: 'github',
|
17
|
+
enum: %w[bitbucket github], desc: 'Repository host.'
|
18
|
+
|
19
|
+
class_option :private, type: :boolean, default: false,
|
20
|
+
desc: 'Publish the gem on a private repository.'
|
21
|
+
|
22
|
+
class_option :quiet, type: :boolean, default: true,
|
23
|
+
desc: 'Suppress detailed messages.', group: :runtime
|
24
|
+
|
25
|
+
class_option :todos, type: :boolean, default: true,
|
26
|
+
desc: 'Generate TODO: messages in generated code.', group: :runtime
|
27
|
+
|
28
|
+
# Surround gem_name with percent symbols when using the property to name files
|
29
|
+
# within the template directory
|
30
|
+
# For example: "generated/%gem_name%"
|
31
|
+
attr_accessor :gem_name
|
32
|
+
|
33
|
+
require_relative 'cli/cli_gem'
|
34
|
+
require_relative 'cli/cli_jekyll'
|
35
|
+
require_relative 'cli/cli_rails'
|
36
|
+
|
37
|
+
def self.exit_on_failure?
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return Path to the Thor generator templates
|
42
|
+
def self.source_root
|
43
|
+
File.expand_path '../../templates', __dir__
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.todo
|
47
|
+
'TODO: ' if @todos
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def count_todos(filename)
|
53
|
+
filename_fq = "#{Nugem.dest_root gem_name}/#{filename}"
|
54
|
+
content = File.read filename_fq
|
55
|
+
content.scan('TODO').length
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize_repository(gem_name)
|
59
|
+
Dir.chdir Nugem.dest_root(gem_name) do
|
60
|
+
# say "Working in #{Dir.pwd}", :green
|
61
|
+
run 'chmod +x bin/*'
|
62
|
+
run 'chmod +x exe/*' if @executable
|
63
|
+
create_local_git_repository
|
64
|
+
FileUtils.rm_f 'Gemfile.lock'
|
65
|
+
# say "Running 'bundle install'", :green
|
66
|
+
# run 'bundle', abort_on_failure: false
|
67
|
+
say 'Creating remote repository', :green
|
68
|
+
create_remote_git_repository @repository \
|
69
|
+
if yes? "Do you want to create a repository on #{@repository.host.camel_case} named #{gem_name}? (y/N)"
|
70
|
+
end
|
71
|
+
say "The #{gem_name} gem was successfully created.", :green
|
72
|
+
report_todos gem_name
|
73
|
+
end
|
74
|
+
|
75
|
+
def report_todos(gem_name)
|
76
|
+
gemspec_todos = count_todos "#{gem_name}.gemspec"
|
77
|
+
readme_todos = count_todos 'README.md'
|
78
|
+
if readme_todos.zero? && gemspec_todos.zero?
|
79
|
+
say "There are no TODOs. You can run 'bundle install' from within your new gem project now.", :blue
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
msg = 'Please complete'
|
84
|
+
msg << " the #{gemspec_todos} TODOs in #{gem_name}.gemspec" if gemspec_todos.positive?
|
85
|
+
msg << ' and' if gemspec_todos.positive? && readme_todos.positive?
|
86
|
+
msg << " the #{readme_todos} TODOs in README.md." if readme_todos.positive?
|
87
|
+
say msg, :yellow
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/nugem/git.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Nugem
|
5
|
+
module Git
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
def create_local_git_repository
|
9
|
+
say 'Creating the local git repository', :green
|
10
|
+
run 'git init'
|
11
|
+
run 'git add .'
|
12
|
+
|
13
|
+
# See https://github.com/rails/thor/blob/v1.2.2/lib/thor/actions.rb#L236-L278
|
14
|
+
run "git commit -aqm 'Initial commit'", abort_on_failure: false
|
15
|
+
end
|
16
|
+
|
17
|
+
def github_config
|
18
|
+
gh_hosts_file = Nugem.expand_env('$HOME/.config/gh/hosts.yml')
|
19
|
+
return nil unless File.exist? gh_hosts_file
|
20
|
+
|
21
|
+
YAML.safe_load(File.read(gh_hosts_file))
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_remote_git_repository(repository)
|
25
|
+
say "Creating a remote #{repository.host} repository", :green
|
26
|
+
if repository.github?
|
27
|
+
gh_config = github_config
|
28
|
+
token = gh_config&.dig('github.com', 'oauth_token')
|
29
|
+
|
30
|
+
token ||= ask('What is your Github personal access token', echo: false)
|
31
|
+
run <<~END_CURL
|
32
|
+
curl --request POST \
|
33
|
+
--user '#{repository.user}:#{token}' \
|
34
|
+
https://api.github.com/user/repos \
|
35
|
+
-d '{"name":"#{repository.name}", "private":#{repository.private?}}'
|
36
|
+
END_CURL
|
37
|
+
else # BitBucket
|
38
|
+
password = ask('Please enter your Bitbucket password', echo: false)
|
39
|
+
fork_policy = repository.public? ? 'allow_forks' : 'no_public_forks'
|
40
|
+
run <<~END_BITBUCKET
|
41
|
+
curl --request POST \
|
42
|
+
--user #{repository.user}:#{password} \
|
43
|
+
https://api.bitbucket.org/2.0/repositories/#{repository.user}/#{repository.name} \
|
44
|
+
-d '{"scm":"git", "fork_policy":"#{fork_policy}", "is_private":"#{repository.private?}"}'
|
45
|
+
END_BITBUCKET
|
46
|
+
end
|
47
|
+
run "git remote add origin #{repository.origin}"
|
48
|
+
say "Pushing initial commit to remote #{repository.host} repository", :green
|
49
|
+
run 'git push -u origin master'
|
50
|
+
end
|
51
|
+
|
52
|
+
def git_repository_user_name(host)
|
53
|
+
global_config = Rugged::Config.global
|
54
|
+
git_config_key = "nugem.#{host}user"
|
55
|
+
user = global_config[git_config_key]
|
56
|
+
|
57
|
+
gh_config = github_config
|
58
|
+
user ||= gh_config&.dig('github.com', 'user')
|
59
|
+
|
60
|
+
user = ask "What is your #{host} user name?" if user.to_s.empty?
|
61
|
+
global_config[git_config_key] = user if user != global_config[git_config_key]
|
62
|
+
user
|
63
|
+
end
|
64
|
+
|
65
|
+
def gem_server_url(private_)
|
66
|
+
if private_
|
67
|
+
global_config = Rugged::Config.global
|
68
|
+
git_config_key = 'nugem.gemserver'
|
69
|
+
url = global_config[git_config_key]
|
70
|
+
|
71
|
+
if url.to_s.empty?
|
72
|
+
url = ask('What is the url of your Geminabox server?')
|
73
|
+
global_config[git_config_key] = url
|
74
|
+
end
|
75
|
+
url
|
76
|
+
else
|
77
|
+
'https://rubygems.org'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Nugem::Repository contains informations about the git repository and the git user
|
2
|
+
module Nugem
|
3
|
+
class Repository
|
4
|
+
attr_reader :gem_server_url, :global_config, :host, :name, :private, :user, :user_name, :user_email
|
5
|
+
|
6
|
+
Host = Struct.new(:domain, :camel_case, :id, keyword_init: true)
|
7
|
+
HOSTS = [
|
8
|
+
Host.new(domain: 'github.com', camel_case: 'GitHub', id: :github),
|
9
|
+
Host.new(domain: 'bitbucket.org', camel_case: 'BitBucket', id: :bitbucket),
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@host = HOSTS.find { |host| host.id == options[:host] }
|
14
|
+
@private = options[:private]
|
15
|
+
@name = options[:name]
|
16
|
+
@user = options[:user]
|
17
|
+
@global_config = Rugged::Config.global
|
18
|
+
abort 'Git global config not found' if @global_config.nil?
|
19
|
+
|
20
|
+
@user_name = @global_config['user.name']
|
21
|
+
@user_email = @global_config['user.email']
|
22
|
+
@gem_server_url = options[:gem_server_url]
|
23
|
+
@private = options[:private]
|
24
|
+
end
|
25
|
+
|
26
|
+
def bitbucket?
|
27
|
+
@host.id == :bitbucket
|
28
|
+
end
|
29
|
+
|
30
|
+
def github?
|
31
|
+
@host.id == :github
|
32
|
+
end
|
33
|
+
|
34
|
+
def origin
|
35
|
+
"git@#{@host.domain}:#{@user}/#{@name}.git"
|
36
|
+
end
|
37
|
+
|
38
|
+
# TODO: Currently all private repositories are on BitBucket and all public repos are on GitHub
|
39
|
+
# TODO: Drop BitBucket?
|
40
|
+
# TODO: Support private repos on GitHub
|
41
|
+
def private?
|
42
|
+
@private
|
43
|
+
end
|
44
|
+
|
45
|
+
def public?
|
46
|
+
!@private
|
47
|
+
end
|
48
|
+
|
49
|
+
def url
|
50
|
+
"https://#{@host.domain}/#{@user}/#{@name}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/nugem.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative 'nugem/git'
|
3
|
+
require_relative 'nugem/repository'
|
4
|
+
require_relative 'nugem/version'
|
5
|
+
require_relative 'util'
|
6
|
+
|
7
|
+
module Nugem
|
8
|
+
# @return Path to the generated gem
|
9
|
+
def self.dest_root(gem_name)
|
10
|
+
File.expand_path "generated/#{gem_name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
class Cli < Thor
|
14
|
+
include Thor::Actions
|
15
|
+
|
16
|
+
package_name 'Nugem'
|
17
|
+
|
18
|
+
# These declarations make the class instance variable values available as an accessor,
|
19
|
+
# which is necessary to name template files that are named '%variable_name%.extension'.
|
20
|
+
# See https://www.rubydoc.info/gems/thor/Thor/Actions#directory-instance_method
|
21
|
+
attr_reader :block_name, :filter_name, :generator_name, :tag_name, :test_framework
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def test_option(default_value)
|
25
|
+
method_option :test_framework, type: :string, default: default_value,
|
26
|
+
enum: %w[minitest rspec],
|
27
|
+
desc: "Use rspec or minitest for the test framework (default is #{default_value})."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/util.rb
ADDED
data/nugem.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'lib/nugem/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.authors = ['Igor Jancev', 'Mike Slinn']
|
5
|
+
spec.bindir = 'exe'
|
6
|
+
spec.email = ['igor@masterybits.com', 'mslinn@mslinn.com']
|
7
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
8
|
+
spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
|
9
|
+
spec.description = <<~END_DESC
|
10
|
+
Nugem creates a scaffold project for new gems. You can choose between Github and Bitbucket,
|
11
|
+
Rubygems or Geminabox, with or without an executable, etc.
|
12
|
+
END_DESC
|
13
|
+
spec.homepage = 'https://github.com/mslinn/nugem'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.name = 'nugem'
|
16
|
+
spec.require_paths = ['lib']
|
17
|
+
spec.required_ruby_version = '>= 3.1.0'
|
18
|
+
spec.summary = 'Nugem creates a scaffold project for new gems.'
|
19
|
+
spec.version = Nugem::VERSION
|
20
|
+
|
21
|
+
spec.add_dependency 'rugged'
|
22
|
+
spec.add_dependency 'thor'
|
23
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../lib/nugem/cli/cli_jekyll'
|
2
|
+
|
3
|
+
class JekyllTagTest
|
4
|
+
RSpec.describe ::Nugem::Cli do
|
5
|
+
it 'tests tag option combinations' do
|
6
|
+
params = [
|
7
|
+
%w[option1 string],
|
8
|
+
%w[option2 boolean],
|
9
|
+
%w[option3 numeric],
|
10
|
+
]
|
11
|
+
expect(params.combination(0).to_a).to eq [[]]
|
12
|
+
expect(params.combination(1).to_a).to eq [
|
13
|
+
[%w[option1 string]],
|
14
|
+
[%w[option2 boolean]],
|
15
|
+
[%w[option3 numeric]],
|
16
|
+
]
|
17
|
+
expect(params.combination(2).to_a).to eq [
|
18
|
+
[%w[option1 string], %w[option2 boolean]],
|
19
|
+
[%w[option1 string], %w[option3 numeric]],
|
20
|
+
[%w[option2 boolean], %w[option3 numeric]],
|
21
|
+
]
|
22
|
+
expect(params.combination(3).to_a).to eq [
|
23
|
+
[%w[option1 string], %w[option2 boolean], %w[option3 numeric]],
|
24
|
+
]
|
25
|
+
|
26
|
+
actual = described_class.combinations params
|
27
|
+
expected = [
|
28
|
+
[],
|
29
|
+
["option1='somevalue'"], ['option2'], ['option3=1234'],
|
30
|
+
["option1='somevalue'", 'option2'],
|
31
|
+
["option1='somevalue'", 'option3=1234'],
|
32
|
+
['option2', 'option3=1234'],
|
33
|
+
["option1='somevalue'", 'option2', 'option3=1234']
|
34
|
+
]
|
35
|
+
expect(actual).to eq(expected)
|
36
|
+
|
37
|
+
actual = described_class.add_demo_example 'my_tag', params, :tag
|
38
|
+
expected = <<~END_EX
|
39
|
+
<!-- #region my_tag -->
|
40
|
+
<h2 id="my_tag">my_tag </h2>
|
41
|
+
{% my_tag %}
|
42
|
+
<!-- endregion -->
|
43
|
+
|
44
|
+
|
45
|
+
<!-- #region my_tag option1='somevalue' -->
|
46
|
+
<h2 id="my_tag">my_tag option1='somevalue'</h2>
|
47
|
+
{% my_tag option1='somevalue' %}
|
48
|
+
<!-- endregion -->
|
49
|
+
|
50
|
+
|
51
|
+
<!-- #region my_tag option2 -->
|
52
|
+
<h2 id="my_tag">my_tag option2</h2>
|
53
|
+
{% my_tag option2 %}
|
54
|
+
<!-- endregion -->
|
55
|
+
|
56
|
+
|
57
|
+
<!-- #region my_tag option3=1234 -->
|
58
|
+
<h2 id="my_tag">my_tag option3=1234</h2>
|
59
|
+
{% my_tag option3=1234 %}
|
60
|
+
<!-- endregion -->
|
61
|
+
|
62
|
+
|
63
|
+
<!-- #region my_tag option1='somevalue' option2 -->
|
64
|
+
<h2 id="my_tag">my_tag option1='somevalue' option2</h2>
|
65
|
+
{% my_tag option1='somevalue' option2 %}
|
66
|
+
<!-- endregion -->
|
67
|
+
|
68
|
+
|
69
|
+
<!-- #region my_tag option1='somevalue' option3=1234 -->
|
70
|
+
<h2 id="my_tag">my_tag option1='somevalue' option3=1234</h2>
|
71
|
+
{% my_tag option1='somevalue' option3=1234 %}
|
72
|
+
<!-- endregion -->
|
73
|
+
|
74
|
+
|
75
|
+
<!-- #region my_tag option2 option3=1234 -->
|
76
|
+
<h2 id="my_tag">my_tag option2 option3=1234</h2>
|
77
|
+
{% my_tag option2 option3=1234 %}
|
78
|
+
<!-- endregion -->
|
79
|
+
|
80
|
+
|
81
|
+
<!-- #region my_tag option1='somevalue' option2 option3=1234 -->
|
82
|
+
<h2 id="my_tag">my_tag option1='somevalue' option2 option3=1234</h2>
|
83
|
+
{% my_tag option1='somevalue' option2 option3=1234 %}
|
84
|
+
<!-- endregion -->
|
85
|
+
END_EX
|
86
|
+
expect(actual).to eq(expected)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative '../lib/nugem'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.filter_run :focus
|
5
|
+
# config.order = "random"
|
6
|
+
config.run_all_when_everything_filtered = true
|
7
|
+
|
8
|
+
# See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
|
9
|
+
config.example_status_persistence_file_path = '../spec/status_persistence.txt'
|
10
|
+
|
11
|
+
config.filter_run_when_matching focus: true
|
12
|
+
end
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nugem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Igor Jancev
|
8
|
+
- Mike Slinn
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2023-07-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rugged
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: thor
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description: |
|
43
|
+
Nugem creates a scaffold project for new gems. You can choose between Github and Bitbucket,
|
44
|
+
Rubygems or Geminabox, with or without an executable, etc.
|
45
|
+
email:
|
46
|
+
- igor@masterybits.com
|
47
|
+
- mslinn@mslinn.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- ".rubocop.yml"
|
53
|
+
- CHANGELOG.md
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- lib/nugem.rb
|
57
|
+
- lib/nugem/cli.rb
|
58
|
+
- lib/nugem/cli/cli_gem.rb
|
59
|
+
- lib/nugem/cli/cli_jekyll.rb
|
60
|
+
- lib/nugem/cli/cli_rails.rb
|
61
|
+
- lib/nugem/cli/jekyll_demo.rb
|
62
|
+
- lib/nugem/git.rb
|
63
|
+
- lib/nugem/repository.rb
|
64
|
+
- lib/nugem/version.rb
|
65
|
+
- lib/util.rb
|
66
|
+
- nugem.gemspec
|
67
|
+
- spec/jekyll_tag_spec.rb
|
68
|
+
- spec/spec_helper.rb
|
69
|
+
- spec/status_persistence.txt
|
70
|
+
homepage: https://github.com/mslinn/nugem
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.1.0
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubygems_version: 3.3.3
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Nugem creates a scaffold project for new gems.
|
93
|
+
test_files: []
|