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.
Files changed (273) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/CODE_OF_CONDUCT.md +73 -0
  4. data/.github/CONTRIBUTING.md +51 -0
  5. data/.github/DESIGN.md +153 -0
  6. data/.github/ISSUE_TEMPLATE.md +38 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  8. data/.github/probots.yml +3 -0
  9. data/.gitignore +19 -0
  10. data/.rubocop.yml +47 -0
  11. data/.ruby-version +1 -0
  12. data/.travis.yml +12 -0
  13. data/Gemfile +22 -0
  14. data/Gemfile.lock +77 -0
  15. data/LICENSE.md +7 -0
  16. data/README.md +13 -0
  17. data/Rakefile +101 -0
  18. data/SECURITY.md +59 -0
  19. data/Vagrantfile +17 -0
  20. data/bin/load_shopify.rb +20 -0
  21. data/bin/shopify +32 -0
  22. data/dev.yml +17 -0
  23. data/docs/Gemfile +5 -0
  24. data/docs/Gemfile.lock +248 -0
  25. data/docs/_config.yml +16 -0
  26. data/docs/_data/nav.yml +26 -0
  27. data/docs/_includes/footer.html +15 -0
  28. data/docs/_includes/head.html +19 -0
  29. data/docs/_includes/sidebar_nav.html +22 -0
  30. data/docs/_includes/toc.html +112 -0
  31. data/docs/_layouts/default.html +79 -0
  32. data/docs/app/node/commands/index.md +82 -0
  33. data/docs/app/node/index.md +35 -0
  34. data/docs/app/rails/commands/index.md +80 -0
  35. data/docs/app/rails/index.md +36 -0
  36. data/docs/core/index.md +70 -0
  37. data/docs/css/docs.css +157 -0
  38. data/docs/getting-started/index.md +61 -0
  39. data/docs/help/start-app/index.md +6 -0
  40. data/docs/images/header.png +0 -0
  41. data/docs/index.md +27 -0
  42. data/docs/installing-ruby.md +28 -0
  43. data/ext/shopify-cli/extconf.rb +27 -0
  44. data/install.sh +7 -0
  45. data/lib/docgen/class_template.md.erb +81 -0
  46. data/lib/docgen/index_template.md.erb +5 -0
  47. data/lib/docgen/markdown.rb +101 -0
  48. data/lib/graphql/admin_introspection.graphql +87 -0
  49. data/lib/graphql/all_organizations.graphql +19 -0
  50. data/lib/graphql/all_orgs_with_apps.graphql +30 -0
  51. data/lib/graphql/api_versions.graphql +6 -0
  52. data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
  53. data/lib/graphql/create_app.graphql +20 -0
  54. data/lib/graphql/create_customer.graphql +9 -0
  55. data/lib/graphql/create_draft_order.graphql +8 -0
  56. data/lib/graphql/create_product.graphql +9 -0
  57. data/lib/graphql/extension_create.graphql +21 -0
  58. data/lib/graphql/extension_update_draft.graphql +18 -0
  59. data/lib/graphql/find_organization.graphql +17 -0
  60. data/lib/graphql/get_app_urls.graphql +6 -0
  61. data/lib/graphql/update_dashboard_urls.graphql +8 -0
  62. data/lib/project_types/extension/cli.rb +71 -0
  63. data/lib/project_types/extension/commands/build.rb +29 -0
  64. data/lib/project_types/extension/commands/create.rb +49 -0
  65. data/lib/project_types/extension/commands/extension_command.rb +22 -0
  66. data/lib/project_types/extension/commands/push.rb +69 -0
  67. data/lib/project_types/extension/commands/register.rb +78 -0
  68. data/lib/project_types/extension/commands/serve.rb +24 -0
  69. data/lib/project_types/extension/commands/tunnel.rb +69 -0
  70. data/lib/project_types/extension/extension_project.rb +85 -0
  71. data/lib/project_types/extension/extension_project_keys.rb +10 -0
  72. data/lib/project_types/extension/features/argo.rb +48 -0
  73. data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
  74. data/lib/project_types/extension/features/argo_setup.rb +54 -0
  75. data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
  76. data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
  77. data/lib/project_types/extension/features/tunnel_url.rb +20 -0
  78. data/lib/project_types/extension/forms/create.rb +52 -0
  79. data/lib/project_types/extension/forms/register.rb +48 -0
  80. data/lib/project_types/extension/messages/message_loading.rb +37 -0
  81. data/lib/project_types/extension/messages/messages.rb +126 -0
  82. data/lib/project_types/extension/models/app.rb +14 -0
  83. data/lib/project_types/extension/models/registration.rb +19 -0
  84. data/lib/project_types/extension/models/type.rb +76 -0
  85. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
  86. data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
  87. data/lib/project_types/extension/models/validation_error.rb +17 -0
  88. data/lib/project_types/extension/models/version.rb +15 -0
  89. data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
  90. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
  91. data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
  92. data/lib/project_types/extension/tasks/create_extension.rb +31 -0
  93. data/lib/project_types/extension/tasks/get_apps.rb +34 -0
  94. data/lib/project_types/extension/tasks/update_draft.rb +29 -0
  95. data/lib/project_types/extension/tasks/user_errors.rb +45 -0
  96. data/lib/project_types/node/cli.rb +37 -0
  97. data/lib/project_types/node/commands/create.rb +117 -0
  98. data/lib/project_types/node/commands/deploy.rb +22 -0
  99. data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
  100. data/lib/project_types/node/commands/generate.rb +51 -0
  101. data/lib/project_types/node/commands/generate/billing.rb +37 -0
  102. data/lib/project_types/node/commands/generate/page.rb +55 -0
  103. data/lib/project_types/node/commands/generate/webhook.rb +33 -0
  104. data/lib/project_types/node/commands/open.rb +16 -0
  105. data/lib/project_types/node/commands/populate.rb +23 -0
  106. data/lib/project_types/node/commands/populate/customer.rb +31 -0
  107. data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
  108. data/lib/project_types/node/commands/populate/product.rb +30 -0
  109. data/lib/project_types/node/commands/serve.rb +45 -0
  110. data/lib/project_types/node/commands/tunnel.rb +39 -0
  111. data/lib/project_types/node/forms/create.rb +87 -0
  112. data/lib/project_types/node/messages/messages.rb +260 -0
  113. data/lib/project_types/rails/cli.rb +41 -0
  114. data/lib/project_types/rails/commands/create.rb +126 -0
  115. data/lib/project_types/rails/commands/deploy.rb +22 -0
  116. data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
  117. data/lib/project_types/rails/commands/generate.rb +49 -0
  118. data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
  119. data/lib/project_types/rails/commands/open.rb +16 -0
  120. data/lib/project_types/rails/commands/populate.rb +23 -0
  121. data/lib/project_types/rails/commands/populate/customer.rb +31 -0
  122. data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
  123. data/lib/project_types/rails/commands/populate/product.rb +30 -0
  124. data/lib/project_types/rails/commands/serve.rb +47 -0
  125. data/lib/project_types/rails/commands/tunnel.rb +39 -0
  126. data/lib/project_types/rails/forms/create.rb +116 -0
  127. data/lib/project_types/rails/gem.rb +56 -0
  128. data/lib/project_types/rails/messages/messages.rb +283 -0
  129. data/lib/project_types/rails/ruby.rb +17 -0
  130. data/lib/project_types/script/cli.rb +76 -0
  131. data/lib/project_types/script/commands/create.rb +45 -0
  132. data/lib/project_types/script/commands/disable.rb +36 -0
  133. data/lib/project_types/script/commands/enable.rb +46 -0
  134. data/lib/project_types/script/commands/push.rb +39 -0
  135. data/lib/project_types/script/config/extension_points.yml +18 -0
  136. data/lib/project_types/script/errors.rb +16 -0
  137. data/lib/project_types/script/forms/create.rb +29 -0
  138. data/lib/project_types/script/forms/enable.rb +24 -0
  139. data/lib/project_types/script/forms/push.rb +19 -0
  140. data/lib/project_types/script/forms/script_form.rb +66 -0
  141. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
  142. data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
  143. data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
  144. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
  145. data/lib/project_types/script/layers/application/build_script.rb +43 -0
  146. data/lib/project_types/script/layers/application/create_script.rb +47 -0
  147. data/lib/project_types/script/layers/application/disable_script.rb +19 -0
  148. data/lib/project_types/script/layers/application/enable_script.rb +21 -0
  149. data/lib/project_types/script/layers/application/extension_points.rb +17 -0
  150. data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
  151. data/lib/project_types/script/layers/application/push_script.rb +30 -0
  152. data/lib/project_types/script/layers/domain/errors.rb +25 -0
  153. data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
  154. data/lib/project_types/script/layers/domain/push_package.rb +29 -0
  155. data/lib/project_types/script/layers/domain/script.rb +18 -0
  156. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
  157. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
  158. data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
  159. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
  160. data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
  161. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
  162. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
  163. data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
  164. data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
  165. data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
  166. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
  167. data/lib/project_types/script/messages/messages.rb +204 -0
  168. data/lib/project_types/script/script_project.rb +37 -0
  169. data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
  170. data/lib/project_types/script/ui/error_handler.rb +136 -0
  171. data/lib/project_types/script/ui/strict_spinner.rb +22 -0
  172. data/lib/rubygems_plugin.rb +18 -0
  173. data/lib/shopify-cli/admin_api.rb +99 -0
  174. data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
  175. data/lib/shopify-cli/admin_api/schema.rb +32 -0
  176. data/lib/shopify-cli/api.rb +104 -0
  177. data/lib/shopify-cli/command.rb +67 -0
  178. data/lib/shopify-cli/commands.rb +28 -0
  179. data/lib/shopify-cli/commands/connect.rb +108 -0
  180. data/lib/shopify-cli/commands/create.rb +50 -0
  181. data/lib/shopify-cli/commands/help.rb +79 -0
  182. data/lib/shopify-cli/commands/logout.rb +23 -0
  183. data/lib/shopify-cli/commands/system.rb +135 -0
  184. data/lib/shopify-cli/commands/version.rb +15 -0
  185. data/lib/shopify-cli/context.rb +372 -0
  186. data/lib/shopify-cli/core.rb +9 -0
  187. data/lib/shopify-cli/core/entry_point.rb +40 -0
  188. data/lib/shopify-cli/core/executor.rb +21 -0
  189. data/lib/shopify-cli/core/help_resolver.rb +20 -0
  190. data/lib/shopify-cli/core/monorail.rb +118 -0
  191. data/lib/shopify-cli/db.rb +114 -0
  192. data/lib/shopify-cli/form.rb +40 -0
  193. data/lib/shopify-cli/git.rb +141 -0
  194. data/lib/shopify-cli/helpers.rb +5 -0
  195. data/lib/shopify-cli/helpers/haikunator.rb +92 -0
  196. data/lib/shopify-cli/heroku.rb +97 -0
  197. data/lib/shopify-cli/js_deps.rb +110 -0
  198. data/lib/shopify-cli/js_system.rb +98 -0
  199. data/lib/shopify-cli/messages/messages.rb +287 -0
  200. data/lib/shopify-cli/oauth.rb +192 -0
  201. data/lib/shopify-cli/oauth/servlet.rb +61 -0
  202. data/lib/shopify-cli/options.rb +40 -0
  203. data/lib/shopify-cli/packager.rb +116 -0
  204. data/lib/shopify-cli/partners_api.rb +114 -0
  205. data/lib/shopify-cli/partners_api/organizations.rb +32 -0
  206. data/lib/shopify-cli/process_supervision.rb +187 -0
  207. data/lib/shopify-cli/project.rb +191 -0
  208. data/lib/shopify-cli/project_type.rb +83 -0
  209. data/lib/shopify-cli/resources.rb +5 -0
  210. data/lib/shopify-cli/resources/env_file.rb +96 -0
  211. data/lib/shopify-cli/sub_command.rb +15 -0
  212. data/lib/shopify-cli/task.rb +10 -0
  213. data/lib/shopify-cli/tasks.rb +32 -0
  214. data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
  215. data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
  216. data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
  217. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
  218. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
  219. data/lib/shopify-cli/tunnel.rb +154 -0
  220. data/lib/shopify-cli/version.rb +3 -0
  221. data/lib/shopify_cli.rb +132 -0
  222. data/shopify-cli.gemspec +40 -0
  223. data/shopify.fish +12 -0
  224. data/shopify.sh +11 -0
  225. data/vendor/deps/cli-kit/REVISION +1 -0
  226. data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
  227. data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
  228. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
  229. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
  230. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
  231. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
  232. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
  233. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
  234. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
  235. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
  236. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
  237. data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
  238. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
  239. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
  240. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
  241. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
  242. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
  243. data/vendor/deps/cli-ui/REVISION +1 -0
  244. data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
  245. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
  246. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
  247. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
  248. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
  249. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
  250. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
  251. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
  252. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
  253. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
  254. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
  255. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
  256. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  257. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
  258. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
  259. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
  260. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
  261. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
  262. data/vendor/deps/smart_properties/REVISION +1 -0
  263. data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
  264. data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
  265. data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
  266. data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
  267. data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
  268. data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
  269. data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
  270. data/vendor/lib/semantic/LICENSE +20 -0
  271. data/vendor/lib/semantic/semantic.rb +4 -0
  272. data/vendor/lib/semantic/version.rb +180 -0
  273. 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