mortar 0.8.8 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,7 @@
19
19
 
20
20
  require 'rexml/document'
21
21
  require 'mortar/helpers'
22
+ require 'mortar/plugin'
22
23
  require 'mortar/project'
23
24
  require 'mortar/version'
24
25
  require 'mortar/api'
@@ -35,6 +36,7 @@ module Mortar
35
36
  Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do |file|
36
37
  require file
37
38
  end
39
+ Mortar::Plugin.load!
38
40
  end
39
41
 
40
42
  def self.commands
@@ -181,6 +181,8 @@ class Mortar::Command::Jobs < Mortar::Command::Base
181
181
  display
182
182
  display("Or by running:\n\n mortar jobs:status #{response['job_id']} --poll")
183
183
  display
184
+
185
+ response['job_id']
184
186
  end
185
187
 
186
188
  alias_command "run", "jobs:run"
@@ -253,6 +255,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base
253
255
 
254
256
  # If polling the status
255
257
  if options[:poll]
258
+ job_status = nil
256
259
  ticking(polling_interval) do |ticks|
257
260
  job_status = api.get_job(job_id).body
258
261
  # If the job is complete exit and display the table normally
@@ -286,10 +289,12 @@ class Mortar::Command::Jobs < Mortar::Command::Base
286
289
  redisplay("[#{spinner(ticks)}] Status: #{job_display_status}")
287
290
  end
288
291
  end
292
+ job_status
289
293
  # If not polling, get the job status and display the results
290
294
  else
291
295
  job_status = api.get_job(job_id).body
292
296
  display_job_status(job_status)
297
+ job_status
293
298
  end
294
299
  end
295
300
 
@@ -0,0 +1,111 @@
1
+ require "mortar/command/base"
2
+
3
+ module Mortar::Command
4
+
5
+ # manage plugins to the mortar gem
6
+ class Plugins < Base
7
+
8
+ # plugins
9
+ #
10
+ # list installed plugins
11
+ #
12
+ #Example:
13
+ #
14
+ # $ mortar plugins
15
+ # === Installed Plugins
16
+ # watchtower
17
+ #
18
+ def index
19
+ validate_arguments!
20
+
21
+ plugins = ::Mortar::Plugin.list
22
+
23
+ if plugins.length > 0
24
+ styled_header("Installed Plugins")
25
+ styled_array(plugins)
26
+ else
27
+ display("You have no installed plugins.")
28
+ end
29
+ end
30
+
31
+ # plugins:install git@github.com:user/repo.git
32
+ #
33
+ # install a plugin
34
+ #
35
+ #Example:
36
+ #
37
+ # $ mortar plugins:install https://github.com/mortardata/watchtower.git
38
+ # Installing watchtower... done
39
+ #
40
+ def install
41
+ plugin = Mortar::Plugin.new(shift_argument)
42
+ validate_arguments!
43
+
44
+ action("Installing #{plugin.name}") do
45
+ begin
46
+ plugin.install
47
+ Mortar::Plugin.load_plugin(plugin.name)
48
+ rescue StandardError => e
49
+ error e
50
+ end
51
+ end
52
+ end
53
+
54
+ # plugins:uninstall PLUGIN
55
+ #
56
+ # uninstall a plugin
57
+ #
58
+ #Example:
59
+ #
60
+ # $ mortar plugins:uninstall watchtower
61
+ # Uninstalling watchtower... done
62
+ #
63
+ def uninstall
64
+ plugin = Mortar::Plugin.new(shift_argument)
65
+ validate_arguments!
66
+
67
+ action("Uninstalling #{plugin.name}") do
68
+ begin
69
+ plugin.uninstall
70
+ rescue Mortar::Plugin::ErrorPluginNotFound => e
71
+ error e
72
+ end
73
+ end
74
+ end
75
+
76
+ # plugins:update [PLUGIN]
77
+ #
78
+ # updates all plugins or a single plugin by name
79
+ #
80
+ #Example:
81
+ #
82
+ # $ mortar plugins:update
83
+ # Updating watchtower... done
84
+ #
85
+ # $ mortar plugins:update watchtower
86
+ # Updating watchtower... done
87
+ #
88
+ def update
89
+ plugins = if plugin = shift_argument
90
+ [plugin]
91
+ else
92
+ ::Mortar::Plugin.list
93
+ end
94
+ validate_arguments!
95
+
96
+ plugins.each do |plugin|
97
+ action("Updating #{plugin}") do
98
+ begin
99
+ Mortar::Plugin.new(plugin).update
100
+ rescue Mortar::Plugin::ErrorUpdatingSymlinkPlugin
101
+ status "skipped symlink"
102
+ rescue StandardError => e
103
+ status "error"
104
+ display e
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -1,6 +1,4 @@
1
- #
2
- # Copyright 2012 Mortar Data Inc.
3
- #
1
+ ## Copyright 2012 Mortar Data Inc.#
4
2
  # Licensed under the Apache License, Version 2.0 (the "License");
