git-fastclone 1.4.5 → 1.5.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f23af05975dc472665784e91a3e69112694837cbd2a873076a7fb3197828970f
4
- data.tar.gz: b3e2a26cbf1aff738c647eb37aa6b661975a396b680352288f68c0ba20da429d
3
+ metadata.gz: 62066971856b4d6e34def960d0ec1214082d546f94a5ffe58b048eb5715511f0
4
+ data.tar.gz: d04c4ac8c866a011b3b6b279b3a9f2e719c6d284314086f91f4c73b189443f50
5
5
  SHA512:
6
- metadata.gz: b9f239ae1a6cdf02d8aef5944f4d704bffaeb0d410191d7f5b7c759ba1d525dca27dd8efcec2e19ac4ffee9787ff3706b16860d0e16ff493136bcb2378b70a7c
7
- data.tar.gz: fb954090b896bf41a396c956847133fc7d367fc564fbc8e3973ed61f2738b16f3926397b4526994d6c6d1781439970055f67e5c7d8137a0174a4f614b69f7a60
6
+ metadata.gz: d807b912fd16fc82e3ce6ea2a3d568f37d1a946efdb750e7279baafa2a0c8206b2b6b298165321a0dd6306a975aacc873f0863c7ff18259b0b0126dd3c83f299
7
+ data.tar.gz: 0dde85446cad33944b3e1e61327b4656c435312fd6ef169b2b82fc4506d6e6bcedebdb0c808b5bdb52e7b0249472c2f033fa86647cadb6626dbcc953efaa6645
data/README.md CHANGED
@@ -43,17 +43,29 @@ Usage
43
43
  gem install git-fastclone
44
44
  git fastclone [options] <git-repo-url>
45
45
 
46
- -b, --branch <branch> Clone a specific branch
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.
46
+ -b, --branch BRANCH Checkout this branch rather than the default
47
+ -v, --verbose Verbose mode
48
+ --print_git_errors Print git output if a command fails
49
+ -c, --color Display colored output
50
+ --config CONFIG Git config applied to the cloned repo
51
+ --lock-timeout N Timeout in seconds to acquire a lock on any reference repo.
52
+ Default is 0 which waits indefinitely.
53
+ --pre-clone-hook command An optional command that should be invoked before cloning mirror repo
51
54
 
52
55
  Change the default `REFERENCE_REPO_DIR` environment variable if necessary.
53
56
 
54
57
  Cygwin users need to add `~/bin` to PATH.
55
58
 
56
59
 
60
+ Hooks
61
+ -----
62
+
63
+ - `pre-clone-hook` is invoked right before cloning a new mirror repo, which gives a change to prepopulate git's mirror from a different source.
64
+ The hook is invoked with given arguments:
65
+ 1. cloning repo url
66
+ 1. path to the repo mirror location
67
+ 1. attempt number, 0-indexed
68
+
57
69
  How to test?
58
70
  ------------
59
71
  Manual testing:
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version string for git-fastclone
4
4
  module GitFastCloneVersion
5
- VERSION = '1.4.5'
5
+ VERSION = '1.5.1'
6
6
  end
data/lib/git-fastclone.rb CHANGED
@@ -162,10 +162,16 @@ module GitFastClone
162
162
  options[:config] = config
163
163
  end
164
164
 
