git-fastclone 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e6bcf21a8d3b9c1b30b93efc17487fa8dfa0c319b8636efc1f96a430e27c876
4
- data.tar.gz: 7720184507344bc94ad63e45b135e0948aab6776d371867159a4cd84dcfd2a0d
3
+ metadata.gz: d83fead53c699b625667b994e06ab9cfe0c25ed62c01239c054ec1523109f986
4
+ data.tar.gz: 9e4513fe51d1e1deb357a1781fadd1df723997df527402c12beb436103ce7b2a
5
5
  SHA512:
6
- metadata.gz: 13e48d37e5162a8288da830232476fb12ba7b8bb01c0ef0834a8eb372a224c0a2f8430d10002a9c54c1ec7fc7713db384ef32d0da9f1707366663bbe10e9ff04
7
- data.tar.gz: 1f74af758cfbd3f47f98f6d4fc1a47e24bf574f9e7b58116b9aa3f6186ab334e66c66e413416641b7ce6494b3099b45158142fbd88b4c1bb3a0bb48a86c9b912
6
+ metadata.gz: ecc286e3180698eab52e06e61d3bf62c27af6524a3ab398d86cf1bbbe336dd9c547609ec6744264be506ea9f41920cf68210b08d6fad752f5d8fc589b069e2be
7
+ data.tar.gz: 653a21b17f4a033ee23bd77f1953a72df9176006ebb320a33ed179e4f7f2a957133a4569f1d91722c65d2d638ee727eae15d41b6b73f5b133d138823365e6937
data/README.md CHANGED
@@ -44,8 +44,10 @@ Usage
44
44
  git fastclone [options] <git-repo-url>
45
45
 
46
46
  -b, --branch <branch> Clone a specific branch
47
- -v, --verbose Shows more info
48
- -c, --color Pretty colors!
47
+ -v, --verbose Verbose mode
48
+ -c, --color Display colored output
49
+ --config CONFIG Git config applied to the cloned repo
50
+ --lock-timeout N Timeout in seconds to acquire a lock on any reference repo.
49
51
 
50
52
  Change the default `REFERENCE_REPO_DIR` environment variable if necessary.
51
53
 
data/bin/git-fastclone CHANGED
@@ -15,7 +15,7 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
18
+ $LOAD_PATH.unshift(File.expand_path("#{File.dirname(__FILE__)}/../lib"))
19
19
 
20
20
  require 'git-fastclone'
21
21
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version string for git-fastclone
4
4
  module GitFastCloneVersion
5
- VERSION = '1.3.0'.freeze
5
+ VERSION = '1.3.1'
6
6
  end
data/lib/git-fastclone.rb CHANGED
@@ -41,7 +41,7 @@ module GitFastClone
41
41
 
42
42
  def reference_repo_dir(url, reference_dir, using_local_repo)
43
43
  if using_local_repo
44
- File.join(reference_dir, 'local' + reference_repo_name(url))
44
+ File.join(reference_dir, "local#{reference_repo_name(url)}")
45
45
  else
46
46
  File.join(reference_dir, reference_repo_name(url))
47
47
  end
@@ -69,9 +69,9 @@ module GitFastClone
69
69
 
70
70
  include GitFastClone::UrlHelper
71
71
 
72
- DEFAULT_REFERENCE_REPO_DIR = '/var/tmp/git-fastclone/reference'.freeze
72
+ DEFAULT_REFERENCE_REPO_DIR = '/var/tmp/git-fastclone/reference'
73
73
 
74
- DEFAULT_GIT_ALLOW_PROTOCOL = 'file:git:http:https:ssh'.freeze
74
+ DEFAULT_GIT_ALLOW_PROTOCOL = 'file:git:http:https:ssh'
75
75
 
76
76
  attr_accessor :reference_dir, :prefetch_submodules, :reference_updated, :reference_mutex,
77
77
  :options, :logger, :abs_clone_path, :using_local_repo, :verbose, :color,
@@ -137,7 +137,7 @@ module GitFastClone
137
137
 
138
138
  opts.on('-v', '--verbose', 'Verbose mode') do
139
139
  self.verbose = true
140
- self.logger = Logger.new(STDOUT)
140
+ self.logger = Logger.new($stdout)
141
141
  logger.formatter = proc do |_severity, _datetime, _progname, msg|
