nugem 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.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` [](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: []
|