5
3
  # you may not use this file except in compliance with the License.
6
4
  # You may obtain a copy of the License at
@@ -0,0 +1,170 @@
1
+ # based on the Rails Plugin
2
+ module Mortar
3
+ class Plugin
4
+ include Mortar::Helpers
5
+ extend Mortar::Helpers
6
+
7
+ class ErrorUpdatingSymlinkPlugin < StandardError; end
8
+ class ErrorUpdatingPlugin < StandardError; end
9
+ class ErrorInstallingDependencies < StandardError; end
10
+ class ErrorInstallingPlugin < StandardError; end
11
+ class ErrorPluginNotFound < StandardError; end
12
+ class ErrorLoadingPlugin < StandardError; end
13
+
14
+ DEPRECATED_PLUGINS = %w(
15
+ test-plugin
16
+ )
17
+
18
+ attr_reader :name, :uri
19
+
20
+ def self.directory
21
+ File.expand_path("#{home_directory}/.mortar/plugins")
22
+ end
23
+
24
+ def self.list
25
+ Dir["#{directory}/*"].sort.select { |entry|
26
+ File.directory? entry and !(entry =='.' || entry == '..')
27
+ }.map { |folder|
28
+ File.basename(folder)
29
+ }
30
+ end
31
+
32
+ def self.without_bundler_env
33
+ original_env = ENV.to_hash
34
+ ENV.delete("BUNDLE_GEMFILE")
35
+ ENV.delete("BUNDLE_PATH")
36
+ ENV.delete("BUNDLE_BIN_PATH")
37
+ ENV.delete("RUBYOPT")
38
+ yield
39
+ ensure
40
+ ENV.replace(original_env.to_hash)
41
+ end
42
+
43
+ def self.install_bundle
44
+ system("bundle install --standalone --without development >> ./../plugin_install.log")
45
+ end
46
+
47
+ def self.load!
48
+ list.each do |plugin|
49
+ next if skip_plugins.include?(plugin)
50
+ load_plugin(plugin)
51
+ end
52
+ end
53
+
54
+ def self.load_plugin(plugin)
55
+ begin
56
+ folder = "#{self.directory}/#{plugin}"
57
+ $: << "#{folder}/lib" if File.directory? "#{folder}/lib"
58
+ load "#{folder}/init.rb" if File.exists? "#{folder}/init.rb"
59
+ rescue ScriptError, StandardError => error
60
+ styled_error(error, "Unable to load plugin #{plugin}.")
61
+ false
62
+ end
63
+ end
64
+
65
+ def self.remove_plugin(plugin)
66
+ FileUtils.rm_rf("#{self.directory}/#{plugin}")
67
+ end
68
+
69
+ def self.skip_plugins
70
+ @skip_plugins ||= ENV["SKIP_PLUGINS"].to_s.split(/[ ,]/)
71
+ end
72
+
73
+ def initialize(uri)
74
+ @uri = uri
75
+ guess_name(uri)
76
+ end
77
+
78
+ def git
79
+ @git ||= Mortar::Git::Git.new
80
+ end
81
+
82
+ def to_s
83
+ name
84
+ end
85
+
86
+ def path
87
+ "#{self.class.directory}/#{name}"
88
+ end
89
+
90
+ def install
91
+ if File.directory?(path)
92
+ uninstall
93
+ end
94
+ FileUtils.mkdir_p(self.class.directory)
95
+ Dir.chdir(self.class.directory) do
96
+ git.git("clone #{uri}", check_success=true, check_git_directory=false)
97
+ unless $?.success?
98
+ FileUtils.rm_rf path
99
+ raise Mortar::Plugin::ErrorInstallingPlugin, <<-ERROR
100
+ Unable to install plugin #{name}.
101
+ Please check the URL and try again.
102
+ ERROR
103
+ end
104
+ end
105
+ install_dependencies
106
+ return true
107
+ end
108
+
109
+ def install_dependencies
110
+ Dir.chdir(path) do
111
+ Mortar::Plugin.without_bundler_env do
112
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("Gemfile", path)
113
+ if File.exists? ENV["BUNDLE_GEMFILE"]
114
+ Mortar::Plugin.install_bundle
115
+ unless $?.success?
116
+ FileUtils.rm_rf path
117
+ raise Mortar::Plugin::ErrorInstallingDependencies, <<-ERROR
118
+ Unable to install dependencies for #{name}.
119
+ Error logs stored to #{Plugin.directory}/plugin_install.log
120
+ Refer to the documentation for this plugin for help.
121
+ ERROR
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def uninstall
129
+ ensure_plugin_exists
130
+ FileUtils.rm_r(path)
131
+ end
132
+
133
+ def update
134
+ ensure_plugin_exists
135
+ if File.symlink?(path)
136
+ raise Mortar::Plugin::ErrorUpdatingSymlinkPlugin
137
+ else
138
+ Dir.chdir(path) do
139
+ unless git.git('config --get branch.master.remote').empty?
140
+ message = git.git("pull")
141
+ unless $?.success?
142
+ raise Mortar::Plugin::ErrorUpdatingPlugin, <<-ERROR
143
+ Unable to update #{name}.
144
+ #{message}
145
+ ERROR
146
+ end
147
+ end
148
+ end
149
+ install_dependencies
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ def ensure_plugin_exists
156
+ unless File.directory?(path)
157
+ raise Mortar::Plugin::ErrorPluginNotFound, <<-ERROR
158
+ #{name} plugin not found.
159
+ ERROR
160
+ end
161
+ end
162
+
163
+ def guess_name(url)
164
+ @name = File.basename(url)
165
+ @name = File.basename(File.dirname(url)) if @name.empty?
166
+ @name.gsub!(/\.git$/, '') if @name =~ /\.git$/
167
+ end
168
+
169
+ end
170
+ end
@@ -16,5 +16,5 @@
16
16
 
