Class: Mortar::Plugin

Inherits:
Object
  • Object
show all
Extended by:
Helpers
Includes:
Helpers
Defined in:
lib/mortar/plugin.rb

Defined Under Namespace

Classes: ErrorInstallingDependencies, ErrorInstallingPlugin, ErrorLoadingPlugin, ErrorPluginNotFound, ErrorUpdatingPlugin, ErrorUpdatingSymlinkPlugin

Constant Summary collapse

DEPRECATED_PLUGINS =
%w(
  test-plugin
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

action, ask, confirm, copy_if_not_present_at_dest, default_host, deprecate, display, display_header, display_object, display_row, display_table, display_with_indent, download_to_file, ensure_dir_exists, error, error_with_failure, error_with_failure=, extended, extended_into, format_bytes, format_date, format_with_bang, full_host, get_terminal_environment, home_directory, host, hprint, hputs, included, included_into, installed_with_omnibus?, json_decode, json_encode, line_formatter, longest, output_with_bang, pending_github_team_state_message, quantify, redisplay, retry_on_exception, running_on_a_mac?, running_on_windows?, set_buffer, shell, spinner, status, string_distance, styled_array, styled_error, styled_hash, styled_header, suggestion, test_name, ticking, time_ago, truncate, warning, with_tty, write_to_file

Constructor Details

#initialize(uri) ⇒ Plugin

Returns a new instance of Plugin.



137
138
139
140
# File 'lib/mortar/plugin.rb', line 137

def initialize(uri)
  @uri = uri
  guess_name(uri)
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



21
22
23
# File 'lib/mortar/plugin.rb', line 21

def name
  @name
end

#uriObject (readonly)

Returns the value of attribute uri.



21
22
23
# File 'lib/mortar/plugin.rb', line 21

def uri
  @uri
end

Class Method Details

.directoryObject



23
24
25
# File 'lib/mortar/plugin.rb', line 23

def self.directory
  File.expand_path("#{home_directory}/.mortar/plugins")
end

.ensure_bundler_installedObject

Internal: Ensures bundler is installed, if it isn’t it’ll raise an error



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/mortar/plugin.rb', line 55

def self.ensure_bundler_installed
  # TODO: Deal with the bundler as a runtime dependency issue
  # before moving these require statements to the top.
  begin
    require 'bundler'
    require 'bundler/cli'
    require 'bundler/friendly_errors'
    require 'monkey_patch/bundler/bundler'
  rescue LoadError => e 
    raise <<-ERROR
Unable to install this plugin. Make sure you have bundler installed:

$ gem install bundler

ERROR
  end
end

.install_bundleObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/mortar/plugin.rb', line 73

def self.install_bundle

  out = StringIO.new
  $stdout = out
  begin
    # WARNING! These 4 lines are a monkey patch.
    Bundler.settings[:path] = "bundle"
    Bundler.settings[:disable_shared_gems] = '1'
    Bundler.bundle_path = nil
    Bundler.send(:configure_gem_home_and_path)

    bundle_def = Bundler.definition({})

    if Gem::Version.new(Bundler::VERSION) < Gem::Version.new("1.3.0")
      Bundler.ui = Bundler::UI::Shell.new(Thor::Base.shell.new)
    else
      Bundler.ui = Bundler::UI::Shell.new({})
      Bundler.ui.level = "silent"
    end

    Bundler::Installer.install(Bundler.root, bundle_def, {
      :standalone => [],
      :disabled_shared_gems => '1'
    })
    result = true
  rescue StandardError => e
    puts e.message
    puts e.backtrace
    out.write e.message
    result = false
  end
  open("#{Plugin.directory}/plugin_install.log", 'a') do |f|
    f.puts out.string
  end
  $stdout = STDOUT
  return result
end

.listObject



27
28
29
30
31
32
33
# File 'lib/mortar/plugin.rb', line 27

def self.list
  Dir["#{directory}/*"].sort.select { |entry|
    File.directory? entry and !(entry =='.' || entry == '..')
  }.map { |folder|
    File.basename(folder)
  }
end

.load!Object



111
112
113
114
115
116
# File 'lib/mortar/plugin.rb', line 111

def self.load!
  list.each do |plugin|
    next if skip_plugins.include?(plugin)
    load_plugin(plugin)
  end
end

.load_plugin(plugin) ⇒ Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/mortar/plugin.rb', line 118

def self.load_plugin(plugin)
  begin
    folder = "#{self.directory}/#{plugin}"
    $: << "#{folder}/lib"    if File.directory? "#{folder}/lib"
    load "#{folder}/init.rb" if File.exists?  "#{folder}/init.rb"
  rescue ScriptError, StandardError => error
    styled_error(error, "Unable to load plugin #{plugin}.")
    false
  end
end

.remove_plugin(plugin) ⇒ Object



129
130
131
# File 'lib/mortar/plugin.rb', line 129

def self.remove_plugin(plugin)
  FileUtils.rm_rf("#{self.directory}/#{plugin}")
end

.skip_pluginsObject



133
134
135
# File 'lib/mortar/plugin.rb', line 133

def self.skip_plugins
  @skip_plugins ||= ENV["SKIP_PLUGINS"].to_s.split(/[ ,]/)
end

.without_bundler_envObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/mortar/plugin.rb', line 35

def self.without_bundler_env 
  original_env = ENV.to_hash
  
  # Raises error on failure
  Mortar::Plugin.ensure_bundler_installed

  ENV.delete("BUNDLE_GEMFILE")
  ENV.delete("BUNDLE_PATH")
  ENV.delete("BUNDLE_BIN_PATH")
  ENV.delete("RUBYOPT")

  # Use monkey patched method to remove existing bundler configuration.
  Bundler.nuke_configuration

  yield
ensure
  ENV.replace(original_env.to_hash)
end

Instance Method Details

#gitObject



142
143
144
# File 'lib/mortar/plugin.rb', line 142

def git
  @git ||= Mortar::Git::Git.new
end

#install(branch = nil) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/mortar/plugin.rb', line 154

def install(branch = nil)
  if File.directory?(path)
    uninstall
  end
  FileUtils.mkdir_p(self.class.directory)
  Dir.chdir(self.class.directory) do
    begin
      git.git("clone #{uri}", check_success=true, check_git_directory=false)
    rescue Mortar::Git::GitError => ge
      FileUtils.rm_rf path
      raise Mortar::Plugin::ErrorInstallingPlugin, <<-ERROR
Unable to install plugin #{name}.

#{ge.message}
ERROR
    end

    if !!branch
      Dir.chdir(name) do
        begin
          git.git("checkout #{branch}", check_success=true, check_git_directory=true)
        rescue Mortar::Git::GitError
          FileUtils.rm_rf path
          raise Mortar::Plugin::ErrorInstallingPlugin, <<-ERROR
Unable to checkout branch #{branch} for plugin #{name}.
Please check the URL and branch and try again.
ERROR
        end
      end
    end
  end
  install_dependencies
  return true
end

#install_dependenciesObject



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/mortar/plugin.rb', line 189

def install_dependencies
  begin
    Dir.chdir(path) do
      Mortar::Plugin.without_bundler_env do
        ENV["BUNDLE_GEMFILE"] = File.expand_path("Gemfile", path)
        if File.exists? ENV["BUNDLE_GEMFILE"]
          unless Mortar::Plugin.install_bundle 
            FileUtils.rm_rf path
            raise Mortar::Plugin::ErrorInstallingDependencies, <<-ERROR
  Unable to install dependencies for #{name}.
  Error logs stored to #{Plugin.directory}/plugin_install.log
  Refer to the documentation for this plugin for help.
  ERROR
          end
        end
      end
    end
  rescue StandardError => e
    FileUtils.rm_rf path
    raise e
  end
end

#pathObject



150
151
152
# File 'lib/mortar/plugin.rb', line 150

def path
  "#{self.class.directory}/#{name}"
end

#to_sObject



146
147
148
# File 'lib/mortar/plugin.rb', line 146

def to_s
  name
end

#uninstallObject



212
213
214
215
# File 'lib/mortar/plugin.rb', line 212

def uninstall
  ensure_plugin_exists
  FileUtils.rm_r(path)
end

#updateObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/mortar/plugin.rb', line 217

def update
  ensure_plugin_exists
  if File.symlink?(path)
    raise Mortar::Plugin::ErrorUpdatingSymlinkPlugin
  else
    Dir.chdir(path) do
      unless git.git('config --get branch.master.remote').empty?
        message = git.git("pull")
        unless $?.success?
          raise Mortar::Plugin::ErrorUpdatingPlugin, <<-ERROR
Unable to update #{name}.
#{message}
ERROR
        end
      end
    end
    install_dependencies
  end
end