mortar 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 copy of the git directory
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(Dir.glob('*', File::FNM_DOTMATCH) - ['.', '..'], tmpdir)
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
- # commit the changes if there are any
148
- if ! is_clean_working_directory?
149
- git("commit -a -m \"mortar development snapshot commit\"")
150
- end
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
- # rebuild the original state of the working set
158
- if did_stash_changes
159
- git("stash pop stash@{0}")
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
- push(project.remote, snapshot_branch)
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 and clean out the branch from the local branches
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
- ensure_local_install_dir_in_gitignore
95
+ ensure_local_install_dirs_in_gitignore
96
96
  end
97
97
 
98
- def ensure_local_install_dir_in_gitignore()
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
- unless gitignore.read().include? local_install_directory_name
102
- gitignore.seek(0, IO::SEEK_END)
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 local_pig_logfile
46
- project_root + "/local-pig.log"
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
@@ -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
- delete_local_log_file
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 delete_local_log_file
259
- if File.exists? local_pig_logfile
260
- FileUtils.rm local_pig_logfile
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'] = local_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
@@ -3,5 +3,6 @@ Gemfile.lock
3
3
  *.class
4
4
  *.log
5
5
  tmp
6
- log
7
6
  .mortar-local
7
+ logs
8
+ illustrate-output
@@ -16,5 +16,5 @@
16
16
 
17
17
  module Mortar
18
18
  # see http://semver.org/
19
- VERSION = "0.7.5"
19
+ VERSION = "0.7.6"
20
20
  end
@@ -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).ensure_local_install_dir_in_gitignore.returns(true)
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 == ""
@@ -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
@@ -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
- write_file(File.join(project.root_path, "README.txt"), "Some README text")
195
+ git = Mortar::Git::Git.new
196
+ git.create_mortar_project_manifest(project.root_path)
197
+
192
198
  remote = "mortar"
193
- `git add README.txt`
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: 9
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 7
9
- - 5
10
- version: 0.7.5
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 00:00:00 Z
18
+ date: 2013-04-23 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mortar-api-ruby