mortar 0.9.1 → 0.9.2
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.
- data/lib/mortar/command/local.rb +37 -1
- data/lib/mortar/command/plugins.rb +3 -3
- data/lib/mortar/command/projects.rb +22 -10
- data/lib/mortar/generators/project_generator.rb +5 -1
- data/lib/mortar/plugin.rb +38 -3
- data/lib/mortar/templates/project/controlscripts/lib/characterize_control.py +23 -0
- data/lib/mortar/templates/project/macros/characterize_macro.pig +129 -0
- data/lib/mortar/templates/project/pigscripts/characterize.pig +6 -0
- data/lib/mortar/templates/project/udfs/jython/top_5_tuple.py +27 -0
- data/lib/mortar/version.rb +1 -1
- data/spec/mortar/command/projects_spec.rb +12 -5
- data/spec/mortar/plugin_spec.rb +16 -1
- data/spec/spec_helper.rb +38 -0
- metadata +9 -5
data/lib/mortar/command/local.rb
CHANGED
@@ -66,12 +66,48 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
66
66
|
error("No such directory #{project_root}")
|
67
67
|
end
|
68
68
|
Dir.chdir(project_root)
|
69
|
-
|
70
69
|
script = validate_script!(script_name)
|
71
70
|
ctrl = Mortar::Local::Controller.new
|
72
71
|
ctrl.run(script, pig_parameters)
|
73
72
|
end
|
74
73
|
|
74
|
+
# local:characterize
|
75
|
+
#
|
76
|
+
# Characterize will inspect your input data, inferring a schema and
|
77
|
+
# generating keys, if needed. It will output CSV containing various
|
78
|
+
# statistics about your data (most common values, percent null, etc.)
|
79
|
+
#
|
80
|
+
# -f, --param-file PARAMFILE # Load pig parameter values from a file
|
81
|
+
#
|
82
|
+
# Load some data and emit statistics.
|
83
|
+
# PARAMFILE:
|
84
|
+
# LOADER=<full class path of loader function>
|
85
|
+
# INPUT_SRC=<Location of the input data>
|
86
|
+
# OUTPUT_PATH=<Relative path from project root for output>
|
87
|
+
# INFER_TYPES=<when true, recursively infers types for input data>
|
88
|
+
#
|
89
|
+
# Example paramfile:
|
90
|
+
# LOADER=org.apache.pig.piggybank.storage.JsonLoader()
|
91
|
+
# INPUT_SRC=s3n://twitter-gardenhose-mortar/example
|
92
|
+
# OUTPUT_PATH=twitter_char
|
93
|
+
# INFER_TYPES=true
|
94
|
+
#
|
95
|
+
def characterize
|
96
|
+
validate_arguments!
|
97
|
+
|
98
|
+
#cd into the project root
|
99
|
+
project_root = options[:project_root] ||= Dir.getwd
|
100
|
+
unless File.directory?(project_root)
|
101
|
+
error("No such directory #{project_root}")
|
102
|
+
end
|
103
|
+
Dir.chdir(project_root)
|
104
|
+
|
105
|
+
controlscript_name = "controlscripts/lib/characterize_control.py"
|
106
|
+
script = validate_script!(controlscript_name)
|
107
|
+
ctrl = Mortar::Local::Controller.new
|
108
|
+
ctrl.run(script, pig_parameters)
|
109
|
+
end
|
110
|
+
|
75
111
|
# local:illustrate PIGSCRIPT [ALIAS]
|
76
112
|
#
|
77
113
|
# Locally illustrate the effects and output of a pigscript.
|
@@ -46,7 +46,7 @@ module Mortar::Command
|
|
46
46
|
plugin.install
|
47
47
|
Mortar::Plugin.load_plugin(plugin.name)
|
48
48
|
rescue StandardError => e
|
49
|
-
error e
|
49
|
+
error e.message
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -68,7 +68,7 @@ module Mortar::Command
|
|
68
68
|
begin
|
69
69
|
plugin.uninstall
|
70
70
|
rescue Mortar::Plugin::ErrorPluginNotFound => e
|
71
|
-
error e
|
71
|
+
error e.message
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -101,7 +101,7 @@ module Mortar::Command
|
|
101
101
|
status "skipped symlink"
|
102
102
|
rescue StandardError => e
|
103
103
|
status "error"
|
104
|
-
display e
|
104
|
+
display e.message
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
@@ -47,19 +47,31 @@ class Mortar::Command::Projects < Mortar::Command::Base
|
|
47
47
|
error("Usage: mortar projects:delete PROJECTNAME\nMust specify PROJECTNAME.")
|
48
48
|
end
|
49
49
|
validate_arguments!
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
projects = api.get_projects().body['projects']
|
51
|
+
project_id = nil
|
52
|
+
if projects.any?
|
53
|
+
projects.each do |project|
|
54
|
+
if project['name'] == name
|
55
|
+
project_id = project['project_id']
|
56
|
+
end
|
57
|
+
end
|
55
58
|
end
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
if project_id.nil?
|
61
|
+
display "\nNo project with name: #{name}"
|
62
|
+
else
|
63
|
+
# delete embedded project mirror if one exists
|
64
|
+
mirror_dir = "#{git.mortar_mirrors_dir()}/#{name}"
|
65
|
+
if File.directory? mirror_dir
|
66
|
+
FileUtils.rm_r mirror_dir
|
67
|
+
end
|
68
|
+
|
69
|
+
# delete Mortar remote
|
70
|
+
action("Sending request to delete project: #{name}") do
|
71
|
+
api.delete_project(project_id).body['project_id']
|
72
|
+
end
|
73
|
+
display "\nYour project has been deleted."
|
61
74
|
end
|
62
|
-
display "\nYour project has been deleted."
|
63
75
|
|
64
76
|
end
|
65
77
|
|
@@ -38,6 +38,7 @@ module Mortar
|
|
38
38
|
|
39
39
|
inside "pigscripts" do
|
40
40
|
generate_file "pigscript.pig", "#{project_name}.pig"
|
41
|
+
copy_file "characterize.pig", "characterize.pig"
|
41
42
|
end
|
42
43
|
|
43
44
|
mkdir "controlscripts"
|
@@ -46,6 +47,7 @@ module Mortar
|
|
46
47
|
mkdir "lib"
|
47
48
|
inside "lib" do
|
48
49
|
copy_file "__init__.py", "__init__.py"
|
50
|
+
copy_file "characterize_control.py", "characterize_control.py"
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -53,6 +55,7 @@ module Mortar
|
|
53
55
|
|
54
56
|
inside "macros" do
|
55
57
|
copy_file "gitkeep", ".gitkeep"
|
58
|
+
copy_file "characterize_macro.pig", "characterize_macro.pig"
|
56
59
|
end
|
57
60
|
|
58
61
|
mkdir "fixtures"
|
@@ -72,6 +75,7 @@ module Mortar
|
|
72
75
|
mkdir "jython"
|
73
76
|
inside "jython" do
|
74
77
|
copy_file "gitkeep", ".gitkeep"
|
78
|
+
copy_file "top_5_tuple.py", "top_5_tuple.py"
|
75
79
|
end
|
76
80
|
|
77
81
|
mkdir "java"
|
@@ -142,4 +146,4 @@ module Mortar
|
|
142
146
|
end
|
143
147
|
end
|
144
148
|
end
|
145
|
-
end
|
149
|
+
end
|
data/lib/mortar/plugin.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# based on the Rails Plugin
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
|
2
5
|
module Mortar
|
3
6
|
class Plugin
|
4
7
|
include Mortar::Helpers
|
@@ -41,7 +44,40 @@ module Mortar
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def self.install_bundle
|
44
|
-
|
47
|
+
# TODO: Deal with the bundler as a runtime dependency issue
|
48
|
+
# before moving these require statements to the top.
|
49
|
+
begin
|
50
|
+
require 'bundler/cli'
|
51
|
+
require 'bundler/friendly_errors'
|
52
|
+
rescue LoadError => e
|
53
|
+
raise <<-ERROR
|
54
|
+
Unable to install this plugin. Make sure you have bundler installed:
|
55
|
+
|
56
|
+
$ gem install bundler
|
57
|
+
|
58
|
+
ERROR
|
59
|
+
end
|
60
|
+
|
61
|
+
out = StringIO.new
|
62
|
+
$stdout = out
|
63
|
+
begin
|
64
|
+
bundle_def = Bundler.definition({})
|
65
|
+
Bundler.ui = Bundler::UI::Shell.new({})
|
66
|
+
Bundler.ui.level = "silent"
|
67
|
+
Bundler.settings[:path] = "bundle"
|
68
|
+
Bundler::Installer.install(Bundler.root, bundle_def, {
|
69
|
+
:standalone => [],
|
70
|
+
})
|
71
|
+
result = true
|
72
|
+
rescue StandardError => e
|
73
|
+
out.write e.message
|
74
|
+
result = false
|
75
|
+
end
|
76
|
+
open("#{Plugin.directory}/plugin_install.log", 'a') do |f|
|
77
|
+
f.puts out.string
|
78
|
+
end
|
79
|
+
$stdout = STDOUT
|
80
|
+
return result
|
45
81
|
end
|
46
82
|
|
47
83
|
def self.load!
|
@@ -111,8 +147,7 @@ ERROR
|
|
111
147
|
Mortar::Plugin.without_bundler_env do
|
112
148
|
ENV["BUNDLE_GEMFILE"] = File.expand_path("Gemfile", path)
|
113
149
|
if File.exists? ENV["BUNDLE_GEMFILE"]
|
114
|
-
Mortar::Plugin.install_bundle
|
115
|
-
unless $?.success?
|
150
|
+
unless Mortar::Plugin.install_bundle
|
116
151
|
FileUtils.rm_rf path
|
117
152
|
raise Mortar::Plugin::ErrorInstallingDependencies, <<-ERROR
|
118
153
|
Unable to install dependencies for #{name}.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from org.apache.pig.scripting import Pig
|
2
|
+
import os
|
3
|
+
|
4
|
+
if __name__ == "__main__":
|
5
|
+
params = Pig.getParameters()
|
6
|
+
loader = params["LOADER"]
|
7
|
+
input_source = params["INPUT_SRC"]
|
8
|
+
output_path = params["OUTPUT_PATH"]
|
9
|
+
infer_types = params["INFER_TYPES"]
|
10
|
+
|
11
|
+
Pig.compileFromFile("../pigscripts/characterize.pig").bind({
|
12
|
+
"LOADER" : loader,
|
13
|
+
"INPUT_SRC" : input_source,
|
14
|
+
"OUTPUT_PATH" : output_path,
|
15
|
+
"INFER_TYPES" : infer_types
|
16
|
+
}).runSingle()
|
17
|
+
|
18
|
+
for root, _, files in os.walk("../%s" % output_path):
|
19
|
+
for f in files:
|
20
|
+
if f[0] != '.':
|
21
|
+
fullpath = os.path.join(root, f)
|
22
|
+
copypath = os.path.join(root, f + '.csv')
|
23
|
+
os.system ("cp %s %s" % (fullpath, copypath))
|
@@ -0,0 +1,129 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2013 Mortar Data Inc.
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
/*
|
18
|
+
* A pig macro to characterize some data.
|
19
|
+
* Take an alias to some pre-loaded data and return a relation
|
20
|
+
* containing statistics about that data in a bag.
|
21
|
+
* Each field is listed up to five times (with their five most common
|
22
|
+
* example values) as a tuple of the following form:
|
23
|
+
* (
|
24
|
+
* Field Name (embedded fields have their parent's field name prepended),
|
25
|
+
* Number of distinct values associated with the field,
|
26
|
+
* Total number of values,
|
27
|
+
* Deciles,
|
28
|
+
* Number of null appearences,
|
29
|
+
* Percentage null,
|
30
|
+
* Minimum value,
|
31
|
+
* Maximum value,
|
32
|
+
* Range of values (Max - Min),
|
33
|
+
* Type,
|
34
|
+
* Values (tuple of top 5 values, bags/chararrays/tuples are converted to length)
|
35
|
+
* Value Counts (tuple of corresponding number of value occurrences)
|
36
|
+
* Original Values (tuple of corresponding original values)
|
37
|
+
* )
|
38
|
+
*
|
39
|
+
* data: {anything}
|
40
|
+
* inferTypes: when true, characterize will infer numeric types for values
|
41
|
+
* without an explicit schema (e.g. values in a complex map object)
|
42
|
+
*
|
43
|
+
* Example:
|
44
|
+
* data = LOAD '/path/to/data' USING JsonLoader();
|
45
|
+
* characterized = Characterize(data, 'true')
|
46
|
+
*/
|
47
|
+
|
48
|
+
REGISTER 's3://mhc-software-mirror/datafu/datafu-0.0.10.jar';
|
49
|
+
REGISTER 's3://mhc-software-mirror/bacon-bits/udfs/java/bacon-bits-0.1.0.jar';
|
50
|
+
REGISTER '../udfs/jython/top_5_tuple.py' USING jython AS top5;
|
51
|
+
|
52
|
+
DEFINE Deciles datafu.pig.stats.StreamingQuantile('11');
|
53
|
+
|
54
|
+
DEFINE Characterize(data, inferTypes)
|
55
|
+
RETURNS out {
|
56
|
+
|
57
|
+
DEFINE Characterize__ExtractFields com.mortardata.pig.ExtractFields('$inferTypes');
|
58
|
+
|
59
|
+
raw_fields = FOREACH $data
|
60
|
+
GENERATE FLATTEN(Characterize__ExtractFields(*)) as
|
61
|
+
(keyname:chararray, type:chararray, val:double, orig:chararray);
|
62
|
+
|
63
|
+
--Group the rows by field name and find the number of unique values for each field in the collection
|
64
|
+
key_groups = GROUP raw_fields BY (keyname);
|
65
|
+
unique_vals = FOREACH key_groups {
|
66
|
+
v = raw_fields.val;
|
67
|
+
null_fields = filter raw_fields by val is null;
|
68
|
+
unique_v = distinct v;
|
69
|
+
GENERATE flatten(group) as keyname:chararray,
|
70
|
+
COUNT(unique_v) as num_distinct_vals_count:long, COUNT(v) as num_vals:long, COUNT(null_fields) as num_null:long,
|
71
|
+
(double) COUNT(null_fields) / (double) COUNT(raw_fields) as percentage_null:double,
|
72
|
+
MIN(unique_v.val) as min_val:double, MAX(unique_v.val) as max_val:double;
|
73
|
+
}
|
74
|
+
|
75
|
+
-- calculate decile tuples for each key (filtering out null values to make datafu happy)
|
76
|
+
no_nulls = filter raw_fields by val is not null;
|
77
|
+
no_null_groups = GROUP no_nulls BY keyname;
|
78
|
+
key_deciles = FOREACH no_null_groups {
|
79
|
+
GENERATE flatten(group) as keyname:chararray, Deciles(no_nulls.val) as deciles:tuple();
|
80
|
+
}
|
81
|
+
|
82
|
+
-- Find the number of times each value occurs for each field
|
83
|
+
key_val_groups = GROUP raw_fields BY (keyname, type, val, orig);
|
84
|
+
key_val_groups_with_counts = FOREACH key_val_groups
|
85
|
+
GENERATE flatten(group),
|
86
|
+
COUNT($1) as val_count:long;
|
87
|
+
|
88
|
+
-- Find the top 5 most common values for each field
|
89
|
+
key_vals = GROUP key_val_groups_with_counts BY (keyname);
|
90
|
+
top_5_vals = FOREACH key_vals {
|
91
|
+
ordered_vals = ORDER key_val_groups_with_counts BY val_count DESC;
|
92
|
+
limited_vals = LIMIT ordered_vals 5;
|
93
|
+
GENERATE flatten(limited_vals);
|
94
|
+
}
|
95
|
+
|
96
|
+
cogroup_result = COGROUP unique_vals BY keyname,
|
97
|
+
top_5_vals BY keyname;
|
98
|
+
|
99
|
+
flat_vals = FOREACH cogroup_result {
|
100
|
+
top_vals = top5.key_bag_to_tuple(top_5_vals);
|
101
|
+
GENERATE flatten(unique_vals) as
|
102
|
+
(keyname:chararray, num_distinct_vals_count:long, num_vals:long,
|
103
|
+
num_null:long, percent_null:double, min_val:double, max_val:double), top_vals.vals as vals,
|
104
|
+
top_vals.type as type:chararray, top_vals.orig as orig:tuple(), top_vals.val_counts as val_counts:tuple();
|
105
|
+
}
|
106
|
+
|
107
|
+
join_result = JOIN flat_vals BY keyname,
|
108
|
+
key_deciles BY keyname;
|
109
|
+
|
110
|
+
-- Clean up columns (remove duplicate keyname field)
|
111
|
+
result = FOREACH join_result
|
112
|
+
GENERATE flat_vals::keyname as Key,
|
113
|
+
num_distinct_vals_count as NDistinct,
|
114
|
+
num_vals as NVals,
|
115
|
+
deciles as Deciles,
|
116
|
+
num_null as NNull,
|
117
|
+
percent_null as PctNull,
|
118
|
+
min_val as Min,
|
119
|
+
max_val as Max,
|
120
|
+
max_val - min_val as Range,
|
121
|
+
type as Type,
|
122
|
+
vals as Vals,
|
123
|
+
val_counts as ValCounts,
|
124
|
+
orig as OrigVals;
|
125
|
+
|
126
|
+
-- -- Sort by field name and number of values
|
127
|
+
$out = ORDER result BY Key;
|
128
|
+
|
129
|
+
};
|
@@ -0,0 +1,6 @@
|
|
1
|
+
IMPORT '../macros/characterize_macro.pig';
|
2
|
+
data = LOAD '$INPUT_SRC'
|
3
|
+
USING $LOADER;
|
4
|
+
characterize_data = Characterize(data, $INFER_TYPES);
|
5
|
+
STORE characterize_data INTO '../$OUTPUT_PATH'
|
6
|
+
USING org.apache.pig.piggybank.storage.CSVExcelStorage(',', 'YES_MULTILINE', 'UNIX', 'WRITE_OUTPUT_HEADER');
|
@@ -0,0 +1,27 @@
|
|
1
|
+
@outputSchema("five:tuple(vals:tuple(v1:double, v2:double, v3:double, v4:double, v5:double), type:chararray, orig:tuple(v1:chararray, v2:chararray, v3:chararray, v4:chararray, v5:chararray), val_counts:tuple(v1:long, v2:long, v3:long, v4:long, v5:long))")
|
2
|
+
def key_bag_to_tuple(input_bag):
|
3
|
+
output = []
|
4
|
+
#sort by val_count
|
5
|
+
input_bag = sorted(input_bag, key=lambda tup: tup[4], reverse=True)
|
6
|
+
vals = [None, None, None, None, None]
|
7
|
+
val_counts = [None, None, None, None, None]
|
8
|
+
orig_vals = [None, None, None, None, None]
|
9
|
+
for idx, t in enumerate(input_bag):
|
10
|
+
vals[idx] = t[2]
|
11
|
+
orig_vals[idx] = t[3]
|
12
|
+
val_counts[idx] = t[4]
|
13
|
+
val_tup = tuple(vals)
|
14
|
+
val_count_tup = tuple(val_counts)
|
15
|
+
orig_val_tup = tuple(orig_vals)
|
16
|
+
output.append(val_tup)
|
17
|
+
if all(i[1] == "NULL" for i in input_bag):
|
18
|
+
output.append("NULL")
|
19
|
+
else:
|
20
|
+
for t in input_bag:
|
21
|
+
if t[1] != "NULL":
|
22
|
+
output.append(t[1])
|
23
|
+
break
|
24
|
+
output.append(orig_val_tup)
|
25
|
+
output.append(val_count_tup)
|
26
|
+
return tuple(output)
|
27
|
+
|
data/lib/mortar/version.rb
CHANGED
@@ -36,9 +36,11 @@ module Mortar::Command
|
|
36
36
|
|
37
37
|
project1 = {'name' => "Project1",
|
38
38
|
'status' => Mortar::API::Projects::STATUS_ACTIVE,
|
39
|
+
'project_id' => 'abcd1234',
|
39
40
|
'git_url' => "git@github.com:mortarcode-dev/Project1"}
|
40
41
|
project2 = {'name' => "Project2",
|
41
42
|
'status' => Mortar::API::Projects::STATUS_ACTIVE,
|
43
|
+
'project_id' => 'defg5678',
|
42
44
|
'git_url' => "git@github.com:mortarcode-dev/Project2"}
|
43
45
|
|
44
46
|
context("index") do
|
@@ -75,12 +77,13 @@ STDERR
|
|
75
77
|
end
|
76
78
|
|
77
79
|
it "deletes project" do
|
78
|
-
|
80
|
+
project_id = "abcd1234"
|
79
81
|
|
80
|
-
mock(Mortar::Auth.api).
|
81
|
-
|
82
|
+
mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
|
83
|
+
mock(Mortar::Auth.api).delete_project(project_id).returns(Excon::Response.new(:body => {}, :status => 200 ))
|
84
|
+
stderr, stdout = execute("projects:delete Project1")
|
82
85
|
stdout.should == <<-STDOUT
|
83
|
-
Sending request to delete project:
|
86
|
+
Sending request to delete project: Project1... done
|
84
87
|
|
85
88
|
Your project has been deleted.
|
86
89
|
STDOUT
|
@@ -127,11 +130,14 @@ STDOUT
|
|
127
130
|
\e[1;32m create\e[0m .gitignore
|
128
131
|
\e[1;32m create\e[0m pigscripts
|
129
132
|
\e[1;32m create\e[0m pigscripts/some_new_project.pig
|
133
|
+
\e[1;32m create\e[0m pigscripts/characterize.pig
|
130
134
|
\e[1;32m create\e[0m controlscripts
|
131
135
|
\e[1;32m create\e[0m controlscripts/lib
|
132
136
|
\e[1;32m create\e[0m controlscripts/lib/__init__.py
|
137
|
+
\e[1;32m create\e[0m controlscripts/lib/characterize_control.py
|
133
138
|
\e[1;32m create\e[0m macros
|
134
139
|
\e[1;32m create\e[0m macros/.gitkeep
|
140
|
+
\e[1;32m create\e[0m macros/characterize_macro.pig
|
135
141
|
\e[1;32m create\e[0m fixtures
|
136
142
|
\e[1;32m create\e[0m fixtures/.gitkeep
|
137
143
|
\e[1;32m create\e[0m udfs
|
@@ -139,6 +145,7 @@ STDOUT
|
|
139
145
|
\e[1;32m create\e[0m udfs/python/some_new_project.py
|
140
146
|
\e[1;32m create\e[0m udfs/jython
|
141
147
|
\e[1;32m create\e[0m udfs/jython/.gitkeep
|
148
|
+
\e[1;32m create\e[0m udfs/jython/top_5_tuple.py
|
142
149
|
\e[1;32m create\e[0m udfs/java
|
143
150
|
\e[1;32m create\e[0m udfs/java/.gitkeep
|
144
151
|
\e[1;32m create\e[0m vendor
|
@@ -426,4 +433,4 @@ STDERR
|
|
426
433
|
|
427
434
|
end
|
428
435
|
end
|
429
|
-
end
|
436
|
+
end
|
data/spec/mortar/plugin_spec.rb
CHANGED
@@ -100,15 +100,30 @@ module Mortar
|
|
100
100
|
|
101
101
|
describe "installing plugins with dependencies" do
|
102
102
|
it "should install plugin dependencies" do
|
103
|
+
## Setup Fake Gem
|
104
|
+
mortar_fake_gem_folder = create_fake_gem("/tmp")
|
103
105
|
plugin_folder = "/tmp/mortar_plugin"
|
104
106
|
FileUtils.mkdir_p(plugin_folder)
|
105
|
-
File.open(plugin_folder + '/Gemfile', 'w') { |f|
|
107
|
+
File.open(plugin_folder + '/Gemfile', 'w') { |f|
|
108
|
+
f.write "gem 'mortar_fake_gem', :path => '#{mortar_fake_gem_folder}'"
|
109
|
+
}
|
110
|
+
File.open(plugin_folder + '/init.rb', 'w') { |f|
|
111
|
+
f.write <<-EOS
|
112
|
+
require File.join(File.dirname(__FILE__), "bundle/bundler/setup")
|
113
|
+
require "mortar_fake_gem"
|
114
|
+
|
115
|
+
PluginTest = MortarFakeGem::WhoIs.awesome?
|
116
|
+
EOS
|
117
|
+
}
|
106
118
|
`cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
|
107
119
|
Plugin.new(plugin_folder).install
|
108
120
|
File.directory?("#{@sandbox}/mortar_plugin").should be_true
|
109
121
|
File.directory?("#{@sandbox}/mortar_plugin/bundle").should be_true
|
110
122
|
File.exist?("#{@sandbox}/mortar_plugin/Gemfile").should be_true
|
111
123
|
File.read("#{@sandbox}/mortar_plugin/README").should == "test\n"
|
124
|
+
|
125
|
+
Plugin.load!
|
126
|
+
PluginTest.should be_true
|
112
127
|
end
|
113
128
|
|
114
129
|
it "should fail to install plugin with bad dependencies" do
|
data/spec/spec_helper.rb
CHANGED
@@ -249,6 +249,44 @@ def git_create_conflict(git, project)
|
|
249
249
|
filename
|
250
250
|
end
|
251
251
|
|
252
|
+
def create_fake_gem(path)
|
253
|
+
mortar_fake_gem = <<-EOS
|
254
|
+
Gem::Specification.new do |s|
|
255
|
+
s.name = "mortar_fake_gem"
|
256
|
+
s.version = "0.0.1"
|
257
|
+
s.summary = "mortar_fake_gem is the best"
|
258
|
+
s.files = [
|
259
|
+
"lib/mortar_fake_gem.rb"
|
260
|
+
]
|
261
|
+
s.require_paths = ["lib"]
|
262
|
+
end
|
263
|
+
EOS
|
264
|
+
|
265
|
+
mortar_fake_gem_rb = <<-EOS
|
266
|
+
module MortarFakeGem
|
267
|
+
class WhoIs
|
268
|
+
def self.awesome?
|
269
|
+
return true
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
EOS
|
274
|
+
|
275
|
+
files = {
|
276
|
+
"mortar_fake_gem.gemspec" => mortar_fake_gem,
|
277
|
+
"lib/mortar_fake_gem.rb" => mortar_fake_gem_rb,
|
278
|
+
}
|
279
|
+
|
280
|
+
FileUtils.mkdir_p(File.join(path, "mortar_fake_gem/lib"))
|
281
|
+
files.each { |file_name, contents|
|
282
|
+
File.open(File.join(path, "/mortar_fake_gem/#{file_name}"), 'w') do |f|
|
283
|
+
f.puts contents
|
284
|
+
end
|
285
|
+
}
|
286
|
+
|
287
|
+
return File.join(path, "mortar_fake_gem")
|
288
|
+
|
289
|
+
end
|
252
290
|
|
253
291
|
def git_add_file(git, project)
|
254
292
|
# add a new file
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mortar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 2
|
10
|
+
version: 0.9.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mortar Data
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-07-
|
18
|
+
date: 2013-07-16 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: mortar-api-ruby
|
@@ -210,12 +210,16 @@ files:
|
|
210
210
|
- lib/mortar/templates/pigscript/python_udf.py
|
211
211
|
- lib/mortar/templates/project/README.md
|
212
212
|
- lib/mortar/templates/project/controlscripts/lib/__init__.py
|
213
|
+
- lib/mortar/templates/project/controlscripts/lib/characterize_control.py
|
213
214
|
- lib/mortar/templates/project/fixtures/gitkeep
|
214
215
|
- lib/mortar/templates/project/gitignore
|
216
|
+
- lib/mortar/templates/project/macros/characterize_macro.pig
|
215
217
|
- lib/mortar/templates/project/macros/gitkeep
|
218
|
+
- lib/mortar/templates/project/pigscripts/characterize.pig
|
216
219
|
- lib/mortar/templates/project/pigscripts/pigscript.pig
|
217
220
|
- lib/mortar/templates/project/udfs/java/gitkeep
|
218
221
|
- lib/mortar/templates/project/udfs/jython/gitkeep
|
222
|
+
- lib/mortar/templates/project/udfs/jython/top_5_tuple.py
|
219
223
|
- lib/mortar/templates/project/udfs/python/python_udf.py
|
220
224
|
- lib/mortar/templates/project/vendor/controlscripts/lib/__init__.py
|
221
225
|
- lib/mortar/templates/project/vendor/macros/gitkeep
|
@@ -289,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
289
293
|
requirements: []
|
290
294
|
|
291
295
|
rubyforge_project:
|
292
|
-
rubygems_version: 1.8.
|
296
|
+
rubygems_version: 1.8.25
|
293
297
|
signing_key:
|
294
298
|
specification_version: 3
|
295
299
|
summary: Client library and CLI to interact with the Mortar service.
|