142
142
  "#{msg}\n"
143
143
  end
@@ -163,7 +163,7 @@ module GitFastClone
163
163
  parse_options
164
164
 
165
165
  unless ARGV[0]
166
- STDERR.puts usage
166
+ warn usage
167
167
  exit(129)
168
168
  end
169
169
 
@@ -189,18 +189,40 @@ module GitFastClone
189
189
  [url, path, options]
190
190
  end
191
191
 
192
+ def clear_clone_dest_if_needed(attempt_number, clone_dest)
193
+ return unless attempt_number.positive?
194
+
195
+ dest_with_dotfiles = Dir.glob("#{clone_dest}/*", File::FNM_DOTMATCH)
196
+ dest_files = dest_with_dotfiles.reject { |f| %w[. ..].include?(File.basename(f)) }
197
+ return if dest_files.empty?
198
+
199
+ clear_clone_dest(dest_files)
200
+ end
201
+
202
+ def clear_clone_dest(dest_files)
203
+ puts 'Non-empty clone directory found, clearing its content now.'
204
+ FileUtils.rm_rf(dest_files)
205
+ end
206
+
192
207
  # Checkout to SOURCE_DIR. Update all submodules recursively. Use reference
193
208
  # repos everywhere for speed.
194
209
  def clone(url, rev, src_dir, config)
210
+ clone_dest = File.join(abs_clone_path, src_dir).to_s
195
211
  initial_time = Time.now
196
212
 
197
- with_git_mirror(url) do |mirror|
213
+ if Dir.exist?(clone_dest) && !Dir.empty?(clone_dest)
214
+ raise "Can't clone into an existing non-empty path: #{clone_dest}"
215
+ end
216
+
217
+ with_git_mirror(url) do |mirror, attempt_number|
218
+ clear_clone_dest_if_needed(attempt_number, clone_dest)
219
+
198
220
  clone_command = '--quiet --reference :mirror :url :path'
199
221
  clone_command += ' --config :config' unless config.nil?
200
222
  Terrapin::CommandLine.new('git clone', clone_command)
201
223
  .run(mirror: mirror.to_s,
202
224
  url: url.to_s,
203
- path: File.join(abs_clone_path, src_dir).to_s,
225
+ path: clone_dest,
204
226
  config: config.to_s)
205
227
  end
206
228
 
@@ -245,7 +267,7 @@ module GitFastClone
245
267
 
246
268
  def thread_update_submodule(submodule_url, submodule_path, threads, pwd)
247
269
  threads << Thread.new do
248
- with_git_mirror(submodule_url) do |mirror|
270
+ with_git_mirror(submodule_url) do |mirror, _|
249
271
  Terrapin::CommandLine.new('cd', ':dir; git submodule update --quiet --reference :mirror :path')
