mortar 0.7.5 → 0.7.6
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/git.rb +77 -34
- data/lib/mortar/local/controller.rb +19 -5
- data/lib/mortar/local/installutil.rb +6 -2
- data/lib/mortar/local/pig.rb +8 -5
- data/lib/mortar/templates/project/gitignore +2 -1
- data/lib/mortar/version.rb +1 -1
- data/spec/mortar/command/local_spec.rb +1 -1
- data/spec/mortar/git_spec.rb +20 -0
- data/spec/spec_helper.rb +15 -4
- metadata +4 -4
data/lib/mortar/git.rb
CHANGED
@@ -87,7 +87,7 @@ module Mortar
|
|
87
87
|
raise GitError, "No commits found in repository. You must do an initial commit to initialize the repository."
|
88
88
|
end
|
89
89
|
|
90
|
-
safe_copy do
|
90
|
+
safe_copy(mortar_snapshot_pathlist) do
|
91
91
|
did_stash_changes = stash_working_dir("Stash for push to master")
|
92
92
|
git('push mortar master')
|
93
93
|
end
|
@@ -95,14 +95,14 @@ module Mortar
|
|
95
95
|
end
|
96
96
|
|
97
97
|
#
|
98
|
-
# Create a safe
|
98
|
+
# Create a safe temporary directory with a given list of filesystem paths (files or dirs) copied into it
|
99
99
|
#
|
100
100
|
|
101
|
-
def safe_copy(&block)
|
101
|
+
def safe_copy(pathlist, &block)
|
102
102
|
# Copy code into a temp directory so we don't confuse editors while snapshotting
|
103
103
|
curdir = Dir.pwd
|
104
104
|
tmpdir = Dir.mktmpdir
|
105
|
-
FileUtils.cp_r(
|
105
|
+
FileUtils.cp_r(pathlist, tmpdir)
|
106
106
|
Dir.chdir(tmpdir)
|
107
107
|
|
108
108
|
if block
|
@@ -113,51 +113,77 @@ module Mortar
|
|
113
113
|
return tmpdir
|
114
114
|
end
|
115
115
|
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Only snapshot filesystem paths that are in a whitelist
|
119
|
+
#
|
120
|
+
|
121
|
+
def mortar_snapshot_pathlist()
|
122
|
+
ensure_mortar_project_manifest_exists()
|
123
|
+
|
124
|
+
snapshot_pathlist = File.read('.mortar-project-manifest').split("\n")
|
125
|
+
snapshot_pathlist << ".git"
|
126
|
+
|
127
|
+
snapshot_pathlist.each do |path|
|
128
|
+
unless File.exists? path
|
129
|
+
Helpers.error(".mortar-project-manifest includes file/dir \"#{path}\" that is not in the mortar project directory.")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
snapshot_pathlist
|
134
|
+
end
|
135
|
+
|
136
|
+
#
|
137
|
+
# Create a snapshot whitelist file if it doesn't already exist
|
138
|
+
#
|
139
|
+
def ensure_mortar_project_manifest_exists()
|
140
|
+
unless File.exists? '.mortar-project-manifest'
|
141
|
+
create_mortar_project_manifest('.')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Create a project manifest file
|
147
|
+
#
|
148
|
+
def create_mortar_project_manifest(path)
|
149
|
+
File.open("#{path}/.mortar-project-manifest", 'w') do |manifest|
|
150
|
+
if File.directory? "#{path}/controlscripts"
|
151
|
+
manifest.puts "controlscripts"
|
152
|
+
end
|
153
|
+
if File.directory? "#{path}/fixtures"
|
154
|
+
manifest.puts "fixtures"
|
155
|
+
end
|
156
|
+
manifest.puts "pigscripts"
|
157
|
+
manifest.puts "macros"
|
158
|
+
manifest.puts "udfs"
|
159
|
+
end
|
160
|
+
end
|
116
161
|
|
117
162
|
#
|
118
163
|
# snapshot
|
119
164
|
#
|
120
165
|
|
121
166
|
def create_snapshot_branch
|
122
|
-
|
123
167
|
# TODO: handle Ctrl-C in the middle
|
124
|
-
# TODO: can we do the equivalent of stash without changing the working directory
|
125
168
|
unless has_commits?
|
126
169
|
raise GitError, "No commits found in repository. You must do an initial commit to initialize the repository."
|
127
170
|
end
|
128
171
|
|
129
172
|
# Copy code into a temp directory so we don't confuse editors while snapshotting
|
130
173
|
curdir = Dir.pwd
|
131
|
-
tmpdir = safe_copy
|
174
|
+
tmpdir = safe_copy(mortar_snapshot_pathlist)
|
132
175
|
|
133
176
|
starting_branch = current_branch
|
134
177
|
snapshot_branch = "mortar-snapshot-#{Mortar::UUID.create_random.to_s}"
|
135
|
-
did_stash_changes = stash_working_dir(snapshot_branch)
|
136
|
-
begin
|
137
|
-
# checkout a new branch
|
138
|
-
git("checkout -b #{snapshot_branch}")
|
139
|
-
|
140
|
-
if did_stash_changes
|
141
|
-
# apply the topmost stash that we just created
|
142
|
-
git("stash apply stash@{0}")
|
143
|
-
end
|
144
|
-
|
145
|
-
add_untracked_files()
|
146
178
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
ensure
|
153
|
-
|
154
|
-
# return to the starting branch
|
155
|
-
git("checkout #{starting_branch}")
|
179
|
+
# checkout a new branch
|
180
|
+
git("checkout -b #{snapshot_branch}")
|
181
|
+
|
182
|
+
add_untracked_files()
|
156
183
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
184
|
+
# commit the changes if there are any
|
185
|
+
if ! is_clean_working_directory?
|
186
|
+
git("commit -a -m \"mortar development snapshot commit\"")
|
161
187
|
end
|
162
188
|
|
163
189
|
Dir.chdir(curdir)
|
@@ -176,11 +202,15 @@ module Mortar
|
|
176
202
|
|
177
203
|
git_ref = Helpers.action("Sending code snapshot to Mortar") do
|
178
204
|
# push the code
|
179
|
-
|
205
|
+
begin
|
206
|
+
push(project.remote, snapshot_branch)
|
207
|
+
rescue
|
208
|
+
retry if retry_snapshot_push?
|
209
|
+
Helpers.error("Could not connect to github remote. Tried #{@snapshot_push_attempts.to_s} times.")
|
210
|
+
end
|
180
211
|
|
181
|
-
# grab the commit hash
|
212
|
+
# grab the commit hash
|
182
213
|
ref = git_ref(snapshot_branch)
|
183
|
-
branch_delete(snapshot_branch)
|
184
214
|
ref
|
185
215
|
end
|
186
216
|
|
@@ -189,6 +219,19 @@ module Mortar
|
|
189
219
|
return git_ref
|
190
220
|
end
|
191
221
|
|
222
|
+
def retry_snapshot_push?
|
223
|
+
@last_snapshot_retry_sleep_time ||= 0
|
224
|
+
@snapshot_retry_sleep_time ||= 1
|
225
|
+
|
226
|
+
sleep(@snapshot_retry_sleep_time)
|
227
|
+
@last_snapshot_retry_sleep_time, @snapshot_retry_sleep_time =
|
228
|
+
@snapshot_retry_sleep_time, @last_snapshot_retry_sleep_time + @snapshot_retry_sleep_time
|
229
|
+
|
230
|
+
@snapshot_push_attempts ||= 0
|
231
|
+
@snapshot_push_attempts += 1
|
232
|
+
@snapshot_push_attempts < 10
|
233
|
+
end
|
234
|
+
|
192
235
|
#
|
193
236
|
# add
|
194
237
|
#
|
@@ -92,16 +92,30 @@ EOF
|
|
92
92
|
jy = Mortar::Local::Jython.new()
|
93
93
|
jy.install_or_update()
|
94
94
|
|
95
|
-
|
95
|
+
ensure_local_install_dirs_in_gitignore
|
96
96
|
end
|
97
97
|
|
98
|
-
def
|
98
|
+
def ensure_local_install_dirs_in_gitignore()
|
99
99
|
if File.exists? local_project_gitignore
|
100
|
-
open(local_project_gitignore, 'r+') do |gitignore|
|
101
|
-
|
102
|
-
|
100
|
+
File.open(local_project_gitignore, 'r+') do |gitignore|
|
101
|
+
contents = gitignore.read()
|
102
|
+
gitignore.seek(0, IO::SEEK_END)
|
103
|
+
|
104
|
+
unless contents[-1] == "\n"
|
105
|
+
gitignore.puts "" # write a newline
|
106
|
+
end
|
107
|
+
|
108
|
+
unless contents.include? local_install_directory_name
|
103
109
|
gitignore.puts local_install_directory_name
|
104
110
|
end
|
111
|
+
|
112
|
+
unless contents.include? "logs"
|
113
|
+
gitignore.puts "logs"
|
114
|
+
end
|
115
|
+
|
116
|
+
unless contents.include? "illustrate-output"
|
117
|
+
gitignore.puts "illustrate-output"
|
118
|
+
end
|
105
119
|
end
|
106
120
|
end
|
107
121
|
end
|
@@ -42,8 +42,12 @@ module Mortar
|
|
42
42
|
File.join(project_root, local_install_directory_name)
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
project_root + "/
|
45
|
+
def local_log_dir
|
46
|
+
project_root + "/logs"
|
47
|
+
end
|
48
|
+
|
49
|
+
def local_udf_log_dir
|
50
|
+
local_log_dir + "/udf"
|
47
51
|
end
|
48
52
|
|
49
53
|
def local_project_gitignore
|
data/lib/mortar/local/pig.rb
CHANGED
@@ -235,7 +235,7 @@ class Mortar::Local::Pig
|
|
235
235
|
# get it to do something interesting, such as '-f some-file.pig'
|
236
236
|
def run_pig_command(cmd, parameters = nil, jython_output = true)
|
237
237
|
unset_hadoop_env_vars
|
238
|
-
|
238
|
+
reset_local_logs
|
239
239
|
# Generate the script for running the command, then
|
240
240
|
# write it to a temp script which will be exectued
|
241
241
|
script_text = script_for_command(cmd, parameters)
|
@@ -255,10 +255,12 @@ class Mortar::Local::Pig
|
|
255
255
|
ENV['HADOOP_CONF_DIR'] = ''
|
256
256
|
end
|
257
257
|
|
258
|
-
def
|
259
|
-
if
|
260
|
-
FileUtils.
|
258
|
+
def reset_local_logs
|
259
|
+
if Dir.exists? local_log_dir
|
260
|
+
FileUtils.rm_rf local_log_dir
|
261
261
|
end
|
262
|
+
Dir.mkdir local_log_dir
|
263
|
+
Dir.mkdir local_udf_log_dir
|
262
264
|
end
|
263
265
|
|
264
266
|
# Generates a bash script which sets up the necessary environment and
|
@@ -298,7 +300,8 @@ class Mortar::Local::Pig
|
|
298
300
|
opts['fs.s3.awsAccessKeyId'] = ENV['AWS_ACCESS_KEY']
|
299
301
|
opts['fs.s3.awsSecretAccessKey'] = ENV['AWS_SECRET_KEY']
|
300
302
|
opts['pig.events.logformat'] = PIG_LOG_FORMAT
|
301
|
-
opts['pig.logfile'] =
|
303
|
+
opts['pig.logfile'] = local_log_dir + "/local-pig.log"
|
304
|
+
opts['pig.udf.scripting.log.dir'] = local_udf_log_dir
|
302
305
|
opts['python.verbose'] = 'error'
|
303
306
|
opts['jython.output'] = true
|
304
307
|
opts['python.home'] = jython_directory
|
data/lib/mortar/version.rb
CHANGED
@@ -145,7 +145,7 @@ STDERR
|
|
145
145
|
mock(j).install_or_update.returns(true)
|
146
146
|
end
|
147
147
|
any_instance_of(Mortar::Local::Controller) do |j|
|
148
|
-
mock(j).
|
148
|
+
mock(j).ensure_local_install_dirs_in_gitignore.returns(true)
|
149
149
|
end
|
150
150
|
stderr, stdout = execute("local:configure")
|
151
151
|
stderr.should == ""
|
data/spec/mortar/git_spec.rb
CHANGED
@@ -16,8 +16,10 @@
|
|
16
16
|
|
17
17
|
require "spec_helper"
|
18
18
|
require "mortar/git"
|
19
|
+
require "mortar/helpers"
|
19
20
|
|
20
21
|
module Mortar
|
22
|
+
|
21
23
|
describe Git do
|
22
24
|
|
23
25
|
before do
|
@@ -280,6 +282,24 @@ STASH
|
|
280
282
|
end
|
281
283
|
end
|
282
284
|
|
285
|
+
it "retries pushing the snapshot branch if there is a socket error" do
|
286
|
+
with_git_initialized_project do |p|
|
287
|
+
# RR seems to only count a method as being called if it completes
|
288
|
+
# So we expect "never", even though it's actually tried N times (tested below)
|
289
|
+
mock(@git).push.never { raise Exception.new }
|
290
|
+
mock(@git).sleep.times(10).with_any_args
|
291
|
+
|
292
|
+
original_stdin, original_stderr, original_stdout = $stdin, $stderr, $stdout
|
293
|
+
$stdin, $stderr, $stdout = StringIO.new, StringIO.new, StringIO.new
|
294
|
+
|
295
|
+
begin
|
296
|
+
@git.create_and_push_snapshot_branch(p)
|
297
|
+
rescue SystemExit
|
298
|
+
ensure
|
299
|
+
$stdin, $stderr, $stdout = original_stdin, original_stderr, original_stdout
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
283
303
|
end
|
284
304
|
|
285
305
|
=begin
|
data/spec/spec_helper.rb
CHANGED
@@ -30,6 +30,7 @@ Excon.defaults[:mock] = true
|
|
30
30
|
require "mortar-api-ruby"
|
31
31
|
|
32
32
|
require "mortar/cli"
|
33
|
+
require "mortar/git"
|
33
34
|
require "rspec"
|
34
35
|
require "rr"
|
35
36
|
require "fakefs/safe"
|
@@ -163,6 +164,9 @@ def with_blank_project(&block)
|
|
163
164
|
FileUtils.mkdir_p(File.join(project_path, "controlscripts"))
|
164
165
|
FileUtils.mkdir_p(File.join(project_path, "pigscripts"))
|
165
166
|
FileUtils.mkdir_p(File.join(project_path, "macros"))
|
167
|
+
FileUtils.mkdir_p(File.join(project_path, "udfs"))
|
168
|
+
FileUtils.mkdir_p(File.join(project_path, "udfs/python"))
|
169
|
+
FileUtils.mkdir_p(File.join(project_path, "udfs/jython"))
|
166
170
|
|
167
171
|
Dir.chdir(project_path)
|
168
172
|
|
@@ -188,9 +192,11 @@ end
|
|
188
192
|
def with_git_initialized_project(&block)
|
189
193
|
# wrap block in a proc that does a commit
|
190
194
|
commit_proc = Proc.new do |project|
|
191
|
-
|
195
|
+
git = Mortar::Git::Git.new
|
196
|
+
git.create_mortar_project_manifest(project.root_path)
|
197
|
+
|
192
198
|
remote = "mortar"
|
193
|
-
`git add
|
199
|
+
`git add .mortar-project-manifest`
|
194
200
|
`git commit -a -m "First commit"`
|
195
201
|
`git remote add #{remote} git@github.com:mortarcode-dev/4dbbd83cae8d5bf8a4000000_#{project.name}.git`
|
196
202
|
project.remote = remote
|
@@ -269,10 +275,15 @@ def create_and_validate_git_snapshot(git)
|
|
269
275
|
# ensure the snapshot branch exists
|
270
276
|
git.git("branch").include?(snapshot_branch).should be_true
|
271
277
|
|
278
|
+
snapshotted_paths = Dir.glob("**/*")
|
279
|
+
snapshotted_paths.should include("controlscripts")
|
280
|
+
snapshotted_paths.should include("pigscripts")
|
281
|
+
snapshotted_paths.should include("macros")
|
282
|
+
snapshotted_paths.should include("udfs/python")
|
283
|
+
snapshotted_paths.should include("udfs/jython")
|
284
|
+
|
272
285
|
Dir.chdir(curdir)
|
273
286
|
FileUtils.remove_entry_secure(snapshot_dir)
|
274
|
-
|
275
|
-
git.branches.should == initial_git_branches
|
276
287
|
end
|
277
288
|
|
278
289
|
require "mortar/helpers"
|
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: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 6
|
10
|
+
version: 0.7.6
|
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-04-
|
18
|
+
date: 2013-04-23 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: mortar-api-ruby
|