shopify-cli 0.9.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/.github/CODEOWNERS +1 -0
- data/.github/CODE_OF_CONDUCT.md +73 -0
- data/.github/CONTRIBUTING.md +51 -0
- data/.github/DESIGN.md +153 -0
- data/.github/ISSUE_TEMPLATE.md +38 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.github/probots.yml +3 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +47 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +77 -0
- data/LICENSE.md +7 -0
- data/README.md +13 -0
- data/Rakefile +101 -0
- data/SECURITY.md +59 -0
- data/Vagrantfile +17 -0
- data/bin/load_shopify.rb +20 -0
- data/bin/shopify +32 -0
- data/dev.yml +17 -0
- data/docs/Gemfile +5 -0
- data/docs/Gemfile.lock +248 -0
- data/docs/_config.yml +16 -0
- data/docs/_data/nav.yml +26 -0
- data/docs/_includes/footer.html +15 -0
- data/docs/_includes/head.html +19 -0
- data/docs/_includes/sidebar_nav.html +22 -0
- data/docs/_includes/toc.html +112 -0
- data/docs/_layouts/default.html +79 -0
- data/docs/app/node/commands/index.md +82 -0
- data/docs/app/node/index.md +35 -0
- data/docs/app/rails/commands/index.md +80 -0
- data/docs/app/rails/index.md +36 -0
- data/docs/core/index.md +70 -0
- data/docs/css/docs.css +157 -0
- data/docs/getting-started/index.md +61 -0
- data/docs/help/start-app/index.md +6 -0
- data/docs/images/header.png +0 -0
- data/docs/index.md +27 -0
- data/docs/installing-ruby.md +28 -0
- data/ext/shopify-cli/extconf.rb +27 -0
- data/install.sh +7 -0
- data/lib/docgen/class_template.md.erb +81 -0
- data/lib/docgen/index_template.md.erb +5 -0
- data/lib/docgen/markdown.rb +101 -0
- data/lib/graphql/admin_introspection.graphql +87 -0
- data/lib/graphql/all_organizations.graphql +19 -0
- data/lib/graphql/all_orgs_with_apps.graphql +30 -0
- data/lib/graphql/api_versions.graphql +6 -0
- data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
- data/lib/graphql/create_app.graphql +20 -0
- data/lib/graphql/create_customer.graphql +9 -0
- data/lib/graphql/create_draft_order.graphql +8 -0
- data/lib/graphql/create_product.graphql +9 -0
- data/lib/graphql/extension_create.graphql +21 -0
- data/lib/graphql/extension_update_draft.graphql +18 -0
- data/lib/graphql/find_organization.graphql +17 -0
- data/lib/graphql/get_app_urls.graphql +6 -0
- data/lib/graphql/update_dashboard_urls.graphql +8 -0
- data/lib/project_types/extension/cli.rb +71 -0
- data/lib/project_types/extension/commands/build.rb +29 -0
- data/lib/project_types/extension/commands/create.rb +49 -0
- data/lib/project_types/extension/commands/extension_command.rb +22 -0
- data/lib/project_types/extension/commands/push.rb +69 -0
- data/lib/project_types/extension/commands/register.rb +78 -0
- data/lib/project_types/extension/commands/serve.rb +24 -0
- data/lib/project_types/extension/commands/tunnel.rb +69 -0
- data/lib/project_types/extension/extension_project.rb +85 -0
- data/lib/project_types/extension/extension_project_keys.rb +10 -0
- data/lib/project_types/extension/features/argo.rb +48 -0
- data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
- data/lib/project_types/extension/features/argo_setup.rb +54 -0
- data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
- data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
- data/lib/project_types/extension/features/tunnel_url.rb +20 -0
- data/lib/project_types/extension/forms/create.rb +52 -0
- data/lib/project_types/extension/forms/register.rb +48 -0
- data/lib/project_types/extension/messages/message_loading.rb +37 -0
- data/lib/project_types/extension/messages/messages.rb +126 -0
- data/lib/project_types/extension/models/app.rb +14 -0
- data/lib/project_types/extension/models/registration.rb +19 -0
- data/lib/project_types/extension/models/type.rb +76 -0
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
- data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
- data/lib/project_types/extension/models/validation_error.rb +17 -0
- data/lib/project_types/extension/models/version.rb +15 -0
- data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
- data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
- data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
- data/lib/project_types/extension/tasks/create_extension.rb +31 -0
- data/lib/project_types/extension/tasks/get_apps.rb +34 -0
- data/lib/project_types/extension/tasks/update_draft.rb +29 -0
- data/lib/project_types/extension/tasks/user_errors.rb +45 -0
- data/lib/project_types/node/cli.rb +37 -0
- data/lib/project_types/node/commands/create.rb +117 -0
- data/lib/project_types/node/commands/deploy.rb +22 -0
- data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
- data/lib/project_types/node/commands/generate.rb +51 -0
- data/lib/project_types/node/commands/generate/billing.rb +37 -0
- data/lib/project_types/node/commands/generate/page.rb +55 -0
- data/lib/project_types/node/commands/generate/webhook.rb +33 -0
- data/lib/project_types/node/commands/open.rb +16 -0
- data/lib/project_types/node/commands/populate.rb +23 -0
- data/lib/project_types/node/commands/populate/customer.rb +31 -0
- data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/node/commands/populate/product.rb +30 -0
- data/lib/project_types/node/commands/serve.rb +45 -0
- data/lib/project_types/node/commands/tunnel.rb +39 -0
- data/lib/project_types/node/forms/create.rb +87 -0
- data/lib/project_types/node/messages/messages.rb +260 -0
- data/lib/project_types/rails/cli.rb +41 -0
- data/lib/project_types/rails/commands/create.rb +126 -0
- data/lib/project_types/rails/commands/deploy.rb +22 -0
- data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
- data/lib/project_types/rails/commands/generate.rb +49 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
- data/lib/project_types/rails/commands/open.rb +16 -0
- data/lib/project_types/rails/commands/populate.rb +23 -0
- data/lib/project_types/rails/commands/populate/customer.rb +31 -0
- data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/rails/commands/populate/product.rb +30 -0
- data/lib/project_types/rails/commands/serve.rb +47 -0
- data/lib/project_types/rails/commands/tunnel.rb +39 -0
- data/lib/project_types/rails/forms/create.rb +116 -0
- data/lib/project_types/rails/gem.rb +56 -0
- data/lib/project_types/rails/messages/messages.rb +283 -0
- data/lib/project_types/rails/ruby.rb +17 -0
- data/lib/project_types/script/cli.rb +76 -0
- data/lib/project_types/script/commands/create.rb +45 -0
- data/lib/project_types/script/commands/disable.rb +36 -0
- data/lib/project_types/script/commands/enable.rb +46 -0
- data/lib/project_types/script/commands/push.rb +39 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/errors.rb +16 -0
- data/lib/project_types/script/forms/create.rb +29 -0
- data/lib/project_types/script/forms/enable.rb +24 -0
- data/lib/project_types/script/forms/push.rb +19 -0
- data/lib/project_types/script/forms/script_form.rb +66 -0
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
- data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
- data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
- data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
- data/lib/project_types/script/layers/application/build_script.rb +43 -0
- data/lib/project_types/script/layers/application/create_script.rb +47 -0
- data/lib/project_types/script/layers/application/disable_script.rb +19 -0
- data/lib/project_types/script/layers/application/enable_script.rb +21 -0
- data/lib/project_types/script/layers/application/extension_points.rb +17 -0
- data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
- data/lib/project_types/script/layers/application/push_script.rb +30 -0
- data/lib/project_types/script/layers/domain/errors.rb +25 -0
- data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
- data/lib/project_types/script/layers/domain/push_package.rb +29 -0
- data/lib/project_types/script/layers/domain/script.rb +18 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
- data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
- data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
- data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
- data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
- data/lib/project_types/script/messages/messages.rb +204 -0
- data/lib/project_types/script/script_project.rb +37 -0
- data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
- data/lib/project_types/script/ui/error_handler.rb +136 -0
- data/lib/project_types/script/ui/strict_spinner.rb +22 -0
- data/lib/rubygems_plugin.rb +18 -0
- data/lib/shopify-cli/admin_api.rb +99 -0
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
- data/lib/shopify-cli/admin_api/schema.rb +32 -0
- data/lib/shopify-cli/api.rb +104 -0
- data/lib/shopify-cli/command.rb +67 -0
- data/lib/shopify-cli/commands.rb +28 -0
- data/lib/shopify-cli/commands/connect.rb +108 -0
- data/lib/shopify-cli/commands/create.rb +50 -0
- data/lib/shopify-cli/commands/help.rb +79 -0
- data/lib/shopify-cli/commands/logout.rb +23 -0
- data/lib/shopify-cli/commands/system.rb +135 -0
- data/lib/shopify-cli/commands/version.rb +15 -0
- data/lib/shopify-cli/context.rb +372 -0
- data/lib/shopify-cli/core.rb +9 -0
- data/lib/shopify-cli/core/entry_point.rb +40 -0
- data/lib/shopify-cli/core/executor.rb +21 -0
- data/lib/shopify-cli/core/help_resolver.rb +20 -0
- data/lib/shopify-cli/core/monorail.rb +118 -0
- data/lib/shopify-cli/db.rb +114 -0
- data/lib/shopify-cli/form.rb +40 -0
- data/lib/shopify-cli/git.rb +141 -0
- data/lib/shopify-cli/helpers.rb +5 -0
- data/lib/shopify-cli/helpers/haikunator.rb +92 -0
- data/lib/shopify-cli/heroku.rb +97 -0
- data/lib/shopify-cli/js_deps.rb +110 -0
- data/lib/shopify-cli/js_system.rb +98 -0
- data/lib/shopify-cli/messages/messages.rb +287 -0
- data/lib/shopify-cli/oauth.rb +192 -0
- data/lib/shopify-cli/oauth/servlet.rb +61 -0
- data/lib/shopify-cli/options.rb +40 -0
- data/lib/shopify-cli/packager.rb +116 -0
- data/lib/shopify-cli/partners_api.rb +114 -0
- data/lib/shopify-cli/partners_api/organizations.rb +32 -0
- data/lib/shopify-cli/process_supervision.rb +187 -0
- data/lib/shopify-cli/project.rb +191 -0
- data/lib/shopify-cli/project_type.rb +83 -0
- data/lib/shopify-cli/resources.rb +5 -0
- data/lib/shopify-cli/resources/env_file.rb +96 -0
- data/lib/shopify-cli/sub_command.rb +15 -0
- data/lib/shopify-cli/task.rb +10 -0
- data/lib/shopify-cli/tasks.rb +32 -0
- data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
- data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
- data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
- data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
- data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
- data/lib/shopify-cli/tunnel.rb +154 -0
- data/lib/shopify-cli/version.rb +3 -0
- data/lib/shopify_cli.rb +132 -0
- data/shopify-cli.gemspec +40 -0
- data/shopify.fish +12 -0
- data/shopify.sh +11 -0
- data/vendor/deps/cli-kit/REVISION +1 -0
- data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
- data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
- data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
- data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
- data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
- data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
- data/vendor/deps/cli-ui/REVISION +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
- data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
- data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
- data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
- data/vendor/deps/smart_properties/REVISION +1 -0
- data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
- data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
- data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
- data/vendor/lib/semantic/LICENSE +20 -0
- data/vendor/lib/semantic/semantic.rb +4 -0
- data/vendor/lib/semantic/version.rb +180 -0
- metadata +374 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'cli/kit'
|
|
2
|
+
require 'English'
|
|
3
|
+
|
|
4
|
+
module CLI
|
|
5
|
+
module Kit
|
|
6
|
+
class ErrorHandler
|
|
7
|
+
def initialize(log_file:, exception_reporter:, tool_name: nil)
|
|
8
|
+
@log_file = log_file
|
|
9
|
+
@exception_reporter_or_proc = exception_reporter || NullExceptionReporter
|
|
10
|
+
@tool_name = tool_name
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module NullExceptionReporter
|
|
14
|
+
def self.report(_exception, _logs)
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call(&block)
|
|
20
|
+
install!
|
|
21
|
+
handle_abort(&block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def handle_exception(error)
|
|
25
|
+
if notify_with = exception_for_submission(error)
|
|
26
|
+
logs = begin
|
|
27
|
+
File.read(@log_file)
|
|
28
|
+
rescue => e
|
|
29
|
+
"(#{e.class}: #{e.message})"
|
|
30
|
+
end
|
|
31
|
+
exception_reporter.report(notify_with, logs)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# maybe we can get rid of this.
|
|
36
|
+
attr_writer :exception
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def exception_for_submission(error)
|
|
41
|
+
case error
|
|
42
|
+
when nil # normal, non-error termination
|
|
43
|
+
nil
|
|
44
|
+
when Interrupt # ctrl-c
|
|
45
|
+
nil
|
|
46
|
+
when CLI::Kit::Abort, CLI::Kit::AbortSilent # Not a bug
|
|
47
|
+
nil
|
|
48
|
+
when SignalException
|
|
49
|
+
skip = %w(SIGTERM SIGHUP SIGINT)
|
|
50
|
+
skip.include?(error.message) ? nil : error
|
|
51
|
+
when SystemExit # "exit N" called
|
|
52
|
+
case error.status
|
|
53
|
+
when CLI::Kit::EXIT_SUCCESS # submit nothing if it was `exit 0`
|
|
54
|
+
nil
|
|
55
|
+
when CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
56
|
+
# if it was `exit 30`, translate the exit code to 1, and submit nothing.
|
|
57
|
+
# 30 is used to signal normal failures that are not indicative of bugs.
|
|
58
|
+
# However, users should see it presented as 1.
|
|
59
|
+
exit 1
|
|
60
|
+
else
|
|
61
|
+
# A weird termination status happened. `error.exception "message"` will maintain backtrace
|
|
62
|
+
# but allow us to set a message
|
|
63
|
+
error.exception("abnormal termination status: #{error.status}")
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
error
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def install!
|
|
71
|
+
at_exit { handle_exception(@exception || $ERROR_INFO) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def handle_abort
|
|
75
|
+
yield
|
|
76
|
+
CLI::Kit::EXIT_SUCCESS
|
|
77
|
+
rescue CLI::Kit::GenericAbort => e
|
|
78
|
+
is_bug = e.is_a?(CLI::Kit::Bug) || e.is_a?(CLI::Kit::BugSilent)
|
|
79
|
+
is_silent = e.is_a?(CLI::Kit::AbortSilent) || e.is_a?(CLI::Kit::BugSilent)
|
|
80
|
+
|
|
81
|
+
print_error_message(e) unless is_silent
|
|
82
|
+
(@exception = e) if is_bug
|
|
83
|
+
|
|
84
|
+
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
85
|
+
rescue Interrupt
|
|
86
|
+
$stderr.puts(format_error_message("Interrupt"))
|
|
87
|
+
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
88
|
+
rescue Errno::ENOSPC
|
|
89
|
+
message = if @tool_name
|
|
90
|
+
"Your disk is full - {{command:#{@tool_name}}} requires free space to operate"
|
|
91
|
+
else
|
|
92
|
+
"Your disk is full - free space is required to operate"
|
|
93
|
+
end
|
|
94
|
+
$stderr.puts(format_error_message(message))
|
|
95
|
+
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def exception_reporter
|
|
99
|
+
if @exception_reporter_or_proc.respond_to?(:report)
|
|
100
|
+
@exception_reporter_or_proc
|
|
101
|
+
else
|
|
102
|
+
@exception_reporter_or_proc.call
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def format_error_message(msg)
|
|
107
|
+
CLI::UI.fmt("{{red:#{msg}}}")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def print_error_message(e)
|
|
111
|
+
$stderr.puts(format_error_message(e.message))
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'cli/kit'
|
|
2
|
+
require 'English'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
module CLI
|
|
6
|
+
module Kit
|
|
7
|
+
class Executor
|
|
8
|
+
def initialize(log_file:)
|
|
9
|
+
FileUtils.mkpath(File.dirname(log_file))
|
|
10
|
+
@log_file = log_file
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(command, command_name, args)
|
|
14
|
+
with_traps do
|
|
15
|
+
with_logging do |id|
|
|
16
|
+
begin
|
|
17
|
+
command.call(args, command_name)
|
|
18
|
+
rescue => e
|
|
19
|
+
begin
|
|
20
|
+
$stderr.puts "This command ran with ID: #{id}"
|
|
21
|
+
$stderr.puts "Please include this information in any issues/report along with relevant logs"
|
|
22
|
+
rescue SystemCallError
|
|
23
|
+
# Outputting to stderr is best-effort. Avoid raising another error when outputting debug info so that
|
|
24
|
+
# we can detect and log the original error, which may even be the source of this error.
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
raise e
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def with_logging(&block)
|
|
36
|
+
return yield unless @log_file
|
|
37
|
+
CLI::UI.log_output_to(@log_file) do
|
|
38
|
+
CLI::UI::StdoutRouter.with_id(on_streams: [CLI::UI::StdoutRouter.duplicate_output_to]) do |id|
|
|
39
|
+
block.call(id)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def with_traps
|
|
45
|
+
twrap('QUIT', method(:quit_handler)) do
|
|
46
|
+
twrap('INFO', method(:info_handler)) do
|
|
47
|
+
yield
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def twrap(signal, handler)
|
|
53
|
+
return yield unless Signal.list.key?(signal)
|
|
54
|
+
|
|
55
|
+
begin
|
|
56
|
+
prev_handler = trap(signal, handler)
|
|
57
|
+
yield
|
|
58
|
+
ensure
|
|
59
|
+
trap(signal, prev_handler)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def quit_handler(_sig)
|
|
64
|
+
z = caller
|
|
65
|
+
CLI::UI.raw do
|
|
66
|
+
$stderr.puts('SIGQUIT: quit')
|
|
67
|
+
$stderr.puts(z)
|
|
68
|
+
end
|
|
69
|
+
exit(CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def info_handler(_sig)
|
|
73
|
+
z = caller
|
|
74
|
+
CLI::UI.raw do
|
|
75
|
+
$stderr.puts('SIGINFO:')
|
|
76
|
+
$stderr.puts(z)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module CLI
|
|
2
|
+
module Kit
|
|
3
|
+
# INI is a language similar to JSON or YAML, but simplied
|
|
4
|
+
# The spec is here: https://en.wikipedia.org/wiki/INI_file
|
|
5
|
+
# This parser includes supports for 2 very basic uses
|
|
6
|
+
# - Sections
|
|
7
|
+
# - Key Value Pairs (within and outside of the sections)
|
|
8
|
+
#
|
|
9
|
+
# [global]
|
|
10
|
+
# key = val
|
|
11
|
+
#
|
|
12
|
+
# Nothing else is supported right now
|
|
13
|
+
# See the ini_test.rb file for more examples
|
|
14
|
+
#
|
|
15
|
+
class Ini
|
|
16
|
+
attr_accessor :ini
|
|
17
|
+
|
|
18
|
+
def initialize(path = nil, config: nil, default_section: nil, convert_types: true)
|
|
19
|
+
@config = if path && File.exist?(path)
|
|
20
|
+
File.readlines(path)
|
|
21
|
+
elsif config
|
|
22
|
+
config.lines
|
|
23
|
+
end
|
|
24
|
+
@ini = {}
|
|
25
|
+
@current_key = nil
|
|
26
|
+
@default_section = default_section
|
|
27
|
+
@convert_types = convert_types
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def parse
|
|
31
|
+
return @ini if @config.nil?
|
|
32
|
+
|
|
33
|
+
@config.each do |l|
|
|
34
|
+
l.strip!
|
|
35
|
+
|
|
36
|
+
# If section, then set current key, this will nest the setting
|
|
37
|
+
if section_designator?(l)
|
|
38
|
+
@current_key = l
|
|
39
|
+
|
|
40
|
+
# A new line will reset the current key
|
|
41
|
+
elsif l.strip.empty?
|
|
42
|
+
@current_key = nil
|
|
43
|
+
|
|
44
|
+
# Otherwise set the values
|
|
45
|
+
else
|
|
46
|
+
k, v = l.split('=', 2).map(&:strip)
|
|
47
|
+
set_val(k, v)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
@ini
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def git_format
|
|
54
|
+
to_ini(@ini, git_format: true).flatten.join("\n")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_s
|
|
58
|
+
to_ini(@ini).flatten.join("\n")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def to_ini(h, git_format: false)
|
|
64
|
+
optional_tab = git_format ? "\t" : ""
|
|
65
|
+
str = []
|
|
66
|
+
h.each do |k, v|
|
|
67
|
+
if section_designator?(k)
|
|
68
|
+
str << "" unless str.empty? || git_format
|
|
69
|
+
str << k
|
|
70
|
+
str << to_ini(v, git_format: git_format)
|
|
71
|
+
else
|
|
72
|
+
str << "#{optional_tab}#{k} = #{v}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
str
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def set_val(key, val)
|
|
79
|
+
return if key.nil? && val.nil?
|
|
80
|
+
|
|
81
|
+
current_key = @current_key || @default_section
|
|
82
|
+
if current_key
|
|
83
|
+
@ini[current_key] ||= {}
|
|
84
|
+
@ini[current_key][key] = typed_val(val)
|
|
85
|
+
else
|
|
86
|
+
@ini[key] = typed_val(val)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def typed_val(val)
|
|
91
|
+
return val.to_s unless @convert_types
|
|
92
|
+
return val.to_i if val =~ /^-?[0-9]+$/
|
|
93
|
+
return val.to_f if val =~ /^-?[0-9]+\.[0-9]*$/
|
|
94
|
+
val.to_s
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def section_designator?(k)
|
|
98
|
+
k.start_with?('[') && k.end_with?(']')
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Copyright (c) 2014-2016 Yuki Nishijima
|
|
2
|
+
|
|
3
|
+
# MIT License
|
|
4
|
+
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
module CLI
|
|
25
|
+
module Kit
|
|
26
|
+
module Levenshtein
|
|
27
|
+
# This code is based directly on the Text gem implementation
|
|
28
|
+
# Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
|
|
29
|
+
#
|
|
30
|
+
# Returns a value representing the "cost" of transforming str1 into str2
|
|
31
|
+
def distance(str1, str2)
|
|
32
|
+
n = str1.length
|
|
33
|
+
m = str2.length
|
|
34
|
+
return m if n.zero?
|
|
35
|
+
return n if m.zero?
|
|
36
|
+
|
|
37
|
+
d = (0..m).to_a
|
|
38
|
+
x = nil
|
|
39
|
+
|
|
40
|
+
# to avoid duplicating an enumerable object, create it outside of the loop
|
|
41
|
+
str2_codepoints = str2.codepoints
|
|
42
|
+
|
|
43
|
+
str1.each_codepoint.with_index(1) do |char1, i|
|
|
44
|
+
j = 0
|
|
45
|
+
while j < m
|
|
46
|
+
cost = char1 == str2_codepoints[j] ? 0 : 1
|
|
47
|
+
x = min3(
|
|
48
|
+
d[j + 1] + 1, # insertion
|
|
49
|
+
i + 1, # deletion
|
|
50
|
+
d[j] + cost # substitution
|
|
51
|
+
)
|
|
52
|
+
d[j] = i
|
|
53
|
+
i = x
|
|
54
|
+
|
|
55
|
+
j += 1
|
|
56
|
+
end
|
|
57
|
+
d[m] = x
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
x
|
|
61
|
+
end
|
|
62
|
+
module_function :distance
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# detects the minimum value out of three arguments. This method is
|
|
67
|
+
# faster than `[a, b, c].min` and puts less GC pressure.
|
|
68
|
+
# See https://github.com/yuki24/did_you_mean/pull/1 for a performance
|
|
69
|
+
# benchmark.
|
|
70
|
+
def min3(a, b, c)
|
|
71
|
+
if a < b && a < c
|
|
72
|
+
a
|
|
73
|
+
elsif b < c
|
|
74
|
+
b
|
|
75
|
+
else
|
|
76
|
+
c
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
module_function :min3
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
module CLI
|
|
5
|
+
module Kit
|
|
6
|
+
class Logger
|
|
7
|
+
MAX_LOG_SIZE = 5 * 1024 * 1000 # 5MB
|
|
8
|
+
MAX_NUM_LOGS = 10
|
|
9
|
+
|
|
10
|
+
# Constructor for CLI::Kit::Logger
|
|
11
|
+
#
|
|
12
|
+
# @param debug_log_file [String] path to the file where debug logs should be stored
|
|
13
|
+
def initialize(debug_log_file:)
|
|
14
|
+
FileUtils.mkpath(File.dirname(debug_log_file))
|
|
15
|
+
@debug_logger = ::Logger.new(debug_log_file, MAX_NUM_LOGS, MAX_LOG_SIZE)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Functionally equivalent to Logger#info
|
|
19
|
+
# Also logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
20
|
+
#
|
|
21
|
+
# @param msg [String] the message to log
|
|
22
|
+
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
23
|
+
def info(msg, debug: true)
|
|
24
|
+
$stdout.puts CLI::UI.fmt(msg)
|
|
25
|
+
@debug_logger.info(format_debug(msg)) if debug
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Functionally equivalent to Logger#warn
|
|
29
|
+
# Also logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
30
|
+
#
|
|
31
|
+
# @param msg [String] the message to log
|
|
32
|
+
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
33
|
+
def warn(msg, debug: true)
|
|
34
|
+
$stdout.puts CLI::UI.fmt("{{yellow:#{msg}}}")
|
|
35
|
+
@debug_logger.warn(format_debug(msg)) if debug
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Functionally equivalent to Logger#error
|
|
39
|
+
# Also logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
40
|
+
#
|
|
41
|
+
# @param msg [String] the message to log
|
|
42
|
+
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
43
|
+
def error(msg, debug: true)
|
|
44
|
+
$stderr.puts CLI::UI.fmt("{{red:#{msg}}}")
|
|
45
|
+
@debug_logger.error(format_debug(msg)) if debug
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Functionally equivalent to Logger#fatal
|
|
49
|
+
# Also logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
50
|
+
#
|
|
51
|
+
# @param msg [String] the message to log
|
|
52
|
+
# @param debug [Boolean] determines if the debug logger will receive the log (default true)
|
|
53
|
+
def fatal(msg, debug: true)
|
|
54
|
+
$stderr.puts CLI::UI.fmt("{{red:{{bold:Fatal:}} #{msg}}}")
|
|
55
|
+
@debug_logger.fatal(format_debug(msg)) if debug
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Similar to Logger#debug, however will not output to STDOUT unless DEBUG env var is set
|
|
59
|
+
# Logs to the debug file, taking into account CLI::UI::StdoutRouter.current_id
|
|
60
|
+
#
|
|
61
|
+
# @param msg [String] the message to log
|
|
62
|
+
def debug(msg)
|
|
63
|
+
$stdout.puts CLI::UI.fmt(msg) if ENV['DEBUG']
|
|
64
|
+
@debug_logger.debug(format_debug(msg))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def format_debug(msg)
|
|
70
|
+
msg = CLI::UI.fmt(msg)
|
|
71
|
+
return msg unless CLI::UI::StdoutRouter.current_id
|
|
72
|
+
"[#{CLI::UI::StdoutRouter.current_id[:id]}] #{msg}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|