git-fastclone 1.4.4 → 1.5.0
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 +32 -9
- data/spec/git_fastclone_runner_spec.rb +57 -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: 8b86bd9aa9bc5a377dd7d5b7b456eb0de1aee7ffd1e746642775d08042e9714f
|
4
|
+
data.tar.gz: '08dff02e06757c022c7ee0fec4890261c3d3efbee76130f2c7f4e0c2cdd91361'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce36dfc95ed1d5621fc32df5721d1b796e1cdbb58c11952351dd124bf14a784bef8624e23bde74be3a3c848fff320201639b0e7737be44c8860860a0fb99a019
|
7
|
+
data.tar.gz: 77a296e5b3c6ea817fef4c0ca6df39c4f33e8f35626fd896d4f41ff9c201bf8de15c57a0543e7a8aac4cf63f7de352a00b01844c964657fb20192abbce3790a4
|
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
@@ -47,13 +47,23 @@ module GitFastClone
|
|
47
47
|
end
|
48
48
|
module_function :reference_repo_dir
|
49
49
|
|
50
|
+
def reference_filename(filename)
|
51
|
+
separator = if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
52
|
+
'__'
|
53
|
+
else
|
54
|
+
':'
|
55
|
+
end
|
56
|
+
"#{separator}#{filename}"
|
57
|
+
end
|
58
|
+
module_function :reference_filename
|
59
|
+
|
50
60
|
def reference_repo_submodule_file(url, reference_dir, using_local_repo)
|
51
|
-
"#{reference_repo_dir(url, reference_dir, using_local_repo)}
|
61
|
+
"#{reference_repo_dir(url, reference_dir, using_local_repo)}#{reference_filename('submodules.txt')}"
|
52
62
|
end
|
53
63
|
module_function :reference_repo_submodule_file
|
54
64
|
|
55
65
|
def reference_repo_lock_file(url, reference_dir, using_local_repo)
|
56
|
-
lock_file_name = "#{reference_repo_dir(url, reference_dir, using_local_repo)}
|
66
|
+
lock_file_name = "#{reference_repo_dir(url, reference_dir, using_local_repo)}#{reference_filename('lock')}"
|
57
67
|
File.open(lock_file_name, File::RDWR | File::CREAT, 0o644)
|
58
68
|
end
|
59
69
|
module_function :reference_repo_lock_file
|
@@ -156,6 +166,11 @@ module GitFastClone
|
|
156
166
|
Default is 0 which waits indefinitely.') do |timeout_secs|
|
157
167
|
self.flock_timeout_secs = timeout_secs.to_i
|
158
168
|
end
|
169
|
+
|
170
|
+
opts.on('--pre-clone-hook command',
|
171
|
+
'An optional command that should be invoked before cloning mirror repo') do |command|
|
172
|
+
options[:pre_clone_hook] = command
|
173
|
+
end
|
159
174
|
end.parse!
|
160
175
|
end
|
161
176
|
|
@@ -314,7 +329,7 @@ module GitFastClone
|
|
314
329
|
# overall checkout or not. When we pre-fetch based off of cached information,
|
315
330
|
# fail_hard is false. When we fetch based off info in a repository directly,
|
316
331
|
# fail_hard is true.
|
317
|
-
def update_reference_repo(url, fail_hard)
|
332
|
+
def update_reference_repo(url, fail_hard, attempt_number)
|
318
333
|
repo_name = reference_repo_name(url)
|
319
334
|
mirror = reference_repo_dir(url, reference_dir, using_local_repo)
|
320
335
|
|
@@ -323,24 +338,26 @@ module GitFastClone
|
|
323
338
|
submodule_file = reference_repo_submodule_file(url, reference_dir, using_local_repo)
|
324
339
|
|
325
340
|
# if prefetch is on, then grab children immediately to frontload network requests
|
326
|
-
prefetch(submodule_file) if File.exist?(submodule_file) && prefetch_submodules
|
341
|
+
prefetch(submodule_file, attempt_number) if File.exist?(submodule_file) && prefetch_submodules
|
327
342
|
|
328
343
|
# Store the fact that our repo has been updated if necessary
|
329
|
-
store_updated_repo(url, mirror, repo_name, fail_hard) unless reference_updated[repo_name]
|
344
|
+
store_updated_repo(url, mirror, repo_name, fail_hard, attempt_number) unless reference_updated[repo_name]
|
330
345
|
end
|
331
346
|
end
|
332
347
|
|
333
348
|
# Grab the children in the event of a prefetch
|
334
|
-
def prefetch(submodule_file)
|
349
|
+
def prefetch(submodule_file, attempt_number)
|
335
350
|
File.readlines(submodule_file).each do |line|
|
336
351
|
# We don't join these threads explicitly
|
337
|
-
Thread.new { update_reference_repo(line.strip, false) }
|
352
|
+
Thread.new { update_reference_repo(line.strip, false, attempt_number) }
|
338
353
|
end
|
339
354
|
end
|
340
355
|
|
341
356
|
# Creates or updates the mirror repo then stores an indication
|
342
357
|
# that this repo has been updated on this run of fastclone
|
343
|
-
def store_updated_repo(url, mirror, repo_name, fail_hard)
|
358
|
+
def store_updated_repo(url, mirror, repo_name, fail_hard, attempt_number)
|
359
|
+
trigger_pre_clone_hook_if_needed(url, mirror, attempt_number)
|
360
|
+
# If pre_clone_hook correctly creates a mirror directory, we don't want to clone, but just update it
|
344
361
|
unless Dir.exist?(mirror)
|
345
362
|
fail_on_error('git', 'clone', verbose ? '--verbose' : '--quiet', '--mirror', url.to_s, mirror.to_s,
|
346
363
|
quiet: !verbose, print_on_failure: print_git_errors)
|
@@ -404,7 +421,7 @@ module GitFastClone
|
|
404
421
|
retries_allowed ||= 1
|
405
422
|
attempt_number ||= 0
|
406
423
|
|
407
|
-
update_reference_repo(url, true)
|
424
|
+
update_reference_repo(url, true, attempt_number)
|
408
425
|
dir = reference_repo_dir(url, reference_dir, using_local_repo)
|
409
426
|
|
410
427
|
# Sometimes remote updates involve re-packing objects on a different thread
|
@@ -431,5 +448,11 @@ module GitFastClone
|
|
431
448
|
def usage
|
432
449
|
'Usage: git fastclone [options] <git-url> [path]'
|
433
450
|
end
|
451
|
+
|
452
|
+
private def trigger_pre_clone_hook_if_needed(url, mirror, attempt_number)
|
453
|
+
return if Dir.exist?(mirror) || !options.include?(:pre_clone_hook)
|
454
|
+
|
455
|
+
popen2e_wrapper(options[:pre_clone_hook], url.to_s, mirror.to_s, attempt_number.to_s, quiet: !verbose)
|
456
|
+
end
|
434
457
|
end
|
435
458
|
end
|
@@ -145,6 +145,54 @@ 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 errors' 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(subject).to receive(:with_git_mirror).and_call_original
|
155
|
+
allow(subject).to receive(:with_reference_repo_lock) do |_url, &block|
|
156
|
+
block.call
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'invokes hook command' do
|
161
|
+
allow(subject).to receive(:fail_on_error)
|
162
|
+
expect(subject).to receive(:popen2e_wrapper).with(
|
163
|
+
pre_clone_hook, 'PH', 'PH/PH', '0',
|
164
|
+
{ quiet: true }
|
165
|
+
) { runner_execution_double }
|
166
|
+
|
167
|
+
subject.clone(placeholder_arg, nil, '.', 'config')
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'does not call clone if hook creates mirror' do
|
171
|
+
allow(subject).to receive(:popen2e_wrapper).with(
|
172
|
+
pre_clone_hook, 'PH', 'PH/PH', '0',
|
173
|
+
{ quiet: true }
|
174
|
+
) do
|
175
|
+
# Emulate creating mirror dir
|
176
|
+
allow(Dir).to receive(:exist?).with('PH/PH').and_return(true)
|
177
|
+
end
|
178
|
+
allow(subject).to receive(:fail_on_error)
|
179
|
+
|
180
|
+
subject.clone(placeholder_arg, nil, '.', 'config')
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'does not call pre-clone hook if mirror is already created' do
|
184
|
+
# Emulate already created mirror dir
|
185
|
+
allow(Dir).to receive(:exist?).and_call_original
|
186
|
+
allow(Dir).to receive(:exist?).with('PH/PH').and_return(true)
|
187
|
+
expect(subject).not_to receive(:popen2e_wrapper).with(
|
188
|
+
pre_clone_hook, 'PH', 'PH/PH', '0',
|
189
|
+
{ quiet: true }
|
190
|
+
)
|
191
|
+
allow(subject).to receive(:fail_on_error)
|
192
|
+
|
193
|
+
subject.clone(placeholder_arg, nil, '.', 'config')
|
194
|
+
end
|
195
|
+
end
|
148
196
|
end
|
149
197
|
|
150
198
|
describe '.clear_clone_dest_if_needed' do
|
@@ -249,7 +297,7 @@ describe GitFastClone::Runner do
|
|
249
297
|
allow(File).to receive(:exist?) { true }
|
250
298
|
subject.prefetch_submodules = true
|
251
299
|
subject.reference_dir = placeholder_arg
|
252
|
-
subject.update_reference_repo(test_url_valid, false)
|
300
|
+
subject.update_reference_repo(test_url_valid, false, 0)
|
253
301
|
end
|
254
302
|
end
|
255
303
|
|
@@ -262,7 +310,7 @@ describe GitFastClone::Runner do
|
|
262
310
|
allow(File).to receive(:exist?) { true }
|
263
311
|
subject.prefetch_submodules = false
|
264
312
|
subject.reference_dir = placeholder_arg
|
265
|
-
subject.update_reference_repo(placeholder_arg, false)
|
313
|
+
subject.update_reference_repo(placeholder_arg, false, 0)
|
266
314
|
end
|
267
315
|
end
|
268
316
|
|
@@ -277,7 +325,7 @@ describe GitFastClone::Runner do
|
|
277
325
|
allow(subject).to receive(:reference_repo_dir) { placeholder_arg }
|
278
326
|
subject.reference_updated = placeholder_hash
|
279
327
|
subject.prefetch_submodules = false
|
280
|
-
subject.update_reference_repo(placeholder_arg, false)
|
328
|
+
subject.update_reference_repo(placeholder_arg, false, 0)
|
281
329
|
end
|
282
330
|
end
|
283
331
|
|
@@ -291,7 +339,7 @@ describe GitFastClone::Runner do
|
|
291
339
|
subject.reference_updated = placeholder_hash
|
292
340
|
subject.reference_dir = placeholder_arg
|
293
341
|
subject.prefetch_submodules = false
|
294
|
-
subject.update_reference_repo(placeholder_arg, false)
|
342
|
+
subject.update_reference_repo(placeholder_arg, false, 0)
|
295
343
|
end
|
296
344
|
end
|
297
345
|
end
|
@@ -302,7 +350,7 @@ describe GitFastClone::Runner do
|
|
302
350
|
|
303
351
|
allow(File).to receive(:readlines) { %w[1 2 3] }
|
304
352
|
subject.prefetch_submodules = true
|
305
|
-
subject.prefetch(placeholder_arg)
|
353
|
+
subject.prefetch(placeholder_arg, 0)
|
306
354
|
end
|
307
355
|
end
|
308
356
|
|
@@ -315,7 +363,7 @@ describe GitFastClone::Runner do
|
|
315
363
|
allow(subject).to receive(:fail_on_error) { raise ex }
|
316
364
|
expect(FileUtils).to receive(:remove_entry_secure).with(placeholder_arg, force: true)
|
317
365
|
expect do
|
318
|
-
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true)
|
366
|
+
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true, 0)
|
319
367
|
end.to raise_error(ex)
|
320
368
|
end
|
321
369
|
|
@@ -327,7 +375,7 @@ describe GitFastClone::Runner do
|
|
327
375
|
allow(subject).to receive(:fail_on_error) { raise ex }
|
328
376
|
expect(FileUtils).to_not receive(:remove_entry_secure).with(placeholder_arg, force: true)
|
329
377
|
expect do
|
330
|
-
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true)
|
378
|
+
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, true, 0)
|
331
379
|
end.to raise_error(ex)
|
332
380
|
end
|
333
381
|
end
|
@@ -340,7 +388,7 @@ describe GitFastClone::Runner do
|
|
340
388
|
allow(subject).to receive(:fail_on_error) { raise ex }
|
341
389
|
expect(FileUtils).to receive(:remove_entry_secure).with(placeholder_arg, force: true)
|
342
390
|
expect do
|
343
|
-
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false)
|
391
|
+
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false, 0)
|
344
392
|
end.to_not raise_error
|
345
393
|
end
|
346
394
|
end
|
@@ -351,7 +399,7 @@ describe GitFastClone::Runner do
|
|
351
399
|
allow(subject).to receive(:fail_on_error)
|
352
400
|
|
353
401
|
subject.reference_updated = placeholder_hash
|
354
|
-
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false)
|
402
|
+
subject.store_updated_repo(placeholder_arg, placeholder_arg, placeholder_arg, false, 0)
|
355
403
|
expect(subject.reference_updated).to eq(placeholder_arg => true)
|
356
404
|
end
|
357
405
|
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.0
|
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-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colorize
|