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.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/LICENSE +21 -0
- data/README.md +197 -0
- data/bin/bin-proxy +19 -0
- data/bin/pantograph +23 -0
- data/pantograph/README.md +11 -0
- data/pantograph/lib/assets/ActionDetails.md.erb +106 -0
- data/pantograph/lib/assets/Actions.md.erb +43 -0
- data/pantograph/lib/assets/DefaultPantfileTemplate +20 -0
- data/pantograph/lib/assets/completions/completion.bash +23 -0
- data/pantograph/lib/assets/completions/completion.fish +39 -0
- data/pantograph/lib/assets/completions/completion.sh +12 -0
- data/pantograph/lib/assets/completions/completion.zsh +23 -0
- data/pantograph/lib/assets/custom_action_template.rb +80 -0
- data/pantograph/lib/assets/report_template.xml.erb +15 -0
- data/pantograph/lib/pantograph/action.rb +194 -0
- data/pantograph/lib/pantograph/action_collector.rb +35 -0
- data/pantograph/lib/pantograph/actions/README.md +3 -0
- data/pantograph/lib/pantograph/actions/actions_helper.rb +166 -0
- data/pantograph/lib/pantograph/actions/add_extra_platforms.rb +45 -0
- data/pantograph/lib/pantograph/actions/artifactory.rb +157 -0
- data/pantograph/lib/pantograph/actions/bundle_install.rb +156 -0
- data/pantograph/lib/pantograph/actions/changelog_from_git_commits.rb +197 -0
- data/pantograph/lib/pantograph/actions/clipboard.rb +52 -0
- data/pantograph/lib/pantograph/actions/cloc.rb +89 -0
- data/pantograph/lib/pantograph/actions/create_pull_request.rb +190 -0
- data/pantograph/lib/pantograph/actions/danger.rb +131 -0
- data/pantograph/lib/pantograph/actions/debug.rb +32 -0
- data/pantograph/lib/pantograph/actions/default_platform.rb +47 -0
- data/pantograph/lib/pantograph/actions/download.rb +76 -0
- data/pantograph/lib/pantograph/actions/echo.rb +14 -0
- data/pantograph/lib/pantograph/actions/ensure_bundle_exec.rb +59 -0
- data/pantograph/lib/pantograph/actions/ensure_env_vars.rb +58 -0
- data/pantograph/lib/pantograph/actions/ensure_git_branch.rb +69 -0
- data/pantograph/lib/pantograph/actions/ensure_git_status_clean.rb +81 -0
- data/pantograph/lib/pantograph/actions/erb.rb +88 -0
- data/pantograph/lib/pantograph/actions/get_build_number_repository.rb +120 -0
- data/pantograph/lib/pantograph/actions/get_github_release.rb +163 -0
- data/pantograph/lib/pantograph/actions/git_add.rb +93 -0
- data/pantograph/lib/pantograph/actions/git_branch.rb +58 -0
- data/pantograph/lib/pantograph/actions/git_commit.rb +80 -0
- data/pantograph/lib/pantograph/actions/git_pull.rb +53 -0
- data/pantograph/lib/pantograph/actions/git_submodule_update.rb +52 -0
- data/pantograph/lib/pantograph/actions/git_tag_exists.rb +74 -0
- data/pantograph/lib/pantograph/actions/github_api.rb +262 -0
- data/pantograph/lib/pantograph/actions/gradle.rb +278 -0
- data/pantograph/lib/pantograph/actions/import.rb +49 -0
- data/pantograph/lib/pantograph/actions/import_from_git.rb +71 -0
- data/pantograph/lib/pantograph/actions/is_ci.rb +51 -0
- data/pantograph/lib/pantograph/actions/jira.rb +115 -0
- data/pantograph/lib/pantograph/actions/lane_context.rb +60 -0
- data/pantograph/lib/pantograph/actions/last_git_commit.rb +58 -0
- data/pantograph/lib/pantograph/actions/last_git_tag.rb +51 -0
- data/pantograph/lib/pantograph/actions/make_changelog_from_jenkins.rb +81 -0
- data/pantograph/lib/pantograph/actions/min_pantograph_version.rb +57 -0
- data/pantograph/lib/pantograph/actions/nexus_upload.rb +230 -0
- data/pantograph/lib/pantograph/actions/notification.rb +75 -0
- data/pantograph/lib/pantograph/actions/number_of_commits.rb +75 -0
- data/pantograph/lib/pantograph/actions/opt_out_usage.rb +40 -0
- data/pantograph/lib/pantograph/actions/pantograph_version.rb +15 -0
- data/pantograph/lib/pantograph/actions/println.rb +14 -0
- data/pantograph/lib/pantograph/actions/prompt.rb +119 -0
- data/pantograph/lib/pantograph/actions/push_git_tags.rb +76 -0
- data/pantograph/lib/pantograph/actions/push_to_git_remote.rb +127 -0
- data/pantograph/lib/pantograph/actions/puts.rb +68 -0
- data/pantograph/lib/pantograph/actions/reset_git_repo.rb +121 -0
- data/pantograph/lib/pantograph/actions/rocket.rb +83 -0
- data/pantograph/lib/pantograph/actions/rsync.rb +74 -0
- data/pantograph/lib/pantograph/actions/ruby_version.rb +56 -0
- data/pantograph/lib/pantograph/actions/say.rb +56 -0
- data/pantograph/lib/pantograph/actions/scp.rb +114 -0
- data/pantograph/lib/pantograph/actions/set_github_release.rb +274 -0
- data/pantograph/lib/pantograph/actions/sh.rb +71 -0
- data/pantograph/lib/pantograph/actions/skip_docs.rb +52 -0
- data/pantograph/lib/pantograph/actions/slack.rb +288 -0
- data/pantograph/lib/pantograph/actions/sonar.rb +156 -0
- data/pantograph/lib/pantograph/actions/ssh.rb +162 -0
- data/pantograph/lib/pantograph/actions/twitter.rb +89 -0
- data/pantograph/lib/pantograph/actions/update_pantograph.rb +177 -0
- data/pantograph/lib/pantograph/actions/zip.rb +120 -0
- data/pantograph/lib/pantograph/auto_complete.rb +82 -0
- data/pantograph/lib/pantograph/boolean.rb +5 -0
- data/pantograph/lib/pantograph/cli_tools_distributor.rb +183 -0
- data/pantograph/lib/pantograph/command_line_handler.rb +43 -0
- data/pantograph/lib/pantograph/commands_generator.rb +344 -0
- data/pantograph/lib/pantograph/configuration_helper.rb +26 -0
- data/pantograph/lib/pantograph/core_ext/bundler_monkey_patch.rb +14 -0
- data/pantograph/lib/pantograph/documentation/actions_list.rb +214 -0
- data/pantograph/lib/pantograph/documentation/docs_generator.rb +95 -0
- data/pantograph/lib/pantograph/documentation/markdown_docs_generator.rb +221 -0
- data/pantograph/lib/pantograph/environment_printer.rb +282 -0
- data/pantograph/lib/pantograph/erb_template_helper.rb +30 -0
- data/pantograph/lib/pantograph/features.rb +4 -0
- data/pantograph/lib/pantograph/helper/README.md +29 -0
- data/pantograph/lib/pantograph/helper/dotenv_helper.rb +50 -0
- data/pantograph/lib/pantograph/helper/gem_helper.rb +26 -0
- data/pantograph/lib/pantograph/helper/git_helper.rb +135 -0
- data/pantograph/lib/pantograph/helper/gradle_helper.rb +62 -0
- data/pantograph/lib/pantograph/helper/sh_helper.rb +134 -0
- data/pantograph/lib/pantograph/junit_generator.rb +27 -0
- data/pantograph/lib/pantograph/lane.rb +97 -0
- data/pantograph/lib/pantograph/lane_list.rb +77 -0
- data/pantograph/lib/pantograph/lane_manager.rb +140 -0
- data/pantograph/lib/pantograph/lane_manager_base.rb +92 -0
- data/pantograph/lib/pantograph/markdown_table_formatter.rb +62 -0
- data/pantograph/lib/pantograph/new_action.rb +47 -0
- data/pantograph/lib/pantograph/one_off.rb +45 -0
- data/pantograph/lib/pantograph/other_action.rb +29 -0
- data/pantograph/lib/pantograph/pant_file.rb +377 -0
- data/pantograph/lib/pantograph/pantograph_require.rb +75 -0
- data/pantograph/lib/pantograph/plugins/plugin_fetcher.rb +55 -0
- data/pantograph/lib/pantograph/plugins/plugin_generator.rb +86 -0
- data/pantograph/lib/pantograph/plugins/plugin_generator_ui.rb +19 -0
- data/pantograph/lib/pantograph/plugins/plugin_info.rb +49 -0
- data/pantograph/lib/pantograph/plugins/plugin_info_collector.rb +159 -0
- data/pantograph/lib/pantograph/plugins/plugin_manager.rb +387 -0
- data/pantograph/lib/pantograph/plugins/plugin_search.rb +46 -0
- data/pantograph/lib/pantograph/plugins/plugin_update_manager.rb +70 -0
- data/pantograph/lib/pantograph/plugins/plugins.rb +12 -0
- data/pantograph/lib/pantograph/plugins/template/%gem_name%.gemspec.erb +35 -0
- data/pantograph/lib/pantograph/plugins/template/.circleci/config.yml +43 -0
- data/pantograph/lib/pantograph/plugins/template/.gitignore +12 -0
- data/pantograph/lib/pantograph/plugins/template/.rspec +5 -0
- data/pantograph/lib/pantograph/plugins/template/.rubocop.yml +179 -0
- data/pantograph/lib/pantograph/plugins/template/.travis.yml +4 -0
- data/pantograph/lib/pantograph/plugins/template/Gemfile +6 -0
- data/pantograph/lib/pantograph/plugins/template/LICENSE.erb +21 -0
- data/pantograph/lib/pantograph/plugins/template/README.md.erb +52 -0
- data/pantograph/lib/pantograph/plugins/template/Rakefile +9 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +47 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +16 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/version.rb.erb +5 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%.rb.erb +16 -0
- data/pantograph/lib/pantograph/plugins/template/pantograph/Pantfile.erb +3 -0
- data/pantograph/lib/pantograph/plugins/template/pantograph/Pluginfile.erb +1 -0
- data/pantograph/lib/pantograph/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
- data/pantograph/lib/pantograph/plugins/template/spec/spec_helper.rb.erb +15 -0
- data/pantograph/lib/pantograph/runner.rb +371 -0
- data/pantograph/lib/pantograph/server/action_command.rb +61 -0
- data/pantograph/lib/pantograph/server/action_command_return.rb +14 -0
- data/pantograph/lib/pantograph/server/command_executor.rb +7 -0
- data/pantograph/lib/pantograph/server/command_parser.rb +36 -0
- data/pantograph/lib/pantograph/server/control_command.rb +23 -0
- data/pantograph/lib/pantograph/server/json_return_value_processor.rb +72 -0
- data/pantograph/lib/pantograph/server/socket_server.rb +232 -0
- data/pantograph/lib/pantograph/server/socket_server_action_command_executor.rb +101 -0
- data/pantograph/lib/pantograph/setup/setup.rb +290 -0
- data/pantograph/lib/pantograph/setup/setup_android.rb +64 -0
- data/pantograph/lib/pantograph/setup/setup_ios.rb +412 -0
- data/pantograph/lib/pantograph/shells.rb +6 -0
- data/pantograph/lib/pantograph/supported_platforms.rb +28 -0
- data/pantograph/lib/pantograph/tools.rb +10 -0
- data/pantograph/lib/pantograph/version.rb +5 -0
- data/pantograph/lib/pantograph.rb +51 -0
- data/pantograph_core/README.md +79 -0
- data/pantograph_core/lib/assets/XMLTemplate.xml.erb +12 -0
- data/pantograph_core/lib/pantograph_core/analytics/action_completion_context.rb +34 -0
- data/pantograph_core/lib/pantograph_core/analytics/action_launch_context.rb +38 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_event_builder.rb +23 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +54 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +71 -0
- data/pantograph_core/lib/pantograph_core/cert_checker.rb +116 -0
- data/pantograph_core/lib/pantograph_core/command_executor.rb +99 -0
- data/pantograph_core/lib/pantograph_core/configuration/commander_generator.rb +103 -0
- data/pantograph_core/lib/pantograph_core/configuration/config_item.rb +314 -0
- data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +332 -0
- data/pantograph_core/lib/pantograph_core/configuration/configuration_file.rb +182 -0
- data/pantograph_core/lib/pantograph_core/core_ext/shellwords.rb +63 -0
- data/pantograph_core/lib/pantograph_core/core_ext/string.rb +17 -0
- data/pantograph_core/lib/pantograph_core/env.rb +9 -0
- data/pantograph_core/lib/pantograph_core/feature/feature.rb +51 -0
- data/pantograph_core/lib/pantograph_core/features.rb +4 -0
- data/pantograph_core/lib/pantograph_core/globals.rb +27 -0
- data/pantograph_core/lib/pantograph_core/helper.rb +409 -0
- data/pantograph_core/lib/pantograph_core/keychain_importer.rb +74 -0
- data/pantograph_core/lib/pantograph_core/languages.rb +14 -0
- data/pantograph_core/lib/pantograph_core/module.rb +29 -0
- data/pantograph_core/lib/pantograph_core/pantograph_folder.rb +39 -0
- data/pantograph_core/lib/pantograph_core/pantograph_pty.rb +57 -0
- data/pantograph_core/lib/pantograph_core/pkg_file_analyser.rb +44 -0
- data/pantograph_core/lib/pantograph_core/print_table.rb +131 -0
- data/pantograph_core/lib/pantograph_core/string_filters.rb +51 -0
- data/pantograph_core/lib/pantograph_core/swag.rb +85 -0
- data/pantograph_core/lib/pantograph_core/tag_version.rb +31 -0
- data/pantograph_core/lib/pantograph_core/test_parser.rb +107 -0
- data/pantograph_core/lib/pantograph_core/ui/disable_colors.rb +17 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_common_error.rb +19 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_crash.rb +11 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_error.rb +25 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_exception.rb +19 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_shell_error.rb +11 -0
- data/pantograph_core/lib/pantograph_core/ui/errors.rb +1 -0
- data/pantograph_core/lib/pantograph_core/ui/github_issue_inspector_reporter.rb +62 -0
- data/pantograph_core/lib/pantograph_core/ui/implementations/shell.rb +159 -0
- data/pantograph_core/lib/pantograph_core/ui/interface.rb +205 -0
- data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +276 -0
- data/pantograph_core/lib/pantograph_core/ui/ui.rb +26 -0
- data/pantograph_core/lib/pantograph_core/update_checker/changelog.rb +37 -0
- data/pantograph_core/lib/pantograph_core/update_checker/update_checker.rb +107 -0
- data/pantograph_core/lib/pantograph_core.rb +45 -0
- metadata +987 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class PluginInfoCollector
|
3
|
+
def initialize(ui = PluginGeneratorUI.new)
|
4
|
+
@ui = ui
|
5
|
+
end
|
6
|
+
|
7
|
+
def collect_info(initial_name = nil)
|
8
|
+
plugin_name = collect_plugin_name(initial_name)
|
9
|
+
author = collect_author(detect_author)
|
10
|
+
email = collect_email(detect_email)
|
11
|
+
summary = collect_summary
|
12
|
+
details = collect_details
|
13
|
+
|
14
|
+
PluginInfo.new(plugin_name, author, email, summary, details)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Plugin name
|
19
|
+
#
|
20
|
+
|
21
|
+
def collect_plugin_name(initial_name = nil)
|
22
|
+
plugin_name = initial_name
|
23
|
+
first_try = true
|
24
|
+
|
25
|
+
loop do
|
26
|
+
if !first_try || plugin_name.to_s.empty?
|
27
|
+
plugin_name = @ui.input("What would you like to be the name of your plugin?")
|
28
|
+
end
|
29
|
+
first_try = false
|
30
|
+
|
31
|
+
unless plugin_name_valid?(plugin_name)
|
32
|
+
fixed_name = fix_plugin_name(plugin_name)
|
33
|
+
|
34
|
+
if plugin_name_valid?(fixed_name)
|
35
|
+
plugin_name = fixed_name if @ui.confirm("\nWould '#{fixed_name}' be okay to use for your plugin name?")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
break if plugin_name_valid?(plugin_name)
|
40
|
+
|
41
|
+
gem_name = PluginManager.to_gem_name(plugin_name)
|
42
|
+
|
43
|
+
if gem_name_taken?(gem_name)
|
44
|
+
# Gem name is already taken on RubyGems
|
45
|
+
@ui.message("\nThe gem name '#{gem_name}' is already taken on RubyGems, please choose a different plugin name.")
|
46
|
+
else
|
47
|
+
# That's a naming error
|
48
|
+
@ui.message("\nPlugin names can only contain lower case letters, numbers, and underscores")
|
49
|
+
@ui.message("and should not contain 'pantograph' or 'plugin'.")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
plugin_name
|
54
|
+
end
|
55
|
+
|
56
|
+
def plugin_name_valid?(name)
|
57
|
+
# Only lower case letters, numbers and underscores allowed
|
58
|
+
/^[a-z0-9_]+$/ =~ name &&
|
59
|
+
# Does not contain the words 'pantograph' or 'plugin' since those will become
|
60
|
+
# part of the gem name
|
61
|
+
[/pantograph/, /plugin/].none? { |regex| regex =~ name } &&
|
62
|
+
# Gem name isn't taken on RubyGems yet
|
63
|
+
!gem_name_taken?(PluginManager.to_gem_name(name))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Checks if the gem name is still free on RubyGems
|
67
|
+
def gem_name_taken?(name)
|
68
|
+
require 'open-uri'
|
69
|
+
require 'json'
|
70
|
+
url = "https://rubygems.org/api/v1/gems/#{name}.json"
|
71
|
+
response = JSON.parse(open(url).read)
|
72
|
+
return !!response['version']
|
73
|
+
rescue
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
# Applies a series of replacement rules to turn the requested plugin name into one
|
78
|
+
# that is acceptable, returning that suggestion
|
79
|
+
def fix_plugin_name(name)
|
80
|
+
name = name.to_s.downcase
|
81
|
+
fixes = {
|
82
|
+
/[\- ]/ => '_', # dashes and spaces become underscores
|
83
|
+
/[^a-z0-9_]/ => '', # anything other than lower case letters, numbers and underscores is removed
|
84
|
+
/pantograph[_]?/ => '', # 'pantograph' or 'pantograph_' is removed
|
85
|
+
/plugin[_]?/ => '' # 'plugin' or 'plugin_' is removed
|
86
|
+
}
|
87
|
+
fixes.each do |regex, replacement|
|
88
|
+
name = name.gsub(regex, replacement)
|
89
|
+
end
|
90
|
+
name
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Author
|
95
|
+
#
|
96
|
+
|
97
|
+
def detect_author
|
98
|
+
git_name = Helper.backticks('git config --get user.name', print: PantographCore::Globals.verbose?).strip
|
99
|
+
return git_name.empty? ? nil : git_name
|
100
|
+
end
|
101
|
+
|
102
|
+
def collect_author(initial_author = nil)
|
103
|
+
return initial_author if author_valid?(initial_author)
|
104
|
+
author = nil
|
105
|
+
loop do
|
106
|
+
author = @ui.input("What is the plugin author's name?")
|
107
|
+
break if author_valid?(author)
|
108
|
+
|
109
|
+
@ui.message('An author name is required.')
|
110
|
+
end
|
111
|
+
|
112
|
+
author
|
113
|
+
end
|
114
|
+
|
115
|
+
def author_valid?(author)
|
116
|
+
!author.to_s.strip.empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Email
|
121
|
+
#
|
122
|
+
|
123
|
+
def detect_email
|
124
|
+
git_email = Helper.backticks('git config --get user.email', print: PantographCore::Globals.verbose?).strip
|
125
|
+
return git_email.empty? ? nil : git_email
|
126
|
+
end
|
127
|
+
|
128
|
+
def collect_email(initial_email = nil)
|
129
|
+
return initial_email || @ui.input("What is the plugin author's email address?")
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Summary
|
134
|
+
#
|
135
|
+
|
136
|
+
def collect_summary
|
137
|
+
summary = nil
|
138
|
+
loop do
|
139
|
+
summary = @ui.input("Please enter a short summary of this pantograph plugin:")
|
140
|
+
break if summary_valid?(summary)
|
141
|
+
|
142
|
+
@ui.message('A summary is required.')
|
143
|
+
end
|
144
|
+
|
145
|
+
summary
|
146
|
+
end
|
147
|
+
|
148
|
+
def summary_valid?(summary)
|
149
|
+
!summary.to_s.strip.empty?
|
150
|
+
end
|
151
|
+
#
|
152
|
+
# Summary
|
153
|
+
#
|
154
|
+
|
155
|
+
def collect_details
|
156
|
+
return @ui.input("Please enter a detailed description of this pantograph plugin:").to_s
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,387 @@
|
|
1
|
+
require "pantograph/cli_tools_distributor"
|
2
|
+
|
3
|
+
module Pantograph
|
4
|
+
class PluginManager
|
5
|
+
require "bundler"
|
6
|
+
|
7
|
+
PLUGINFILE_NAME = "Pluginfile".freeze
|
8
|
+
DEFAULT_GEMFILE_PATH = "Gemfile".freeze
|
9
|
+
AUTOGENERATED_LINE = "# Autogenerated by pantograph\n#\n# Ensure this file is checked in to source control!\n\n"
|
10
|
+
GEMFILE_SOURCE_LINE = "source \"https://rubygems.org\"\n"
|
11
|
+
PANTOGRAPH_PLUGIN_PREFIX = "pantograph-plugin-"
|
12
|
+
TROUBLESHOOTING_URL = "https://docs.pantograph.tools/plugins/plugins-troubleshooting/"
|
13
|
+
|
14
|
+
#####################################################
|
15
|
+
# @!group Reading the files and their paths
|
16
|
+
#####################################################
|
17
|
+
|
18
|
+
def gemfile_path
|
19
|
+
# This is pretty important, since we don't know what kind of
|
20
|
+
# Gemfile the user has (e.g. Gemfile, gems.rb, or custom env variable)
|
21
|
+
Bundler::SharedHelpers.default_gemfile.to_s
|
22
|
+
rescue Bundler::GemfileNotFound
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def pluginfile_path
|
27
|
+
if PantographCore::PantographFolder.path
|
28
|
+
return File.join(PantographCore::PantographFolder.path, PLUGINFILE_NAME)
|
29
|
+
else
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def gemfile_content
|
35
|
+
File.read(gemfile_path) if gemfile_path && File.exist?(gemfile_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def pluginfile_content
|
39
|
+
File.read(pluginfile_path) if pluginfile_path && File.exist?(pluginfile_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
#####################################################
|
43
|
+
# @!group Helpers
|
44
|
+
#####################################################
|
45
|
+
|
46
|
+
def self.plugin_prefix
|
47
|
+
PANTOGRAPH_PLUGIN_PREFIX
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.to_gem_name(plugin_name)
|
51
|
+
plugin_name.start_with?(plugin_prefix) ? plugin_name : (plugin_prefix + plugin_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns an array of gems that are added to the Gemfile or Pluginfile
|
55
|
+
def available_gems
|
56
|
+
return [] unless gemfile_path
|
57
|
+
dsl = Bundler::Dsl.evaluate(gemfile_path, nil, true)
|
58
|
+
return dsl.dependencies.map(&:name)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns an array of pantograph plugins that are added to the Gemfile or Pluginfile
|
62
|
+
# The returned array contains the string with their prefixes (e.g. pantograph-plugin-xcversion)
|
63
|
+
def available_plugins
|
64
|
+
available_gems.keep_if do |current|
|
65
|
+
current.start_with?(self.class.plugin_prefix)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Check if a plugin is added as dependency to either the
|
70
|
+
# Gemfile or the Pluginfile
|
71
|
+
def plugin_is_added_as_dependency?(plugin_name)
|
72
|
+
UI.user_error!("pantograph plugins must start with '#{self.class.plugin_prefix}' string") unless plugin_name.start_with?(self.class.plugin_prefix)
|
73
|
+
return available_plugins.include?(plugin_name)
|
74
|
+
end
|
75
|
+
|
76
|
+
#####################################################
|
77
|
+
# @!group Modifying dependencies
|
78
|
+
#####################################################
|
79
|
+
|
80
|
+
def add_dependency(plugin_name)
|
81
|
+
UI.user_error!("pantograph is not setup for this project, make sure you have a pantograph folder") unless pluginfile_path
|
82
|
+
plugin_name = self.class.plugin_prefix + plugin_name unless plugin_name.start_with?(self.class.plugin_prefix)
|
83
|
+
|
84
|
+
if plugin_name.gsub(self.class.plugin_prefix, '').include?("-")
|
85
|
+
# e.g. "pantograph-plugin-ya_tu-sabes" (which is invalid)
|
86
|
+
UI.user_error!("Plugin name must not contain a '-', did you mean '_'?")
|
87
|
+
end
|
88
|
+
|
89
|
+
unless plugin_is_added_as_dependency?(plugin_name)
|
90
|
+
content = pluginfile_content || AUTOGENERATED_LINE
|
91
|
+
|
92
|
+
unless content.end_with?("\n")
|
93
|
+
content += "\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
line_to_add = "gem '#{plugin_name}'"
|
97
|
+
line_to_add += gem_dependency_suffix(plugin_name)
|
98
|
+
UI.verbose("Adding line: #{line_to_add}")
|
99
|
+
|
100
|
+
content += "#{line_to_add}\n"
|
101
|
+
File.write(pluginfile_path, content)
|
102
|
+
UI.success("Plugin '#{plugin_name}' was added to '#{pluginfile_path}'")
|
103
|
+
end
|
104
|
+
|
105
|
+
# We do this *after* creating the Plugin file
|
106
|
+
# Since `bundle exec` would be broken if something fails on the way
|
107
|
+
ensure_plugins_attached!
|
108
|
+
|
109
|
+
true
|
110
|
+
end
|
111
|
+
|
112
|
+
# Get a suffix (e.g. `path` or `git` for the gem dependency)
|
113
|
+
def gem_dependency_suffix(plugin_name)
|
114
|
+
return "" unless self.class.fetch_gem_info_from_rubygems(plugin_name).nil?
|
115
|
+
|
116
|
+
selection_git_url = "Git URL"
|
117
|
+
selection_path = "Local Path"
|
118
|
+
selection_rubygems = "RubyGems.org ('#{plugin_name}' seems to not be available there)"
|
119
|
+
selection_gem_server = "Other Gem Server"
|
120
|
+
selection = UI.select(
|
121
|
+
"Seems like the plugin is not available on RubyGems, what do you want to do?",
|
122
|
+
[selection_git_url, selection_path, selection_rubygems, selection_gem_server]
|
123
|
+
)
|
124
|
+
|
125
|
+
if selection == selection_git_url
|
126
|
+
git_url = UI.input('Please enter the URL to the plugin, including the protocol (e.g. https:// or git://)')
|
127
|
+
return ", git: '#{git_url}'"
|
128
|
+
elsif selection == selection_path
|
129
|
+
path = UI.input('Please enter the relative path to the plugin you want to use. It has to point to the directory containing the .gemspec file')
|
130
|
+
return ", path: '#{path}'"
|
131
|
+
elsif selection == selection_rubygems
|
132
|
+
return ""
|
133
|
+
elsif selection == selection_gem_server
|
134
|
+
source_url = UI.input('Please enter the gem source URL which hosts the plugin you want to use, including the protocol (e.g. https:// or git://)')
|
135
|
+
return ", source: '#{source_url}'"
|
136
|
+
else
|
137
|
+
UI.user_error!("Unknown input #{selection}")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Modify the user's Gemfile to load the plugins
|
142
|
+
def attach_plugins_to_gemfile!(path_to_gemfile)
|
143
|
+
content = gemfile_content || (AUTOGENERATED_LINE + GEMFILE_SOURCE_LINE)
|
144
|
+
|
145
|
+
# We have to make sure pantograph is also added to the Gemfile, since we now use
|
146
|
+
# bundler to run pantograph
|
147
|
+
content += "\ngem 'pantograph'\n" unless available_gems.include?('pantograph')
|
148
|
+
content += "\n#{self.class.code_to_attach}\n"
|
149
|
+
|
150
|
+
File.write(path_to_gemfile, content)
|
151
|
+
end
|
152
|
+
|
153
|
+
#####################################################
|
154
|
+
# @!group Accessing RubyGems
|
155
|
+
#####################################################
|
156
|
+
|
157
|
+
def self.fetch_gem_info_from_rubygems(gem_name)
|
158
|
+
require 'open-uri'
|
159
|
+
require 'json'
|
160
|
+
url = "https://rubygems.org/api/v1/gems/#{gem_name}.json"
|
161
|
+
begin
|
162
|
+
JSON.parse(open(url).read)
|
163
|
+
rescue
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
#####################################################
|
169
|
+
# @!group Installing and updating dependencies
|
170
|
+
#####################################################
|
171
|
+
|
172
|
+
# Warning: This will exec out
|
173
|
+
# This is necessary since the user might be prompted for their password
|
174
|
+
def install_dependencies!
|
175
|
+
# Using puts instead of `UI` to have the same style as the `echo`
|
176
|
+
puts("Installing plugin dependencies...")
|
177
|
+
ensure_plugins_attached!
|
178
|
+
with_clean_bundler_env do
|
179
|
+
cmd = "bundle install"
|
180
|
+
cmd << " --quiet" unless PantographCore::Globals.verbose?
|
181
|
+
cmd << " && echo 'Successfully installed plugins'"
|
182
|
+
UI.command(cmd) if PantographCore::Globals.verbose?
|
183
|
+
exec(cmd)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Warning: This will exec out
|
188
|
+
# This is necessary since the user might be prompted for their password
|
189
|
+
def update_dependencies!
|
190
|
+
puts("Updating plugin dependencies...")
|
191
|
+
ensure_plugins_attached!
|
192
|
+
plugins = available_plugins
|
193
|
+
if plugins.empty?
|
194
|
+
UI.user_error!("No plugins are installed")
|
195
|
+
end
|
196
|
+
with_clean_bundler_env do
|
197
|
+
cmd = "bundle update"
|
198
|
+
cmd << " #{plugins.join(' ')}"
|
199
|
+
cmd << " --quiet" unless PantographCore::Globals.verbose?
|
200
|
+
cmd << " && echo 'Successfully updated plugins'"
|
201
|
+
UI.command(cmd) if PantographCore::Globals.verbose?
|
202
|
+
exec(cmd)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def with_clean_bundler_env
|
207
|
+
# There is an interesting problem with using exec to call back into Bundler
|
208
|
+
# The `bundle ________` command that we exec, inherits all of the Bundler
|
209
|
+
# state we'd already built up during this run. That was causing the command
|
210
|
+
# to fail, telling us to install the Gem we'd just introduced, even though
|
211
|
+
# that is exactly what we are trying to do!
|
212
|
+
#
|
213
|
+
# Bundler.with_clean_env solves this problem by resetting Bundler state before the
|
214
|
+
# exec'd call gets merged into this process.
|
215
|
+
|
216
|
+
Bundler.with_clean_env do
|
217
|
+
yield if block_given?
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
#####################################################
|
222
|
+
# @!group Initial setup
|
223
|
+
#####################################################
|
224
|
+
|
225
|
+
def setup
|
226
|
+
UI.important("It looks like pantograph plugins are not yet set up for this project.")
|
227
|
+
|
228
|
+
path_to_gemfile = gemfile_path || DEFAULT_GEMFILE_PATH
|
229
|
+
|
230
|
+
if gemfile_content.to_s.length > 0
|
231
|
+
UI.important("pantograph will modify your existing Gemfile at path '#{path_to_gemfile}'")
|
232
|
+
else
|
233
|
+
UI.important("pantograph will create a new Gemfile at path '#{path_to_gemfile}'")
|
234
|
+
end
|
235
|
+
|
236
|
+
UI.important("This change is necessary for pantograph plugins to work")
|
237
|
+
|
238
|
+
unless UI.confirm("Should pantograph modify the Gemfile at path '#{path_to_gemfile}' for you?")
|
239
|
+
UI.important("Please add the following code to '#{path_to_gemfile}':")
|
240
|
+
puts("")
|
241
|
+
puts(self.class.code_to_attach.magenta) # we use `puts` instead of `UI` to make it easier to copy and paste
|
242
|
+
UI.user_error!("Please update '#{path_to_gemfile} and run pantograph again")
|
243
|
+
end
|
244
|
+
|
245
|
+
attach_plugins_to_gemfile!(path_to_gemfile)
|
246
|
+
UI.success("Successfully modified '#{path_to_gemfile}'")
|
247
|
+
end
|
248
|
+
|
249
|
+
# The code required to load the Plugins file
|
250
|
+
def self.code_to_attach
|
251
|
+
if PantographCore::PantographFolder.path
|
252
|
+
pantograph_folder_name = File.basename(PantographCore::PantographFolder.path)
|
253
|
+
else
|
254
|
+
pantograph_folder_name = "pantograph"
|
255
|
+
end
|
256
|
+
"plugins_path = File.join(File.dirname(__FILE__), '#{pantograph_folder_name}', '#{PluginManager::PLUGINFILE_NAME}')\n" \
|
257
|
+
"eval_gemfile(plugins_path) if File.exist?(plugins_path)"
|
258
|
+
end
|
259
|
+
|
260
|
+
# Makes sure, the user's Gemfile actually loads the Plugins file
|
261
|
+
def plugins_attached?
|
262
|
+
gemfile_path && gemfile_content.include?(PluginManager::PLUGINFILE_NAME)
|
263
|
+
end
|
264
|
+
|
265
|
+
def ensure_plugins_attached!
|
266
|
+
return if plugins_attached?
|
267
|
+
self.setup
|
268
|
+
end
|
269
|
+
|
270
|
+
#####################################################
|
271
|
+
# @!group Requiring the plugins
|
272
|
+
#####################################################
|
273
|
+
|
274
|
+
# Iterate over all available plugins
|
275
|
+
# which follow the naming convention
|
276
|
+
# pantograph-plugin-[plugin_name]
|
277
|
+
# This will make sure to load the action
|
278
|
+
# and all its helpers
|
279
|
+
def load_plugins
|
280
|
+
UI.verbose("Checking if there are any plugins that should be loaded...")
|
281
|
+
|
282
|
+
loaded_plugins = false
|
283
|
+
available_plugins.each do |gem_name|
|
284
|
+
UI.verbose("Loading '#{gem_name}' plugin")
|
285
|
+
begin
|
286
|
+
# BEFORE requiring the gem, we get a list of loaded actions
|
287
|
+
# This way we can check inside `store_plugin_reference` if
|
288
|
+
# any actions were overwritten
|
289
|
+
self.loaded_pantograph_actions.concat(Pantograph::Actions.constants)
|
290
|
+
|
291
|
+
PantographRequire.install_gem_if_needed(gem_name: gem_name, require_gem: true)
|
292
|
+
|
293
|
+
store_plugin_reference(gem_name)
|
294
|
+
loaded_plugins = true
|
295
|
+
rescue StandardError, ScriptError => ex # some errors, like ScriptError are not caught unless explicitly
|
296
|
+
UI.error("Error loading plugin '#{gem_name}': #{ex}")
|
297
|
+
|
298
|
+
# We'll still add it to the table, to make the error
|
299
|
+
# much more visible and obvious
|
300
|
+
self.plugin_references[gem_name] = {
|
301
|
+
version_number: Pantograph::ActionCollector.determine_version(gem_name),
|
302
|
+
actions: []
|
303
|
+
}
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
if !loaded_plugins && self.pluginfile_content.to_s.include?(PluginManager.plugin_prefix)
|
308
|
+
UI.error("It seems like you wanted to load some plugins, however they couldn't be loaded")
|
309
|
+
UI.error("Please follow the troubleshooting guide: #{TROUBLESHOOTING_URL}")
|
310
|
+
end
|
311
|
+
|
312
|
+
skip_print_plugin_info = self.plugin_references.empty? || CLIToolsDistributor.running_version_command? || PantographCore::Env.truthy?("PANTOGRAPH_ENV_PRINTER")
|
313
|
+
|
314
|
+
# We want to avoid printing output other than the version number if we are running `pantograph -v`
|
315
|
+
print_plugin_information(self.plugin_references) unless skip_print_plugin_info
|
316
|
+
end
|
317
|
+
|
318
|
+
# Prints a table all the plugins that were loaded
|
319
|
+
def print_plugin_information(references)
|
320
|
+
rows = references.collect do |current|
|
321
|
+
if current[1][:actions].empty?
|
322
|
+
# Something is wrong with this plugin, no available actions
|
323
|
+
[current[0].red, current[1][:version_number], "No actions found".red]
|
324
|
+
else
|
325
|
+
[current[0], current[1][:version_number], current[1][:actions].join("\n")]
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
require 'terminal-table'
|
330
|
+
puts(Terminal::Table.new({
|
331
|
+
rows: PantographCore::PrintTable.transform_output(rows),
|
332
|
+
title: "Used plugins".green,
|
333
|
+
headings: ["Plugin", "Version", "Action"]
|
334
|
+
}))
|
335
|
+
puts("")
|
336
|
+
end
|
337
|
+
|
338
|
+
#####################################################
|
339
|
+
# @!group Reference between plugins to actions
|
340
|
+
#####################################################
|
341
|
+
|
342
|
+
# Connection between plugins and their actions
|
343
|
+
# Example value of plugin_references
|
344
|
+
# => {"pantograph-plugin-ruby" => {
|
345
|
+
# version_number: "0.1.0",
|
346
|
+
# actions: [:rspec, :rubocop]
|
347
|
+
# }}
|
348
|
+
def plugin_references
|
349
|
+
@plugin_references ||= {}
|
350
|
+
end
|
351
|
+
|
352
|
+
# Contains an array of symbols for the action classes
|
353
|
+
def loaded_pantograph_actions
|
354
|
+
@pantograph_actions ||= []
|
355
|
+
end
|
356
|
+
|
357
|
+
def store_plugin_reference(gem_name)
|
358
|
+
module_name = gem_name.gsub(PluginManager.plugin_prefix, '').pantograph_class
|
359
|
+
# We store a collection of the imported plugins
|
360
|
+
# This way we can tell which action came from what plugin
|
361
|
+
# (a plugin may contain any number of actions)
|
362
|
+
version_number = Pantograph::ActionCollector.determine_version(gem_name)
|
363
|
+
references = Pantograph.const_get(module_name).all_classes.collect do |path|
|
364
|
+
next unless File.dirname(path).end_with?("/actions") # we only want to match actions
|
365
|
+
|
366
|
+
File.basename(path).gsub("_action", "").gsub(".rb", "").to_sym # the _action is optional
|
367
|
+
end
|
368
|
+
references.compact!
|
369
|
+
|
370
|
+
# Check if this overwrites a built-in action and
|
371
|
+
# show a warning if that's the case
|
372
|
+
references.each do |current_ref|
|
373
|
+
# current_ref is a symbol, e.g. :emoji_fetcher
|
374
|
+
class_name = (current_ref.to_s.pantograph_class + 'Action').to_sym
|
375
|
+
|
376
|
+
if self.loaded_pantograph_actions.include?(class_name)
|
377
|
+
UI.important("Plugin '#{module_name}' overwrites already loaded action '#{current_ref}'")
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
self.plugin_references[gem_name] = {
|
382
|
+
version_number: version_number,
|
383
|
+
actions: references
|
384
|
+
}
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class PluginSearch
|
3
|
+
require 'terminal-table'
|
4
|
+
require 'word_wrap'
|
5
|
+
|
6
|
+
def self.print_plugins(search_query: nil)
|
7
|
+
if search_query
|
8
|
+
UI.message("Looking for pantograph plugins containing '#{search_query}'...")
|
9
|
+
else
|
10
|
+
UI.message("Listing all available pantograph plugins")
|
11
|
+
end
|
12
|
+
|
13
|
+
plugins = Pantograph::PluginFetcher.fetch_gems(search_query: search_query)
|
14
|
+
|
15
|
+
if plugins.empty?
|
16
|
+
UI.user_error!("Couldn't find any available pantograph plugins containing '#{search_query}'")
|
17
|
+
end
|
18
|
+
|
19
|
+
rows = plugins.collect do |current|
|
20
|
+
[
|
21
|
+
current.name.green,
|
22
|
+
WordWrap.ww(current.info, 50),
|
23
|
+
current.downloads
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
params = {
|
28
|
+
rows: PantographCore::PrintTable.transform_output(rows),
|
29
|
+
title: (search_query ? "pantograph plugins '#{search_query}'" : "Available pantograph plugins").green,
|
30
|
+
headings: ["Name", "Description", "Downloads"]
|
31
|
+
}
|
32
|
+
|
33
|
+
puts("")
|
34
|
+
puts(Terminal::Table.new(params))
|
35
|
+
puts("")
|
36
|
+
|
37
|
+
if plugins.count == 1
|
38
|
+
print_plugin_details(plugins.last)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.print_plugin_details(plugin)
|
43
|
+
UI.message("You can find more information for #{plugin.name} on #{plugin.homepage.green}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Pantograph
|
2
|
+
# Alert the user when updates for plugins are available
|
3
|
+
class PluginUpdateManager
|
4
|
+
def self.start_looking_for_updates
|
5
|
+
return if PantographCore::Env.truthy?("PANTOGRAPH_SKIP_UPDATE_CHECK")
|
6
|
+
|
7
|
+
Thread.new do
|
8
|
+
self.plugin_references.each do |plugin_name, current_plugin|
|
9
|
+
begin
|
10
|
+
self.server_results[plugin_name] = fetch_latest_version(plugin_name)
|
11
|
+
rescue
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.show_update_status
|
18
|
+
return if PantographCore::Env.truthy?("PANTOGRAPH_SKIP_UPDATE_CHECK")
|
19
|
+
|
20
|
+
# We set self.server_results to be nil
|
21
|
+
# this way the table is not printed twice
|
22
|
+
# (next to the summary table or when an exception happens)
|
23
|
+
return unless self.server_results.count > 0
|
24
|
+
|
25
|
+
rows = []
|
26
|
+
self.plugin_references.each do |plugin_name, current_plugin|
|
27
|
+
latest_version = self.server_results[plugin_name]
|
28
|
+
next if latest_version.nil?
|
29
|
+
current_version = Gem::Version.new(current_plugin[:version_number])
|
30
|
+
next if current_version >= latest_version
|
31
|
+
|
32
|
+
rows << [
|
33
|
+
plugin_name.gsub(PluginManager.plugin_prefix, ''),
|
34
|
+
current_version.to_s.red,
|
35
|
+
latest_version.to_s.green
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
if rows.empty?
|
40
|
+
UI.verbose("All plugins are up to date")
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'terminal-table'
|
45
|
+
puts(Terminal::Table.new({
|
46
|
+
rows: PantographCore::PrintTable.transform_output(rows),
|
47
|
+
title: "Plugin updates available".yellow,
|
48
|
+
headings: ["Plugin", "Your Version", "Latest Version"]
|
49
|
+
}))
|
50
|
+
UI.message("To update all plugins, just run")
|
51
|
+
UI.command "bundle exec pantograph update_plugins"
|
52
|
+
puts('')
|
53
|
+
@server_results = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.plugin_references
|
57
|
+
Pantograph.plugin_manager.plugin_references
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.fetch_latest_version(gem_name)
|
61
|
+
Gem::Version.new(PluginManager.fetch_gem_info_from_rubygems(gem_name)["version"])
|
62
|
+
rescue
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.server_results
|
67
|
+
@server_results ||= {}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
require 'find'
|
4
|
+
|
5
|
+
require 'pantograph/plugins/plugin_info'
|
6
|
+
require 'pantograph/plugins/plugin_generator'
|
7
|
+
require 'pantograph/plugins/plugin_generator_ui'
|
8
|
+
require 'pantograph/plugins/plugin_info_collector'
|
9
|
+
require 'pantograph/plugins/plugin_manager'
|
10
|
+
require 'pantograph/plugins/plugin_search'
|
11
|
+
require 'pantograph/plugins/plugin_fetcher'
|
12
|
+
require 'pantograph/plugins/plugin_update_manager'
|