165
- opts.on('--lock-timeout N', 'Timeout in seconds to acquire a lock on any reference repo.
166
- Default is 0 which waits indefinitely.') do |timeout_secs|
165
+ opts.on('--lock-timeout N', 'Timeout in seconds to acquire a lock on any reference repo.',
166
+ 'Default is 0 which waits indefinitely.') do |timeout_secs|
167
167
  self.flock_timeout_secs = timeout_secs.to_i
168
168
  end
169
+
170
+ opts.on('--pre-clone-hook script_file',
171
+ 'An optional file that should be invoked before cloning mirror repo',
172
+ 'No-op when a file is missing') do |script_file|
173
+ options[:pre_clone_hook] = script_file
174
+ end
169
175
  end.parse!
170
176
  end
171
177
 
@@ -324,7 +330,7 @@ module GitFastClone
324
330
  # overall checkout or not. When we pre-fetch based off of cached information,
325
331
  # fail_hard is false. When we fetch based off info in a repository directly,
326
332
  # fail_hard is true.
327
- def update_reference_repo(url, fail_hard)
333
+ def update_reference_repo(url, fail_hard, attempt_number)
328
334
  repo_name = reference_repo_name(url)
329
335
  mirror = reference_repo_dir(url, reference_dir, using_local_repo)
330
336
 
@@ -333,24 +339,26 @@ module GitFastClone
333
339
  submodule_file = reference_repo_submodule_file(url, reference_dir, using_local_repo)
334
340
 
335
341
  # if prefetch is on, then grab children immediately to frontload network requests
336
- prefetch(submodule_file) if File.exist?(submodule_file) && prefetch_submodules
342
+ prefetch(submodule_file, attempt_number) if File.exist?(submodule_file) && prefetch_submodules
337
343
 
338
344
  # Store the fact that our repo has been updated if necessary
339
- store_updated_repo(url, mirror, repo_name, fail_hard) unless reference_updated[repo_name]
345
+ store_updated_repo(url, mirror, repo_name, fail_hard, attempt_number) unless reference_updated[repo_name]
340
346
  end
341
347
  end
342
348
 
343
349
  # Grab the children in the event of a prefetch
344
- def prefetch(submodule_file)
350
+ def prefetch(submodule_file, attempt_number)
345
351
  File.readlines(submodule_file).each do |line|
346
352
  # We don't join these threads explicitly
347
- Thread.new { update_reference_repo(line.strip, false) }
353
+ Thread.new { update_reference_repo(line.strip, false, attempt_number) }
348
354
  end
349
355
  end
350
356
 
351
357
  # Creates or updates the mirror repo then stores an indication
352
358
  # that this repo has been updated on this run of fastclone
353
- def store_updated_repo(url, mirror, repo_name, fail_hard)
359
+ def store_updated_repo(url, mirror, repo_name, fail_hard, attempt_number)
360
+ trigger_pre_clone_hook_if_needed(url, mirror, attempt_number)
361
+ # If pre_clone_hook correctly creates a mirror directory, we don't want to clone, but just update it
354
362
  unless Dir.exist?(mirror)
355
363
  fail_on_error('git', 'clone', verbose ? '--verbose' : '--quiet', '--mirror', url.to_s, mirror.to_s,
356
364
  quiet: !verbose, print_on_failure: print_git_errors)
@@ -414,7 +422,7 @@ module GitFastClone
414
422
  retries_allowed ||= 1
415
423
  attempt_number ||= 0
416
424
 
417
- update_reference_repo(url, true)
425
+ update_reference_repo(url, true, attempt_number)
418
426
  dir = reference_repo_dir(url, reference_dir, using_local_repo)
419
427
 
420
428
  # Sometimes remote updates involve re-packing objects on a different thread
@@ -441,5 +449,17 @@ module GitFastClone
441
449
  def usage
442
450
  'Usage: git fastclone [options] <git-url> [path]'
443
451
  end
452
+
453
+ private def trigger_pre_clone_hook_if_needed(url, mirror, attempt_number)
454
+ return if Dir.exist?(mirror) || !options.include?(:pre_clone_hook)
455
+
456
+ hook_command = options[:pre_clone_hook]
457
+ unless File.exist?(File.expand_path(hook_command))
458
+ puts 'pre_clone_hook script is missing' if verbose
459
+ return
460
+ end
461
+
462
+ popen2e_wrapper(hook_command, url.to_s, mirror.to_s, attempt_number.to_s, quiet: !verbose)
463
+ end
444
464
  end
445
465
  end
@@ -145,6 +145,72 @@ describe GitFastClone::Runner do
145
145
  subject.clone(placeholder_arg, nil, '.', 'config')
146
146
  end
147
147
  end
148
+
149
+ context 'with pre-clone-hook' do
150
+ let(:pre_clone_hook) { '/some/command' }
151
+ before(:each) do
152
+ subject.options[:pre_clone_hook] = pre_clone_hook
153
+ subject.reference_dir = placeholder_arg
154
+ allow(File).to receive(:exist?).and_call_original
155
+ allow(File).to receive(:exist?).with(pre_clone_hook).and_return(true)
156
+ allow(subject).to receive(:with_git_mirror).and_call_original
157
+ allow(subject).to receive(:with_reference_repo_lock) do |_url, &block|
158
+ block.call
159
+ end
160
+ end
161
+
162
+ it 'invokes hook command' do
163
+ allow(subject).to receive(:fail_on_error)
164
+ expect(subject).to receive(:popen2e_wrapper).with(
165
+ pre_clone_hook, 'PH', 'PH/PH', '0',
166
+ { quiet: true }
167
+ ) { runner_execution_double }
168
+
169
+ subject.clone(placeholder_arg, nil, '.', 'config')
170
+ end
171
+
172
+ it 'does not call clone if hook creates mirror' do
173
+ allow(subject).to receive(:popen2e_wrapper).with(
174
+ pre_clone_hook, 'PH', 'PH/PH', '0',
175
+ { quiet: true }
176
+ ) do
177
+ # Emulate creating mirror dir
178
+ allow(Dir).to receive(:exist?).with('PH/PH').and_return(true)
179
+ end
180
+ allow(subject).to receive(:fail_on_error)
181
+
182
+ subject.clone(placeholder_arg, nil, '.', 'config')
183
+ end
184
+
185
+ it 'does not call pre-clone hook if mirror is already created' do
186
+ # Emulate already created mirror dir
187
+ allow(Dir).to receive(:exist?).and_call_original
188
+ allow(Dir).to receive(:exist?).with('PH/PH').and_return(true)
189
+ expect(subject).not_to receive(:popen2e_wrapper).with(
190
+ pre_clone_hook, 'PH', 'PH/PH', '0',
191
+ { quiet: true }
192
+ )
193
+ allow(subject).to receive(:fail_on_error)
194
+
195
+ subject.clone(placeholder_arg, nil, '.', 'config')
196
+ end
197
+
198
+ context 'non-existing script' do
199
+ before(:each) do
200
+ allow(File).to receive(:exist?).with(pre_clone_hook).and_return(false)
201
+ end
202
+
203
+ it 'does not invoke hook command' do
204
+ allow(subject).to receive(:fail_on_error)
205
+ expect(subject).not_to receive(:popen2e_wrapper).with(
206
+ pre_clone_hook, 'PH', 'PH/PH', '0',
207
+ { quiet: true }
208
+ )
209
+
210
+ subject.clone(placeholder_arg, nil, '.', 'config')
211
+ end
212
+ end
213
+ end
148
214
  end
149
215
 
150
216
  describe '.clear_clone_dest_if_needed' do
@@ -249,7 +315,7 @@ describe GitFastClone::Runner do
249
315
  allow(File).to receive(:exist?) { true }
250
316
  subject.prefetch_submodules = true
251
317
  subject.reference_dir = placeholder_arg
252
- subject.update_reference_repo(test_url_valid, false)
318
+ subject.update_reference_repo(test_url_valid, false, 0)
253
319
  end
254
320
  end
255
321
 
@@ -262,7 +328,7 @@ describe GitFastClone::Runner do
262
328
  allow(File).to receive(:exist?) { true }
263
329
  subject.prefetch_submodules = false
264
330
  subject.reference_dir = placeholder_arg
265
- subject.update_reference_repo(placeholder_arg, false)
331
+ subject.update_reference_repo(placeholder_arg, false, 0)
266
332
  end
267
333
  end
268
334
 
@@ -277,7 +343,7 @@ describe GitFastClone::Runner do
277
343
  allow(subject).to receive(:reference_repo_dir) { placeholder_arg }
278
344
  subject.reference_updated = placeholder_hash
279
345
  subject.prefetch_submodules = false
280
- subject.update_reference_repo(placeholder_arg, false)
346
+ subject.update_reference_repo(placeholder_arg, false, 0)
281
347
  end
282
348
  end
283
349
 
@@ -291,7 +357,7 @@ describe GitFastClone::Runner do
291
357
  subject.reference_updated = placeholder_hash
292
358
  subject.reference_dir = placeholder_arg
293
359
  subject.prefetch_submodules = false
294
- subject.update_reference_repo(placeholder_arg, false)
360
+ subject.update_reference_repo(placeholder_arg, false, 0)
295
361
  end
296
362
  end
297
363
  end
@@ -302,7 +368,7 @@ describe GitFastClone::Runner do
302
368
 
303
369
  allow(File).to receive(:readlines) { %w[1 2 3] }
304
370
  subject.prefetch_submodules = true
305
- subject.prefetch(placeholder_arg)
371
+ subject.prefetch(placeholder_arg, 0)
306
372
  end
307
373
  end
308
374
 
@@ -315,7 +381,7 @@ describe GitFastClone::Runner do
315
381
  allow(subject).to receive(:fail_on_error) { raise ex }
316
382
  expect(FileUtils).to receive(:remove_entry_secure).with(placeholder_arg, force: true)
317
383
  expect do
318
- subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true)
384
+ subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true, 0)
319
385
  end.to raise_error(ex)
