kettle-jem 7.0.0 → 7.1.3
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +1505 -0
- data/LICENSE.md +13 -0
- data/README.md +794 -0
- data/exe/kettle-jem +20 -0
- data/lib/kettle/jem/cli.rb +334 -0
- data/lib/kettle/jem/license_txt_migrator.rb +33 -0
- data/lib/kettle/jem/rakelib/install.rake +10 -0
- data/lib/kettle/jem/rakelib/prepare.rake +10 -0
- data/lib/kettle/jem/rakelib/selftest.rake +10 -0
- data/lib/kettle/jem/rakelib/template.rake +10 -0
- data/lib/kettle/jem/tasks/install_task.rb +2178 -0
- data/lib/kettle/jem/tasks/prepare_task.rb +274 -0
- data/lib/kettle/jem/tasks/self_test_task.rb +256 -0
- data/lib/kettle/jem/tasks/template_task.rb +124 -0
- data/lib/kettle/jem/tasks.rb +6 -0
- data/lib/kettle/jem/templates/.aiignore.example +19 -0
- data/lib/kettle/jem/templates/.config/mise/env.sh +26 -0
- data/lib/kettle/jem/templates/.devcontainer/apt-install/devcontainer-feature.json.example +9 -0
- data/lib/kettle/jem/templates/.devcontainer/apt-install/install.sh.example +19 -0
- data/lib/kettle/jem/templates/.devcontainer/devcontainer.json.example +27 -0
- data/lib/kettle/jem/templates/.devcontainer/scripts/setup-tree-sitter.sh.example +210 -0
- data/lib/kettle/jem/templates/.env.local.example +67 -0
- data/lib/kettle/jem/templates/.envrc.example +4 -0
- data/lib/kettle/jem/templates/.envrc.no-osc.example +4 -0
- data/lib/kettle/jem/templates/.gemrc.example +1 -0
- data/lib/kettle/jem/templates/.git-hooks/commit-msg.example +60 -0
- data/lib/kettle/jem/templates/.git-hooks/commit-subjects-goalie.txt.example +8 -0
- data/lib/kettle/jem/templates/.git-hooks/footer-template.erb.txt.example +16 -0
- data/lib/kettle/jem/templates/.git-hooks/prepare-commit-msg.example +9 -0
- data/lib/kettle/jem/templates/.github/.codecov.yml.example +14 -0
- data/lib/kettle/jem/templates/.github/FUNDING.yml.example +10 -0
- data/lib/kettle/jem/templates/.github/FUNDING.yml.no-osc.example +10 -0
- data/lib/kettle/jem/templates/.github/copilot_instructions.md.example +1 -0
- data/lib/kettle/jem/templates/.github/dependabot.yml.example +13 -0
- data/lib/kettle/jem/templates/.github/workflows/auto-assign.yml.example +21 -0
- data/lib/kettle/jem/templates/.github/workflows/coverage.yml.example +102 -0
- data/lib/kettle/jem/templates/.github/workflows/current.yml.example +86 -0
- data/lib/kettle/jem/templates/.github/workflows/dep-heads.yml.example +249 -0
- data/lib/kettle/jem/templates/.github/workflows/dependency-review.yml.example +22 -0
- data/lib/kettle/jem/templates/.github/workflows/discord-notifier.yml.example +39 -0
- data/lib/kettle/jem/templates/.github/workflows/framework-ci.yml.example +81 -0
- data/lib/kettle/jem/templates/.github/workflows/heads.yml.example +212 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby-10.0.yml.example +91 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby-9.1.yml.example +90 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby-9.2.yml.example +95 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby-9.3.yml.example +95 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby-9.4.yml.example +95 -0
- data/lib/kettle/jem/templates/.github/workflows/jruby.yml.example +91 -0
- data/lib/kettle/jem/templates/.github/workflows/license-eye.yml.example +43 -0
- data/lib/kettle/jem/templates/.github/workflows/locked_deps.yml.example +89 -0
- data/lib/kettle/jem/templates/.github/workflows/opencollective.yml.example +44 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-2.3.yml.example +80 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-2.4.yml.example +84 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-2.5.yml.example +84 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-2.6.yml.example +84 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-2.7.yml.example +84 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-3.0.yml.example +85 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-3.1.yml.example +83 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-3.2.yml.example +80 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-3.3.yml.example +80 -0
- data/lib/kettle/jem/templates/.github/workflows/ruby-3.4.yml.example +80 -0
- data/lib/kettle/jem/templates/.github/workflows/style.yml.example +78 -0
- data/lib/kettle/jem/templates/.github/workflows/templating.yml.example +86 -0
- data/lib/kettle/jem/templates/.github/workflows/truffle.yml.example +91 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-22.3.yml.example +92 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-23.0.yml.example +92 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-23.1.yml.example +78 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-24.2.yml.example +91 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-25.0.yml.example +96 -0
- data/lib/kettle/jem/templates/.github/workflows/truffleruby-33.0.yml.example +91 -0
- data/lib/kettle/jem/templates/.github/workflows/unlocked_deps.yml.example +93 -0
- data/lib/kettle/jem/templates/.gitignore.example +53 -0
- data/lib/kettle/jem/templates/.gitlab-ci.yml.example +134 -0
- data/lib/kettle/jem/templates/.idea/.gitignore.example +44 -0
- data/lib/kettle/jem/templates/.licenserc.yaml.example +8 -0
- data/lib/kettle/jem/templates/.opencollective.yml.example +3 -0
- data/lib/kettle/jem/templates/.qlty/qlty.toml.example +79 -0
- data/lib/kettle/jem/templates/.rspec.example +10 -0
- data/lib/kettle/jem/templates/.rubocop.example +1 -0
- data/lib/kettle/jem/templates/.rubocop.yml.example +47 -0
- data/lib/kettle/jem/templates/.rubocop_rspec.yml.example +55 -0
- data/lib/kettle/jem/templates/.simplecov.example +18 -0
- data/lib/kettle/jem/templates/.structuredmerge/git-drivers.toml.example +86 -0
- data/lib/kettle/jem/templates/.structuredmerge/kettle-jem.yml.example +519 -0
- data/lib/kettle/jem/templates/.yard-lint.yml.example +54 -0
- data/lib/kettle/jem/templates/.yardignore.example +13 -0
- data/lib/kettle/jem/templates/.yardopts.example +14 -0
- data/lib/kettle/jem/templates/AGENTS.md.example +283 -0
- data/lib/kettle/jem/templates/AGPL-3.0-only.md.example +235 -0
- data/lib/kettle/jem/templates/Appraisal.root.gemfile.example +26 -0
- data/lib/kettle/jem/templates/Appraisals.example +150 -0
- data/lib/kettle/jem/templates/Big-Time-Public-License.md.example +99 -0
- data/lib/kettle/jem/templates/CHANGELOG.md.example +33 -0
- data/lib/kettle/jem/templates/CHANGELOG.transfer.md +109 -0
- data/lib/kettle/jem/templates/CITATION.cff.example +20 -0
- data/lib/kettle/jem/templates/CODE_OF_CONDUCT.md.example +134 -0
- data/lib/kettle/jem/templates/CONTRIBUTING.md.example +292 -0
- data/lib/kettle/jem/templates/FUNDING.md.example +74 -0
- data/lib/kettle/jem/templates/FUNDING.md.no-osc.example +63 -0
- data/lib/kettle/jem/templates/Gemfile.example +52 -0
- data/lib/kettle/jem/templates/IRP.md.example +34 -0
- data/lib/kettle/jem/templates/LICENSE.md.example +3 -0
- data/lib/kettle/jem/templates/MIT.md.example +21 -0
- data/lib/kettle/jem/templates/PolyForm-Noncommercial-1.0.0.md.example +131 -0
- data/lib/kettle/jem/templates/PolyForm-Small-Business-1.0.0.md.example +121 -0
- data/lib/kettle/jem/templates/README.md.example +544 -0
- data/lib/kettle/jem/templates/REEK +0 -0
- data/lib/kettle/jem/templates/RUBOCOP.md.example +78 -0
- data/lib/kettle/jem/templates/Rakefile.example +163 -0
- data/lib/kettle/jem/templates/SECURITY.md.example +21 -0
- data/lib/kettle/jem/templates/bin/setup.example +36 -0
- data/lib/kettle/jem/templates/certs/pboling.pem.example +27 -0
- data/lib/kettle/jem/templates/gem.gemspec.example +161 -0
- data/lib/kettle/jem/templates/gemfiles/modular/benchmark/r4/v0.5.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/benchmark/vHEAD.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/cgi/r4/v0.5.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/cgi/vHEAD.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/changelog.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/coverage.gemfile.example +14 -0
- data/lib/kettle/jem/templates/gemfiles/modular/coverage_local.gemfile.example +34 -0
- data/lib/kettle/jem/templates/gemfiles/modular/debug.gemfile.example +22 -0
- data/lib/kettle/jem/templates/gemfiles/modular/documentation.gemfile.example +24 -0
- data/lib/kettle/jem/templates/gemfiles/modular/documentation_local.gemfile.example +20 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r2/v3.0.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r2.3/default.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r2.6/v2.2.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r3/v5.0.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r3.1/v4.0.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/r4/v5.0.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/erb/vHEAD.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/json/truffleruby_22_3.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/json/truffleruby_23_0.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/json/truffleruby_23_1.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/mutex_m/r2/v0.3.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/mutex_m/r3/v0.3.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/mutex_m/r4/v0.3.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/mutex_m/vHEAD.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/optional.gemfile.example +16 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/r2.3/recording.gemfile.example +16 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/r2.4/recording.gemfile.example +18 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/r2.5/recording.gemfile.example +16 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/r3/recording.gemfile.example +16 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/r4/recording.gemfile.example +16 -0
- data/lib/kettle/jem/templates/gemfiles/modular/recording/vHEAD.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/rspec.gemfile.example +4 -0
- data/lib/kettle/jem/templates/gemfiles/modular/runtime_heads.gemfile.example +14 -0
- data/lib/kettle/jem/templates/gemfiles/modular/shunted.gemfile.example +21 -0
- data/lib/kettle/jem/templates/gemfiles/modular/stringio/r2/v3.0.gemfile.example +5 -0
- data/lib/kettle/jem/templates/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile.example +4 -0
- data/lib/kettle/jem/templates/gemfiles/modular/stringio/r3/v3.0.gemfile.example +5 -0
- data/lib/kettle/jem/templates/gemfiles/modular/stringio/r4/v3.0.gemfile.example +5 -0
- data/lib/kettle/jem/templates/gemfiles/modular/stringio/vHEAD.gemfile.example +2 -0
- data/lib/kettle/jem/templates/gemfiles/modular/style.gemfile.example +33 -0
- data/lib/kettle/jem/templates/gemfiles/modular/style_local.gemfile.example +26 -0
- data/lib/kettle/jem/templates/gemfiles/modular/templating.gemfile.example +34 -0
- data/lib/kettle/jem/templates/gemfiles/modular/templating_local.gemfile.example +73 -0
- data/lib/kettle/jem/templates/gemfiles/modular/webrick/r4/v1.9.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/webrick/vHEAD.gemfile.example +1 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r2/libs.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r2.3/libs.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r2.4/libs.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r2.6/libs.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r3/libs.gemfile.example +3 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r3.1/libs.gemfile.example +5 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/r4/libs.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs/vHEAD.gemfile.example +6 -0
- data/lib/kettle/jem/templates/gemfiles/modular/x_std_libs.gemfile.example +12 -0
- data/lib/kettle/jem/templates/lib/gem/version.rb.example +1 -0
- data/lib/kettle/jem/templates/lib/gem/version_gem.rb.example +1 -0
- data/lib/kettle/jem/templates/mise.toml.example +25 -0
- data/lib/kettle/jem/templates/mise.toml.no-osc.example +25 -0
- data/lib/kettle/jem/templates/parsers.toml.example +19 -0
- data/lib/kettle/jem/templates/readme/partials/basic_usage.md.example +28 -0
- data/lib/kettle/jem/templates/readme/partials/configuration.md.example +112 -0
- data/lib/kettle/jem/templates/readme/partials/synopsis.md.example +3 -0
- data/lib/kettle/jem/templates/shim/.github/workflows/current.yml.example +40 -0
- data/lib/kettle/jem/templates/shim/.rspec.example +5 -0
- data/lib/kettle/jem/templates/shim/.structuredmerge/kettle-jem.yml.example +28 -0
- data/lib/kettle/jem/templates/shim/CHANGELOG.md.example +9 -0
- data/lib/kettle/jem/templates/shim/Gemfile.example +14 -0
- data/lib/kettle/jem/templates/shim/README.md.example +25 -0
- data/lib/kettle/jem/templates/shim/Rakefile.example +8 -0
- data/lib/kettle/jem/templates/shim/gem.gemspec.example +45 -0
- data/lib/kettle/jem/templates/shim/lib/compat_require.rb.example +3 -0
- data/lib/kettle/jem/templates/shim/lib/entrypoint.rb.example +3 -0
- data/lib/kettle/jem/templates/shim/lib/version.rb.example +1 -0
- data/lib/kettle/jem/templates/shim/spec/shim_spec.rb.example +15 -0
- data/lib/kettle/jem/templates/shim/spec/spec_helper.rb.example +23 -0
- data/lib/kettle/jem/templates/sig/gem.rbs.example +1 -0
- data/lib/kettle/jem/templates/spec/README.md.example +28 -0
- data/lib/kettle/jem/templates/spec/spec_helper.rb.example +39 -0
- data/lib/kettle/jem/version.rb +5 -3
- data/lib/kettle/jem/version_gem.rb +8 -0
- data/lib/kettle/jem.rb +18540 -1517
- data/lib/kettle-jem.rb +2 -1
- data/sig/kettle/jem.rbs +8 -0
- data.tar.gz.sig +0 -0
- metadata +870 -32
- metadata.gz.sig +0 -0
data/exe/kettle-jem
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
script_basename = File.basename(__FILE__)
|
|
5
|
+
repo_lib = File.expand_path("../lib", __dir__)
|
|
6
|
+
$LOAD_PATH.unshift(repo_lib) if File.directory?(repo_lib) && !$LOAD_PATH.include?(repo_lib)
|
|
7
|
+
|
|
8
|
+
require "kettle/jem/version"
|
|
9
|
+
|
|
10
|
+
if ARGV.first == "version" || ARGV.any? { |arg| arg == "-v" || arg == "--version" }
|
|
11
|
+
puts Kettle::Jem::Version::VERSION
|
|
12
|
+
exit(0)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require "kettle-jem"
|
|
16
|
+
|
|
17
|
+
machine_output = ARGV.any? { |arg| arg == "--json" || arg.start_with?("--events") }
|
|
18
|
+
puts "== #{script_basename} v#{Kettle::Jem::Version::VERSION} ==" if ARGV.include?("--verbose") && !machine_output
|
|
19
|
+
|
|
20
|
+
exit(Kettle::Jem::CLI.run(ARGV, env: ENV, out: $stdout, err: $stderr))
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "optparse"
|
|
6
|
+
|
|
7
|
+
module Kettle
|
|
8
|
+
module Jem
|
|
9
|
+
module CLI
|
|
10
|
+
USAGE = <<~USAGE
|
|
11
|
+
Usage:
|
|
12
|
+
kettle-jem [PROJECT_ROOT] [--accept-config] [--bootstrap-mode] [--quiet|--verbose]
|
|
13
|
+
kettle-jem setup [PROJECT_ROOT] [--accept-config] [--bootstrap-mode] [--quiet|--verbose]
|
|
14
|
+
kettle-jem prepare [PROJECT_ROOT] [--json|--events[=TYPE,...]] [--report PATH] [--accept|--force] [--quiet|--verbose]
|
|
15
|
+
kettle-jem plan [PROJECT_ROOT] [--json|--events[=TYPE,...]] [--report PATH] [--accept|--force|--interactive] [--failure-mode MODE] [--prompt-answer ID=ACTION]
|
|
16
|
+
kettle-jem apply [PROJECT_ROOT] [--json|--events[=TYPE,...]] [--report PATH] [--accept|--force|--interactive] [--failure-mode MODE] [--prompt-answer ID=ACTION]
|
|
17
|
+
kettle-jem template [PROJECT_ROOT] [--json|--events[=TYPE,...]] [--report PATH] [--accept|--force|--interactive] [--failure-mode MODE] [--prompt-answer ID=ACTION]
|
|
18
|
+
kettle-jem install [PROJECT_ROOT] [--json|--events[=TYPE,...]] [--report PATH] [--accept|--force|--interactive] [--failure-mode MODE] [--prompt-answer ID=ACTION]
|
|
19
|
+
kettle-jem manifest [PROJECT_ROOT] [--json]
|
|
20
|
+
kettle-jem selftest [PROJECT_ROOT] [--json] [--report PATH] [--destination PATH] [--template-root PATH] [--selftest-output PATH]
|
|
21
|
+
kettle-jem version
|
|
22
|
+
USAGE
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
def run(argv = ARGV, env: ENV, out: $stdout, err: $stderr)
|
|
27
|
+
command, args = normalize_command(argv)
|
|
28
|
+
return print_help(out) if command == "help"
|
|
29
|
+
return print_version(out) if command == "version"
|
|
30
|
+
|
|
31
|
+
options = parse_options(args)
|
|
32
|
+
project_root = File.expand_path(options.fetch(:project_root) || Dir.pwd)
|
|
33
|
+
ensure_not_running_from_own_context!(command, project_root)
|
|
34
|
+
print_debug_snapshot(command, project_root: project_root, env: env, err: err) if debug_enabled?(env)
|
|
35
|
+
options[:event_io] = out
|
|
36
|
+
result = execute(command, project_root: project_root, env: env, options: options)
|
|
37
|
+
write_report(options[:report_path], result) if options[:report_path]
|
|
38
|
+
print_result(command, result, options: options, out: out)
|
|
39
|
+
0
|
|
40
|
+
rescue OptionParser::ParseError, ArgumentError => error
|
|
41
|
+
err.puts(error.message)
|
|
42
|
+
err.puts(USAGE)
|
|
43
|
+
2
|
|
44
|
+
rescue => error
|
|
45
|
+
err.puts("#{error.class}: #{error.message}")
|
|
46
|
+
err.puts(error.backtrace.join("\n")) if debug_enabled?(env)
|
|
47
|
+
1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def normalize_command(argv)
|
|
51
|
+
args = Array(argv).dup
|
|
52
|
+
command = args.shift
|
|
53
|
+
return ["help", []] if command == "help" || command == "--help" || command == "-h"
|
|
54
|
+
return ["setup", []] if command.nil?
|
|
55
|
+
|
|
56
|
+
unless command_allowed?(command)
|
|
57
|
+
args.unshift(command)
|
|
58
|
+
command = "setup"
|
|
59
|
+
end
|
|
60
|
+
command = "version" if command == "version" || command == "--version" || command == "-v"
|
|
61
|
+
raise ArgumentError, "Unsupported kettle-jem command #{command.inspect}" unless command_allowed?(command)
|
|
62
|
+
|
|
63
|
+
[command, args]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def command_allowed?(command)
|
|
67
|
+
%w[setup prepare plan apply template install manifest selftest help version].include?(command)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def parse_options(args)
|
|
71
|
+
options = {
|
|
72
|
+
json: false,
|
|
73
|
+
events: false,
|
|
74
|
+
run_options: {}
|
|
75
|
+
}
|
|
76
|
+
parser = OptionParser.new do |opts|
|
|
77
|
+
opts.banner = USAGE
|
|
78
|
+
opts.on("--json", "Print the full machine-readable result as JSON.") { options[:json] = true }
|
|
79
|
+
opts.on("--events[=TYPES]", "Print newline-delimited JSON progress events. Optional comma-separated TYPES filter.") do |value|
|
|
80
|
+
options[:events] = true
|
|
81
|
+
options[:event_types] = value if value
|
|
82
|
+
end
|
|
83
|
+
opts.on("--report PATH", "Write the full machine-readable result to PATH as JSON.") do |path|
|
|
84
|
+
options[:report_path] = path
|
|
85
|
+
end
|
|
86
|
+
opts.on("--accept", "Use non-interactive default decisions.") { options[:run_options][:accept] = true }
|
|
87
|
+
opts.on("--force", "Alias for --accept.") { options[:run_options][:force] = true }
|
|
88
|
+
opts.on("--interactive", "Use interactive decision mode when supported.") do
|
|
89
|
+
options[:run_options][:interactive] = true
|
|
90
|
+
end
|
|
91
|
+
opts.on("--quiet", "Suppress normal text output.") do
|
|
92
|
+
options[:run_options][:quiet] = true
|
|
93
|
+
end
|
|
94
|
+
opts.on("--verbose", "Request verbose diagnostics where supported.") do
|
|
95
|
+
options[:run_options][:verbose] = true
|
|
96
|
+
end
|
|
97
|
+
opts.on("--failure-mode MODE", "Set the template failure mode.") do |mode|
|
|
98
|
+
options[:run_options][:failure_mode] = mode
|
|
99
|
+
end
|
|
100
|
+
opts.on("--prompt-answer ID=ACTION", "Answer an interactive decision prompt.") do |value|
|
|
101
|
+
id, action = value.to_s.split("=", 2)
|
|
102
|
+
raise OptionParser::InvalidArgument, "--prompt-answer must use ID=ACTION" if id.to_s.empty? || action.to_s.empty?
|
|
103
|
+
|
|
104
|
+
(options[:run_options][:prompt_answers] ||= {})[id] = action
|
|
105
|
+
options[:run_options][:interactive] = true
|
|
106
|
+
end
|
|
107
|
+
opts.on("--allowed VALUE", "Set the env-file change policy.") do |value|
|
|
108
|
+
options[:run_options][:allowed] = value
|
|
109
|
+
end
|
|
110
|
+
opts.on("--hook-templates VALUE", "Set hook template handling.") do |value|
|
|
111
|
+
options[:run_options][:hook_templates] = value
|
|
112
|
+
end
|
|
113
|
+
opts.on("--hook_templates VALUE", "Alias for --hook-templates.") do |value|
|
|
114
|
+
options[:run_options][:hook_templates] = value
|
|
115
|
+
end
|
|
116
|
+
opts.on("--git-drivers VALUE", "Set Git diff/merge driver setup handling.") do |value|
|
|
117
|
+
options[:run_options][:git_drivers] = value
|
|
118
|
+
end
|
|
119
|
+
opts.on("--git_drivers VALUE", "Alias for --git-drivers.") do |value|
|
|
120
|
+
options[:run_options][:git_drivers] = value
|
|
121
|
+
end
|
|
122
|
+
opts.on("--dry-run", "Plan supported post-template actions without applying them.") do
|
|
123
|
+
options[:run_options][:dry_run] = true
|
|
124
|
+
end
|
|
125
|
+
opts.on("--check", "Verify supported post-template setup without changing files.") do
|
|
126
|
+
options[:run_options][:git_drivers] = "check"
|
|
127
|
+
end
|
|
128
|
+
opts.on("--undo", "Undo supported post-template setup.") do
|
|
129
|
+
options[:run_options][:git_drivers] = "undo"
|
|
130
|
+
end
|
|
131
|
+
opts.on("--only PATHS", "Restrict templating to comma-separated paths or patterns.") do |value|
|
|
132
|
+
(options[:run_options][:only] ||= []) << value
|
|
133
|
+
end
|
|
134
|
+
opts.on("--include PATHS", "Include comma-separated paths or patterns.") do |value|
|
|
135
|
+
(options[:run_options][:include] ||= []) << value
|
|
136
|
+
end
|
|
137
|
+
opts.on("--skip-commit", "Skip bootstrap commit behavior.") do
|
|
138
|
+
options[:run_options][:skip_commit] = true
|
|
139
|
+
end
|
|
140
|
+
opts.on("--skip-drift-check", "Skip post-apply duplicate drift checking.") do
|
|
141
|
+
options[:run_options][:skip_drift_check] = true
|
|
142
|
+
end
|
|
143
|
+
opts.on("--skip-duplicate-drift", "Alias for --skip-drift-check.") do
|
|
144
|
+
options[:run_options][:skip_drift_check] = true
|
|
145
|
+
end
|
|
146
|
+
opts.on("--skip-rubocop-gradual", "Skip post-template RuboCop Gradual autocorrect.") do
|
|
147
|
+
options[:run_options][:skip_rubocop_gradual] = true
|
|
148
|
+
end
|
|
149
|
+
opts.on("--skip-binstubs", "Skip post-template curated Bundler binstub generation.") do
|
|
150
|
+
options[:run_options][:skip_binstubs] = true
|
|
151
|
+
end
|
|
152
|
+
opts.on("--checksums VALUE", "Set checksum skip mode: template, dest, ignore-template, ignore-dest, or off.") do |value|
|
|
153
|
+
options[:run_options][:checksums] = value
|
|
154
|
+
end
|
|
155
|
+
opts.on("--ignore-checksums", "Alias for --checksums off.") do
|
|
156
|
+
options[:run_options][:checksums] = "off"
|
|
157
|
+
end
|
|
158
|
+
opts.on("--accept-config", "Accept first-run template config bootstrap.") do
|
|
159
|
+
options[:run_options][:accept_config] = true
|
|
160
|
+
end
|
|
161
|
+
opts.on("--bootstrap-mode", "Force first-run bootstrap mode.") do
|
|
162
|
+
options[:run_options][:bootstrap_mode] = true
|
|
163
|
+
end
|
|
164
|
+
opts.on("--template-profile PROFILE", "Use a packaged template profile.") do |value|
|
|
165
|
+
options[:run_options][:template_profile] = value
|
|
166
|
+
end
|
|
167
|
+
opts.on("--shimmed-gem GEM", "Runtime gem required by the shim profile.") do |value|
|
|
168
|
+
options[:run_options][:shimmed_gem] = value
|
|
169
|
+
end
|
|
170
|
+
opts.on("--shimmed-require REQUIRE", "Require path loaded by the shim profile.") do |value|
|
|
171
|
+
options[:run_options][:shimmed_require] = value
|
|
172
|
+
end
|
|
173
|
+
opts.on("--destination PATH", "Selftest destination root.") do |path|
|
|
174
|
+
options[:destination_root] = path
|
|
175
|
+
end
|
|
176
|
+
opts.on("--template-root PATH", "Selftest template root.") do |path|
|
|
177
|
+
options[:template_root] = path
|
|
178
|
+
end
|
|
179
|
+
opts.on("--selftest-output PATH", "Selftest output root.") do |path|
|
|
180
|
+
options[:selftest_output_root] = path
|
|
181
|
+
end
|
|
182
|
+
opts.on("--min-divergence-threshold PERCENT", "Fail selftest when divergence exceeds PERCENT.") do |value|
|
|
183
|
+
options[:min_divergence_threshold] = Float(value)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
remaining = parser.parse(args)
|
|
187
|
+
raise ArgumentError, "Expected at most one PROJECT_ROOT" if remaining.length > 1
|
|
188
|
+
raise OptionParser::InvalidOption, "--events cannot be combined with --json" if options[:events] && options[:json]
|
|
189
|
+
|
|
190
|
+
options[:project_root] = remaining.first
|
|
191
|
+
options
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def execute(command, project_root:, env:, options:)
|
|
195
|
+
run_options = options.fetch(:run_options)
|
|
196
|
+
if options[:events]
|
|
197
|
+
run_options[:event_stream] = Kettle::Jem.event_stream(
|
|
198
|
+
options.fetch(:event_io),
|
|
199
|
+
types: options[:event_types]
|
|
200
|
+
)
|
|
201
|
+
end
|
|
202
|
+
case command
|
|
203
|
+
when "setup"
|
|
204
|
+
Kettle::Jem.setup_project(project_root, env: env, run_options: run_options)
|
|
205
|
+
when "prepare"
|
|
206
|
+
Kettle::Jem::Tasks::PrepareTask.run(project_root: project_root, env: env, run_options: run_options)
|
|
207
|
+
when "plan"
|
|
208
|
+
Kettle::Jem.plan_project(project_root, env: env, run_options: run_options)
|
|
209
|
+
when "apply"
|
|
210
|
+
Kettle::Jem.apply_project(project_root, env: env, run_options: run_options)
|
|
211
|
+
when "template"
|
|
212
|
+
if scoped_template_run?(run_options)
|
|
213
|
+
Kettle::Jem::Tasks::TemplateTask.run(project_root: project_root, env: env, run_options: run_options)
|
|
214
|
+
else
|
|
215
|
+
Kettle::Jem::Tasks::InstallTask.run(project_root: project_root, env: env, run_options: run_options)
|
|
216
|
+
end
|
|
217
|
+
when "install"
|
|
218
|
+
Kettle::Jem::Tasks::InstallTask.run(project_root: project_root, env: env, run_options: run_options)
|
|
219
|
+
when "manifest"
|
|
220
|
+
Kettle::Jem.template_manifest(project_root: project_root)
|
|
221
|
+
when "selftest"
|
|
222
|
+
Kettle::Jem::Tasks::SelfTestTask.run(
|
|
223
|
+
project_root: project_root,
|
|
224
|
+
destination_root: options[:destination_root] || project_root,
|
|
225
|
+
template_root: options[:template_root],
|
|
226
|
+
output_root: options[:selftest_output_root],
|
|
227
|
+
min_divergence_threshold: options[:min_divergence_threshold]
|
|
228
|
+
)
|
|
229
|
+
else
|
|
230
|
+
raise ArgumentError, "Unsupported kettle-jem command #{command.inspect}"
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def scoped_template_run?(run_options)
|
|
235
|
+
run_options = run_options.to_h
|
|
236
|
+
run_options.key?(:only) || run_options.key?(:include)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def ensure_not_running_from_own_context!(command, project_root)
|
|
240
|
+
return if %w[help version].include?(command)
|
|
241
|
+
|
|
242
|
+
current_root = canonical_path(Dir.pwd)
|
|
243
|
+
own_root = canonical_path(File.expand_path("../../..", __dir__))
|
|
244
|
+
target_root = canonical_path(project_root)
|
|
245
|
+
return unless current_root == own_root && target_root != own_root
|
|
246
|
+
|
|
247
|
+
raise ArgumentError,
|
|
248
|
+
"Refusing to run kettle-jem from its own project root against #{project_root}; " \
|
|
249
|
+
"run from the destination repository so its environment is loaded, or target kettle-jem itself."
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def canonical_path(path)
|
|
253
|
+
File.realpath(path)
|
|
254
|
+
rescue Errno::ENOENT
|
|
255
|
+
File.expand_path(path)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def print_result(command, result, options:, out:)
|
|
259
|
+
return if options[:events]
|
|
260
|
+
return if options.fetch(:run_options, {})[:quiet] && !options[:json]
|
|
261
|
+
|
|
262
|
+
if options[:json]
|
|
263
|
+
out.puts(JSON.pretty_generate(result))
|
|
264
|
+
return
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
case command
|
|
268
|
+
when "setup"
|
|
269
|
+
out.puts("setup: #{result.fetch(:setup_status)}")
|
|
270
|
+
result.fetch(:changed_files, []).each { |path| out.puts(" #{path}") }
|
|
271
|
+
result.fetch(:diagnostics, []).each do |diagnostic|
|
|
272
|
+
message = diagnostic.is_a?(Hash) ? diagnostic[:message] || diagnostic["message"] : diagnostic
|
|
273
|
+
out.puts(" #{message}") unless message.to_s.empty?
|
|
274
|
+
end
|
|
275
|
+
when "manifest"
|
|
276
|
+
entries = result.fetch(:entries, [])
|
|
277
|
+
out.puts("template manifest: #{entries.length} entr#{(entries.length == 1) ? "y" : "ies"}")
|
|
278
|
+
when "selftest"
|
|
279
|
+
comparison = result.fetch(:comparison, {})
|
|
280
|
+
divergent = comparison.fetch(:changed, []).size +
|
|
281
|
+
comparison.fetch(:added, []).size +
|
|
282
|
+
comparison.fetch(:removed, []).size
|
|
283
|
+
out.puts("selftest: #{divergent} divergent file#{"s" unless divergent == 1}")
|
|
284
|
+
out.puts(" report: #{result.fetch(:report_path)}") if result[:report_path]
|
|
285
|
+
else
|
|
286
|
+
changed_files = result.fetch(:changed_files, [])
|
|
287
|
+
out.puts("#{result.fetch(:mode)}: #{changed_files.length} changed file#{"s" unless changed_files.length == 1}")
|
|
288
|
+
changed_files.each { |path| out.puts(" #{path}") }
|
|
289
|
+
Array(result[:warnings]).map(&:to_s).reject(&:empty?).uniq.each do |warning|
|
|
290
|
+
out.puts(" warning: #{warning}")
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def write_report(path, result)
|
|
296
|
+
FileUtils.mkdir_p(File.dirname(File.expand_path(path)))
|
|
297
|
+
File.write(path, "#{JSON.pretty_generate(result)}\n")
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def print_debug_snapshot(command, project_root:, env:, err:)
|
|
301
|
+
err.puts("[kettle-jem] DEBUG: early environment snapshot")
|
|
302
|
+
err.puts(" command=#{command.inspect}")
|
|
303
|
+
err.puts(" project_root=#{project_root.inspect}")
|
|
304
|
+
%w[DEBUG KETTLE_JEM_DEBUG KETTLE_DEV_DEBUG KETTLE_DEV_DEV BUNDLE_GEMFILE BUNDLE_PATH GEM_HOME GEM_PATH RUBYOPT RUBYLIB PWD].each do |key|
|
|
305
|
+
err.puts(" #{key}=#{env_value(env, key).inspect}")
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def debug_enabled?(env)
|
|
310
|
+
%w[DEBUG KETTLE_JEM_DEBUG KETTLE_DEV_DEBUG].any? { |key| env_true?(env_value(env, key)) }
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def env_true?(value)
|
|
314
|
+
/\A(?:true|t|yes|y|on|1)\z/i.match?(value.to_s.strip)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def env_value(env, key)
|
|
318
|
+
env.fetch(key, nil)
|
|
319
|
+
rescue KeyError
|
|
320
|
+
nil
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def print_help(out)
|
|
324
|
+
out.puts(USAGE)
|
|
325
|
+
0
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def print_version(out)
|
|
329
|
+
out.puts(Kettle::Jem::Version::VERSION)
|
|
330
|
+
0
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kettle
|
|
4
|
+
module Jem
|
|
5
|
+
# Recognizes MIT license text and extracts copyright lines from its preamble.
|
|
6
|
+
class LicenseTxtMigrator
|
|
7
|
+
MIT_PHRASES = [
|
|
8
|
+
"permission is hereby granted",
|
|
9
|
+
"without restriction"
|
|
10
|
+
].freeze
|
|
11
|
+
|
|
12
|
+
def initialize(content)
|
|
13
|
+
@content = content.to_s
|
|
14
|
+
@analysis = Ast::Merge::Text::FileAnalysis.new(@content)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def mit_license?
|
|
18
|
+
text = @analysis.searchable_text.downcase
|
|
19
|
+
MIT_PHRASES.all? { |phrase| text.include?(phrase) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def copyright_lines
|
|
23
|
+
lines = @analysis.statements.select { |node| node.is_a?(Ast::Merge::Text::LineNode) }
|
|
24
|
+
boundary = lines.index do |node|
|
|
25
|
+
@analysis.searchable_text(nodes: [node]).downcase.include?("permission is hereby granted")
|
|
26
|
+
end
|
|
27
|
+
lines.first(boundary || lines.length)
|
|
28
|
+
.select { |node| node.content.match?(/copyright/i) }
|
|
29
|
+
.map(&:content)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|