mortar 0.8.8 → 0.9.0

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