320
386
  end
321
387
 
@@ -327,7 +393,7 @@ describe GitFastClone::Runner do
327
393
  allow(subject).to receive(:fail_on_error) { raise ex }
328
394
  expect(FileUtils).to_not receive(:remove_entry_secure).with(placeholder_arg, force: true)
329
395
  expect do
330
- subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true)
396
+ subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true, 0)
331
397
  end.to raise_error(ex)
332
398
  end
333
399
  end
@@ -340,7 +406,7 @@ describe GitFastClone::Runner do
340
406
  allow(subject).to receive(:fail_on_error) { raise ex }
341
407
  expect(FileUtils).to receive(:remove_entry_secure).with(placeholder_arg, force: true)
342
408
  expect do
343
- subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false)
409
+ subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false, 0)
344
410
  end.to_not raise_error
345
411
  end
346
412
  end
@@ -351,7 +417,7 @@ describe GitFastClone::Runner do
351
417
  allow(subject).to receive(:fail_on_error)
352
418
 
353
419
  subject.reference_updated = placeholder_hash
354
- subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false)
420
+ subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false, 0)
355
421
  expect(subject.reference_updated).to eq(placeholder_arg => true)
356
422
  end
357
423
  end
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.4.5
4
+ version: 1.5.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: 2023-12-14 00:00:00.000000000 Z
12
+ date: 2024-03-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize