pantograph 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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