pantograph 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE +21 -0
  4. data/README.md +197 -0
  5. data/bin/bin-proxy +19 -0
  6. data/bin/pantograph +23 -0
  7. data/pantograph/README.md +11 -0
  8. data/pantograph/lib/assets/ActionDetails.md.erb +106 -0
  9. data/pantograph/lib/assets/Actions.md.erb +43 -0
  10. data/pantograph/lib/assets/DefaultPantfileTemplate +20 -0
  11. data/pantograph/lib/assets/completions/completion.bash +23 -0
  12. data/pantograph/lib/assets/completions/completion.fish +39 -0
  13. data/pantograph/lib/assets/completions/completion.sh +12 -0
  14. data/pantograph/lib/assets/completions/completion.zsh +23 -0
  15. data/pantograph/lib/assets/custom_action_template.rb +80 -0
  16. data/pantograph/lib/assets/report_template.xml.erb +15 -0
  17. data/pantograph/lib/pantograph/action.rb +194 -0
  18. data/pantograph/lib/pantograph/action_collector.rb +35 -0
  19. data/pantograph/lib/pantograph/actions/README.md +3 -0
  20. data/pantograph/lib/pantograph/actions/actions_helper.rb +166 -0
  21. data/pantograph/lib/pantograph/actions/add_extra_platforms.rb +45 -0
  22. data/pantograph/lib/pantograph/actions/artifactory.rb +157 -0
  23. data/pantograph/lib/pantograph/actions/bundle_install.rb +156 -0
  24. data/pantograph/lib/pantograph/actions/changelog_from_git_commits.rb +197 -0
  25. data/pantograph/lib/pantograph/actions/clipboard.rb +52 -0
  26. data/pantograph/lib/pantograph/actions/cloc.rb +89 -0
  27. data/pantograph/lib/pantograph/actions/create_pull_request.rb +190 -0
  28. data/pantograph/lib/pantograph/actions/danger.rb +131 -0
  29. data/pantograph/lib/pantograph/actions/debug.rb +32 -0
  30. data/pantograph/lib/pantograph/actions/default_platform.rb +47 -0
  31. data/pantograph/lib/pantograph/actions/download.rb +76 -0
  32. data/pantograph/lib/pantograph/actions/echo.rb +14 -0
  33. data/pantograph/lib/pantograph/actions/ensure_bundle_exec.rb +59 -0
  34. data/pantograph/lib/pantograph/actions/ensure_env_vars.rb +58 -0
  35. data/pantograph/lib/pantograph/actions/ensure_git_branch.rb +69 -0
  36. data/pantograph/lib/pantograph/actions/ensure_git_status_clean.rb +81 -0
  37. data/pantograph/lib/pantograph/actions/erb.rb +88 -0
  38. data/pantograph/lib/pantograph/actions/get_build_number_repository.rb +120 -0
  39. data/pantograph/lib/pantograph/actions/get_github_release.rb +163 -0
  40. data/pantograph/lib/pantograph/actions/git_add.rb +93 -0
  41. data/pantograph/lib/pantograph/actions/git_branch.rb +58 -0
  42. data/pantograph/lib/pantograph/actions/git_commit.rb +80 -0
  43. data/pantograph/lib/pantograph/actions/git_pull.rb +53 -0
  44. data/pantograph/lib/pantograph/actions/git_submodule_update.rb +52 -0
  45. data/pantograph/lib/pantograph/actions/git_tag_exists.rb +74 -0
  46. data/pantograph/lib/pantograph/actions/github_api.rb +262 -0
  47. data/pantograph/lib/pantograph/actions/gradle.rb +278 -0
  48. data/pantograph/lib/pantograph/actions/import.rb +49 -0
  49. data/pantograph/lib/pantograph/actions/import_from_git.rb +71 -0
  50. data/pantograph/lib/pantograph/actions/is_ci.rb +51 -0
  51. data/pantograph/lib/pantograph/actions/jira.rb +115 -0
  52. data/pantograph/lib/pantograph/actions/lane_context.rb +60 -0
  53. data/pantograph/lib/pantograph/actions/last_git_commit.rb +58 -0
  54. data/pantograph/lib/pantograph/actions/last_git_tag.rb +51 -0
  55. data/pantograph/lib/pantograph/actions/make_changelog_from_jenkins.rb +81 -0
  56. data/pantograph/lib/pantograph/actions/min_pantograph_version.rb +57 -0
  57. data/pantograph/lib/pantograph/actions/nexus_upload.rb +230 -0
  58. data/pantograph/lib/pantograph/actions/notification.rb +75 -0
  59. data/pantograph/lib/pantograph/actions/number_of_commits.rb +75 -0
  60. data/pantograph/lib/pantograph/actions/opt_out_usage.rb +40 -0
  61. data/pantograph/lib/pantograph/actions/pantograph_version.rb +15 -0
  62. data/pantograph/lib/pantograph/actions/println.rb +14 -0
  63. data/pantograph/lib/pantograph/actions/prompt.rb +119 -0
  64. data/pantograph/lib/pantograph/actions/push_git_tags.rb +76 -0
  65. data/pantograph/lib/pantograph/actions/push_to_git_remote.rb +127 -0
  66. data/pantograph/lib/pantograph/actions/puts.rb +68 -0
  67. data/pantograph/lib/pantograph/actions/reset_git_repo.rb +121 -0
  68. data/pantograph/lib/pantograph/actions/rocket.rb +83 -0
  69. data/pantograph/lib/pantograph/actions/rsync.rb +74 -0
  70. data/pantograph/lib/pantograph/actions/ruby_version.rb +56 -0
  71. data/pantograph/lib/pantograph/actions/say.rb +56 -0
  72. data/pantograph/lib/pantograph/actions/scp.rb +114 -0
  73. data/pantograph/lib/pantograph/actions/set_github_release.rb +274 -0
  74. data/pantograph/lib/pantograph/actions/sh.rb +71 -0
  75. data/pantograph/lib/pantograph/actions/skip_docs.rb +52 -0
  76. data/pantograph/lib/pantograph/actions/slack.rb +288 -0
  77. data/pantograph/lib/pantograph/actions/sonar.rb +156 -0
  78. data/pantograph/lib/pantograph/actions/ssh.rb +162 -0
  79. data/pantograph/lib/pantograph/actions/twitter.rb +89 -0
  80. data/pantograph/lib/pantograph/actions/update_pantograph.rb +177 -0
  81. data/pantograph/lib/pantograph/actions/zip.rb +120 -0
  82. data/pantograph/lib/pantograph/auto_complete.rb +82 -0
  83. data/pantograph/lib/pantograph/boolean.rb +5 -0
  84. data/pantograph/lib/pantograph/cli_tools_distributor.rb +183 -0
  85. data/pantograph/lib/pantograph/command_line_handler.rb +43 -0
  86. data/pantograph/lib/pantograph/commands_generator.rb +344 -0
  87. data/pantograph/lib/pantograph/configuration_helper.rb +26 -0
  88. data/pantograph/lib/pantograph/core_ext/bundler_monkey_patch.rb +14 -0
  89. data/pantograph/lib/pantograph/documentation/actions_list.rb +214 -0
  90. data/pantograph/lib/pantograph/documentation/docs_generator.rb +95 -0
  91. data/pantograph/lib/pantograph/documentation/markdown_docs_generator.rb +221 -0
  92. data/pantograph/lib/pantograph/environment_printer.rb +282 -0
  93. data/pantograph/lib/pantograph/erb_template_helper.rb +30 -0
  94. data/pantograph/lib/pantograph/features.rb +4 -0
  95. data/pantograph/lib/pantograph/helper/README.md +29 -0
  96. data/pantograph/lib/pantograph/helper/dotenv_helper.rb +50 -0
  97. data/pantograph/lib/pantograph/helper/gem_helper.rb +26 -0
  98. data/pantograph/lib/pantograph/helper/git_helper.rb +135 -0
  99. data/pantograph/lib/pantograph/helper/gradle_helper.rb +62 -0
  100. data/pantograph/lib/pantograph/helper/sh_helper.rb +134 -0
  101. data/pantograph/lib/pantograph/junit_generator.rb +27 -0
  102. data/pantograph/lib/pantograph/lane.rb +97 -0
  103. data/pantograph/lib/pantograph/lane_list.rb +77 -0
  104. data/pantograph/lib/pantograph/lane_manager.rb +140 -0
  105. data/pantograph/lib/pantograph/lane_manager_base.rb +92 -0
  106. data/pantograph/lib/pantograph/markdown_table_formatter.rb +62 -0
  107. data/pantograph/lib/pantograph/new_action.rb +47 -0
  108. data/pantograph/lib/pantograph/one_off.rb +45 -0
  109. data/pantograph/lib/pantograph/other_action.rb +29 -0
  110. data/pantograph/lib/pantograph/pant_file.rb +377 -0
  111. data/pantograph/lib/pantograph/pantograph_require.rb +75 -0
  112. data/pantograph/lib/pantograph/plugins/plugin_fetcher.rb +55 -0
  113. data/pantograph/lib/pantograph/plugins/plugin_generator.rb +86 -0
  114. data/pantograph/lib/pantograph/plugins/plugin_generator_ui.rb +19 -0
  115. data/pantograph/lib/pantograph/plugins/plugin_info.rb +49 -0
  116. data/pantograph/lib/pantograph/plugins/plugin_info_collector.rb +159 -0
  117. data/pantograph/lib/pantograph/plugins/plugin_manager.rb +387 -0
  118. data/pantograph/lib/pantograph/plugins/plugin_search.rb +46 -0
  119. data/pantograph/lib/pantograph/plugins/plugin_update_manager.rb +70 -0
  120. data/pantograph/lib/pantograph/plugins/plugins.rb +12 -0
  121. data/pantograph/lib/pantograph/plugins/template/%gem_name%.gemspec.erb +35 -0
  122. data/pantograph/lib/pantograph/plugins/template/.circleci/config.yml +43 -0
  123. data/pantograph/lib/pantograph/plugins/template/.gitignore +12 -0
  124. data/pantograph/lib/pantograph/plugins/template/.rspec +5 -0
  125. data/pantograph/lib/pantograph/plugins/template/.rubocop.yml +179 -0
  126. data/pantograph/lib/pantograph/plugins/template/.travis.yml +4 -0
  127. data/pantograph/lib/pantograph/plugins/template/Gemfile +6 -0
  128. data/pantograph/lib/pantograph/plugins/template/LICENSE.erb +21 -0
  129. data/pantograph/lib/pantograph/plugins/template/README.md.erb +52 -0
  130. data/pantograph/lib/pantograph/plugins/template/Rakefile +9 -0
  131. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +47 -0
  132. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +16 -0
  133. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/version.rb.erb +5 -0
  134. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%.rb.erb +16 -0
  135. data/pantograph/lib/pantograph/plugins/template/pantograph/Pantfile.erb +3 -0
  136. data/pantograph/lib/pantograph/plugins/template/pantograph/Pluginfile.erb +1 -0
  137. data/pantograph/lib/pantograph/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
  138. data/pantograph/lib/pantograph/plugins/template/spec/spec_helper.rb.erb +15 -0
  139. data/pantograph/lib/pantograph/runner.rb +371 -0
  140. data/pantograph/lib/pantograph/server/action_command.rb +61 -0
  141. data/pantograph/lib/pantograph/server/action_command_return.rb +14 -0
  142. data/pantograph/lib/pantograph/server/command_executor.rb +7 -0
  143. data/pantograph/lib/pantograph/server/command_parser.rb +36 -0
  144. data/pantograph/lib/pantograph/server/control_command.rb +23 -0
  145. data/pantograph/lib/pantograph/server/json_return_value_processor.rb +72 -0
  146. data/pantograph/lib/pantograph/server/socket_server.rb +232 -0
  147. data/pantograph/lib/pantograph/server/socket_server_action_command_executor.rb +101 -0
  148. data/pantograph/lib/pantograph/setup/setup.rb +290 -0
  149. data/pantograph/lib/pantograph/setup/setup_android.rb +64 -0
  150. data/pantograph/lib/pantograph/setup/setup_ios.rb +412 -0
  151. data/pantograph/lib/pantograph/shells.rb +6 -0
  152. data/pantograph/lib/pantograph/supported_platforms.rb +28 -0
  153. data/pantograph/lib/pantograph/tools.rb +10 -0
  154. data/pantograph/lib/pantograph/version.rb +5 -0
  155. data/pantograph/lib/pantograph.rb +51 -0
  156. data/pantograph_core/README.md +79 -0
  157. data/pantograph_core/lib/assets/XMLTemplate.xml.erb +12 -0
  158. data/pantograph_core/lib/pantograph_core/analytics/action_completion_context.rb +34 -0
  159. data/pantograph_core/lib/pantograph_core/analytics/action_launch_context.rb +38 -0
  160. data/pantograph_core/lib/pantograph_core/analytics/analytics_event_builder.rb +23 -0
  161. data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +54 -0
  162. data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +71 -0
  163. data/pantograph_core/lib/pantograph_core/cert_checker.rb +116 -0
  164. data/pantograph_core/lib/pantograph_core/command_executor.rb +99 -0
  165. data/pantograph_core/lib/pantograph_core/configuration/commander_generator.rb +103 -0
  166. data/pantograph_core/lib/pantograph_core/configuration/config_item.rb +314 -0
  167. data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +332 -0
  168. data/pantograph_core/lib/pantograph_core/configuration/configuration_file.rb +182 -0
  169. data/pantograph_core/lib/pantograph_core/core_ext/shellwords.rb +63 -0
  170. data/pantograph_core/lib/pantograph_core/core_ext/string.rb +17 -0
  171. data/pantograph_core/lib/pantograph_core/env.rb +9 -0
  172. data/pantograph_core/lib/pantograph_core/feature/feature.rb +51 -0
  173. data/pantograph_core/lib/pantograph_core/features.rb +4 -0
  174. data/pantograph_core/lib/pantograph_core/globals.rb +27 -0
  175. data/pantograph_core/lib/pantograph_core/helper.rb +409 -0
  176. data/pantograph_core/lib/pantograph_core/keychain_importer.rb +74 -0
  177. data/pantograph_core/lib/pantograph_core/languages.rb +14 -0
  178. data/pantograph_core/lib/pantograph_core/module.rb +29 -0
  179. data/pantograph_core/lib/pantograph_core/pantograph_folder.rb +39 -0
  180. data/pantograph_core/lib/pantograph_core/pantograph_pty.rb +57 -0
  181. data/pantograph_core/lib/pantograph_core/pkg_file_analyser.rb +44 -0
  182. data/pantograph_core/lib/pantograph_core/print_table.rb +131 -0
  183. data/pantograph_core/lib/pantograph_core/string_filters.rb +51 -0
  184. data/pantograph_core/lib/pantograph_core/swag.rb +85 -0
  185. data/pantograph_core/lib/pantograph_core/tag_version.rb +31 -0
  186. data/pantograph_core/lib/pantograph_core/test_parser.rb +107 -0
  187. data/pantograph_core/lib/pantograph_core/ui/disable_colors.rb +17 -0
  188. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_common_error.rb +19 -0
  189. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_crash.rb +11 -0
  190. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_error.rb +25 -0
  191. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_exception.rb +19 -0
  192. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_shell_error.rb +11 -0
  193. data/pantograph_core/lib/pantograph_core/ui/errors.rb +1 -0
  194. data/pantograph_core/lib/pantograph_core/ui/github_issue_inspector_reporter.rb +62 -0
  195. data/pantograph_core/lib/pantograph_core/ui/implementations/shell.rb +159 -0
  196. data/pantograph_core/lib/pantograph_core/ui/interface.rb +205 -0
  197. data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +276 -0
  198. data/pantograph_core/lib/pantograph_core/ui/ui.rb +26 -0
  199. data/pantograph_core/lib/pantograph_core/update_checker/changelog.rb +37 -0
  200. data/pantograph_core/lib/pantograph_core/update_checker/update_checker.rb +107 -0
  201. data/pantograph_core/lib/pantograph_core.rb +45 -0
  202. metadata +987 -0
