gem-bootstrap 0.1.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/bin/gem-boostrap +8 -0
- data/lib/gem-bootstrap/builder.rb +24 -0
- data/lib/gem-bootstrap/cli.rb +130 -0
- data/lib/gem-bootstrap/configuration.rb +113 -0
- data/lib/gem-bootstrap/file_conflict_manager.rb +68 -0
- data/lib/gem-bootstrap/file_writer.rb +71 -0
- data/lib/gem-bootstrap/github_helper.rb +44 -0
- data/lib/gem-bootstrap/io.rb +30 -0
- data/lib/gem-bootstrap/option_parser.rb +26 -0
- data/lib/gem-bootstrap/rake_helper.rb +20 -0
- data/lib/gem-bootstrap/shell_helper.rb +23 -0
- data/lib/gem-bootstrap/source_generator.rb +57 -0
- data/lib/gem-bootstrap.rb +15 -0
- data/templates/CHANGELOG.md.mustache +6 -0
- data/templates/Gemfile.mustache +5 -0
- data/templates/LICENSE.txt.mustache +21 -0
- data/templates/README.md.mustache +28 -0
- data/templates/Rakefile.mustache +26 -0
- data/templates/VERSION.mustache +1 -0
- data/templates/{{gem_name}}.gemspec.mustache +35 -0
- metadata +336 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 565a02a27168251cd3ff2c3453ee2d3e1f1718b3
|
4
|
+
data.tar.gz: c51cb50b1249d4e155e5e50393a2156aa598260c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8368cc83b8d6eca9656045ab14ca23646f5767f4e56d53dec340f92a7976fe7e18547de9873fe68aa1d6f21610deb31357b6dc66c3c92fd1236a1e355564c2f9
|
7
|
+
data.tar.gz: d0d4e90a339689178b3aa3fe796d55567ff7914743504fac88e16ad99f091b703265e03cdd197a49083797aae27bde306053b9551fd06eca4a258b4218e33a1b
|
data/bin/gem-boostrap
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemBootstrap
|
4
|
+
# @api private
|
5
|
+
class Builder
|
6
|
+
|
7
|
+
# @param [Configuration] config
|
8
|
+
# @param [Io] io
|
9
|
+
def initialize(config:, io:)
|
10
|
+
@generator = SourceGenerator.new(config: config)
|
11
|
+
@file_writer = FileWriter.new(io: io)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [String] dir
|
15
|
+
# @return [Enumerable<String,String>] Returns an enumerable of
|
16
|
+
# file paths and file contents as strings.
|
17
|
+
def generate_src(dir:)
|
18
|
+
@generator.generate_src.each do |file_path, file_contents|
|
19
|
+
@file_writer.write(File.join(dir, file_path), file_contents)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'net/http'
|
5
|
+
require 'netrc'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
module GemBootstrap
|
9
|
+
# @api private
|
10
|
+
class CLI
|
11
|
+
|
12
|
+
MISSING_GH_USERNAME =
|
13
|
+
'Unable to determine GitHub username, use --github-username option'
|
14
|
+
|
15
|
+
GEM_NAME_NOT_AVAILABLE = "The gem name `%s' is not available."
|
16
|
+
|
17
|
+
RUBYGEMS_URI = 'https://rubygems.org/api/v1/gems/%s.json'
|
18
|
+
|
19
|
+
# @param [Io] io
|
20
|
+
def initialize(io: Io.new)
|
21
|
+
@io = io
|
22
|
+
@shell = ShellHelper.new(io: io)
|
23
|
+
@gh = GitHubHelper.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(args)
|
27
|
+
catch(:exit) do
|
28
|
+
options = OptionParser.new.parse(args)
|
29
|
+
config = build_config(options)
|
30
|
+
generate_src(config)
|
31
|
+
|
32
|
+
throw :exit, 0 if options.source?
|
33
|
+
|
34
|
+
bundle_install(config)
|
35
|
+
ensure_gem_name_available(config)
|
36
|
+
setup_github_repo(config)
|
37
|
+
|
38
|
+
0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def build_config(options)
|
45
|
+
display_help(options, exit_code: 0) if options.help?
|
46
|
+
display_help(options, exit_code: 1) if invalid_options?(options)
|
47
|
+
apply_github_username(options)
|
48
|
+
Configuration.build(options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def invalid_options?(options)
|
52
|
+
# TODO : there must be a single argument and it must be a valid gem-name
|
53
|
+
options.arguments.size != 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def display_help(options, exit_code: 0)
|
57
|
+
@io.puts(options)
|
58
|
+
throw :exit, exit_code
|
59
|
+
end
|
60
|
+
|
61
|
+
def apply_github_username(options)
|
62
|
+
options[:github_username] ||= github_username
|
63
|
+
end
|
64
|
+
|
65
|
+
def github_username
|
66
|
+
@gh.github_username
|
67
|
+
rescue StandardError
|
68
|
+
error_with(MISSING_GH_USERNAME)
|
69
|
+
end
|
70
|
+
|
71
|
+
def error_with(msg)
|
72
|
+
@io.warn(msg)
|
73
|
+
throw :exit, 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def mkdir(dir)
|
77
|
+
FileUtils.mkdir(dir) unless File.exist?(dir)
|
78
|
+
end
|
79
|
+
|
80
|
+
def generate_src(config)
|
81
|
+
mkdir(config.gem_name)
|
82
|
+
builder = Builder.new(config: config, io: @io)
|
83
|
+
builder.generate_src(dir: config.gem_name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def ensure_gem_name_available(config)
|
87
|
+
# check to see if the gem name is available on RubyGems.org
|
88
|
+
uri = URI.parse(format(RUBYGEMS_URI, config.gem_name))
|
89
|
+
if Net::HTTP.get_response(uri).code.to_i != 404
|
90
|
+
error_with(format(GEM_NAME_NOT_AVAILABLE, config.gem_name))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def setup_github_repo(config)
|
95
|
+
@gh.create_repo(
|
96
|
+
name: config.gem_name,
|
97
|
+
description: config.project_summary,
|
98
|
+
homepage: config.github_url
|
99
|
+
)
|
100
|
+
git_init_commit_push(config)
|
101
|
+
rescue StandardError => e
|
102
|
+
error_with("Failed to create github repository: #{e.message}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def git_init_commit_push(config)
|
106
|
+
Dir.chdir(config.gem_name) do
|
107
|
+
sh('git init .')
|
108
|
+
sh("git config user.name #{config.author_name.inspect}")
|
109
|
+
sh("git config user.email #{config.author_email.inspect}")
|
110
|
+
sh('git add .')
|
111
|
+
sh('git commit -m "Add basic test, build, and release scripts"')
|
112
|
+
sh("git remote add origin git@github.com:#{config.github_repo}.git")
|
113
|
+
sh('git push -u origin master')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def bundle_install(config)
|
118
|
+
Dir.chdir(config.gem_name) do
|
119
|
+
sh('gem install bundler')
|
120
|
+
sh('bundle install')
|
121
|
+
sh('rake test')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def sh(command)
|
126
|
+
@shell.exec(command)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
def initialize(
|
10
|
+
project_name:,
|
11
|
+
module_name:,
|
12
|
+
gem_name:,
|
13
|
+
author_name:,
|
14
|
+
author_email:,
|
15
|
+
github_username:
|
16
|
+
)
|
17
|
+
@project_name = project_name
|
18
|
+
@module_name = module_name
|
19
|
+
@gem_name = gem_name
|
20
|
+
@author_name = author_name
|
21
|
+
@author_email = author_email
|
22
|
+
@project_summary = project_name
|
23
|
+
@github_username = github_username
|
24
|
+
@github_repo = "#{github_username}/#{gem_name}"
|
25
|
+
@year = Time.now.utc.year
|
26
|
+
@docs_url = "https://www.rubydoc.info/github/#{github_repo}/master"
|
27
|
+
@gitter_url = "https://gitter.im/#{github_username}"
|
28
|
+
@github_url = "https://github.com/#{github_repo}"
|
29
|
+
@changelog_url = @github_url + '/blob/master/CHANGELOG.md'
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String]
|
33
|
+
attr_reader :project_name
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
attr_reader :project_summary
|
37
|
+
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :module_name
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
attr_reader :gem_name
|
43
|
+
|
44
|
+
# @return [String]
|
45
|
+
attr_reader :author_name
|
46
|
+
|
47
|
+
# @return [String]
|
48
|
+
attr_reader :author_email
|
49
|
+
|
50
|
+
# @return [String]
|
51
|
+
attr_reader :github_username
|
52
|
+
|
53
|
+
# @return [String]
|
54
|
+
attr_reader :github_repo
|
55
|
+
|
56
|
+
# @return [Integer]
|
57
|
+
attr_reader :year
|
58
|
+
|
59
|
+
# @return [String]
|
60
|
+
attr_reader :docs_url
|
61
|
+
|
62
|
+
# @return [String]
|
63
|
+
attr_reader :gitter_url
|
64
|
+
|
65
|
+
# @return [String]
|
66
|
+
attr_reader :github_url
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
attr_reader :changelog_url
|
70
|
+
|
71
|
+
class << self
|
72
|
+
|
73
|
+
# @param [Slop::Options] options
|
74
|
+
def build(options)
|
75
|
+
gem_name = options.arguments.first
|
76
|
+
new(
|
77
|
+
project_name: project_name(gem_name),
|
78
|
+
module_name: module_name(gem_name),
|
79
|
+
gem_name: gem_name,
|
80
|
+
author_name: author(options),
|
81
|
+
author_email: email(options),
|
82
|
+
github_username: options[:github_username]
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def gem_name(options)
|
89
|
+
options.arguments.first
|
90
|
+
end
|
91
|
+
|
92
|
+
def project_name(gem_name)
|
93
|
+
ActiveSupport::Inflector.titleize(gem_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def module_name(gem_name)
|
97
|
+
ActiveSupport::Inflector.camelize(
|
98
|
+
ActiveSupport::Inflector.underscore(gem_name)
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def author(options)
|
103
|
+
options[:author] || `git config user.name`.strip
|
104
|
+
end
|
105
|
+
|
106
|
+
def email(options)
|
107
|
+
options[:email] || `git config user.email`.strip
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'diffy'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class FileConflictManager
|
8
|
+
|
9
|
+
PROMPT = 'Overwrite %<path>s? (enter "h" for help) [ynaqdh]: '
|
10
|
+
|
11
|
+
def initialize(io:)
|
12
|
+
@io = io
|
13
|
+
@overwrite_all = false
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Boolean]
|
17
|
+
def overwrite_all?
|
18
|
+
@overwrite_all
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Boolean] Returns `true` if the file should be overwritten
|
22
|
+
def should_overwrite?(file_path, old_contents, new_contents)
|
23
|
+
if @overwrite_all
|
24
|
+
true
|
25
|
+
else
|
26
|
+
ask(file_path, old_contents, new_contents)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def ask(path, old, new)
|
33
|
+
loop do
|
34
|
+
case prompt(path).downcase.strip
|
35
|
+
when 'y' then return true
|
36
|
+
when 'n' then return false
|
37
|
+
when 'a' then return @overwrite_all = true
|
38
|
+
when 'q' then throw :exit, 0
|
39
|
+
when 'd' then print_diff(old, new)
|
40
|
+
else print_help
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def prompt(file_path)
|
46
|
+
@io.write(format(PROMPT, path: file_path))
|
47
|
+
@io.readline.downcase.strip
|
48
|
+
end
|
49
|
+
|
50
|
+
def print_diff(left, right)
|
51
|
+
@io.write("\n")
|
52
|
+
@io.write(Diffy::Diff.new(left, right).to_s(:color))
|
53
|
+
@io.write("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def print_help
|
57
|
+
@io.write(<<-HELP)
|
58
|
+
y - yes, overwrite
|
59
|
+
n - no, skip this file
|
60
|
+
a - all, overwrite this and all others
|
61
|
+
q - quit, abort
|
62
|
+
d - diff, show the differences
|
63
|
+
h - help, show this help
|
64
|
+
HELP
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rainbow'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class FileWriter
|
8
|
+
|
9
|
+
def initialize(io:)
|
10
|
+
@conflicts = FileConflictManager.new(io: io)
|
11
|
+
@io = io
|
12
|
+
end
|
13
|
+
|
14
|
+
def write(file_path, file_contents)
|
15
|
+
if File.exist?(file_path)
|
16
|
+
handle_file_exists(file_path, file_contents)
|
17
|
+
else
|
18
|
+
handle_new_file(file_path, file_contents)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def handle_new_file(file_path, file_contents)
|
25
|
+
directory = File.dirname(file_path)
|
26
|
+
FileUtils.mkdir_p(directory) unless File.exist?(directory)
|
27
|
+
File.write(file_path, file_contents)
|
28
|
+
log('create', :green, file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [String] file_path
|
32
|
+
# @param [String] file_contents
|
33
|
+
def handle_file_exists(file_path, file_contents)
|
34
|
+
old_contents = File.read(file_path)
|
35
|
+
new_contents = file_contents
|
36
|
+
if old_contents == new_contents
|
37
|
+
log('identical', :white, file_path)
|
38
|
+
else
|
39
|
+
handle_file_conflict(file_path, old_contents, new_contents)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [String] file_path
|
44
|
+
# @param [String] old
|
45
|
+
# @param [String] new
|
46
|
+
def handle_file_conflict(file_path, old, new)
|
47
|
+
if @conflicts.overwrite_all?
|
48
|
+
log('force', :yellow, file_path)
|
49
|
+
File.write(file_path, new)
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
log('conflict', :red, file_path)
|
54
|
+
if @conflicts.should_overwrite?(file_path, old, new)
|
55
|
+
log('force', :yellow, file_path)
|
56
|
+
File.write(file_path, new)
|
57
|
+
else
|
58
|
+
log('skip', :yellow, file_path)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [String] action
|
63
|
+
# @param [Symbol] color
|
64
|
+
# @param [String] file_path
|
65
|
+
def log(action, color, file_path)
|
66
|
+
action = Rainbow(format('%13s', action)).bold.send(color)
|
67
|
+
@io.puts(action + ' ' + file_path)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'octokit'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class GitHubHelper
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@octokit = Octokit::Client.new(octokit_creds)
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_repo(name:, description:, homepage:)
|
14
|
+
@octokit.create_repository(
|
15
|
+
name,
|
16
|
+
description: description,
|
17
|
+
homepage: homepage,
|
18
|
+
private: false,
|
19
|
+
has_issues: true,
|
20
|
+
has_wiki: true,
|
21
|
+
has_downloads: true,
|
22
|
+
organization: nil,
|
23
|
+
team_id: nil,
|
24
|
+
auto_init: false,
|
25
|
+
gitignore_template: nil
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def github_username
|
30
|
+
@octokit.user[:login]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def octokit_creds
|
36
|
+
if ENV['GITHUB_ACCESS_TOKEN']
|
37
|
+
{ access_token: ENV['GITHUB_ACCESS_TOKEN'] }
|
38
|
+
else
|
39
|
+
{ netrc: true }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemBootstrap
|
4
|
+
# @api private
|
5
|
+
class Io
|
6
|
+
|
7
|
+
def initialize(input: $stdin, output: $stdout, error: $stderr)
|
8
|
+
@input = input
|
9
|
+
@output = output
|
10
|
+
@error = error
|
11
|
+
end
|
12
|
+
|
13
|
+
def puts(string)
|
14
|
+
@output.puts(string)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(string)
|
18
|
+
@output.write(string)
|
19
|
+
end
|
20
|
+
|
21
|
+
def warn(string)
|
22
|
+
@error.puts(string)
|
23
|
+
end
|
24
|
+
|
25
|
+
def readline
|
26
|
+
@input.readline
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'slop'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class OptionParser
|
8
|
+
|
9
|
+
def parse(args)
|
10
|
+
Slop.parse(args, banner: banner) do |o|
|
11
|
+
o.string '--author', 'Author name'
|
12
|
+
o.string '--email', 'Author email'
|
13
|
+
o.string '--github-username'
|
14
|
+
o.bool '--source', 'Only generate source'
|
15
|
+
o.bool '-h', '--help'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def banner
|
22
|
+
"usage: gem-boostrap \033[4mgem_name\033[0m [options]"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemBootstrap
|
4
|
+
# @api private
|
5
|
+
class RakeHelper
|
6
|
+
|
7
|
+
# @param [IO] output
|
8
|
+
def initialize(output: $stdout)
|
9
|
+
@output = output
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [IO]
|
13
|
+
attr_reader :output
|
14
|
+
|
15
|
+
def test
|
16
|
+
sh('rake test')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class ShellHelper
|
8
|
+
|
9
|
+
# @param [Io] io
|
10
|
+
def initialize(io: Io.new)
|
11
|
+
@io = io
|
12
|
+
end
|
13
|
+
|
14
|
+
def exec(command)
|
15
|
+
# $CHILD_STATUS.exitstatus
|
16
|
+
# $CHILD_STATUS.pid
|
17
|
+
# TODO : deal with errors
|
18
|
+
# TODO : direct input/output of the command to @input and @output
|
19
|
+
system(command)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mustache'
|
4
|
+
|
5
|
+
module GemBootstrap
|
6
|
+
# @api private
|
7
|
+
class SourceGenerator
|
8
|
+
|
9
|
+
TEMPLATES_DIR = File.expand_path('../../templates', __dir__)
|
10
|
+
|
11
|
+
# @param [Configuration] config
|
12
|
+
def initialize(config:, templates_dir: TEMPLATES_DIR)
|
13
|
+
@config = config
|
14
|
+
@templates_dir = templates_dir
|
15
|
+
@mustache = Mustache.new
|
16
|
+
@mustache.raise_on_context_miss = true
|
17
|
+
@mustache.template_path = templates_dir
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
attr_reader :templates_dir
|
22
|
+
|
23
|
+
# @return [Enumerable<String,String>] Returns an enumerable of
|
24
|
+
# file paths and file contents as strings.
|
25
|
+
def generate_src
|
26
|
+
Enumerator.new do |y|
|
27
|
+
Dir.glob("#{templates_dir}/**/{.*,*}.mustache").each do |template_path|
|
28
|
+
y << [
|
29
|
+
src_path(template_path),
|
30
|
+
src_code(template_path),
|
31
|
+
]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# The path contains two things that must be removed or replaced:
|
39
|
+
#
|
40
|
+
# * Prune ".mustache" from the end of the string
|
41
|
+
# * Expand mustache variables, e.g. '{{gem_name}}'
|
42
|
+
#
|
43
|
+
def src_path(path)
|
44
|
+
path = path[(templates_dir.length + 1)..-10]
|
45
|
+
render(path)
|
46
|
+
end
|
47
|
+
|
48
|
+
def src_code(template_path)
|
49
|
+
render(File.read(template_path))
|
50
|
+
end
|
51
|
+
|
52
|
+
def render(template)
|
53
|
+
@mustache.render(template, @config)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'gem-bootstrap/builder'
|
4
|
+
require_relative 'gem-bootstrap/cli'
|
5
|
+
require_relative 'gem-bootstrap/configuration'
|
6
|
+
require_relative 'gem-bootstrap/file_writer'
|
7
|
+
require_relative 'gem-bootstrap/file_conflict_manager'
|
8
|
+
require_relative 'gem-bootstrap/github_helper'
|
9
|
+
require_relative 'gem-bootstrap/io'
|
10
|
+
require_relative 'gem-bootstrap/option_parser'
|
11
|
+
require_relative 'gem-bootstrap/source_generator'
|
12
|
+
require_relative 'gem-bootstrap/shell_helper'
|
13
|
+
|
14
|
+
# Provides a CLI for bootstrapping a new Ruby gem project.
|
15
|
+
module GemBootstrap; end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright {{year}} {{author_name}}
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is furnished
|
10
|
+
to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# {{project_name}}
|
2
|
+
|
3
|
+
[](https://travis-ci.org/{{github_repo}})
|
4
|
+
[](https://coveralls.io/github/{{github_repo}}?branch=master)
|
5
|
+
[](https://codeclimate.com/github/{{github_repo}}/maintainability)
|
6
|
+
|
7
|
+
{{project_summary}}
|
8
|
+
|
9
|
+
## Links of Interest
|
10
|
+
|
11
|
+
* [Documentation]({{docs_url}})
|
12
|
+
* [Changelog]({{changelog_url}})
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add {{gem_name}} to your project's Gemfile and then bundle install.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem '{{gem_name}}', '0.1.0-alpha'
|
20
|
+
```
|
21
|
+
|
22
|
+
## Basic Usage
|
23
|
+
|
24
|
+
...
|
25
|
+
|
26
|
+
## License
|
27
|
+
|
28
|
+
{{>LICENSE.txt}}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('lib', __dir__))
|
4
|
+
|
5
|
+
Dir.glob('tasks/**/*.rake').each do |task_file|
|
6
|
+
load(task_file)
|
7
|
+
end
|
8
|
+
|
9
|
+
desc 'Removes built docs, gems, and test files'
|
10
|
+
task 'clean' => [
|
11
|
+
'test:clean',
|
12
|
+
'docs:clean',
|
13
|
+
'gem:clean',
|
14
|
+
]
|
15
|
+
|
16
|
+
task 'build' => [
|
17
|
+
'test',
|
18
|
+
'rubocop',
|
19
|
+
'docs',
|
20
|
+
'gem',
|
21
|
+
]
|
22
|
+
|
23
|
+
task 'default' => [
|
24
|
+
'test',
|
25
|
+
'rubocop',
|
26
|
+
]
|
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0-alpha
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = '{{gem_name}}'
|
6
|
+
spec.version = File.read(File.expand_path('VERSION', __dir__)).strip
|
7
|
+
spec.summary = '{{project_summary}}'
|
8
|
+
spec.authors = ['{{author_name}}']
|
9
|
+
spec.email = ['{{author_email}}']
|
10
|
+
spec.homepage = '{{github_url}}'
|
11
|
+
spec.license = 'MIT'
|
12
|
+
spec.require_paths = ['lib']
|
13
|
+
spec.files = Dir['lib/**/*.rb']
|
14
|
+
|
15
|
+
spec.metadata = {
|
16
|
+
'bug_tracker_uri' => '{{github_url}}/issues',
|
17
|
+
'changelog_uri' => '{{changelog_url}}',
|
18
|
+
'documentation_uri' => '{{docs_url}}',
|
19
|
+
'homepage_uri' => '{{github_url}}',
|
20
|
+
'mailing_list_uri' => '{{gitter_url}}',
|
21
|
+
'source_code_uri' => '{{github_url}}',
|
22
|
+
'wiki_uri' => '{{github_url}}/wiki',
|
23
|
+
}
|
24
|
+
|
25
|
+
spec.add_development_dependency('coveralls', '~> 0.8')
|
26
|
+
spec.add_development_dependency('kramdown', '~> 1.16')
|
27
|
+
spec.add_development_dependency('pry', '~> 0.11')
|
28
|
+
spec.add_development_dependency('rake', '~> 12.3')
|
29
|
+
spec.add_development_dependency('rspec', '~> 3.7')
|
30
|
+
spec.add_development_dependency('rubocop', '~> 0.56')
|
31
|
+
spec.add_development_dependency('semver-string', '~> 1.0')
|
32
|
+
spec.add_development_dependency('yard', '~> 0.9')
|
33
|
+
spec.add_development_dependency('yard-sitemap', '~> 1.0')
|
34
|
+
end
|
35
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
ADDED
@@ -0,0 +1,336 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem-bootstrap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- The Incognito Coder
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-07-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: diff-lcs
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: diffy
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mustache
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: netrc
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.11'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: octokit
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.9'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.9'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rainbow
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '12.3'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '12.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: semver-string
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: slop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '4.6'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '4.6'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: travis
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.8'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '1.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: coveralls
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.8'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.8'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: kramdown
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '1.16'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '1.16'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: pry
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0.11'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0.11'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: rake
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - "~>"
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '12.3'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - "~>"
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '12.3'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: rspec
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '3.7'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - "~>"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '3.7'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: rubocop
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - "~>"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0.56'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - "~>"
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0.56'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: yard
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - "~>"
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0.9'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - "~>"
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0.9'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: yard-sitemap
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - "~>"
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '1.0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - "~>"
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '1.0'
|
279
|
+
description:
|
280
|
+
email:
|
281
|
+
- theincognitocoder@gmail.com
|
282
|
+
executables:
|
283
|
+
- gem-boostrap
|
284
|
+
extensions: []
|
285
|
+
extra_rdoc_files: []
|
286
|
+
files:
|
287
|
+
- bin/gem-boostrap
|
288
|
+
- lib/gem-bootstrap.rb
|
289
|
+
- lib/gem-bootstrap/builder.rb
|
290
|
+
- lib/gem-bootstrap/cli.rb
|
291
|
+
- lib/gem-bootstrap/configuration.rb
|
292
|
+
- lib/gem-bootstrap/file_conflict_manager.rb
|
293
|
+
- lib/gem-bootstrap/file_writer.rb
|
294
|
+
- lib/gem-bootstrap/github_helper.rb
|
295
|
+
- lib/gem-bootstrap/io.rb
|
296
|
+
- lib/gem-bootstrap/option_parser.rb
|
297
|
+
- lib/gem-bootstrap/rake_helper.rb
|
298
|
+
- lib/gem-bootstrap/shell_helper.rb
|
299
|
+
- lib/gem-bootstrap/source_generator.rb
|
300
|
+
- templates/CHANGELOG.md.mustache
|
301
|
+
- templates/Gemfile.mustache
|
302
|
+
- templates/LICENSE.txt.mustache
|
303
|
+
- templates/README.md.mustache
|
304
|
+
- templates/Rakefile.mustache
|
305
|
+
- templates/VERSION.mustache
|
306
|
+
- templates/{{gem_name}}.gemspec.mustache
|
307
|
+
homepage: https://github.com/theincognitocoder/gem-bootstrap
|
308
|
+
licenses:
|
309
|
+
- MIT
|
310
|
+
metadata:
|
311
|
+
bug_tracker_uri: https://github.com/theincognitocoder/gem-bootstrap/issues
|
312
|
+
changelog_uri: https://github.com/theincognitocoder/gem-bootstrap/blob/master/CHANGELOG.md
|
313
|
+
documentation_uri: https://www.rubydoc.info/github/theincognitocoder/gem-bootstrap/master
|
314
|
+
homepage_uri: https://github.com/theincognitocoder/gem-bootstrap
|
315
|
+
source_code_uri: https://github.com/theincognitocoder/gem-bootstrap
|
316
|
+
post_install_message:
|
317
|
+
rdoc_options: []
|
318
|
+
require_paths:
|
319
|
+
- lib
|
320
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
321
|
+
requirements:
|
322
|
+
- - ">="
|
323
|
+
- !ruby/object:Gem::Version
|
324
|
+
version: '0'
|
325
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
326
|
+
requirements:
|
327
|
+
- - ">="
|
328
|
+
- !ruby/object:Gem::Version
|
329
|
+
version: '0'
|
330
|
+
requirements: []
|
331
|
+
rubyforge_project:
|
332
|
+
rubygems_version: 2.5.1
|
333
|
+
signing_key:
|
334
|
+
specification_version: 4
|
335
|
+
summary: CLI for bootstrapping new Ruby gem projects.
|
336
|
+
test_files: []
|