git 4.3.2 → 5.0.0.beta.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/.github/copilot-instructions.md +67 -2705
- data/.github/pull_request_template.md +3 -1
- data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
- data/.github/skills/command-implementation/REFERENCE.md +993 -0
- data/.github/skills/command-implementation/SKILL.md +229 -0
- data/.github/skills/command-test-conventions/SKILL.md +660 -0
- data/.github/skills/command-yard-documentation/SKILL.md +426 -0
- data/.github/skills/dependency-management/SKILL.md +72 -0
- data/.github/skills/development-workflow/SKILL.md +506 -0
- data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +586 -0
- data/.github/skills/facade-implementation/REFERENCE.md +840 -0
- data/.github/skills/facade-implementation/SKILL.md +260 -0
- data/.github/skills/facade-test-conventions/SKILL.md +380 -0
- data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
- data/.github/skills/make-skill-template/SKILL.md +176 -0
- data/.github/skills/pr-readiness-review/SKILL.md +185 -0
- data/.github/skills/project-context/SKILL.md +313 -0
- data/.github/skills/pull-request-review/SKILL.md +168 -0
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
- data/.github/skills/release-management/SKILL.md +125 -0
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
- data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
- data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
- data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
- data/.github/skills/reviewing-skills/SKILL.md +189 -0
- data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
- data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
- data/.github/skills/test-debugging/SKILL.md +160 -0
- data/.github/skills/yard-documentation/SKILL.md +793 -0
- data/.github/workflows/continuous_integration.yml +3 -2
- data/.github/workflows/enforce_conventional_commits.yml +1 -1
- data/.github/workflows/experimental_continuous_integration.yml +2 -2
- data/.github/workflows/release.yml +3 -4
- data/.gitignore +8 -0
- data/.husky/pre-commit +13 -0
- data/.release-please-manifest.json +1 -1
- data/.rspec +3 -0
- data/.rubocop.yml +7 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -40
- data/CONTRIBUTING.md +694 -53
- data/README.md +17 -5
- data/Rakefile +61 -9
- data/commitlint.test +4 -0
- data/git.gemspec +14 -8
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/base.rb +486 -410
- data/lib/git/branch.rb +380 -43
- data/lib/git/branch_delete_failure.rb +31 -0
- data/lib/git/branch_delete_result.rb +63 -0
- data/lib/git/branch_info.rb +178 -0
- data/lib/git/branches.rb +130 -24
- data/lib/git/command_line/base.rb +245 -0
- data/lib/git/command_line/capturing.rb +249 -0
- data/lib/git/command_line/result.rb +96 -0
- data/lib/git/command_line/streaming.rb +194 -0
- data/lib/git/command_line.rb +43 -322
- data/lib/git/command_line_result.rb +4 -88
- data/lib/git/commands/add.rb +131 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +252 -0
- data/lib/git/commands/am/continue.rb +43 -0
- data/lib/git/commands/am/quit.rb +43 -0
- data/lib/git/commands/am/retry.rb +47 -0
- data/lib/git/commands/am/show_current_patch.rb +64 -0
- data/lib/git/commands/am/skip.rb +42 -0
- data/lib/git/commands/am.rb +33 -0
- data/lib/git/commands/apply.rb +237 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +140 -0
- data/lib/git/commands/arguments.rb +3510 -0
- data/lib/git/commands/base.rb +403 -0
- data/lib/git/commands/branch/copy.rb +94 -0
- data/lib/git/commands/branch/create.rb +173 -0
- data/lib/git/commands/branch/delete.rb +80 -0
- data/lib/git/commands/branch/list.rb +162 -0
- data/lib/git/commands/branch/move.rb +94 -0
- data/lib/git/commands/branch/set_upstream.rb +86 -0
- data/lib/git/commands/branch/show_current.rb +49 -0
- data/lib/git/commands/branch/unset_upstream.rb +57 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +364 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +210 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +151 -0
- data/lib/git/commands/checkout/files.rb +115 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +105 -0
- data/lib/git/commands/clean.rb +100 -0
- data/lib/git/commands/clone.rb +240 -0
- data/lib/git/commands/commit.rb +272 -0
- data/lib/git/commands/commit_tree.rb +100 -0
- data/lib/git/commands/config_option_syntax/add.rb +83 -0
- data/lib/git/commands/config_option_syntax/get.rb +117 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +102 -0
- data/lib/git/commands/config_option_syntax/list.rb +107 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
- data/lib/git/commands/config_option_syntax/set.rb +114 -0
- data/lib/git/commands/config_option_syntax/unset.rb +89 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +155 -0
- data/lib/git/commands/diff.rb +656 -0
- data/lib/git/commands/diff_files.rb +518 -0
- data/lib/git/commands/diff_index.rb +496 -0
- data/lib/git/commands/fetch.rb +352 -0
- data/lib/git/commands/fsck.rb +136 -0
- data/lib/git/commands/gc.rb +132 -0
- data/lib/git/commands/grep.rb +338 -0
- data/lib/git/commands/init.rb +99 -0
- data/lib/git/commands/log.rb +632 -0
- data/lib/git/commands/ls_files.rb +191 -0
- data/lib/git/commands/ls_remote.rb +155 -0
- data/lib/git/commands/ls_tree.rb +131 -0
- data/lib/git/commands/maintenance/register.rb +75 -0
- data/lib/git/commands/maintenance/run.rb +104 -0
- data/lib/git/commands/maintenance/start.rb +66 -0
- data/lib/git/commands/maintenance/stop.rb +55 -0
- data/lib/git/commands/maintenance/unregister.rb +79 -0
- data/lib/git/commands/maintenance.rb +31 -0
- data/lib/git/commands/merge/abort.rb +44 -0
- data/lib/git/commands/merge/continue.rb +44 -0
- data/lib/git/commands/merge/quit.rb +46 -0
- data/lib/git/commands/merge/start.rb +245 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +86 -0
- data/lib/git/commands/mv.rb +77 -0
- data/lib/git/commands/name_rev.rb +114 -0
- data/lib/git/commands/pull.rb +377 -0
- data/lib/git/commands/push.rb +246 -0
- data/lib/git/commands/read_tree.rb +149 -0
- data/lib/git/commands/remote/add.rb +91 -0
- data/lib/git/commands/remote/get_url.rb +66 -0
- data/lib/git/commands/remote/list.rb +54 -0
- data/lib/git/commands/remote/prune.rb +61 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +69 -0
- data/lib/git/commands/remote/set_branches.rb +63 -0
- data/lib/git/commands/remote/set_head.rb +82 -0
- data/lib/git/commands/remote/set_url.rb +71 -0
- data/lib/git/commands/remote/set_url_add.rb +61 -0
- data/lib/git/commands/remote/set_url_delete.rb +64 -0
- data/lib/git/commands/remote/show.rb +71 -0
- data/lib/git/commands/remote/update.rb +72 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +277 -0
- data/lib/git/commands/reset.rb +147 -0
- data/lib/git/commands/rev_parse.rb +297 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +57 -0
- data/lib/git/commands/revert/quit.rb +47 -0
- data/lib/git/commands/revert/skip.rb +44 -0
- data/lib/git/commands/revert/start.rb +153 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +114 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
- data/lib/git/commands/show_ref/exists.rb +78 -0
- data/lib/git/commands/show_ref/list.rb +145 -0
- data/lib/git/commands/show_ref/verify.rb +120 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +75 -0
- data/lib/git/commands/stash/branch.rb +65 -0
- data/lib/git/commands/stash/clear.rb +41 -0
- data/lib/git/commands/stash/create.rb +58 -0
- data/lib/git/commands/stash/drop.rb +67 -0
- data/lib/git/commands/stash/list.rb +39 -0
- data/lib/git/commands/stash/pop.rb +78 -0
- data/lib/git/commands/stash/push.rb +103 -0
- data/lib/git/commands/stash/show.rb +149 -0
- data/lib/git/commands/stash/store.rb +63 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +169 -0
- data/lib/git/commands/symbolic_ref/delete.rb +68 -0
- data/lib/git/commands/symbolic_ref/read.rb +95 -0
- data/lib/git/commands/symbolic_ref/update.rb +76 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +139 -0
- data/lib/git/commands/tag/delete.rb +55 -0
- data/lib/git/commands/tag/list.rb +143 -0
- data/lib/git/commands/tag/verify.rb +71 -0
- data/lib/git/commands/tag.rb +26 -0
- data/lib/git/commands/update_ref/batch.rb +140 -0
- data/lib/git/commands/update_ref/delete.rb +92 -0
- data/lib/git/commands/update_ref/update.rb +106 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +52 -0
- data/lib/git/commands/worktree/add.rb +140 -0
- data/lib/git/commands/worktree/list.rb +64 -0
- data/lib/git/commands/worktree/lock.rb +58 -0
- data/lib/git/commands/worktree/management_base.rb +51 -0
- data/lib/git/commands/worktree/move.rb +66 -0
- data/lib/git/commands/worktree/prune.rb +67 -0
- data/lib/git/commands/worktree/remove.rb +63 -0
- data/lib/git/commands/worktree/repair.rb +76 -0
- data/lib/git/commands/worktree/unlock.rb +47 -0
- data/lib/git/commands/worktree.rb +43 -0
- data/lib/git/commands/write_tree.rb +68 -0
- data/lib/git/commands.rb +89 -0
- data/lib/git/detached_head_info.rb +54 -0
- data/lib/git/diff.rb +297 -7
- data/lib/git/diff_file_numstat_info.rb +29 -0
- data/lib/git/diff_file_patch_info.rb +134 -0
- data/lib/git/diff_file_raw_info.rb +127 -0
- data/lib/git/diff_info.rb +169 -0
- data/lib/git/diff_path_status.rb +78 -19
- data/lib/git/diff_result.rb +32 -0
- data/lib/git/diff_stats.rb +59 -14
- data/lib/git/dirstat_info.rb +86 -0
- data/lib/git/errors.rb +65 -2
- data/lib/git/execution_context/global.rb +56 -0
- data/lib/git/execution_context/repository.rb +147 -0
- data/lib/git/execution_context.rb +482 -0
- data/lib/git/file_ref.rb +74 -0
- data/lib/git/fsck_object.rb +9 -9
- data/lib/git/fsck_result.rb +1 -1
- data/lib/git/lib.rb +1606 -1028
- data/lib/git/log.rb +15 -2
- data/lib/git/object.rb +92 -22
- data/lib/git/parsers/branch.rb +224 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/diff.rb +585 -0
- data/lib/git/parsers/fsck.rb +133 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/stash.rb +208 -0
- data/lib/git/parsers/tag.rb +257 -0
- data/lib/git/remote.rb +133 -9
- data/lib/git/repository/branching.rb +572 -0
- data/lib/git/repository/committing.rb +191 -0
- data/lib/git/repository/configuring.rb +156 -0
- data/lib/git/repository/diffing.rb +775 -0
- data/lib/git/repository/inspecting.rb +153 -0
- data/lib/git/repository/logging.rb +247 -0
- data/lib/git/repository/merging.rb +295 -0
- data/lib/git/repository/object_operations.rb +1101 -0
- data/lib/git/repository/path_resolver.rb +207 -0
- data/lib/git/repository/remote_operations.rb +753 -0
- data/lib/git/repository/shared_private.rb +51 -0
- data/lib/git/repository/staging.rb +390 -0
- data/lib/git/repository/stashing.rb +107 -0
- data/lib/git/repository/status_operations.rb +180 -0
- data/lib/git/repository/worktree_operations.rb +159 -0
- data/lib/git/repository.rb +264 -1
- data/lib/git/stash.rb +85 -4
- data/lib/git/stash_info.rb +104 -0
- data/lib/git/stashes.rb +130 -13
- data/lib/git/status.rb +224 -18
- data/lib/git/tag_delete_failure.rb +31 -0
- data/lib/git/tag_delete_result.rb +63 -0
- data/lib/git/tag_info.rb +105 -0
- data/lib/git/version.rb +109 -2
- data/lib/git/version_constraint.rb +81 -0
- data/lib/git/worktree.rb +120 -5
- data/lib/git/worktrees.rb +107 -7
- data/lib/git.rb +114 -18
- data/redesign/1_architecture_existing.md +54 -18
- data/redesign/2_architecture_redesign.md +365 -46
- data/redesign/3_architecture_implementation.md +1451 -54
- data/tasks/gem_tasks.rake +4 -0
- data/tasks/npm_tasks.rake +7 -0
- data/tasks/rspec.rake +48 -0
- data/tasks/test.rake +13 -1
- data/tasks/yard.rake +34 -7
- metadata +349 -20
- data/lib/git/index.rb +0 -6
- data/lib/git/path.rb +0 -38
- data/lib/git/working_directory.rb +0 -6
- /data/{release-please-config.json → .release-please-config.json} +0 -0
|
@@ -0,0 +1,753 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/config_option_syntax'
|
|
4
|
+
require 'git/commands/fetch'
|
|
5
|
+
require 'git/commands/pull'
|
|
6
|
+
require 'git/commands/push'
|
|
7
|
+
require 'git/commands/remote'
|
|
8
|
+
require 'git/remote'
|
|
9
|
+
|
|
10
|
+
require 'git/repository/shared_private'
|
|
11
|
+
|
|
12
|
+
module Git
|
|
13
|
+
class Repository
|
|
14
|
+
# Mixin that adds remote operation facade methods to {Git::Repository}
|
|
15
|
+
#
|
|
16
|
+
# Included by {Git::Repository}.
|
|
17
|
+
#
|
|
18
|
+
# @api public
|
|
19
|
+
#
|
|
20
|
+
module RemoteOperations
|
|
21
|
+
# Key normalizations for {#fetch} options
|
|
22
|
+
#
|
|
23
|
+
# Maps dash-style option keys (which the 4.x `Git::Lib#fetch` accepted)
|
|
24
|
+
# to their canonical underscore-style equivalents.
|
|
25
|
+
#
|
|
26
|
+
# @return [Hash{Symbol => Symbol}]
|
|
27
|
+
#
|
|
28
|
+
# @api private
|
|
29
|
+
#
|
|
30
|
+
FETCH_KEY_NORMALIZATIONS = { 'update-head-ok': :update_head_ok, 'prune-tags': :prune_tags }.freeze
|
|
31
|
+
private_constant :FETCH_KEY_NORMALIZATIONS
|
|
32
|
+
|
|
33
|
+
# Option keys accepted by {#fetch}
|
|
34
|
+
#
|
|
35
|
+
# Derived from the 4.x `FETCH_OPTION_MAP` in `Git::Lib`.
|
|
36
|
+
#
|
|
37
|
+
# @return [Array<Symbol>]
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
#
|
|
41
|
+
FETCH_ALLOWED_OPTS = %i[all tags t prune p prune_tags P force f update_head_ok u unshallow depth ref].freeze
|
|
42
|
+
private_constant :FETCH_ALLOWED_OPTS
|
|
43
|
+
|
|
44
|
+
# Download objects and refs from a remote repository
|
|
45
|
+
#
|
|
46
|
+
# Fetches branches and/or tags from one or more other repositories, along
|
|
47
|
+
# with the objects necessary to complete their histories. The local
|
|
48
|
+
# tracking references are updated but the working directory is not
|
|
49
|
+
# modified.
|
|
50
|
+
#
|
|
51
|
+
# @example Fetch from the default remote
|
|
52
|
+
# repo.fetch
|
|
53
|
+
#
|
|
54
|
+
# @example Fetch from a named remote
|
|
55
|
+
# repo.fetch('upstream')
|
|
56
|
+
#
|
|
57
|
+
# @example Fetch all remotes at once
|
|
58
|
+
# repo.fetch(all: true)
|
|
59
|
+
#
|
|
60
|
+
# @example Fetch and prune deleted remote branches
|
|
61
|
+
# repo.fetch('origin', prune: true)
|
|
62
|
+
#
|
|
63
|
+
# @example Fetch a specific refspec
|
|
64
|
+
# repo.fetch('origin', ref: 'refs/heads/main:refs/remotes/origin/main')
|
|
65
|
+
#
|
|
66
|
+
# @example Fetch multiple refspecs
|
|
67
|
+
# repo.fetch('origin', ref: ['refs/heads/main', 'refs/heads/develop'])
|
|
68
|
+
#
|
|
69
|
+
# @example Fetch and include all tags
|
|
70
|
+
# repo.fetch('origin', tags: true)
|
|
71
|
+
#
|
|
72
|
+
# @overload fetch(remote = 'origin', opts = {})
|
|
73
|
+
#
|
|
74
|
+
# @param remote [String, Hash, nil] the remote name or URL to fetch from
|
|
75
|
+
#
|
|
76
|
+
# When a Hash is given it is treated as `opts` and `remote` defaults to
|
|
77
|
+
# `nil` (which omits the remote positional argument and lets git use the
|
|
78
|
+
# configured default).
|
|
79
|
+
#
|
|
80
|
+
# @param opts [Hash] options for the fetch command
|
|
81
|
+
#
|
|
82
|
+
# @option opts [Boolean, nil] :all (nil) fetch from all configured remotes
|
|
83
|
+
# (`--all`)
|
|
84
|
+
#
|
|
85
|
+
# @option opts [Boolean, nil] :tags (nil) fetch all tags from the remote
|
|
86
|
+
# (`--tags`)
|
|
87
|
+
#
|
|
88
|
+
# Alias: `:t`
|
|
89
|
+
#
|
|
90
|
+
# @option opts [Boolean, nil] :prune (nil) remove remote-tracking references
|
|
91
|
+
# that no longer exist on the remote (`--prune`)
|
|
92
|
+
#
|
|
93
|
+
# Alias: `:p`
|
|
94
|
+
#
|
|
95
|
+
# @option opts [Boolean, nil] :prune_tags (nil) remove local tags that no
|
|
96
|
+
# longer exist on the remote (`--prune-tags`)
|
|
97
|
+
#
|
|
98
|
+
# Alias: `:P`. The legacy dash-style key `:'prune-tags'` is also accepted
|
|
99
|
+
# and normalized automatically.
|
|
100
|
+
#
|
|
101
|
+
# @option opts [Boolean, nil] :force (nil) override the fast-forward check
|
|
102
|
+
# when using explicit refspecs (`--force`)
|
|
103
|
+
#
|
|
104
|
+
# Alias: `:f`
|
|
105
|
+
#
|
|
106
|
+
# @option opts [Boolean, nil] :update_head_ok (nil) allow `git fetch` to
|
|
107
|
+
# update the branch pointed to by `HEAD` (`--update-head-ok`)
|
|
108
|
+
#
|
|
109
|
+
# Alias: `:u`. The legacy dash-style key `:'update-head-ok'` is also
|
|
110
|
+
# accepted and normalized automatically.
|
|
111
|
+
#
|
|
112
|
+
# @option opts [Boolean, nil] :unshallow (nil) convert a shallow clone into a
|
|
113
|
+
# full repository (`--unshallow`)
|
|
114
|
+
#
|
|
115
|
+
# @option opts [String, Integer] :depth (nil) limit history to N commits
|
|
116
|
+
# from each branch tip (`--depth=N`)
|
|
117
|
+
#
|
|
118
|
+
# @option opts [String, Array<String>] :ref (nil) one or more refspecs to
|
|
119
|
+
# fetch; forwarded as positional arguments after the remote name. An
|
|
120
|
+
# explicit `remote` is required when `:ref` is given.
|
|
121
|
+
#
|
|
122
|
+
# @return [String] the merged stdout from the fetch command
|
|
123
|
+
#
|
|
124
|
+
# @raise [ArgumentError] when unsupported option keys are provided or `:ref`
|
|
125
|
+
# is supplied without an explicit remote
|
|
126
|
+
#
|
|
127
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
128
|
+
#
|
|
129
|
+
def fetch(remote = 'origin', opts = {})
|
|
130
|
+
remote, opts = Private.resolve_fetch_target(remote, opts)
|
|
131
|
+
|
|
132
|
+
opts = Private.normalize_fetch_keys(opts)
|
|
133
|
+
SharedPrivate.assert_valid_opts!(FETCH_ALLOWED_OPTS, **opts)
|
|
134
|
+
|
|
135
|
+
opts = opts.dup
|
|
136
|
+
refspecs = Array(opts.delete(:ref)).compact
|
|
137
|
+
positionals = [*([remote] if remote), *refspecs]
|
|
138
|
+
|
|
139
|
+
Git::Commands::Fetch.new(@execution_context).call(*positionals, **opts, merge: true).stdout
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Option keys accepted by {#pull}
|
|
143
|
+
#
|
|
144
|
+
# Derived from the 4.x `PULL_OPTION_MAP` in `Git::Lib`.
|
|
145
|
+
#
|
|
146
|
+
# @return [Array<Symbol>]
|
|
147
|
+
#
|
|
148
|
+
# @api private
|
|
149
|
+
#
|
|
150
|
+
PULL_ALLOWED_OPTS = %i[allow_unrelated_histories].freeze
|
|
151
|
+
private_constant :PULL_ALLOWED_OPTS
|
|
152
|
+
|
|
153
|
+
# Incorporate changes from a remote repository into the current branch
|
|
154
|
+
#
|
|
155
|
+
# Fetches from the given remote and merges into the current branch. In its
|
|
156
|
+
# default mode, `git pull` is shorthand for `git fetch` followed by
|
|
157
|
+
# `git merge FETCH_HEAD`. The merge editor is suppressed (`--no-edit`) and
|
|
158
|
+
# progress output is silenced (`--no-progress`) by default.
|
|
159
|
+
#
|
|
160
|
+
# @example Pull from the default remote and branch
|
|
161
|
+
# repo.pull
|
|
162
|
+
#
|
|
163
|
+
# @example Pull from a named remote
|
|
164
|
+
# repo.pull('upstream')
|
|
165
|
+
#
|
|
166
|
+
# @example Pull a specific branch from a remote
|
|
167
|
+
# repo.pull('origin', 'main')
|
|
168
|
+
#
|
|
169
|
+
# @example Pull allowing unrelated histories
|
|
170
|
+
# repo.pull('origin', 'main', allow_unrelated_histories: true)
|
|
171
|
+
#
|
|
172
|
+
# @overload pull(remote = nil, branch = nil, opts = {})
|
|
173
|
+
#
|
|
174
|
+
# @param remote [String, nil] the remote name or URL to pull from
|
|
175
|
+
#
|
|
176
|
+
# When nil, git uses the tracking remote for the current branch.
|
|
177
|
+
#
|
|
178
|
+
# @param branch [String, nil] the remote branch name to pull
|
|
179
|
+
#
|
|
180
|
+
# When nil, git uses the tracking branch for the current branch.
|
|
181
|
+
# A branch may not be specified without also specifying a remote.
|
|
182
|
+
#
|
|
183
|
+
# @param opts [Hash] options for the pull command
|
|
184
|
+
#
|
|
185
|
+
# @option opts [Boolean, nil] :allow_unrelated_histories (nil) allow merging
|
|
186
|
+
# histories that do not share a common ancestor
|
|
187
|
+
# (`--allow-unrelated-histories`)
|
|
188
|
+
#
|
|
189
|
+
# @return [String] the stdout from the pull command
|
|
190
|
+
#
|
|
191
|
+
# @raise [ArgumentError] when a branch is given without a remote, or when
|
|
192
|
+
# unsupported option keys are provided
|
|
193
|
+
#
|
|
194
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
195
|
+
#
|
|
196
|
+
def pull(remote = nil, branch = nil, opts = {})
|
|
197
|
+
raise ArgumentError, 'You must specify a remote if a branch is specified' if remote.nil? && !branch.nil?
|
|
198
|
+
|
|
199
|
+
SharedPrivate.assert_valid_opts!(PULL_ALLOWED_OPTS, **opts)
|
|
200
|
+
positional_args = [remote, branch].compact
|
|
201
|
+
Git::Commands::Pull
|
|
202
|
+
.new(@execution_context)
|
|
203
|
+
.call(*positional_args, no_edit: true, no_progress: true, **opts)
|
|
204
|
+
.stdout
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Option keys accepted by {#push}
|
|
208
|
+
#
|
|
209
|
+
# Derived from the 4.x `PUSH_OPTION_MAP` in `Git::Lib`.
|
|
210
|
+
#
|
|
211
|
+
# @return [Array<Symbol>]
|
|
212
|
+
#
|
|
213
|
+
# @api private
|
|
214
|
+
#
|
|
215
|
+
PUSH_ALLOWED_OPTS = %i[mirror delete force f push_option all tags].freeze
|
|
216
|
+
private_constant :PUSH_ALLOWED_OPTS
|
|
217
|
+
|
|
218
|
+
# Push refs to a remote repository
|
|
219
|
+
#
|
|
220
|
+
# @example Push using the current branch's default remote and push configuration
|
|
221
|
+
# repo.push
|
|
222
|
+
#
|
|
223
|
+
# @example Push to a named remote
|
|
224
|
+
# repo.push('origin')
|
|
225
|
+
#
|
|
226
|
+
# @example Force-push the current branch to a named remote
|
|
227
|
+
# repo.push('origin', force: true)
|
|
228
|
+
#
|
|
229
|
+
# @example Push a specific branch to a named remote
|
|
230
|
+
# repo.push('origin', 'main')
|
|
231
|
+
#
|
|
232
|
+
# @example Push a branch and all tags to a named remote
|
|
233
|
+
# repo.push('origin', 'main', tags: true)
|
|
234
|
+
#
|
|
235
|
+
# @example Push all branches to a named remote
|
|
236
|
+
# repo.push('origin', all: true)
|
|
237
|
+
#
|
|
238
|
+
# @example Mirror all refs to a named remote
|
|
239
|
+
# repo.push('origin', mirror: true)
|
|
240
|
+
#
|
|
241
|
+
# @overload push(options = {})
|
|
242
|
+
# Push using the current branch's default remote and push configuration
|
|
243
|
+
#
|
|
244
|
+
# @param options [Hash] push options (see option list below)
|
|
245
|
+
#
|
|
246
|
+
# @option options [Boolean, nil] :all (nil) push all branches (`--all`)
|
|
247
|
+
#
|
|
248
|
+
# @option options [Boolean, nil] :mirror (nil) push all refs under
|
|
249
|
+
# `refs/` to the remote (`--mirror`)
|
|
250
|
+
#
|
|
251
|
+
# When `:tags` is also given, the separate tags push is suppressed.
|
|
252
|
+
#
|
|
253
|
+
# @option options [Boolean, nil] :tags (nil) push all refs under
|
|
254
|
+
# `refs/tags/` in a second `git push` invocation (`--tags`)
|
|
255
|
+
#
|
|
256
|
+
# When `:mirror` is also given, the tags push is suppressed because
|
|
257
|
+
# `--mirror` already includes tags.
|
|
258
|
+
#
|
|
259
|
+
# @option options [Boolean, nil] :force (nil) force updates,
|
|
260
|
+
# overriding the fast-forward check (`--force`)
|
|
261
|
+
#
|
|
262
|
+
# Alias: `:f`
|
|
263
|
+
#
|
|
264
|
+
# @option options [Boolean, nil] :delete (nil) delete the named refs
|
|
265
|
+
# from the remote (`--delete`)
|
|
266
|
+
#
|
|
267
|
+
# @option options [String, Array<String>] :push_option (nil) one or
|
|
268
|
+
# more server-side push option values (`--push-option=<value>`,
|
|
269
|
+
# repeatable)
|
|
270
|
+
#
|
|
271
|
+
# @return [String] the stdout from the push command
|
|
272
|
+
#
|
|
273
|
+
# @overload push(remote, options = {})
|
|
274
|
+
# Push to the given remote using the current branch's default push configuration
|
|
275
|
+
#
|
|
276
|
+
# @param remote [String] the remote name or URL to push to
|
|
277
|
+
#
|
|
278
|
+
# @param options [Hash] push options (see option list below)
|
|
279
|
+
#
|
|
280
|
+
# @option options [Boolean, nil] :all (nil) push all branches (`--all`)
|
|
281
|
+
#
|
|
282
|
+
# @option options [Boolean, nil] :mirror (nil) push all refs under
|
|
283
|
+
# `refs/` to the remote (`--mirror`)
|
|
284
|
+
#
|
|
285
|
+
# When `:tags` is also given, the separate tags push is suppressed.
|
|
286
|
+
#
|
|
287
|
+
# @option options [Boolean, nil] :tags (nil) push all refs under
|
|
288
|
+
# `refs/tags/` in a second `git push` invocation (`--tags`)
|
|
289
|
+
#
|
|
290
|
+
# When `:mirror` is also given, the tags push is suppressed because
|
|
291
|
+
# `--mirror` already includes tags.
|
|
292
|
+
#
|
|
293
|
+
# @option options [Boolean, nil] :force (nil) force updates,
|
|
294
|
+
# overriding the fast-forward check (`--force`)
|
|
295
|
+
#
|
|
296
|
+
# Alias: `:f`
|
|
297
|
+
#
|
|
298
|
+
# @option options [Boolean, nil] :delete (nil) delete the named refs
|
|
299
|
+
# from the remote (`--delete`)
|
|
300
|
+
#
|
|
301
|
+
# @option options [String, Array<String>] :push_option (nil) one or
|
|
302
|
+
# more server-side push option values (`--push-option=<value>`,
|
|
303
|
+
# repeatable)
|
|
304
|
+
#
|
|
305
|
+
# @return [String] the stdout from the push command
|
|
306
|
+
#
|
|
307
|
+
# @overload push(remote, branch, options = {})
|
|
308
|
+
# Push a branch or refspec to the given remote
|
|
309
|
+
#
|
|
310
|
+
# @param remote [String] the remote name or URL to push to
|
|
311
|
+
#
|
|
312
|
+
# @param branch [String] the branch name or refspec to push
|
|
313
|
+
#
|
|
314
|
+
# @param options [Hash] push options (see option list below)
|
|
315
|
+
#
|
|
316
|
+
# @option options [Boolean, nil] :all (nil) push all branches (`--all`)
|
|
317
|
+
#
|
|
318
|
+
# @option options [Boolean, nil] :mirror (nil) push all refs under
|
|
319
|
+
# `refs/` to the remote (`--mirror`)
|
|
320
|
+
#
|
|
321
|
+
# When `:tags` is also given, the separate tags push is suppressed.
|
|
322
|
+
#
|
|
323
|
+
# @option options [Boolean, nil] :tags (nil) push all refs under
|
|
324
|
+
# `refs/tags/` in a second `git push` invocation (`--tags`)
|
|
325
|
+
#
|
|
326
|
+
# When `:mirror` is also given, the tags push is suppressed because
|
|
327
|
+
# `--mirror` already includes tags.
|
|
328
|
+
#
|
|
329
|
+
# @option options [Boolean, nil] :force (nil) force updates,
|
|
330
|
+
# overriding the fast-forward check (`--force`)
|
|
331
|
+
#
|
|
332
|
+
# Alias: `:f`
|
|
333
|
+
#
|
|
334
|
+
# @option options [Boolean, nil] :delete (nil) delete the named refs
|
|
335
|
+
# from the remote (`--delete`)
|
|
336
|
+
#
|
|
337
|
+
# @option options [String, Array<String>] :push_option (nil) one or
|
|
338
|
+
# more server-side push option values (`--push-option=<value>`,
|
|
339
|
+
# repeatable)
|
|
340
|
+
#
|
|
341
|
+
# @return [String] the stdout from the push command
|
|
342
|
+
#
|
|
343
|
+
# @raise [ArgumentError] if `remote` is nil when `branch` is given
|
|
344
|
+
#
|
|
345
|
+
# @overload push(remote, branch, tags)
|
|
346
|
+
# Backward-compatible shorthand for `push(remote, branch, tags: tags)`
|
|
347
|
+
#
|
|
348
|
+
# @param remote [String] the remote name or URL to push to
|
|
349
|
+
#
|
|
350
|
+
# @param branch [String] the branch name or refspec to push
|
|
351
|
+
#
|
|
352
|
+
# @param tags [Boolean] whether to push all tags; equivalent to `tags: tags`
|
|
353
|
+
#
|
|
354
|
+
# @return [String] the stdout from the push command
|
|
355
|
+
#
|
|
356
|
+
# @raise [ArgumentError] if a branch is given and remote is nil
|
|
357
|
+
#
|
|
358
|
+
# @raise [ArgumentError] when unsupported option keys are provided
|
|
359
|
+
#
|
|
360
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
361
|
+
#
|
|
362
|
+
def push(remote = nil, branch = nil, opts = nil)
|
|
363
|
+
remote, branch, opts = Private.normalize_push_args(remote, branch, opts)
|
|
364
|
+
SharedPrivate.assert_valid_opts!(PUSH_ALLOWED_OPTS, **opts)
|
|
365
|
+
raise ArgumentError, 'remote is required if branch is specified' if !remote && branch
|
|
366
|
+
|
|
367
|
+
first_result = Private.push_refs(@execution_context, remote, branch, opts)
|
|
368
|
+
return first_result.stdout unless Private.push_tags_separately?(opts)
|
|
369
|
+
|
|
370
|
+
Private.push_tags(@execution_context, remote, opts).stdout
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Option keys accepted by {#add_remote}
|
|
374
|
+
#
|
|
375
|
+
# Derived from the 4.x `REMOTE_ADD_OPTION_MAP` in `Git::Lib`.
|
|
376
|
+
ADD_REMOTE_ALLOWED_OPTS = %i[fetch track].freeze
|
|
377
|
+
private_constant :ADD_REMOTE_ALLOWED_OPTS
|
|
378
|
+
|
|
379
|
+
# Register a new remote in the local repository
|
|
380
|
+
#
|
|
381
|
+
# Associates `name` with `url` and optionally fetches immediately or
|
|
382
|
+
# configures which branches are tracked.
|
|
383
|
+
#
|
|
384
|
+
# @example Add a remote
|
|
385
|
+
# repo.add_remote('upstream', 'https://github.com/user/repo.git')
|
|
386
|
+
#
|
|
387
|
+
# @example Add a remote and fetch immediately
|
|
388
|
+
# repo.add_remote('upstream', 'https://github.com/user/repo.git', fetch: true)
|
|
389
|
+
#
|
|
390
|
+
# @example Add a remote tracking a specific branch
|
|
391
|
+
# repo.add_remote('upstream', 'https://github.com/user/repo.git', track: 'main')
|
|
392
|
+
#
|
|
393
|
+
# @param name [String] the name for the new remote
|
|
394
|
+
#
|
|
395
|
+
# @param url [String, Git::Base] the URL of the remote repository
|
|
396
|
+
#
|
|
397
|
+
# A {Git::Base} instance is accepted for local references and converted
|
|
398
|
+
# to `url.repo.to_s`.
|
|
399
|
+
#
|
|
400
|
+
# @param opts [Hash] options for adding the remote
|
|
401
|
+
#
|
|
402
|
+
# @option opts [Boolean, nil] :fetch (nil) fetch from the remote immediately
|
|
403
|
+
# after adding it (`-f`)
|
|
404
|
+
#
|
|
405
|
+
# The deprecated alias `:with_fetch` is accepted and normalized
|
|
406
|
+
# automatically.
|
|
407
|
+
#
|
|
408
|
+
# @option opts [String, nil] :track (nil) track only the given branch during
|
|
409
|
+
# fetch (`-t`)
|
|
410
|
+
#
|
|
411
|
+
# @return [Git::Remote] the newly added remote
|
|
412
|
+
#
|
|
413
|
+
# @raise [ArgumentError] when unsupported option keys are provided
|
|
414
|
+
#
|
|
415
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
416
|
+
#
|
|
417
|
+
def add_remote(name, url, opts = {})
|
|
418
|
+
url = url.repo.to_s if url.is_a?(Git::Base)
|
|
419
|
+
opts = Private.normalize_add_remote_keys(opts)
|
|
420
|
+
SharedPrivate.assert_valid_opts!(ADD_REMOTE_ALLOWED_OPTS, **opts)
|
|
421
|
+
Git::Commands::Remote::Add.new(@execution_context).call(name, url, **opts)
|
|
422
|
+
|
|
423
|
+
Git::Remote.new(self, name)
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Removes a remote from this repository
|
|
427
|
+
#
|
|
428
|
+
# Deletes the remote named `name` along with its associated configuration,
|
|
429
|
+
# tracking references, and remote-tracking branches.
|
|
430
|
+
#
|
|
431
|
+
# @example Remove a remote named 'upstream'
|
|
432
|
+
# repo.remove_remote('upstream')
|
|
433
|
+
#
|
|
434
|
+
# @param name [String] the name of the remote to remove
|
|
435
|
+
#
|
|
436
|
+
# @return [Git::CommandLineResult] the result of calling `git remote remove`
|
|
437
|
+
#
|
|
438
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
439
|
+
#
|
|
440
|
+
def remove_remote(name)
|
|
441
|
+
Git::Commands::Remote::Remove.new(@execution_context).call(name)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# Sets the URL for an existing remote
|
|
445
|
+
#
|
|
446
|
+
# Replaces the fetch URL configured for the remote named `name`.
|
|
447
|
+
#
|
|
448
|
+
# @example Set the URL for a remote
|
|
449
|
+
# repo.set_remote_url('origin', 'https://github.com/user/repo.git')
|
|
450
|
+
#
|
|
451
|
+
# @example Set the URL from a local repository reference
|
|
452
|
+
# source = Git.open('/path/to/source')
|
|
453
|
+
# repo.set_remote_url('origin', source)
|
|
454
|
+
#
|
|
455
|
+
# @param name [String] the name of the remote to update
|
|
456
|
+
#
|
|
457
|
+
# @param url [String, Git::Base] the new URL for the remote
|
|
458
|
+
#
|
|
459
|
+
# A {Git::Base} instance is accepted for local references and converted
|
|
460
|
+
# to `url.repo.to_s`.
|
|
461
|
+
#
|
|
462
|
+
# @return [Git::Remote] the updated remote
|
|
463
|
+
#
|
|
464
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
465
|
+
#
|
|
466
|
+
def set_remote_url(name, url)
|
|
467
|
+
url = url.repo.to_s if url.is_a?(Git::Base)
|
|
468
|
+
Git::Commands::Remote::SetUrl.new(@execution_context).call(name, url)
|
|
469
|
+
|
|
470
|
+
Git::Remote.new(self, name)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Configures which branches are fetched for a remote
|
|
474
|
+
#
|
|
475
|
+
# Uses `git remote set-branches` to set or append fetch refspecs. When the
|
|
476
|
+
# `add:` option is `false`, the `--add` flag is not passed to the git
|
|
477
|
+
# command and the tracked branch list is replaced.
|
|
478
|
+
#
|
|
479
|
+
# @example Replace fetched branches with a single glob pattern
|
|
480
|
+
# repo.remote_set_branches('origin', 'feature/*')
|
|
481
|
+
#
|
|
482
|
+
# @example Append a glob pattern to existing fetched branches
|
|
483
|
+
# repo.remote_set_branches('origin', 'release/*', add: true)
|
|
484
|
+
#
|
|
485
|
+
# @example Configure multiple explicit branches
|
|
486
|
+
# repo.remote_set_branches('origin', 'main', 'development', 'hotfix')
|
|
487
|
+
#
|
|
488
|
+
# @param name [String] the remote name (for example, `"origin"`)
|
|
489
|
+
#
|
|
490
|
+
# @param branches [Array<String>] branch names or globs (for example, `'*'`)
|
|
491
|
+
#
|
|
492
|
+
# @param add [Boolean] when `true`, append to existing refspecs instead of
|
|
493
|
+
# replacing them
|
|
494
|
+
#
|
|
495
|
+
# @return [void]
|
|
496
|
+
#
|
|
497
|
+
# @raise [ArgumentError] when no branches are provided
|
|
498
|
+
#
|
|
499
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
500
|
+
#
|
|
501
|
+
def remote_set_branches(name, *branches, add: false)
|
|
502
|
+
branch_list = branches.flatten
|
|
503
|
+
raise ArgumentError, 'branches are required' if branch_list.empty?
|
|
504
|
+
|
|
505
|
+
Git::Commands::Remote::SetBranches.new(@execution_context).call(name, *branch_list, add: add)
|
|
506
|
+
|
|
507
|
+
nil
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
# Return the git configuration entries for a named remote
|
|
511
|
+
#
|
|
512
|
+
# Reads `git config --list` and returns all entries whose keys begin with
|
|
513
|
+
# `remote.<name>.`, with the `remote.<name>.` prefix stripped. This
|
|
514
|
+
# typically yields at least `"url"` and `"fetch"` for a configured remote.
|
|
515
|
+
#
|
|
516
|
+
# @example Retrieve the config for the 'origin' remote
|
|
517
|
+
# repo.config_remote('origin')
|
|
518
|
+
# #=> {
|
|
519
|
+
# # 'url' => 'https://github.com/user/repo.git',
|
|
520
|
+
# # 'fetch' => '+refs/heads/*:refs/remotes/origin/*'
|
|
521
|
+
# # }
|
|
522
|
+
#
|
|
523
|
+
# @param name [String] the name of the remote (e.g. `"origin"`)
|
|
524
|
+
#
|
|
525
|
+
# @return [Hash{String => String}] configuration entries for the remote,
|
|
526
|
+
# keyed without the `remote.<name>.` prefix
|
|
527
|
+
#
|
|
528
|
+
# Returns an empty hash when no entries are found.
|
|
529
|
+
#
|
|
530
|
+
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
531
|
+
#
|
|
532
|
+
def config_remote(name)
|
|
533
|
+
prefix = "remote.#{name}."
|
|
534
|
+
Private.config_list(@execution_context).each_with_object({}) do |(key, value), hsh|
|
|
535
|
+
hsh[key.delete_prefix(prefix)] = value if key.start_with?(prefix)
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
# Returns a {Git::Remote} object for the named remote
|
|
540
|
+
#
|
|
541
|
+
# @example Get the default 'origin' remote
|
|
542
|
+
# repo.remote #=> #<Git::Remote 'origin'>
|
|
543
|
+
#
|
|
544
|
+
# @example Get a named remote
|
|
545
|
+
# repo.remote('upstream') #=> #<Git::Remote 'upstream'>
|
|
546
|
+
#
|
|
547
|
+
# @param name [String] the remote name (defaults to `'origin'`)
|
|
548
|
+
#
|
|
549
|
+
# @return [Git::Remote] the remote object
|
|
550
|
+
#
|
|
551
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
552
|
+
#
|
|
553
|
+
def remote(name = 'origin')
|
|
554
|
+
Git::Remote.new(self, name)
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
# Returns all configured remotes as {Git::Remote} objects
|
|
558
|
+
#
|
|
559
|
+
# @example List all remotes
|
|
560
|
+
# repo.remotes #=> [#<Git::Remote 'origin'>, #<Git::Remote 'upstream'>]
|
|
561
|
+
#
|
|
562
|
+
# @return [Array<Git::Remote>] one {Git::Remote} for each configured remote
|
|
563
|
+
#
|
|
564
|
+
# Returns an empty array when no remotes are configured.
|
|
565
|
+
#
|
|
566
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
567
|
+
#
|
|
568
|
+
def remotes
|
|
569
|
+
result = Git::Commands::Remote::List.new(@execution_context).call
|
|
570
|
+
result.stdout.split("\n").map { |name| Git::Remote.new(self, name) }
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
# Helpers private to the `RemoteOperations` topic module
|
|
574
|
+
#
|
|
575
|
+
# @api private
|
|
576
|
+
#
|
|
577
|
+
module Private
|
|
578
|
+
module_function
|
|
579
|
+
|
|
580
|
+
# Resolve the (remote, opts) pair for {#fetch}, supporting the hash-only form
|
|
581
|
+
#
|
|
582
|
+
# `fetch` may be called as `fetch(remote, opts)` or `fetch(opts)`. When a bare
|
|
583
|
+
# options hash is passed the remote is treated as nil. A `:ref` is only
|
|
584
|
+
# meaningful with an explicit remote, so requesting one without a remote (it
|
|
585
|
+
# would otherwise be silently promoted to the remote-name slot) is rejected.
|
|
586
|
+
#
|
|
587
|
+
# @param remote [String, Hash, nil] the remote name, or an options hash
|
|
588
|
+
# @param opts [Hash] the options hash when remote is given positionally
|
|
589
|
+
#
|
|
590
|
+
# @return [Array(String, Hash), Array(nil, Hash)] the resolved remote and opts
|
|
591
|
+
#
|
|
592
|
+
# @raise [ArgumentError] when :ref is supplied without an explicit remote
|
|
593
|
+
#
|
|
594
|
+
# @api private
|
|
595
|
+
#
|
|
596
|
+
def resolve_fetch_target(remote, opts)
|
|
597
|
+
if remote.is_a?(Hash)
|
|
598
|
+
opts = remote
|
|
599
|
+
remote = nil
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
raise ArgumentError, ':ref requires an explicit remote' if remote.nil? && opts.key?(:ref)
|
|
603
|
+
|
|
604
|
+
[remote, opts]
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
# Normalize dash-style option keys to their underscore equivalents
|
|
608
|
+
#
|
|
609
|
+
# Converts any key in {FETCH_KEY_NORMALIZATIONS} from its dash-style symbol
|
|
610
|
+
# form (e.g., `:'update-head-ok'`) to the canonical underscore-style form
|
|
611
|
+
# (e.g., `:update_head_ok`). Unrecognized keys are returned unchanged.
|
|
612
|
+
#
|
|
613
|
+
# @param opts [Hash] the raw options hash passed by the caller
|
|
614
|
+
#
|
|
615
|
+
# @return [Hash] a new hash with all applicable keys normalized
|
|
616
|
+
#
|
|
617
|
+
# @api private
|
|
618
|
+
#
|
|
619
|
+
def normalize_fetch_keys(opts)
|
|
620
|
+
opts.transform_keys do |k|
|
|
621
|
+
sym = k.is_a?(Symbol) ? k : k.to_sym
|
|
622
|
+
FETCH_KEY_NORMALIZATIONS.fetch(sym, sym)
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
# Normalize the flexible argument list accepted by {RemoteOperations#push}
|
|
627
|
+
#
|
|
628
|
+
# Handles three call forms:
|
|
629
|
+
# - `push(opts)` — Hash promoted from `remote` position
|
|
630
|
+
# - `push(remote, opts)` — Hash promoted from `branch` position
|
|
631
|
+
# - `push(remote, branch, true|false)` — Boolean `opts` converted to
|
|
632
|
+
# `{ tags: opts }` for backward compatibility
|
|
633
|
+
#
|
|
634
|
+
# @param remote [String, Hash, nil] remote name, URL, or opts hash
|
|
635
|
+
# @param branch [String, Hash, nil] branch/refspec, or opts hash
|
|
636
|
+
# @param opts [Hash, Boolean, nil] options hash or legacy Boolean shorthand
|
|
637
|
+
#
|
|
638
|
+
# @return [Array(String|nil, String|nil, Hash)] normalized [remote, branch, opts]
|
|
639
|
+
#
|
|
640
|
+
# @api private
|
|
641
|
+
#
|
|
642
|
+
def normalize_push_args(remote, branch, opts)
|
|
643
|
+
if branch.is_a?(Hash)
|
|
644
|
+
opts = branch
|
|
645
|
+
branch = nil
|
|
646
|
+
elsif remote.is_a?(Hash)
|
|
647
|
+
opts = remote
|
|
648
|
+
remote = nil
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
opts ||= {}
|
|
652
|
+
|
|
653
|
+
# Backwards compatibility for `push(remote, branch, true)` to push tags
|
|
654
|
+
# without requiring the caller to use keyword arguments
|
|
655
|
+
|
|
656
|
+
opts = { tags: opts } if [true, false].include?(opts)
|
|
657
|
+
[remote, branch, opts]
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# Issue the refs push (first push when `:tags` is given separately)
|
|
661
|
+
#
|
|
662
|
+
# Strips `:tags` from the options so that only refs — not tags — are pushed
|
|
663
|
+
# in this first call. Tags are pushed in a separate call when
|
|
664
|
+
# {push_tags_separately?} is true.
|
|
665
|
+
#
|
|
666
|
+
# @param execution_context [Git::ExecutionContext::Repository] the repository execution context
|
|
667
|
+
# @param remote [String, nil] remote name or URL
|
|
668
|
+
# @param branch [String, nil] branch or refspec
|
|
669
|
+
# @param opts [Hash] push options (`:tags` key will be stripped)
|
|
670
|
+
#
|
|
671
|
+
# @return [Git::CommandLineResult]
|
|
672
|
+
#
|
|
673
|
+
# @api private
|
|
674
|
+
#
|
|
675
|
+
def push_refs(execution_context, remote, branch, opts)
|
|
676
|
+
positionals = [remote, branch].compact
|
|
677
|
+
Git::Commands::Push.new(execution_context).call(*positionals, **opts.except(:tags))
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
# Return true when tags must be pushed in a second separate invocation
|
|
681
|
+
#
|
|
682
|
+
# Tags are pushed separately when `:tags` is truthy AND `:mirror` is not set.
|
|
683
|
+
# When `:mirror` is set, the mirror push already includes all refs and tags,
|
|
684
|
+
# so a second tags-only call would be redundant.
|
|
685
|
+
#
|
|
686
|
+
# @param opts [Hash] the normalized push options
|
|
687
|
+
#
|
|
688
|
+
# @return [Boolean]
|
|
689
|
+
#
|
|
690
|
+
# @api private
|
|
691
|
+
#
|
|
692
|
+
def push_tags_separately?(opts)
|
|
693
|
+
opts[:tags] && !opts[:mirror]
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
# Issue the tags push (second push when `:tags` is requested without `:mirror`)
|
|
697
|
+
#
|
|
698
|
+
# @param execution_context [Git::ExecutionContext::Repository] the repository execution context
|
|
699
|
+
# @param remote [String, nil] remote name or URL
|
|
700
|
+
# @param opts [Hash] push options (`:tags` key included to emit `--tags`)
|
|
701
|
+
#
|
|
702
|
+
# @return [Git::CommandLineResult]
|
|
703
|
+
#
|
|
704
|
+
# @api private
|
|
705
|
+
#
|
|
706
|
+
def push_tags(execution_context, remote, opts)
|
|
707
|
+
Git::Commands::Push.new(execution_context).call(*[remote].compact, **opts)
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Normalize deprecated {#add_remote} option keys to their canonical equivalents
|
|
711
|
+
#
|
|
712
|
+
# Renames the deprecated `:with_fetch` key to `:fetch`, removing it from
|
|
713
|
+
# the copy. When both keys are present, `:with_fetch` takes precedence.
|
|
714
|
+
#
|
|
715
|
+
# @param opts [Hash] the raw options hash passed by the caller
|
|
716
|
+
#
|
|
717
|
+
# @return [Hash] a new hash with all applicable keys normalized
|
|
718
|
+
#
|
|
719
|
+
# @api private
|
|
720
|
+
#
|
|
721
|
+
def normalize_add_remote_keys(opts)
|
|
722
|
+
normalized = opts.dup
|
|
723
|
+
normalized[:fetch] = normalized.delete(:with_fetch) if normalized.key?(:with_fetch)
|
|
724
|
+
normalized
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
# Retrieve all config entries as a flat hash
|
|
728
|
+
#
|
|
729
|
+
# Runs `git config --list` and parses each `key=value` line into a hash.
|
|
730
|
+
# When no value is present for a key, the value defaults to an empty string.
|
|
731
|
+
#
|
|
732
|
+
# @param execution_context [Git::ExecutionContext::Repository] the
|
|
733
|
+
# execution context for the repository
|
|
734
|
+
#
|
|
735
|
+
# @return [Hash{String => String}] all visible config entries, keyed by
|
|
736
|
+
# their full dotted key names
|
|
737
|
+
#
|
|
738
|
+
# For example, `"remote.origin.url"` is a valid key.
|
|
739
|
+
#
|
|
740
|
+
# @api private
|
|
741
|
+
#
|
|
742
|
+
def config_list(execution_context)
|
|
743
|
+
lines = Git::Commands::ConfigOptionSyntax::List.new(execution_context).call.stdout.split("\n")
|
|
744
|
+
lines.each_with_object({}) do |line, hsh|
|
|
745
|
+
key, value = line.split('=', 2)
|
|
746
|
+
hsh[key] = value || ''
|
|
747
|
+
end
|
|
748
|
+
end
|
|
749
|
+
end
|
|
750
|
+
private_constant :Private
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
end
|