@@ -0,0 +1,23 @@
1
+ module PantographCore
2
+ class AnalyticsEventBuilder
3
+ attr_accessor :action_name
4
+
5
+ # pantograph_client_language valid options are :ruby
6
+ def initialize(p_hash: nil, session_id: nil, action_name: nil, pantograph_client_language: :ruby)
7
+ @p_hash = p_hash
8
+ @session_id = session_id
9
+ @action_name = action_name
10
+ @pantograph_client_language = pantograph_client_language
11
+ end
12
+
13
+ def new_event(action_stage)
14
+ {
15
+ client_id: @p_hash,
16
+ category: "pantograph Client Language - #{@pantograph_client_language}",
17
+ action: action_stage,
18
+ label: action_name,
19
+ value: nil
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ require 'faraday'
2
+ require 'openssl'
3
+ require 'json'
4
+
5
+ require_relative '../helper'
6
+
7
+ module PantographCore
8
+ class AnalyticsIngesterClient
9
+ GA_URL = "https://www.google-analytics.com"
10
+
11
+ private_constant :GA_URL
12
+
13
+ def initialize(ga_tracking)
14
+ @ga_tracking = ga_tracking
15
+ end
16
+
17
+ def post_event(event)
18
+ # If our users want to opt out of usage metrics, don't post the events.
19
+ # Learn more at https://docs.pantograph.tools/#metrics
20
+ if Helper.test? || PantographCore::Env.truthy?("PANTOGRAPH_OPT_OUT_USAGE")
21
+ return nil
22
+ end
23
+ return Thread.new do
24
+ send_request(event)
25
+ end
26
+ end
27
+
28
+ def send_request(event, retries: 2)
29
+ post_request(event)
30
+ rescue
31
+ retries -= 1
32
+ retry if retries >= 0
33
+ end
34
+
35
+ def post_request(event)
36
+ connection = Faraday.new(GA_URL) do |conn|
37
+ conn.request(:url_encoded)
38
+ conn.adapter(Faraday.default_adapter)
39
+ end
40
+ connection.headers[:user_agent] = 'pantograph/' + Pantograph::VERSION
41
+ connection.post("/collect", {
42
+ v: "1", # API Version
43
+ tid: @ga_tracking, # Tracking ID / Property ID
44
+ cid: event[:client_id], # Client ID
45
+ t: "event", # Event hit type
46
+ ec: event[:category], # Event category
47
+ ea: event[:action], # Event action
48
+ el: event[:label] || "na", # Event label
49
+ ev: event[:value] || "0", # Event value
50
+ aip: "1" # IP anonymization
51
+ })
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,71 @@
1
+ require_relative 'analytics_ingester_client'
2
+ require_relative 'action_launch_context'
3
+ require_relative 'analytics_event_builder'
4
+
5
+ module PantographCore
6
+ class AnalyticsSession
7
+ GA_TRACKING = "UA-121171860-1"
8
+
9
+ private_constant :GA_TRACKING
10
+ attr_accessor :session_id
11
+ attr_accessor :client
12
+
13
+ def initialize(analytics_ingester_client: AnalyticsIngesterClient.new(GA_TRACKING))
14
+ require 'securerandom'
15
+ @session_id = SecureRandom.uuid
16
+ @client = analytics_ingester_client
17
+ @threads = []
18
+ @launch_event_sent = false
19
+ end
20
+
21
+ def action_launched(launch_context: nil)
22
+ unless did_show_message?
23
+ show_message
24
+ end
25
+
26
+ if @launch_event_sent || launch_context.p_hash.nil?
27
+ return
28
+ end
29
+
30
+ @launch_event_sent = true
31
+ builder = AnalyticsEventBuilder.new(
32
+ p_hash: launch_context.p_hash,
33
+ session_id: session_id,
34
+ action_name: nil,
35
+ pantograph_client_language: launch_context.pantograph_client_language
36
+ )
37
+
38
+ launch_event = builder.new_event(:launch)
39
+ post_thread = client.post_event(launch_event)
40
+ unless post_thread.nil?
41
+ @threads << post_thread
42
+ end
43
+ end
44
+
45
+ def action_completed(completion_context: nil)
46
+ end
47
+
48
+ def show_message
49
+ UI.message("Sending anonymous analytics information")
50
+ UI.message("Learn more at https://docs.pantograph.tools/#metrics")
51
+ UI.message("No personal or sensitive data is sent.")
52
+ UI.message("You can disable this by adding `opt_out_usage` at the top of your Pantfile")
53
+ end
54
+
55
+ def did_show_message?
56
+ file_name = ".did_show_opt_info"
57
+
58
+ new_path = File.join(PantographCore.pantograph_user_dir, file_name)
59
+ did_show = File.exist?(new_path)
60
+
61
+ return did_show if did_show
62
+
63
+ File.write(new_path, '1')
64
+ false
65
+ end
66
+
67
+ def finalize_session
68
+ @threads.map(&:join)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,116 @@
1
+ require 'tempfile'
2
+ require 'openssl'
3
+
4
+ require_relative 'helper'
5
+
6
+ module PantographCore
7
+ # This class checks if a specific certificate is installed on the current mac
8
+ class CertChecker
9
+ def self.installed?(path, in_keychain: nil)
10
+ UI.user_error!("Could not find file '#{path}'") unless File.exist?(path)
11
+
12
+ ids = installed_identies(in_keychain: in_keychain)
13
+ finger_print = sha1_fingerprint(path)
14
+
15
+ return ids.include?(finger_print)
16
+ end
17
+
18
+ # Legacy Method, use `installed?` instead
19
+ def self.is_installed?(path)
20
+ installed?(path)
21
+ end
22
+
23
+ def self.installed_identies(in_keychain: nil)
24
+ install_wwdr_certificate unless wwdr_certificate_installed?
25
+
26
+ available = list_available_identities(in_keychain: in_keychain)
27
+ # Match for this text against word boundaries to avoid edge cases around multiples of 10 identities!
28
+ if /\b0 valid identities found\b/ =~ available
29
+ UI.error([
30
+ "There are no local code signing identities found.",
31
+ "You can run" << " `security find-identity -v -p codesigning #{in_keychain}".rstrip << "` to get this output.",
32
+ "This Stack Overflow thread has more information: https://stackoverflow.com/q/35390072/774.",
33
+ "(Check in Keychain Access for an expired WWDR certificate: https://stackoverflow.com/a/35409835/774 has more info.)"
34
+ ].join("\n"))
35
+ end
36
+
37
+ ids = []
38
+ available.split("\n").each do |current|
39
+ next if current.include?("REVOKED")
40
+ begin
41
+ (ids << current.match(/.*\) ([[:xdigit:]]*) \".*/)[1])
42
+ rescue
43
+ # the last line does not match
44
+ end
45
+ end
46
+
47
+ return ids
48
+ end
49
+
50
+ def self.list_available_identities(in_keychain: nil)
51
+ commands = ['security find-identity -v -p codesigning']
52
+ commands << in_keychain if in_keychain
53
+ `#{commands.join(' ')}`
54
+ end
55
+
56
+ def self.wwdr_certificate_installed?
57
+ certificate_name = "Apple Worldwide Developer Relations Certification Authority"
58
+ keychain = wwdr_keychain
59
+ response = Helper.backticks("security find-certificate -c '#{certificate_name}' #{keychain.shellescape}", print: PantographCore::Globals.verbose?)
60
+ return response.include?("attributes:")
61
+ end
62
+
63
+ def self.install_wwdr_certificate
64
+ url = 'https://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
65
+ file = Tempfile.new('AppleWWDRCA')
66
+ filename = file.path
67
+ keychain = wwdr_keychain
68
+ keychain = "-k #{keychain.shellescape}" unless keychain.empty?
69
+
70
+ require 'open3'
71
+
72
+ import_command = "curl -f -o #{filename} #{url} && security import #{filename} #{keychain}"
73
+ UI.verbose("Installing WWDR Cert: #{import_command}")
74
+
75
+ stdout, stderr, _status = Open3.capture3(import_command)
76
+ if PantographCore::Globals.verbose?
77
+ UI.command_output(stdout)
78
+ UI.command_output(stderr)
79
+ end
80
+
81
+ unless $?.success?
82
+ UI.verbose("Failed to install WWDR Certificate, checking output to see why")
83
+ # Check the command output, WWDR might already exist
84
+ unless /The specified item already exists in the keychain./ =~ stderr
85
+ UI.user_error!("Could not install WWDR certificate")
86
+ end
87
+ UI.verbose("WWDR Certificate was already installed")
88
+ end
89
+ return true
90
+ end
91
+
92
+ def self.wwdr_keychain
93
+ priority = [
94
+ "security list-keychains -d user",
95
+ "security default-keychain -d user"
96
+ ]
97
+ priority.each do |command|
98
+ keychains = Helper.backticks(command, print: PantographCore::Globals.verbose?).split("\n")
99
+ unless keychains.empty?
100
+ # Select first keychain name from returned keychains list
101
+ return keychains[0].strip.tr('"', '')
102
+ end
103
+ end
104
+ return ""
105
+ end
106
+
107
+ def self.sha1_fingerprint(path)
108
+ file_data = File.read(path.to_s)
109
+ cert = OpenSSL::X509::Certificate.new(file_data)
110
+ return OpenSSL::Digest::SHA1.new(cert.to_der).to_s.upcase
111
+ rescue => error
112
+ UI.error(error)
113
+ UI.user_error!("Error parsing certificate '#{path}'")
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,99 @@
1
+ require_relative 'ui/ui'
2
+ require_relative 'globals'
3
+ require_relative 'pantograph_pty'
4
+
5
+ module PantographCore
6
+ # Executes commands and takes care of error handling and more
7
+ class CommandExecutor
8
+ class << self
9
+ # Cross-platform way of finding an executable in the $PATH. Respects the $PATHEXT, which lists
10
+ # valid file extensions for executables on Windows.
11
+ #
12
+ # which('ruby') #=> /usr/bin/ruby
13
+ #
14
+ # Derived from https://stackoverflow.com/a/5471032/3005
15
+ def which(cmd)
16
+ # PATHEXT contains the list of file extensions that Windows considers executable, semicolon separated.
17
+ # e.g. ".COM;.EXE;.BAT;.CMD"
18
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : []
19
+ exts << '' # Always have an empty string (= no file extension)
20
+
21
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
22
+ exts.each do |ext|
23
+ cmd_path = File.join(path, "#{cmd}#{ext}")
24
+ return cmd_path if Helper.executable?(cmd_path)
25
+ end
26
+ end
27
+
28
+ return nil
29
+ end
30
+
31
+ # @param command [String] The command to be executed
32
+ # @param print_all [Boolean] Do we want to print out the command output while running?
33
+ # @param print_command [Boolean] Should we print the command that's being executed
34
+ # @param error [Block] A block that's called if an error occurs
35
+ # @param prefix [Array] An array containing a prefix + block which might get applied to the output
36
+ # @param loading [String] A loading string that is shown before the first output
37
+ # @param suppress_output [Boolean] Should we print the command's output?
38
+ # @return [String] All the output as string
39
+ def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, loading: nil, suppress_output: false)
40
+ print_all = true if PantographCore::Globals.verbose?
41
+ prefix ||= {}
42
+
43
+ output = []
44
+ command = command.join(" ") if command.kind_of?(Array)
45
+ UI.command(command) if print_command
46
+
47
+ if print_all && loading # this is only used to show the "Loading text"...
48
+ UI.command_output(loading)
49
+ end
50
+
51
+ begin
52
+ status = PantographCore::PantographPty.spawn(command) do |command_stdout, command_stdin, pid|
53
+ command_stdout.each do |l|
54
+ line = l.chomp
55
+ output << line
56
+
57
+ next unless print_all
58
+
59
+ # Prefix the current line with a string
60
+ prefix.each do |element|
61
+ line = element[:prefix] + line if element[:block] && element[:block].call(line)
62
+ end
63
+
64
+ UI.command_output(line) unless suppress_output
65
+ end
66
+ end
67
+ rescue => ex
68
+ # PantographPty adds exit_status on to StandardError so every error will have a status code
69
+ status = ex.exit_status
70
+
71
+ # This could happen when the environment is wrong:
72
+ # > invalid byte sequence in US-ASCII (ArgumentError)
73
+ output << ex.to_s
74
+ o = output.join("\n")
75
+ puts(o)
76
+ if error
77
+ error.call(o, nil)
78
+ else
79
+ raise ex
80
+ end
81
+ end
82
+
83
+ # Exit status for build command, should be 0 if build succeeded
84
+ if status != 0
85
+ o = output.join("\n")
86
+ puts(o) unless suppress_output # the user has the right to see the raw output
87
+ UI.error("Exit status: #{status}")
88
+ if error
89
+ error.call(o, status)
90
+ else
91
+ UI.user_error!("Exit status: #{status}")
92
+ end
93
+ end
94
+
95
+ return output.join("\n")
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,103 @@
1
+ require 'commander'
2
+
3
+ require_relative '../module'
4
+ require_relative '../ui/ui'
5
+
6
+ module PantographCore
7
+ class CommanderGenerator
8
+ include Commander::Methods
9
+
10
+ # Calls the appropriate methods for commander to show the available parameters
11
+ def generate(options, command: nil)
12
+ # First, enable `always_trace`, to show the stack trace
13
+ always_trace!
14
+
15
+ used_switches = []
16
+ options.each do |option|
17
+ next if option.description.to_s.empty? # "private" options
18
+ next unless option.display_in_shell
19
+
20
+ short_switch = option.short_option
21
+ key = option.key
22
+ validate_short_switch(used_switches, short_switch, key)
23
+
24
+ type = option.data_type
25
+
26
+ # We added type: Hash to code generation, but Ruby's OptionParser doesn't like that
27
+ # so we need to switch that to something that is supported, luckily, we have an `is_string`
28
+ # property and if that is false, we'll default to nil
29
+ if type == Hash
30
+ type = option.is_string ? String : nil
31
+ end
32
+
33
+ # Boolean is a pantograph thing, it's either TrueClass, or FalseClass, but we won't know
34
+ # that until runtime, so nil is the best we get
35
+ if type == Pantograph::Boolean
36
+ type = nil
37
+ end
38
+
39
+ # This is an important bit of trickery to solve the boolean option situation.
40
+ #
41
+ # Typically, boolean command line flags do not accept trailing values. If the flag
42
+ # is present, the value is true, if it is missing, the value is false. pantograph
43
+ # supports this style of flag. For example, you can specify a flag like `--clean`,
44
+ # and the :clean option will be true.
45
+ #
46
+ # However, pantograph also supports another boolean flag style that accepts trailing
47
+ # values much like options for Strings and other value types. That looks like
48
+ # `--include_bitcode false` The problem is that this does not work out of the box
49
+ # for Commander and OptionsParser. So, we need to get tricky.
50
+ #
51
+ # The value_appendix below acts as a placeholder in the switch definition that
52
+ # states that we expect to have a trailing value for our options. When an option
53
+ # declares a data type, we use the name of that data type in all caps like:
54
+ # "--devices ARRAY". When the data type is nil, this implies that we're going
55
+ # to be doing some special handling on that value. One special thing we do
56
+ # automatically in Configuration is to coerce special Strings into boolean values.
57
+ #
58
+ # If the data type is nil, the trick we do is to specify a value placeholder, but
59
+ # we wrap it in [] brackets to mark it as optional. That means that the trailing
60
+ # value may or may not be present for this flag. If the flag is present, but the
61
+ # value is not, we get a value of `true`. Perfect for the boolean flag base-case!
62
+ # If the value is there, we'll actually get it back as a String, which we can
63
+ # later coerce into a boolean.
64
+ #
65
+ # In this way we support handling boolean flags with or without trailing values.
66
+ value_appendix = (type || '[VALUE]').to_s.upcase
67
+ long_switch = "--#{option.key} #{value_appendix}"
68
+
69
+ description = option.description
70
+ description += " (#{option.env_name})" unless option.env_name.to_s.empty?
71
+
72
+ # We compact this array here to remove the short_switch variable if it is nil.
73
+ # Passing a nil value to global_option has been shown to create problems with
74
+ # option parsing!
75
+ #
76
+ # See: https://github.com/pantograph/pantograph_core/pull/89
77
+ #
78
+ # If we don't have a data type for this option, we tell it to act like a String.
79
+ # This allows us to get a reasonable value for boolean options that can be
80
+ # automatically coerced or otherwise handled by the ConfigItem for others.
81
+ args = [short_switch, long_switch, (type || String), description].compact
82
+
83
+ if command
84
+ command.option(*args)
85
+ else
86
+ # This is the call to Commander to set up the option we've been building.
87
+ global_option(*args)
88
+ end
89
+ end
90
+ end
91
+
92
+ def validate_short_switch(used_switches, short_switch, key)
93
+ return if short_switch.nil?
94
+
95
+ UI.user_error!("Short option #{short_switch} already taken for key #{key}") if used_switches.include?(short_switch)
96
+ UI.user_error!("-v is already used for the version (key #{key})") if short_switch == "-v"
97
+ UI.user_error!("-h is already used for the help screen (key #{key})") if short_switch == "-h"
98
+ UI.user_error!("-t is already used for the trace screen (key #{key})") if short_switch == "-t"
99
+
100
+ used_switches << short_switch
101
+ end
102
+ end
103
+ end