mortar 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|