17
17
  module Mortar
18
18
  # see http://semver.org/
19
- VERSION = "0.8.8"
19
+ VERSION = "0.9.0"
20
20
  end
@@ -89,7 +89,7 @@ module Mortar
89
89
  lambda { @git.git("--version") }.should_not raise_error
90
90
  end
91
91
  end
92
-
92
+
93
93
  it "raises error on no .git file" do
94
94
  with_no_git_directory do
95
95
  lambda {@git.git("--version") }.should raise_error(Mortar::Git::GitError)
@@ -0,0 +1,164 @@
1
+ require "spec_helper"
2
+ require "mortar/auth"
3
+ require "mortar/plugin"
4
+
5
+ module Mortar
6
+ describe Plugin do
7
+
8
+ it "lives in ~/.mortar/plugins" do
9
+ stub(Mortar::Plugin).home_directory.returns '/home/user'
10
+ Plugin.directory.should == '/home/user/.mortar/plugins'
11
+ end
12
+
13
+ it "extracts the name from git urls" do
14
+ Plugin.new('git://github.com/mortar/plugin.git').name.should == 'plugin'
15
+ end
16
+
17
+ describe "management" do
18
+ before(:each) do
19
+ @sandbox = "/tmp/mortar_plugins_spec_#{Process.pid}"
20
+ FileUtils.mkdir_p(@sandbox)
21
+ stub(Dir).pwd.returns @sandbox
22
+ stub(Plugin).directory.returns @sandbox
23
+ end
24
+
25
+ after(:each) do
26
+ FileUtils.rm_rf(@sandbox)
27
+ end
28
+
29
+ it "lists installed plugins" do
30
+ FileUtils.mkdir_p(@sandbox + '/plugin1')
31
+ FileUtils.mkdir_p(@sandbox + '/plugin2')
32
+ Plugin.list.should include 'plugin1'
33
+ Plugin.list.should include 'plugin2'
34
+ end
35
+
36
+ it "installs pulling from the plugin url" do
37
+ plugin_folder = "/tmp/mortar_plugin"
38
+ FileUtils.rm_rf(plugin_folder)
39
+ FileUtils.mkdir_p(plugin_folder)
40
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
41
+ Plugin.new(plugin_folder).install
42
+ File.directory?("#{@sandbox}/mortar_plugin").should be_true
43
+ File.read("#{@sandbox}/mortar_plugin/README").should == "test\n"
44
+ end
45
+
46
+ it "reinstalls over old copies" do
47
+ plugin_folder = "/tmp/mortar_plugin"
48
+ FileUtils.rm_rf(plugin_folder)
49
+ FileUtils.mkdir_p(plugin_folder)
50
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
51
+ Plugin.new(plugin_folder).install
52
+ Plugin.new(plugin_folder).install
53
+ File.directory?("#{@sandbox}/mortar_plugin").should be_true
54
+ File.read("#{@sandbox}/mortar_plugin/README").should == "test\n"
55
+ end
56
+
57
+ context "update" do
58
+
59
+ before(:each) do
60
+ plugin_folder = "/tmp/mortar_plugin"
61
+ FileUtils.mkdir_p(plugin_folder)
62
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
63
+ Plugin.new(plugin_folder).install
64
+ `cd #{plugin_folder} && echo 'updated' > README && git add . && git commit -m 'my plugin update'`
65
+ end
66
+
67
+ it "updates existing copies" do
68
+ Plugin.new('mortar_plugin').update
69
+ File.directory?("#{@sandbox}/mortar_plugin").should be_true
70
+ File.read("#{@sandbox}/mortar_plugin/README").should == "updated\n"
71
+ end
72
+
73
+ it "raises exception on symlinked plugins" do
74
+ `cd #{@sandbox} && ln -s mortar_plugin mortar_plugin_symlink`
75
+ lambda { Plugin.new('mortar_plugin_symlink').update }.should raise_error Mortar::Plugin::ErrorUpdatingSymlinkPlugin
76
+ end
77
+
78
+ end
79
+
80
+
81
+ it "uninstalls removing the folder" do
82
+ FileUtils.mkdir_p(@sandbox + '/plugin1')
83
+ Plugin.new('git://github.com/mortar/plugin1.git').uninstall
84
+ Plugin.list.should == []
85
+ end
86
+
87
+ it "adds the lib folder in the plugin to the load path, if present" do
88
+ FileUtils.mkdir_p(@sandbox + '/plugin/lib')
89
+ File.open(@sandbox + '/plugin/lib/my_custom_plugin_file.rb', 'w') { |f| f.write "" }
90
+ Plugin.load!
91
+ $:.should include(@sandbox + '/plugin/lib')
92
+ end
93
+
94
+ it "loads init.rb, if present" do
95
+ FileUtils.mkdir_p(@sandbox + '/plugin')
96
+ File.open(@sandbox + '/plugin/init.rb', 'w') { |f| f.write "LoadedInit = true" }
97
+ Plugin.load!
98
+ LoadedInit.should be_true
99
+ end
100
+
101
+ describe "installing plugins with dependencies" do
102
+ it "should install plugin dependencies" do
103
+ plugin_folder = "/tmp/mortar_plugin"
104
+ FileUtils.mkdir_p(plugin_folder)
105
+ File.open(plugin_folder + '/Gemfile', 'w') { |f| f.write "# dummy content" }
106
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
107
+ Plugin.new(plugin_folder).install
108
+ File.directory?("#{@sandbox}/mortar_plugin").should be_true
109
+ File.directory?("#{@sandbox}/mortar_plugin/bundle").should be_true
110
+ File.exist?("#{@sandbox}/mortar_plugin/Gemfile").should be_true
111
+ File.read("#{@sandbox}/mortar_plugin/README").should == "test\n"
112
+ end
113
+
114
+ it "should fail to install plugin with bad dependencies" do
115
+ mock(Plugin).install_bundle { system("exit 1") }
116
+ plugin_folder = "/tmp/mortar_plugin"
117
+ FileUtils.mkdir_p(plugin_folder)
118
+ File.open(plugin_folder + '/Gemfile', 'w') { |f| f.write "# dummy content" }
119
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
120
+ lambda { Plugin.new(plugin_folder).install }.should raise_error Mortar::Plugin::ErrorInstallingDependencies
121
+ end
122
+
123
+ it "should have logs when bundle install fails" do
124
+ plugin_folder = "/tmp/mortar_plugin"
125
+ FileUtils.mkdir_p(plugin_folder)
126
+ File.open(plugin_folder + '/Gemfile', 'w') { |f| f.write "non_existent_command" }
127
+ `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
128
+ lambda { Plugin.new(plugin_folder).install }.should raise_error Mortar::Plugin::ErrorInstallingDependencies
129
+ File.exists?("#{Plugin.directory}/plugin_install.log").should be_true
130
+ end
131
+ end
132
+
133
+ describe "when there are plugin load errors" do
134
+ before(:each) do
135
+ FileUtils.mkdir_p(@sandbox + '/some_plugin/lib')
136
+ File.open(@sandbox + '/some_plugin/init.rb', 'w') { |f| f.write "require 'some_non_existant_file'" }
137
+ end
138
+
139
+ it "should not throw an error" do
140
+ capture_stderr do
141
+ lambda { Plugin.load! }.should_not raise_error
142
+ end
143
+ end
144
+
145
+ it "should fail gracefully" do
146
+ stderr = capture_stderr do
147
+ Plugin.load!
148
+ end
149
+ stderr.should include('some_non_existant_file (LoadError)')
150
+ end
151
+
152
+ it "should still load other plugins" do
153
+ FileUtils.mkdir_p(@sandbox + '/some_plugin_2/lib')
154
+ File.open(@sandbox + '/some_plugin_2/init.rb', 'w') { |f| f.write "LoadedPlugin2 = true" }
155
+ stderr = capture_stderr do
156
+ Plugin.load!
157
+ end
158
+ stderr.should include('some_non_existant_file (LoadError)')
159
+ LoadedPlugin2.should be_true
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
metadata CHANGED
@@ -1,167 +1,179 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mortar
3
- version: !ruby/object:Gem::Version
4
- version: 0.8.8
3
+ version: !ruby/object:Gem::Version
4
+ hash: 59
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Mortar Data
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-06-28 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-07-08 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: mortar-api-ruby
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: 0.6.3
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
- requirements:
25
+ requirements:
27
26
  - - ~>
28
- - !ruby/object:Gem::Version
27
+ - !ruby/object:Gem::Version
28
+ hash: 1
29
+ segments:
30
+ - 0
31
+ - 6
32
+ - 3
29
33
  version: 0.6.3
30
- - !ruby/object:Gem::Dependency
31
- name: netrc
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '0.7'
38
34
  type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: netrc
39
38
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
41
40
  none: false
42
- requirements:
41
+ requirements:
43
42
  - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '0.7'
46
- - !ruby/object:Gem::Dependency
43
+ - !ruby/object:Gem::Version
44
+ hash: 5
45
+ segments:
46
+ - 0
47
+ - 7
48
+ version: "0.7"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
47
52
  name: launchy
48
- requirement: !ruby/object:Gem::Requirement
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
49
55
  none: false
50
- requirements:
56
+ requirements:
51
57
  - - ~>
52
- - !ruby/object:Gem::Version
53
- version: '2.1'
58
+ - !ruby/object:Gem::Version
59
+ hash: 1
60
+ segments:
61
+ - 2
62
+ - 1
63
+ version: "2.1"
54
64
  type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: bundler
55
68
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
57
70
  none: false
58
- requirements:
71
+ requirements:
59
72
  - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '2.1'
62
- - !ruby/object:Gem::Dependency
73
+ - !ruby/object:Gem::Version
74
+ hash: 11
75
+ segments:
76
+ - 1
77
+ - 2
78
+ version: "1.2"
79
+ type: :runtime
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
63
82
  name: excon
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: '0.15'
70
- type: :development
71
83
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: '0.15'
78
- - !ruby/object:Gem::Dependency
79
- name: fakefs
80
- requirement: !ruby/object:Gem::Requirement
84
+ requirement: &id005 !ruby/object:Gem::Requirement
81
85
  none: false
82
- requirements:
86
+ requirements:
83
87
  - - ~>
84
- - !ruby/object:Gem::Version
85
- version: 0.4.2
88
+ - !ruby/object:Gem::Version
89
+ hash: 21
90
+ segments:
91
+ - 0
92
+ - 15
93
+ version: "0.15"
86
94
  type: :development
95
+ version_requirements: *id005
96
+ - !ruby/object:Gem::Dependency
97
+ name: fakefs
87
98
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
99
+ requirement: &id006 !ruby/object:Gem::Requirement
89
100
  none: false
90
- requirements:
101
+ requirements:
91
102
  - - ~>
92
- - !ruby/object:Gem::Version
103
+ - !ruby/object:Gem::Version
104
+ hash: 11
105
+ segments:
106
+ - 0
107
+ - 4
108
+ - 2
93
109
  version: 0.4.2
94
- - !ruby/object:Gem::Dependency
95
- name: gem-release
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
110
  type: :development
111
+ version_requirements: *id006
112
+ - !ruby/object:Gem::Dependency
113
+ name: gem-release
103
114
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- - !ruby/object:Gem::Dependency
111
- name: rake
112
- requirement: !ruby/object:Gem::Requirement
115
+ requirement: &id007 !ruby/object:Gem::Requirement
113
116
  none: false
114
- requirements:
115
- - - ! '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
118
124
  type: :development
125
+ version_requirements: *id007
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
119
128
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ! '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: rr
128
- requirement: !ruby/object:Gem::Requirement
129
+ requirement: &id008 !ruby/object:Gem::Requirement
129
130
  none: false
130
- requirements:
131
- - - ! '>='
132
- - !ruby/object:Gem::Version
133
- version: '0'
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
134
138
  type: :development
139
+ version_requirements: *id008
140
+ - !ruby/object:Gem::Dependency
141
+ name: rr
135
142
  prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
143
+ requirement: &id009 !ruby/object:Gem::Requirement
137
144
  none: false
138
- requirements:
139
- - - ! '>='
140
- - !ruby/object:Gem::Version
141
- version: '0'
142
- - !ruby/object:Gem::Dependency
143
- name: rspec
144
- requirement: !ruby/object:Gem::Requirement
145
- none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
150
152
  type: :development
153
+ version_requirements: *id009
154
+ - !ruby/object:Gem::Dependency
155
+ name: rspec
151
156
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
157
+ requirement: &id010 !ruby/object:Gem::Requirement
153
158
  none: false
154
- requirements:
155
- - - ! '>='
156
- - !ruby/object:Gem::Version
157
- version: '0'
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ hash: 3
163
+ segments:
164
+ - 0
165
+ version: "0"
166
+ type: :development
167
+ version_requirements: *id010
158
168
  description: Client library and command-line tool to interact with the Mortar service.
159
169
  email: support@mortardata.com
160
- executables:
170
+ executables:
161
171
  - mortar
162
172
  extensions: []
173
+
163
174
  extra_rdoc_files: []
164
- files:
175
+
176
+ files:
165
177
  - README.md
166
178
  - bin/mortar
167
179
  - css/illustrate.css
@@ -186,6 +198,7 @@ files:
186
198
  - lib/mortar/command/jobs.rb
187
199
  - lib/mortar/command/local.rb
188
200
  - lib/mortar/command/pigscripts.rb
201
+ - lib/mortar/command/plugins.rb
189
202
  - lib/mortar/command/projects.rb
190
203
  - lib/mortar/command/validate.rb
191
204
  - lib/mortar/command/version.rb
@@ -204,6 +217,7 @@ files:
204
217
  - lib/mortar/local/jython.rb
205
218
  - lib/mortar/local/pig.rb
206
219
  - lib/mortar/local/python.rb
220
+ - lib/mortar/plugin.rb
207
221
  - lib/mortar/project.rb
208
222
  - lib/mortar/templates/controlscript/controlscript.py
209
223
  - lib/mortar/templates/macro/macro.pig
@@ -253,6 +267,7 @@ files:
253
267
  - spec/mortar/local/jython_spec.rb
254
268
  - spec/mortar/local/pig_spec.rb
255
269
  - spec/mortar/local/python_spec.rb
270
+ - spec/mortar/plugin_spec.rb
256
271
  - spec/mortar/project_spec.rb
257
272
  - spec/mortar/updater_spec.rb
258
273
  - spec/spec.opts
@@ -260,26 +275,38 @@ files:
260
275
  - spec/support/display_message_matcher.rb
261
276
  homepage: http://mortardata.com/
262
277
  licenses: []
278
+
263
279
  post_install_message:
264
280
  rdoc_options: []
265
- require_paths:
281
+
282
+ require_paths:
266
283
  - lib
267
- required_ruby_version: !ruby/object:Gem::Requirement
284
+ required_ruby_version: !ruby/object:Gem::Requirement
268
285
  none: false
269
- requirements:
270
- - - ! '>='
271
- - !ruby/object:Gem::Version
286
+ requirements:
287
+ - - ">="
288
+ - !ruby/object:Gem::Version
289
+ hash: 57
290
+ segments:
291
+ - 1
292
+ - 8
293
+ - 7
272
294
  version: 1.8.7
273
- required_rubygems_version: !ruby/object:Gem::Requirement
295
+ required_rubygems_version: !ruby/object:Gem::Requirement
274
296
  none: false
275
- requirements:
276
- - - ! '>='
277
- - !ruby/object:Gem::Version
278
- version: '0'
297
+ requirements:
298
+ - - ">="
299
+ - !ruby/object:Gem::Version
300
+ hash: 3
301
+ segments:
302
+ - 0
303
+ version: "0"
279
304
  requirements: []
305
+
280
306
  rubyforge_project:
281
- rubygems_version: 1.8.23
307
+ rubygems_version: 1.8.24
282
308
  signing_key:
283
309
  specification_version: 3
284
310
  summary: Client library and CLI to interact with the Mortar service.
285
311
  test_files: []
312
+