git 5.0.0 → 5.0.2

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.
@@ -1,814 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'git/commands/clone'
4
- require 'git/commands/init'
5
- require 'git/execution_context/global'
6
- require 'git/execution_context/repository'
7
- require 'git/repository/path_resolver'
8
- require 'pathname'
9
-
10
- module Git
11
- class Repository
12
- # Implementation of the {Git} module factory entry points
13
- #
14
- # Provides `.open`, `.init`, `.clone`, and `.bare` — the four methods that
15
- # construct a {Git::Repository}. Extended onto the {Git} module so that
16
- # `Git.open(...)`, `Git.init(...)`, etc. resolve here.
17
- #
18
- # @api private
19
- #
20
- module Factories # rubocop:disable Metrics/ModuleLength
21
- # Clone a repository into a new directory
22
- #
23
- # @example Clone into the default directory
24
- # repository = Git.clone('https://github.com/ruby-git/ruby-git.git')
25
- #
26
- # @example Clone into a specific directory
27
- # repo_url = 'https://github.com/ruby-git/ruby-git.git'
28
- # repository = Git.clone(repo_url, 'local')
29
- #
30
- # @example Clone a bare repository
31
- # repo_url = 'https://github.com/ruby-git/ruby-git.git'
32
- # repository = Git.clone(repo_url, nil, bare: true)
33
- #
34
- # @param repository_url [String, URI, Pathname] the URL or path of the repository to clone
35
- #
36
- # @param directory [String, Pathname, nil] the local directory name to clone into;
37
- # git derives the name from the URL when `nil`
38
- #
39
- # @param options [Hash] options that control cloning
40
- #
41
- # Some options configure the returned {Git::Repository} instance after
42
- # the clone completes. Supported `git clone` options are forwarded.
43
- #
44
- # @option options [String, nil] :template template directory to use
45
- #
46
- # @option options [Boolean, nil] :local use the local clone optimization
47
- #
48
- # @option options [Boolean, nil] :no_local disable the local clone optimization
49
- #
50
- # @option options [Boolean, nil] :shared set up a shared clone
51
- #
52
- # @option options [Boolean, nil] :no_hardlinks copy files instead of hardlinks
53
- #
54
- # @option options [Boolean, nil] :quiet suppress progress output
55
- #
56
- # @option options [Boolean, nil] :verbose run verbosely
57
- #
58
- # @option options [Boolean, nil] :progress force progress output
59
- #
60
- # @option options [Boolean, nil] :no_checkout skip checking out `HEAD`
61
- #
62
- # @option options [Boolean, nil] :bare clone as a bare repository
63
- #
64
- # @option options [Boolean, nil] :mirror set up a mirror of the source
65
- # (implies `:bare`)
66
- #
67
- # @option options [String, nil] :origin remote name to use instead of `origin`
68
- #
69
- # @option options [String, nil] :branch the branch or tag to check out after cloning
70
- #
71
- # @option options [String, nil] :revision revision to check out after cloning
72
- #
73
- # @option options [String, nil] :upload_pack remote `git-upload-pack` path
74
- #
75
- # @option options [String, Array<String>, nil] :reference reference repository
76
- #
77
- # @option options [String, Array<String>, nil] :reference_if_able
78
- # optional reference repository
79
- #
80
- # @option options [Boolean, nil] :dissociate stop borrowing from references
81
- #
82
- # @option options [String, nil] :separate_git_dir alternate git directory path
83
- #
84
- # @option options [String, Array<String>, nil] :server_option
85
- # protocol-v2 server options
86
- #
87
- # @option options [Integer, String, nil] :depth create a shallow clone
88
- #
89
- # @option options [String, nil] :shallow_since create a shallow clone by date
90
- #
91
- # @option options [String, Array<String>, nil] :shallow_exclude
92
- # exclude commits reachable from a ref
93
- #
94
- # @option options [Boolean, nil] :single_branch clone one branch's history
95
- #
96
- # @option options [Boolean, nil] :no_single_branch clone all branch history
97
- #
98
- # @option options [Boolean, nil] :tags include tags in the clone
99
- #
100
- # @option options [Boolean, nil] :no_tags exclude tags from the clone
101
- #
102
- # @option options [Boolean, String, Array<String>, nil] :recurse_submodules
103
- # initialize submodules after cloning
104
- #
105
- # Pass `true` to initialize all submodules, or pass a pathspec string or
106
- # array for a subset.
107
- #
108
- # @option options [Boolean, nil] :shallow_submodules use depth 1 for submodules
109
- #
110
- # @option options [Boolean, nil] :no_shallow_submodules use full submodule history
111
- #
112
- # @option options [Boolean, nil] :remote_submodules use submodule remote branches
113
- #
114
- # @option options [Boolean, nil] :no_remote_submodules use recorded submodule SHAs
115
- #
116
- # @option options [Integer, String, nil] :jobs submodule jobs to run concurrently
117
- #
118
- # @option options [Boolean, nil] :sparse enable sparse checkout
119
- #
120
- # @option options [Boolean, nil] :reject_shallow reject shallow source repositories
121
- #
122
- # @option options [Boolean, nil] :no_reject_shallow allow shallow sources
123
- #
124
- # @option options [String, nil] :filter specify a partial clone filter
125
- #
126
- # @option options [Boolean, nil] :also_filter_submodules filter submodules too
127
- #
128
- # @option options [String, Array<String>, nil] :config repository config entries
129
- #
130
- # @option options [String, nil] :bundle_uri bundle URI to prefetch
131
- #
132
- # @option options [String, nil] :ref_format ref storage format
133
- #
134
- # @option options [Numeric, nil] :timeout command timeout in seconds
135
- #
136
- # @option options [String, nil] :repository alternate git directory path
137
- #
138
- # Preferred facade spelling for `git clone --separate-git-dir`.
139
- #
140
- # @option options [String, nil, :use_global_config] :git_ssh path to a custom
141
- # SSH executable
142
- #
143
- # Pass `:use_global_config` (the default) to use
144
- # `Git.config.git_ssh`.
145
- #
146
- # @option options [String, :use_global_config] :binary_path path to the git
147
- # binary
148
- #
149
- # Pass `:use_global_config` (the default) to use
150
- # `Git.config.binary_path`.
151
- #
152
- # @option options [Logger, nil] :log logger used for git operations
153
- #
154
- # @option options [String, nil] :index a non-standard path to the index file
155
- #
156
- # @option options [String, Pathname, nil] :chdir run `git clone` from within
157
- # this directory
158
- #
159
- # @option options [String, Pathname, nil] :path deprecated; use `:chdir` instead
160
- #
161
- # @option options [Boolean, nil] :recursive deprecated; use
162
- # `:recurse_submodules` instead
163
- #
164
- # @option options [String, nil] :remote deprecated; use `:origin` instead
165
- #
166
- # @return [Git::Repository] a repository bound to the cloned working copy or
167
- # bare repository
168
- #
169
- # @raise [ArgumentError] if unsupported options are provided
170
- #
171
- # @raise [Git::FailedError] if git exits with a non-zero exit status
172
- #
173
- # @raise [Git::UnexpectedResultError] if the cloned directory cannot be
174
- # determined from git's output
175
- #
176
- # @api public
177
- #
178
- def clone(repository_url, directory = nil, options = {})
179
- opts, context_opts = prepare_clone_options(options)
180
- clone_result = run_clone_command(repository_url, directory, opts, context_opts)
181
- paths = resolve_paths_from_clone_result(clone_result, opts, context_opts)
182
-
183
- from_paths(clone_repository_options(context_opts), paths)
184
- end
185
-
186
- # Create an empty Git repository or reinitialize an existing one
187
- #
188
- # @example Initialize in the current directory
189
- # repository = Git.init
190
- #
191
- # @example Initialize in a specific directory
192
- # repository = Git.init('/path/to/project')
193
- #
194
- # @example Initialize a bare repository
195
- # repository = Git.init('/path/to/project.git', bare: true)
196
- #
197
- # @param directory [String] the directory to initialize; defaults to `'.'`
198
- #
199
- # @param options [Hash] options that control initialization
200
- #
201
- # Some options configure the returned {Git::Repository} instance after
202
- # the repository is initialized.
203
- #
204
- # @option options [Boolean, nil] :bare create a bare repository at `directory`
205
- #
206
- # @option options [String, nil] :initial_branch the name for the initial branch
207
- #
208
- # @option options [String, nil] :repository path for the `.git` directory
209
- #
210
- # Writes a gitfile in the working tree. Alias: `:separate_git_dir`.
211
- #
212
- # @option options [String, nil] :separate_git_dir alias for `:repository`
213
- #
214
- # @option options [String, nil, :use_global_config] :git_ssh path to a custom
215
- # SSH executable
216
- #
217
- # Pass `:use_global_config` (the default) to use
218
- # `Git.config.git_ssh`.
219
- #
220
- # @option options [String, :use_global_config] :binary_path path to the git
221
- # binary
222
- #
223
- # Pass `:use_global_config` (the default) to use
224
- # `Git.config.binary_path`.
225
- #
226
- # @option options [Logger, nil] :log logger used for git operations
227
- #
228
- # @option options [String, nil] :index custom index path for the returned
229
- # repository
230
- #
231
- # Ignored when `:bare` is `true`.
232
- #
233
- # @return [Git::Repository] a repository bound to the newly initialized repository
234
- #
235
- # @raise [Git::FailedError] if git exits with a non-zero exit status
236
- #
237
- # @api public
238
- #
239
- def init(directory = '.', options = {})
240
- options = options.dup
241
- if options.key?(:separate_git_dir) && options[:repository].nil?
242
- options[:repository] = options.delete(:separate_git_dir)
243
- end
244
-
245
- run_init_command(directory, options)
246
- open_after_init(directory, options)
247
- end
248
-
249
- # Open a working copy at an existing path
250
- #
251
- # @example Open the working copy in the current directory
252
- # repository = Git.open('.')
253
- #
254
- # @param working_dir [String] the path to the root of the working copy
255
- #
256
- # May be any path inside the working tree when `:repository` is not given.
257
- #
258
- # @param options [Hash] options that control how the repository is located
259
- #
260
- # @option options [String, nil] :repository a non-standard path to the
261
- # `.git` directory
262
- #
263
- # When given, `working_dir` is used as-is (the working tree root is not
264
- # auto-detected).
265
- #
266
- # @option options [String, nil] :index a non-standard path to the index file
267
- #
268
- # @option options [Logger, nil] :log logger used for git operations
269
- #
270
- # @option options [String, nil, :use_global_config] :git_ssh
271
- # path to a custom SSH executable
272
- #
273
- # Pass `:use_global_config` (the default) to use
274
- # `Git.config.git_ssh`.
275
- #
276
- # @option options [String, :use_global_config] :binary_path
277
- # path to the git binary
278
- #
279
- # Pass `:use_global_config` (the default) to use
280
- # `Git.config.binary_path`.
281
- #
282
- # @return [Git::Repository] a repository bound to the resolved paths
283
- #
284
- # @raise [ArgumentError] if `working_dir` is not a directory or is not inside
285
- # a git working tree
286
- #
287
- # @note This method opens working copies only. To open a bare repository, use
288
- # `Git.bare`.
289
- #
290
- # @api public
291
- #
292
- def open(working_dir, options = {})
293
- raise ArgumentError, "'#{working_dir}' is not a directory" unless Dir.exist?(working_dir)
294
-
295
- working_dir = resolve_open_working_dir(working_dir, options) unless options[:repository]
296
-
297
- paths = PathResolver.resolve_paths(
298
- working_directory: working_dir,
299
- repository: options[:repository],
300
- index: options[:index]
301
- )
302
-
303
- from_paths(options, paths)
304
- end
305
-
306
- # Open an existing bare repository at `git_dir`
307
- #
308
- # @example Open a bare repository
309
- # repository = Git.bare('/path/to/repo.git')
310
- #
311
- # @param git_dir [String] the path to the bare repository directory
312
- #
313
- # @param options [Hash] options used to configure the repository instance
314
- #
315
- # @option options [Logger, nil] :log logger used for git operations
316
- #
317
- # @option options [String, nil, :use_global_config] :git_ssh
318
- # path to a custom SSH executable
319
- #
320
- # Pass `:use_global_config` (the default) to use
321
- # `Git.config.git_ssh`.
322
- #
323
- # @option options [String, :use_global_config] :binary_path
324
- # path to the git binary
325
- #
326
- # Pass `:use_global_config` (the default) to use
327
- # `Git.config.binary_path`.
328
- #
329
- # @return [Git::Repository] a repository bound to the bare repository directory
330
- #
331
- # @api public
332
- #
333
- def bare(git_dir, options = {})
334
- paths = PathResolver.resolve_paths(repository: git_dir, bare: true)
335
-
336
- from_paths(options, paths)
337
- end
338
-
339
- private
340
-
341
- # Run the `git clone` command using a global execution context
342
- #
343
- # @param repository_url [String, URI, Pathname] the URL or path of the repository to clone
344
- #
345
- # @param directory [String, Pathname, nil] the local directory name to clone into
346
- #
347
- # @param opts [Hash] command-ready clone options
348
- #
349
- # @param context_opts [Hash] context options produced while preparing clone
350
- # options
351
- #
352
- # @option opts [Boolean, nil] :bare clone as a bare repository
353
- #
354
- # @option context_opts [String, :use_global_config] :binary_path path to
355
- # the git binary
356
- #
357
- # @option context_opts [String, nil, :use_global_config] :git_ssh path to
358
- # a custom SSH executable
359
- #
360
- # @option context_opts [Logger, nil] :logger logger used for clone
361
- # operations
362
- #
363
- # @return [Git::CommandLine::Result] the result of running `git clone`
364
- #
365
- # @raise [ArgumentError] if unsupported options are provided
366
- #
367
- # @raise [Git::FailedError] if git exits with a non-zero exit status
368
- #
369
- # @api private
370
- #
371
- def run_clone_command(repository_url, directory, opts, context_opts)
372
- context = Git::ExecutionContext::Global.new(
373
- binary_path: context_opts[:binary_path],
374
- git_ssh: context_opts[:git_ssh],
375
- logger: context_opts[:logger]
376
- )
377
-
378
- Git::Commands::Clone.new(context).call(repository_url, directory, **opts)
379
- end
380
-
381
- # Resolve repository paths from a completed clone result
382
- #
383
- # @param clone_result [Git::CommandLine::Result] the completed clone result
384
- #
385
- # @param opts [Hash] command-ready clone options
386
- #
387
- # @param context_opts [Hash] context options produced while preparing clone
388
- # options
389
- #
390
- # @option opts [String, Pathname, nil] :chdir run `git clone` from within
391
- # this directory
392
- #
393
- # @option opts [Boolean, nil] :bare clone as a bare repository
394
- #
395
- # @option opts [Boolean, nil] :mirror set up a mirror of the source
396
- #
397
- # @option context_opts [String, nil] :index custom index path for the
398
- # returned repository
399
- #
400
- # @return [Hash{Symbol => (String, nil)}] resolved path hash
401
- #
402
- # @raise [Git::UnexpectedResultError] if the clone directory cannot be parsed
403
- #
404
- # @api private
405
- #
406
- def resolve_paths_from_clone_result(clone_result, opts, context_opts)
407
- clone_dir, cloned_bare = parse_clone_stderr(clone_result.stderr)
408
- chdir = opts[:chdir]
409
- clone_dir = File.join(chdir, clone_dir) if chdir && !Pathname.new(clone_dir).absolute?
410
-
411
- bare = opts[:bare] || opts[:mirror] || cloned_bare
412
- resolve_clone_paths(clone_dir, bare, context_opts[:index])
413
- end
414
-
415
- # Build repository construction options from clone context options
416
- #
417
- # @param context_opts [Hash] context options produced while preparing clone
418
- # options
419
- #
420
- # @return [Hash{Symbol => Object}] repository construction options
421
- #
422
- # @api private
423
- #
424
- def clone_repository_options(context_opts)
425
- {
426
- git_ssh: context_opts[:git_ssh],
427
- binary_path: context_opts[:binary_path],
428
- log: context_opts[:logger]
429
- }
430
- end
431
-
432
- # Build the `:binary_path` and `:git_ssh` execution-context defaults
433
- #
434
- # Reads the values from the caller-supplied options, falling back to the
435
- # `:use_global_config` sentinel for any the caller did not provide so the
436
- # value is resolved from `Git::Config.instance` at call time.
437
- #
438
- # @param options [Hash] the caller-supplied options hash
439
- #
440
- # @option options [String, :use_global_config] :binary_path path to the
441
- # git binary
442
- #
443
- # @option options [String, nil, :use_global_config] :git_ssh path to a
444
- # custom SSH executable
445
- #
446
- # @return [Hash] context defaults with two keys: `:binary_path`
447
- # (`String` or `:use_global_config` — `nil` is not valid and raises
448
- # `ArgumentError` in {Git::ExecutionContext#initialize}) and `:git_ssh`
449
- # (`String`, `nil`, or `:use_global_config`)
450
- #
451
- # @api private
452
- #
453
- def context_defaults(options)
454
- {
455
- binary_path: options.fetch(:binary_path, :use_global_config),
456
- git_ssh: options.fetch(:git_ssh, :use_global_config)
457
- }
458
- end
459
-
460
- # Resolve the worktree root to use as the working directory for {.open}
461
- #
462
- # @param working_dir [String] a path inside the working tree
463
- #
464
- # @param options [Hash] the caller-supplied options hash from {.open}
465
- #
466
- # @option options [String, :use_global_config] :binary_path path to the
467
- # git binary
468
- #
469
- # @option options [String, nil, :use_global_config] :git_ssh path to a
470
- # custom SSH executable
471
- #
472
- # @return [String] the absolute path to the root of the working tree
473
- #
474
- # @raise [ArgumentError] if `working_dir` is not inside a git working tree
475
- #
476
- # @api private
477
- #
478
- def resolve_open_working_dir(working_dir, options)
479
- PathResolver.root_of_worktree(working_dir, **context_defaults(options))
480
- end
481
-
482
- # Build a repository from caller options and resolved paths
483
- #
484
- # @param options [Hash] the caller-supplied options (`:git_ssh`,
485
- # `:binary_path`, `:log`)
486
- #
487
- # @param paths [Hash{Symbol => (String, nil)}] the resolved paths
488
- #
489
- # @option options [String, nil, :use_global_config] :git_ssh path to a
490
- # custom SSH executable
491
- #
492
- # @option options [String, :use_global_config] :binary_path path to the
493
- # git binary
494
- #
495
- # @option options [Logger, nil] :log logger used for git operations
496
- #
497
- # @return [Git::Repository] the constructed repository
498
- #
499
- # @api private
500
- #
501
- def from_paths(options, paths)
502
- Git::Repository.new(execution_context: Git::ExecutionContext::Repository.from_hash(
503
- options.merge(paths), logger: options[:log]
504
- ))
505
- end
506
-
507
- # Extract facade-level options from the raw clone options and return
508
- # command-ready options
509
- #
510
- # Returns `[command_opts, context_opts]` where `command_opts` is the
511
- # caller's options with facade-level keys removed. Remaining keys are
512
- # forwarded to `Git::Commands::Clone`, which raises `ArgumentError` for
513
- # unsupported ones. `context_opts` contains values used for the execution
514
- # context and post-clone path resolution.
515
- #
516
- # @param options [Hash] raw caller-supplied options
517
- #
518
- # @option options [Boolean, nil] :bare clone as a bare repository
519
- #
520
- # @return [Array<Hash>] a two-element tuple `[command_opts, context_opts]`
521
- #
522
- # @api private
523
- #
524
- def prepare_clone_options(options)
525
- opts = options.dup
526
- deprecate_clone_path_option!(opts)
527
- deprecate_clone_recursive_option!(opts)
528
- deprecate_clone_remote_option!(opts)
529
- context_opts = extract_clone_context_options!(opts)
530
- normalize_clone_repository_option!(opts)
531
-
532
- [opts, context_opts]
533
- end
534
-
535
- # Extract clone context options from command-ready options
536
- #
537
- # @param opts [Hash] clone options (mutated in place)
538
- #
539
- # @option opts [Logger, nil] :log logger used for clone operations
540
- #
541
- # @option opts [String, nil, :use_global_config] :git_ssh path to a
542
- # custom SSH executable
543
- #
544
- # @option opts [String, :use_global_config] :binary_path path to the git
545
- # binary
546
- #
547
- # @option opts [String, nil] :index custom index path for the returned
548
- # repository
549
- #
550
- # @return [Hash{Symbol => Object}] context options for clone setup
551
- #
552
- # @api private
553
- #
554
- def extract_clone_context_options!(opts)
555
- {
556
- logger: opts.delete(:log),
557
- git_ssh: opts.key?(:git_ssh) ? opts.delete(:git_ssh) : :use_global_config,
558
- binary_path: opts.key?(:binary_path) ? opts.delete(:binary_path) : :use_global_config,
559
- index: opts.delete(:index)
560
- }
561
- end
562
-
563
- # Normalize the clone repository option for `git clone`
564
- #
565
- # @param opts [Hash] clone options (mutated in place)
566
- #
567
- # @option opts [String, nil] :repository alternate git directory path
568
- #
569
- # @return [void] mutates `opts` in place
570
- #
571
- # @api private
572
- #
573
- def normalize_clone_repository_option!(opts)
574
- return unless opts.key?(:repository)
575
-
576
- repository_val = opts.delete(:repository)
577
- opts[:separate_git_dir] = repository_val if repository_val
578
- end
579
-
580
- # Resolve paths for the cloned repository
581
- #
582
- # @param clone_dir [String] the directory reported by `git clone`
583
- #
584
- # @param bare [Boolean] whether the clone is bare
585
- #
586
- # @param index [String, nil] optional custom index path
587
- #
588
- # @return [Hash{Symbol => (String, nil)}] resolved path hash
589
- #
590
- # @api private
591
- #
592
- def resolve_clone_paths(clone_dir, bare, index)
593
- args = bare ? { repository: clone_dir, bare: true } : { working_directory: clone_dir }
594
- PathResolver.resolve_paths(**args, index: index)
595
- end
596
-
597
- # Run the `git init` command using a global execution context
598
- #
599
- # @param directory [String] the directory to initialize
600
- #
601
- # @param options [Hash] the normalized options hash (after alias resolution)
602
- #
603
- # @option options [Boolean, nil] :bare create a bare repository at
604
- # `directory`
605
- #
606
- # @option options [String, nil] :initial_branch the name for the initial
607
- # branch
608
- #
609
- # @option options [String, nil] :repository path for the `.git` directory
610
- #
611
- # @option options [String, :use_global_config] :binary_path path to the
612
- # git binary
613
- #
614
- # @option options [String, nil, :use_global_config] :git_ssh path to a
615
- # custom SSH executable
616
- #
617
- # @option options [Logger, nil] :log logger used for git operations
618
- #
619
- # @return [Git::CommandLine::Result] the result of running `git init`
620
- #
621
- # @raise [Git::FailedError] if git exits with a non-zero exit status
622
- #
623
- # @api private
624
- #
625
- def run_init_command(directory, options)
626
- init_opts = options.slice(:bare, :initial_branch)
627
- init_opts[:separate_git_dir] = options[:repository] if options.key?(:repository)
628
-
629
- context = Git::ExecutionContext::Global.new(**context_defaults(options), logger: options[:log])
630
- Git::Commands::Init.new(context).call(directory, **init_opts)
631
- end
632
-
633
- # Open the repository produced by `git init`
634
- #
635
- # @param directory [String] the initialized directory
636
- #
637
- # @param options [Hash] the normalized options hash
638
- #
639
- # @option options [Boolean, nil] :bare create a bare repository at
640
- # `directory`
641
- #
642
- # @option options [String, nil] :repository path for the `.git` directory
643
- #
644
- # @option options [String, nil] :index custom index path for the returned
645
- # repository
646
- #
647
- # @option options [String, :use_global_config] :binary_path path to the
648
- # git binary
649
- #
650
- # @option options [String, nil, :use_global_config] :git_ssh path to a
651
- # custom SSH executable
652
- #
653
- # @option options [Logger, nil] :log logger used for git operations
654
- #
655
- # @return [Git::Repository] the repository opened after initialization
656
- #
657
- # @api private
658
- #
659
- def open_after_init(directory, options)
660
- return bare(options[:repository] || directory, base_open_options_after_init(options)) if options[:bare]
661
-
662
- self.open(directory, worktree_open_options_after_init(options))
663
- end
664
-
665
- # Build common options for opening a repository after `git init`
666
- #
667
- # @param options [Hash] the normalized options hash
668
- #
669
- # @option options [String, nil, :use_global_config] :git_ssh path to a
670
- # custom SSH executable
671
- #
672
- # @option options [String, :use_global_config] :binary_path path to the
673
- # git binary
674
- #
675
- # @option options [Logger, nil] :log logger used for git operations
676
- #
677
- # @return [Hash{Symbol => Object}] options accepted by {.open} and {.bare}
678
- #
679
- # @api private
680
- #
681
- def base_open_options_after_init(options)
682
- {
683
- git_ssh: options.fetch(:git_ssh, :use_global_config),
684
- binary_path: options.fetch(:binary_path, :use_global_config)
685
- }.tap do |open_opts|
686
- open_opts[:log] = options[:log] if options[:log]
687
- end
688
- end
689
-
690
- # Build worktree options for opening a repository after `git init`
691
- #
692
- # @param options [Hash] the normalized options hash
693
- #
694
- # @option options [String, nil, :use_global_config] :git_ssh path to a
695
- # custom SSH executable
696
- #
697
- # @option options [String, :use_global_config] :binary_path path to the
698
- # git binary
699
- #
700
- # @option options [Logger, nil] :log logger used for git operations
701
- #
702
- # @option options [String, nil] :index custom index path for the returned
703
- # repository
704
- #
705
- # @option options [String, nil] :repository path for the `.git` directory
706
- #
707
- # @return [Hash{Symbol => Object}] options accepted by {.open}
708
- #
709
- # @api private
710
- #
711
- def worktree_open_options_after_init(options)
712
- base_open_options_after_init(options).tap do |open_opts|
713
- open_opts[:index] = options[:index] if options[:index]
714
- open_opts[:repository] = options[:repository] if options[:repository]
715
- end
716
- end
717
-
718
- # Parse the clone directory and bare status from `git clone` stderr output
719
- #
720
- # @param stderr [String] stderr output from `git clone`
721
- #
722
- # @return [Array] a two-element tuple `[clone_dir, bare]`
723
- #
724
- # @raise [Git::UnexpectedResultError] if the stderr output cannot be parsed
725
- #
726
- # @api private
727
- #
728
- def parse_clone_stderr(stderr)
729
- match = stderr.match(/Cloning into (?:(bare repository) )?'(.+)'\.\.\./)
730
- raise Git::UnexpectedResultError, "Unable to determine clone directory from: #{stderr}" unless match
731
-
732
- [match[2], !match[1].nil?]
733
- end
734
-
735
- # Handle the deprecated `:path` option for {clone}
736
- #
737
- # @param opts [Hash] clone options (mutated in place)
738
- #
739
- # @option opts [String, Pathname, nil] :path deprecated; use `:chdir`
740
- # instead
741
- #
742
- # @option opts [String, Pathname, nil] :chdir run `git clone` from within
743
- # this directory
744
- #
745
- # @return [void] mutates `opts` in place
746
- #
747
- # @api private
748
- #
749
- def deprecate_clone_path_option!(opts)
750
- return unless opts.key?(:path)
751
-
752
- if defined?(Git::Deprecation)
753
- Git::Deprecation.warn(
754
- 'The :path option for Git.clone is deprecated and will be removed in v6.0.0. ' \
755
- 'Use :chdir instead.'
756
- )
757
- end
758
- path = opts.delete(:path)
759
- opts[:chdir] ||= path
760
- end
761
-
762
- # Handle the deprecated `:recursive` option for {clone}
763
- #
764
- # @param opts [Hash] clone options (mutated in place)
765
- #
766
- # @option opts [Boolean, nil] :recursive deprecated; use
767
- # `:recurse_submodules` instead
768
- #
769
- # @option opts [Boolean, String, Array<String>, nil] :recurse_submodules
770
- # initialize submodules after cloning
771
- #
772
- # @return [void] mutates `opts` in place
773
- #
774
- # @api private
775
- #
776
- def deprecate_clone_recursive_option!(opts)
777
- return unless opts.key?(:recursive)
778
-
779
- if defined?(Git::Deprecation)
780
- Git::Deprecation.warn(
781
- 'The :recursive option for Git.clone is deprecated and will be removed in v6.0.0. ' \
782
- 'Use :recurse_submodules instead.'
783
- )
784
- end
785
- opts[:recurse_submodules] = opts.delete(:recursive)
786
- end
787
-
788
- # Handle the deprecated `:remote` option for {clone}
789
- #
790
- # @param opts [Hash] clone options (mutated in place)
791
- #
792
- # @option opts [String, nil] :remote deprecated; use `:origin` instead
793
- #
794
- # @option opts [String, nil] :origin remote name to use instead of
795
- # `origin`
796
- #
797
- # @return [void] mutates `opts` in place
798
- #
799
- # @api private
800
- #
801
- def deprecate_clone_remote_option!(opts)
802
- return unless opts.key?(:remote)
803
-
804
- if defined?(Git::Deprecation)
805
- Git::Deprecation.warn(
806
- 'The :remote option for Git.clone is deprecated and will be removed in v6.0.0. ' \
807
- 'Use :origin instead.'
808
- )
809
- end
810
- opts[:origin] = opts.delete(:remote)
811
- end
812
- end
813
- end
814
- end