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 +4 -4
- data/README.md +17 -5
- data/lib/git-fastclone/version.rb +1 -1
- data/lib/git-fastclone.rb +29 -9
- data/spec/git_fastclone_runner_spec.rb +75 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62066971856b4d6e34def960d0ec1214082d546f94a5ffe58b048eb5715511f0
|
4
|
+
data.tar.gz: d04c4ac8c866a011b3b6b279b3a9f2e719c6d284314086f91f4c73b189443f50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
47
|
-
-v, --verbose
|
48
|
-
|
49
|
-
|
50
|
-
--
|
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:
|
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
|
+
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:
|
12
|
+
date: 2024-03-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colorize
|