250
272
  .run(dir: File.join(abs_clone_path, pwd).to_s,
251
273
  mirror: mirror.to_s,
@@ -270,14 +292,12 @@ module GitFastClone
270
292
  lockfile.close
271
293
  end
272
294
 
273
- def with_reference_repo_thread_lock(url)
295
+ def with_reference_repo_thread_lock(url, &block)
274
296
  # We also need thread level locking because pre-fetch means multiple threads can
275
297
  # attempt to update the same repository from a single git-fastclone process
276
298
  # file locks in posix are tracked per process, not per userland thread.
277
299
  # This gives us the equivalent of pthread_mutex around these accesses.
278
- reference_mutex[reference_repo_name(url)].synchronize do
279
- yield
280
- end
300
+ reference_mutex[reference_repo_name(url)].synchronize(&block)
281
301
  end
282
302
 
283
303
  def update_submodule_reference(url, submodule_url_list)
@@ -338,6 +358,31 @@ module GitFastClone
338
358
  raise e if fail_hard
339
359
  end
340
360
 
361
+ def retriable_error?(error)
362
+ error_strings = [
363
+ 'fatal: missing blob object',
364
+ 'fatal: remote did not send all necessary objects',
365
+ /fatal: packed object [a-z0-9]+ \(stored in .*?\) is corrupt/,
366
+ /fatal: pack has \d+ unresolved delta/,
367
+ 'error: unable to read sha1 file of ',
368
+ 'fatal: did not receive expected object',
369
+ /^fatal: unable to read tree [a-z0-9]+\n^warning: Clone succeeded, but checkout failed/
370
+ ]
371
+ error.to_s =~ /^STDERR:\n.*^#{Regexp.union(error_strings)}/m
372
+ end
373
+
374
+ def print_formatted_error(error)
375
+ indented_error = error.to_s.split("\n").map { |s| "> #{s}\n" }.join
376
+ puts "Encountered a retriable error:\n#{indented_error}\n\nRemoving the fastclone cache."
377
+ end
378
+
379
+ # To avoid corruption of the cache, if we failed to update or check out we remove
380
+ # the cache directory entirely. This may cause the current clone to fail, but if the
381
+ # underlying error from git is transient it will not affect future clones.
382
+ def clear_cache(dir)
383
+ FileUtils.remove_entry_secure(dir, force: true)
384
+ end
385
+
341
386
  # This command will create and bring the mirror up-to-date on-demand,
342
387
  # blocking any code passed in while the mirror is brought up-to-date
343
388
  #
@@ -354,27 +399,18 @@ module GitFastClone
354
399
  # This makes sure we have control and unlock when the block returns:
355
400
  with_reference_repo_lock(url) do
356
401
  dir = reference_repo_dir(url, reference_dir, using_local_repo)
357
- retries_left = 1
402
+ retries_allowed = 1
403
+ attempt_number = 0
358
404
 
359
405
  begin
360
- yield dir
406
+ yield dir, attempt_number
361
407
  rescue Terrapin::ExitStatusError => e
362
- error_strings = [
363
- 'fatal: missing blob object',
364
- 'fatal: remote did not send all necessary objects',
365
- /fatal: packed object [a-z0-9]+ \(stored in .*?\) is corrupt/,
366
- /fatal: pack has \d+ unresolved delta/,
367
- 'error: unable to read sha1 file of ',
368
- 'fatal: did not receive expected object',
369
- /^fatal: unable to read tree [a-z0-9]+\n^warning: Clone succeeded, but checkout failed/
370
- ]
371
- if e.to_s =~ /^STDERR:\n.+^#{Regexp.union(error_strings)}/m
372
- # To avoid corruption of the cache, if we failed to update or check out we remove
373
- # the cache directory entirely. This may cause the current clone to fail, but if the
374
- # underlying error from git is transient it will not affect future clones.
375
- FileUtils.remove_entry_secure(dir, force: true)
376
- if retries_left > 0
377
- retries_left -= 1
408
+ if retriable_error?(e)
409
+ print_formatted_error(e)
410
+ clear_cache(dir)
411
+
412
+ if attempt_number < retries_allowed
413
+ attempt_number += 1
378
414
  retry
379
415
  end
380
416
  end
@@ -91,7 +91,8 @@ describe GitFastClone::Runner do
91
91
  expect(Time).to receive(:now).twice { 0 }
92
92
  allow(Dir).to receive(:pwd) { '/pwd' }
93
93
  allow(Dir).to receive(:chdir).and_yield
94
- allow(subject).to receive(:with_git_mirror).and_yield('/cache')
94
+ allow(subject).to receive(:with_git_mirror).and_yield('/cache', 0)
95
+ expect(subject).to receive(:clear_clone_dest_if_needed).once {}
95
96
  end
96
97
 
97
98
  it 'should clone correctly' do
@@ -114,21 +115,39 @@ describe GitFastClone::Runner do
114
115
  subject.clone(placeholder_arg, placeholder_arg, '.', nil)
115
116
  end
116
117
 
117
- describe 'with custom configs' do
118
- it 'should clone correctly' do
119
- expect(Terrapin::CommandLine).to receive(:new).with(
120
- 'git clone',
121
- '--quiet --reference :mirror :url :path --config :config'
122
- ) { terrapin_commandline_double }
123
- expect(terrapin_commandline_double).to receive(:run).with(
124
- mirror: '/cache',
125
- url: placeholder_arg,
126
- path: '/pwd/.',
127
- config: 'config'
128
- )
129
-
130
- subject.clone(placeholder_arg, nil, '.', 'config')
131
- end
118
+ it 'should clone correctly with custom configs' do
119
+ expect(Terrapin::CommandLine).to receive(:new).with(
120
+ 'git clone',
121
+ '--quiet --reference :mirror :url :path --config :config'
122
+ ) { terrapin_commandline_double }
123
+ expect(terrapin_commandline_double).to receive(:run).with(
124
+ mirror: '/cache',
125
+ url: placeholder_arg,
126
+ path: '/pwd/.',
127
+ config: 'config'
128
+ )
129
+
130
+ subject.clone(placeholder_arg, nil, '.', 'config')
131
+ end
132
+ end
133
+
134
+ describe '.clear_clone_dest_if_needed' do
135
+ it 'does not clear on first attempt' do
136
+ expect(Dir).not_to receive(:glob)
137
+ expect(subject).not_to receive(:clear_clone_dest)
138
+ subject.clear_clone_dest_if_needed(0, '/some/path')
139
+ end
140
+
141
+ it 'does not clear if the directory is only FNM_DOTMATCH self and parent refs' do
142
+ expect(Dir).to receive(:glob).and_return(%w[. ..])
143
+ expect(subject).not_to receive(:clear_clone_dest)
144
+ subject.clear_clone_dest_if_needed(1, '/some/path')
145
+ end
146
+
147
+ it 'does clear if the directory is not empty' do
148
+ expect(Dir).to receive(:glob).and_return(%w[. .. /some/path/file.txt])
149
+ expect(subject).to receive(:clear_clone_dest) {}
150
+ subject.clear_clone_dest_if_needed(1, '/some/path')
132
151
  end
133
152
  end
134
153
 
@@ -312,209 +331,154 @@ describe GitFastClone::Runner do
312
331
  end
313
332
 
314
333
  describe '.with_git_mirror' do
315
- it 'should yield properly' do
334
+ before(:each) do
316
335
  allow(subject).to receive(:update_reference_repo) {}
317
- expect(subject).to receive(:reference_repo_dir)
336
+ allow(subject).to receive(:print_formatted_error) {}
337
+ expect(subject).to receive(:reference_repo_dir).and_return(test_reference_repo_dir)
318
338
  expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
339
+ end
319
340
 
320
- subject.with_git_mirror(test_url_valid) do
321
- yielded << test_url_valid
322
- end
341
+ def retriable_error
342
+ %(
343
+ STDOUT:
323
344
 
324
- expect(yielded).to eq([test_url_valid])
345
+ STDERR:
346
+
347
+ fatal: bad object ee35b1e14e7c3a53dcc14d82606e5b872f6a05a7
348
+ fatal: remote did not send all necessary objects
349
+ ).strip.split("\n").map(&:strip).join("\n")
325
350
  end
326
351
 
327
- it 'should retry when the cache looks corrupted' do
328
- allow(subject).to receive(:update_reference_repo) {}
329
- expect(subject).to receive(:reference_repo_dir)
330
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
352
+ def try_with_git_mirror(responses, results)
353
+ lambdas = responses.map do |response|
354
+ if response == true
355
+ # Simulate successful response
356
+ ->(url) { url }
357
+ else
358
+ # Simulate failed error response
359
+ ->(_url) { raise Terrapin::ExitStatusError, response }
360
+ end
361
+ end
331
362
 
332
- responses = [
333
- lambda { |_url|
334
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
335
- STDOUT:
336
-
337
- STDERR:
338
-
339
- fatal: bad object ee35b1e14e7c3a53dcc14d82606e5b872f6a05a7
340
- fatal: remote did not send all necessary objects
341
- ERROR
342
- },
343
- ->(url) { url }
344
- ]
345
- subject.with_git_mirror(test_url_valid) do
346
- yielded << responses.shift.call(test_url_valid)
363
+ subject.with_git_mirror(test_url_valid) do |url, attempt|
364
+ raise 'Not enough responses were provided!' if lambdas.empty?
365
+
366
+ yielded << [lambdas.shift.call(url), attempt]
347
367
  end
348
368
 
349
- expect(responses).to be_empty
350
- expect(yielded).to eq([test_url_valid])
369
+ expect(lambdas).to be_empty
370
+ expect(yielded).to eq(results)
351
371
  end
352
372
 
353
- it 'should retry when the clone succeeds but checkout fails with corrupt packed object' do
354
- allow(subject).to receive(:update_reference_repo) {}
355
- expect(subject).to receive(:reference_repo_dir)
356
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
357
-
358
- responses = [
359
- lambda { |_url|
360
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
361
- STDOUT:
362
-
363
- STDERR:
364
-
365
- fatal: packed object 7c4d79704f8adf701f38a7bfb3e33ec5342542f1 (stored in /private/var/tmp/git-fastclone/reference/some-repo.git/objects/pack/pack-d37d7ed3e88d6e5f0ac141a7b0a2b32baf6e21a0.pack) is corrupt
366
- warning: Clone succeeded, but checkout failed.
367
- You can inspect what was checked out with 'git status' and retry with 'git restore --source=HEAD :/'
368
- ERROR
369
- },
370
- ->(url) { url }
371
- ]
372
- subject.with_git_mirror(test_url_valid) do
373
- yielded << responses.shift.call(test_url_valid)
374
- end
373
+ it 'should yield properly' do
374
+ expect(subject).not_to receive(:clear_cache)
375
+ try_with_git_mirror([true], [[test_reference_repo_dir, 0]])
376
+ end
375
377
 
376
- expect(responses).to be_empty
377
- expect(yielded).to eq([test_url_valid])
378
+ it 'should retry once for retriable errors' do
379
+ expect(subject).to receive(:clear_cache).once {}
380
+ try_with_git_mirror([retriable_error, true], [[test_reference_repo_dir, 1]])
378
381
  end
379
382
 
380
- it 'should retry when the clone succeeds but checkout fails with unable to read tree' do
381
- allow(subject).to receive(:update_reference_repo) {}
382
- expect(subject).to receive(:reference_repo_dir)
383
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
383
+ it 'should only retry twice at most' do
384
+ expect(subject).to receive(:clear_cache).twice {}
385
+ expect do
386
+ try_with_git_mirror([retriable_error, retriable_error], [])
387
+ end.to raise_error(Terrapin::ExitStatusError)
388
+ end
384
389
 
385
- responses = [
386
- lambda { |_url|
387
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
388
- STDOUT:
389
-
390
- STDERR:
391
-
392
- error: Could not read 92cf57b8f07df010ab5f607b109c325e30e46235
393
- fatal: unable to read tree 0c32c0521d3b0bfb4e74e4a39b97a84d1a3bb9a1
394
- warning: Clone succeeded, but checkout failed.
395
- You can inspect what was checked out with 'git status'
396
- and retry with 'git restore --source=HEAD :/'
397
- ERROR
398
- },
399
- ->(url) { url }
400
- ]
401
- subject.with_git_mirror(test_url_valid) do
402
- yielded << responses.shift.call(test_url_valid)
403
- end
390
+ it 'should not retry for non-retriable errors' do
391
+ expect(subject).not_to receive(:clear_cache)
392
+ expect do
393
+ try_with_git_mirror(['Some unexpected error message'], [])
394
+ end.to raise_error(Terrapin::ExitStatusError)
395
+ end
396
+ end
404
397
 
405
- expect(responses).to be_empty
406
- expect(yielded).to eq([test_url_valid])
398
+ describe '.retriable_error?' do
399
+ def format_error(error)
400
+ error_wrapper = "STDOUT:\n\nSTDERR:\n#{error}"
401
+ error_wrapper.strip.lines.map(&:strip).join("\n")
407
402
  end
408
403
 
409
- it 'should retry when one delta is missing' do
410
- allow(subject).to receive(:update_reference_repo) {}
411
- expect(subject).to receive(:reference_repo_dir)
412
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
404
+ it 'not for a random error message' do
405
+ error = format_error 'random error message'
413
406
 
414
- responses = [
415
- lambda { |_url|
416
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
417
- STDOUT:
418
-
419
- STDERR:
420
-
421
- error: Could not read f7fad86d06fee0678f9af7203b6031feabb40c3e
422
- fatal: pack has 1 unresolved delta
423
- fatal: index-pack failed
424
- ERROR
425
- },
426
- ->(url) { url }
427
- ]
428
- subject.with_git_mirror(test_url_valid) do
429
- yielded << responses.shift.call(test_url_valid)
430
- end
407
+ expect(subject.retriable_error?(error)).to be_falsey
408
+ end
431
409
 
432
- expect(responses).to be_empty
433
- expect(yielded).to eq([test_url_valid])
410
+ it 'when the cache looks corrupted' do
411
+ error = format_error <<-ERROR
412
+ fatal: bad object ee35b1e14e7c3a53dcc14d82606e5b872f6a05a7
413
+ fatal: remote did not send all necessary objects
414
+ ERROR
415
+
416
+ expect(subject.retriable_error?(error)).to be_truthy
434
417
  end
435
418
 
436
- it 'should retry when deltas are missing' do
437
- allow(subject).to receive(:update_reference_repo) {}
438
- expect(subject).to receive(:reference_repo_dir)
439
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
419
+ it 'when the clone succeeds but checkout fails with corrupt packed object' do
420
+ error = format_error <<-ERROR
421
+ fatal: packed object 7c4d79704f8adf701f38a7bfb3e33ec5342542f1 (stored in /private/var/tmp/git-fastclone/reference/some-repo.git/objects/pack/pack-d37d7ed3e88d6e5f0ac141a7b0a2b32baf6e21a0.pack) is corrupt
422
+ warning: Clone succeeded, but checkout failed.
423
+ You can inspect what was checked out with 'git status' and retry with 'git restore --source=HEAD :/'
424
+ ERROR
440
425
 
441
- responses = [
442
- lambda { |_url|
443
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
444
- STDOUT:
445
-
446
- STDERR:
447
-
448
- error: Could not read f7fad86d06fee0678f9af7203b6031feabb40c3e
449
- fatal: pack has 138063 unresolved deltas
450
- fatal: index-pack failed
451
- ERROR
452
- },
453
- ->(url) { url }
454
- ]
455
- subject.with_git_mirror(test_url_valid) do
456
- yielded << responses.shift.call(test_url_valid)
457
- end
426
+ expect(subject.retriable_error?(error)).to be_truthy
427
+ end
458
428
 
459
- expect(responses).to be_empty
460
- expect(yielded).to eq([test_url_valid])
429
+ it 'when the clone succeeds but checkout fails with unable to read tree' do
430
+ error = format_error <<-ERROR
431
+ error: Could not read 92cf57b8f07df010ab5f607b109c325e30e46235
432
+ fatal: unable to read tree 0c32c0521d3b0bfb4e74e4a39b97a84d1a3bb9a1
433
+ warning: Clone succeeded, but checkout failed.
434
+ You can inspect what was checked out with 'git status'
435
+ and retry with 'git restore --source=HEAD :/'
436
+ ERROR
437
+
438
+ expect(subject.retriable_error?(error)).to be_truthy
461
439
  end
462
- end
463
440
 
464
- it 'should retry when the cache errors with unable to read sha1 file' do
465
- allow(subject).to receive(:update_reference_repo) {}
466
- expect(subject).to receive(:reference_repo_dir)
467
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
468
-
469
- responses = [
470
- lambda { |_url|
471
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
472
- STDOUT:
473
-
474
- STDERR:
475
-
476
- error: unable to read sha1 file of sqiosbuild/lib/action/action.rb (6113b739af82d8b07731de8a58d6e233301f80ab)
477
- fatal: unable to checkout working tree
478
- warning: Clone succeeded, but checkout failed.
479
- You can inspect what was checked out with 'git status'
480
- and retry with 'git restore --source=HEAD :/'
481
- ERROR
482
- },
483
- ->(url) { url }
484
- ]
485
- subject.with_git_mirror(test_url_valid) do
486
- yielded << responses.shift.call(test_url_valid)
487
- end
488
-
489
- expect(responses).to be_empty
490
- expect(yielded).to eq([test_url_valid])
491
- end
441
+ it 'when one delta is missing' do
442
+ error = format_error <<-ERROR
443
+ error: Could not read f7fad86d06fee0678f9af7203b6031feabb40c3e
444
+ fatal: pack has 1 unresolved delta
445
+ fatal: index-pack failed
446
+ ERROR
447
+
448
+ expect(subject.retriable_error?(error)).to be_truthy
449
+ end
492
450
 
493
- it 'should retry when the cache errors with did not receive expected object' do
494
- allow(subject).to receive(:update_reference_repo) {}
495
- expect(subject).to receive(:reference_repo_dir)
496
- expect(subject).to receive(:reference_repo_lock_file).and_return(lockfile)
451
+ it 'when deltas are missing' do
452
+ error = format_error <<-ERROR
453
+ error: Could not read f7fad86d06fee0678f9af7203b6031feabb40c3e
454
+ fatal: pack has 138063 unresolved deltas
455
+ fatal: index-pack failed
456
+ ERROR
497
457
 
498
- responses = [
499
- lambda { |_url|
500
- raise Terrapin::ExitStatusError, <<-ERROR.gsub(/^ {12}/, '')
501
- STDOUT:
458
+ expect(subject.retriable_error?(error)).to be_truthy
459
+ end
502
460
 
503
- STDERR:
461
+ it 'when the cache errors with unable to read sha1 file' do
462
+ error = format_error <<-ERROR
463
+ error: unable to read sha1 file of sqiosbuild/lib/action/action.rb (6113b739af82d8b07731de8a58d6e233301f80ab)
464
+ fatal: unable to checkout working tree
465
+ warning: Clone succeeded, but checkout failed.
466
+ You can inspect what was checked out with 'git status'
467
+ and retry with 'git restore --source=HEAD :/'
468
+ ERROR
504
469
 
505
- error: Could not read 6682dfe81f66656436e60883dd795e7ec6735153
506
- error: Could not read 0cd3703c23fa44c0043d97fbc26356a23939f31b
507
- fatal: did not receive expected object 3c64c9dd49c79bd09aa13d4b05ac18263ca29ccd
508
- fatal: index-pack failed
509
- ERROR
510
- },
511
- ->(url) { url }
512
- ]
513
- subject.with_git_mirror(test_url_valid) do
514
- yielded << responses.shift.call(test_url_valid)
470
+ expect(subject.retriable_error?(error)).to be_truthy
515
471
  end
516
472
 
517
- expect(responses).to be_empty
518
- expect(yielded).to eq([test_url_valid])
473
+ it 'when the cache errors with did not receive expected object' do
474
+ error = format_error <<-ERROR
475
+ error: Could not read 6682dfe81f66656436e60883dd795e7ec6735153
476
+ error: Could not read 0cd3703c23fa44c0043d97fbc26356a23939f31b
477
+ fatal: did not receive expected object 3c64c9dd49c79bd09aa13d4b05ac18263ca29ccd
478
+ fatal: index-pack failed
479
+ ERROR
480
+
481
+ expect(subject.retriable_error?(error)).to be_truthy
482
+ end
519
483
  end
520
484
  end
@@ -62,7 +62,7 @@ describe GitFastClone::UrlHelper do
62
62
  allow(subject).to receive(:reference_repo_name) { test_reference_dir }
63
63
 
64
64
  expect(subject.reference_repo_dir(test_url_valid, test_reference_dir, false))
65
- .to eq(test_reference_dir + '/' + test_reference_dir)
65
+ .to eq("#{test_reference_dir}/#{test_reference_dir}")
66
66
  end
67
67
  end
68
68
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-fastclone
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Tauraso
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-12-03 00:00:00.000000000 Z
12
+ date: 2022-12-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize
@@ -61,7 +61,8 @@ files:
61
61
  homepage: http://square.github.io/git-fastclone/
62
62
  licenses:
63
63
  - Apache
64
- metadata: {}
64
+ metadata:
65
+ rubygems_mfa_required: 'true'
65
66
  post_install_message:
66
67
  rdoc_options: []
67
68
  require_paths:
@@ -70,18 +71,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
71
  requirements:
71
72
  - - ">="
72
73
  - !ruby/object:Gem::Version
73
- version: '0'
74
+ version: '2.7'
74
75
  required_rubygems_version: !ruby/object:Gem::Requirement
75
76
  requirements:
76
77
  - - ">="
77
78
  - !ruby/object:Gem::Version
78
79
  version: '0'
79
80
  requirements: []
80
- rubygems_version: 3.1.6
81
+ rubygems_version: 3.3.7
81
82
  signing_key:
82
83
  specification_version: 4
83
84
  summary: git-clone --recursive on steroids!
84
- test_files:
85
- - spec/git_fastclone_runner_spec.rb
86
- - spec/git_fastclone_url_helper_spec.rb
87
- - spec/spec_helper.rb
85
+ test_files: []