git 4.3.2 → 5.0.0.beta.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.
- checksums.yaml +4 -4
- data/.github/copilot-instructions.md +73 -2705
- data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
- 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/KEYWORD_ARG_REMEDIATION.md +22 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +600 -0
- data/.github/skills/facade-implementation/REFERENCE.md +840 -0
- data/.github/skills/facade-implementation/SKILL.md +274 -0
- data/.github/skills/facade-test-conventions/SKILL.md +394 -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 +12 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -40
- data/CONTRIBUTING.md +694 -53
- data/README.md +67 -15
- data/Rakefile +61 -9
- data/UPGRADING.md +141 -0
- data/commitlint.test +4 -0
- data/git.gemspec +18 -7
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/branch.rb +369 -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 +122 -24
- data/lib/git/command_line/base.rb +255 -0
- data/lib/git/command_line/capturing.rb +251 -0
- data/lib/git/command_line/result.rb +96 -0
- data/lib/git/command_line/streaming.rb +196 -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 +404 -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 +369 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +216 -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 +107 -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 +57 -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 +87 -0
- data/lib/git/config.rb +17 -0
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +665 -0
- data/lib/git/deprecation.rb +9 -0
- data/lib/git/detached_head_info.rb +54 -0
- data/lib/git/diff.rb +293 -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 +67 -19
- data/lib/git/diff_result.rb +32 -0
- data/lib/git/diff_stats.rb +51 -14
- data/lib/git/dirstat_info.rb +86 -0
- data/lib/git/errors.rb +65 -2
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +136 -0
- data/lib/git/execution_context.rb +501 -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/log.rb +9 -2
- data/lib/git/object.rb +90 -27
- data/lib/git/parsers/branch.rb +224 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/config_entry.rb +110 -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_remote.rb +79 -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 +120 -9
- data/lib/git/repository/branching.rb +743 -0
- data/lib/git/repository/committing.rb +187 -0
- data/lib/git/repository/configuring.rb +351 -0
- data/lib/git/repository/context_helpers.rb +264 -0
- data/lib/git/repository/diffing.rb +775 -0
- data/lib/git/repository/factories.rb +682 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +247 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +357 -0
- data/lib/git/repository/object_operations.rb +1199 -0
- data/lib/git/repository/path_resolver.rb +207 -0
- data/lib/git/repository/remote_operations.rb +898 -0
- data/lib/git/repository/shared_private.rb +51 -0
- data/lib/git/repository/staging.rb +554 -0
- data/lib/git/repository/stashing.rb +143 -0
- data/lib/git/repository/status_operations.rb +201 -0
- data/lib/git/repository/worktree_operations.rb +159 -0
- data/lib/git/repository.rb +203 -1
- data/lib/git/stash.rb +78 -4
- data/lib/git/stash_info.rb +104 -0
- data/lib/git/stashes.rb +125 -13
- data/lib/git/status.rb +215 -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 +108 -6
- data/lib/git/worktrees.rb +94 -7
- data/lib/git.rb +260 -61
- data/redesign/1_architecture_existing.md +54 -18
- data/redesign/2_architecture_redesign.md +365 -46
- data/redesign/3_architecture_implementation.md +1497 -63
- data/redesign/Phase 4 - Step A.md +360 -0
- data/redesign/beta_release.md +107 -0
- data/redesign/c1c2_audit.md +566 -0
- data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
- data/redesign/config_design.rb +501 -0
- 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 +365 -22
- data/lib/git/base.rb +0 -1128
- data/lib/git/index.rb +0 -6
- data/lib/git/lib.rb +0 -2277
- 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,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
class Repository
|
|
5
|
+
# Internal helpers shared by `Git::Repository::*` topic modules
|
|
6
|
+
#
|
|
7
|
+
# Methods defined here use `module_function` so they are callable as
|
|
8
|
+
# `SharedPrivate.foo(...)` from any topic module within `Git::Repository`
|
|
9
|
+
# without being added to `Git::Repository`'s instance namespace via `include`.
|
|
10
|
+
#
|
|
11
|
+
# The constant is declared `private_constant` so it is inaccessible from
|
|
12
|
+
# outside the `Git::Repository` class body; callers inside topic modules use
|
|
13
|
+
# the short unqualified form `SharedPrivate.foo(...)`.
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
module SharedPrivate
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
# Validate that `options` contains only keys listed in `allowed`
|
|
21
|
+
#
|
|
22
|
+
# Used by facade methods to enforce that only documented options (those
|
|
23
|
+
# named in `@option` tags) are accepted, even when the underlying command
|
|
24
|
+
# class would accept more keys. This prevents silent expansion of the
|
|
25
|
+
# facade's public contract.
|
|
26
|
+
#
|
|
27
|
+
# @example Reject an undocumented option
|
|
28
|
+
# ADD_ALLOWED_OPTS = %i[all force].freeze
|
|
29
|
+
#
|
|
30
|
+
# SharedPrivate.assert_valid_opts!(ADD_ALLOWED_OPTS, bogus: true)
|
|
31
|
+
# #=> raises ArgumentError: Unknown options: bogus
|
|
32
|
+
#
|
|
33
|
+
# @param allowed [Array<Symbol>] the keys permitted by the facade method
|
|
34
|
+
#
|
|
35
|
+
# @param options [Hash] the options hash provided by the caller
|
|
36
|
+
#
|
|
37
|
+
# @return [void]
|
|
38
|
+
#
|
|
39
|
+
# @raise [ArgumentError] when `options` contains any key not in `allowed`
|
|
40
|
+
#
|
|
41
|
+
def assert_valid_opts!(allowed, **options)
|
|
42
|
+
unknown = options.keys - allowed
|
|
43
|
+
return if unknown.empty?
|
|
44
|
+
|
|
45
|
+
raise ArgumentError, "Unknown options: #{unknown.join(', ')}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private_constant :SharedPrivate
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/add'
|
|
4
|
+
require 'git/commands/am/apply'
|
|
5
|
+
require 'git/commands/apply'
|
|
6
|
+
require 'git/commands/clean'
|
|
7
|
+
require 'git/commands/ls_files'
|
|
8
|
+
require 'git/commands/mv'
|
|
9
|
+
require 'git/commands/read_tree'
|
|
10
|
+
require 'git/commands/reset'
|
|
11
|
+
require 'git/commands/rm'
|
|
12
|
+
require 'git/escaped_path'
|
|
13
|
+
require 'git/repository/shared_private'
|
|
14
|
+
|
|
15
|
+
module Git
|
|
16
|
+
class Repository
|
|
17
|
+
# Facade methods for staging-area operations: adding, resetting, moving,
|
|
18
|
+
# removing, and cleaning files
|
|
19
|
+
#
|
|
20
|
+
# Included by {Git::Repository}.
|
|
21
|
+
#
|
|
22
|
+
# @api public
|
|
23
|
+
#
|
|
24
|
+
module Staging
|
|
25
|
+
# Option keys accepted by {#add}
|
|
26
|
+
ADD_ALLOWED_OPTS = %i[all force].freeze
|
|
27
|
+
private_constant :ADD_ALLOWED_OPTS
|
|
28
|
+
|
|
29
|
+
# Update the index with the current content found in the working tree
|
|
30
|
+
#
|
|
31
|
+
# @overload add(paths = '.', **options)
|
|
32
|
+
#
|
|
33
|
+
# @example Stage all changed files
|
|
34
|
+
# repo.add
|
|
35
|
+
#
|
|
36
|
+
# @example Stage a specific file
|
|
37
|
+
# repo.add('README.md')
|
|
38
|
+
#
|
|
39
|
+
# @example Stage all changes including deletions
|
|
40
|
+
# repo.add(all: true)
|
|
41
|
+
#
|
|
42
|
+
# @param paths [String, Array<String>] a file or files to add (relative to
|
|
43
|
+
# the worktree root); defaults to `'.'` (all files)
|
|
44
|
+
#
|
|
45
|
+
# @param options [Hash] options for the add command
|
|
46
|
+
#
|
|
47
|
+
# @option options [Boolean, nil] :all (nil) add, modify, and remove index
|
|
48
|
+
# entries to match the worktree
|
|
49
|
+
#
|
|
50
|
+
# @option options [Boolean, nil] :force (nil) allow adding otherwise ignored
|
|
51
|
+
# files
|
|
52
|
+
#
|
|
53
|
+
# @return [String] git's stdout from the add
|
|
54
|
+
#
|
|
55
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
56
|
+
#
|
|
57
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
58
|
+
#
|
|
59
|
+
def add(paths = '.', **)
|
|
60
|
+
SharedPrivate.assert_valid_opts!(ADD_ALLOWED_OPTS, **)
|
|
61
|
+
Git::Commands::Add.new(@execution_context).call(*Array(paths), **).stdout
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Option keys accepted by {#reset}
|
|
65
|
+
RESET_ALLOWED_OPTS = %i[hard].freeze
|
|
66
|
+
private_constant :RESET_ALLOWED_OPTS
|
|
67
|
+
|
|
68
|
+
# Reset the current HEAD to a specified state
|
|
69
|
+
#
|
|
70
|
+
# @example Reset the index and working tree to HEAD
|
|
71
|
+
# repo.reset
|
|
72
|
+
#
|
|
73
|
+
# @example Hard reset to a specific commit
|
|
74
|
+
# repo.reset('HEAD~1', hard: true)
|
|
75
|
+
#
|
|
76
|
+
# @param commitish [String, nil] the commit or tree-ish to reset to;
|
|
77
|
+
# defaults to HEAD when `nil`
|
|
78
|
+
#
|
|
79
|
+
# @param opts [Hash] options for the reset command
|
|
80
|
+
#
|
|
81
|
+
# @option opts [Boolean, nil] :hard (nil) reset the index and working
|
|
82
|
+
# tree; discards all tracked changes
|
|
83
|
+
#
|
|
84
|
+
# @return [String] git's stdout from the reset
|
|
85
|
+
#
|
|
86
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
87
|
+
#
|
|
88
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
89
|
+
#
|
|
90
|
+
def reset(commitish = nil, opts = {})
|
|
91
|
+
SharedPrivate.assert_valid_opts!(RESET_ALLOWED_OPTS, **opts)
|
|
92
|
+
Git::Commands::Reset.new(@execution_context).call(commitish, **opts).stdout
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Reset the current HEAD to a specified state with `--hard`
|
|
96
|
+
#
|
|
97
|
+
# @deprecated Use {#reset} with `hard: true` instead.
|
|
98
|
+
#
|
|
99
|
+
# @example Hard reset to HEAD
|
|
100
|
+
# repo.reset_hard
|
|
101
|
+
#
|
|
102
|
+
# @example Hard reset to a specific commit
|
|
103
|
+
# repo.reset_hard('HEAD~1')
|
|
104
|
+
#
|
|
105
|
+
# @param commitish [String, nil] the commit or tree-ish to reset to;
|
|
106
|
+
# defaults to HEAD when `nil`
|
|
107
|
+
#
|
|
108
|
+
# @param opts [Hash] options passed through to {#reset}
|
|
109
|
+
#
|
|
110
|
+
# @return [String] git's stdout from the reset
|
|
111
|
+
#
|
|
112
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
113
|
+
#
|
|
114
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
115
|
+
#
|
|
116
|
+
def reset_hard(commitish = nil, opts = {})
|
|
117
|
+
Git::Deprecation.warn(
|
|
118
|
+
'Git::Repository::Staging#reset_hard is deprecated and will be removed in a future version. ' \
|
|
119
|
+
'Use #reset(commitish, hard: true) instead.'
|
|
120
|
+
)
|
|
121
|
+
reset(commitish, **opts, hard: true)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Apply a patch file to the working tree
|
|
125
|
+
#
|
|
126
|
+
# Reads the unified diff in `file` and applies it to the working tree via
|
|
127
|
+
# `git apply`. If `file` does not exist, the method returns `nil` without
|
|
128
|
+
# calling git — preserving the 4.x `Git::Base#apply` no-op contract.
|
|
129
|
+
#
|
|
130
|
+
# @example Apply a patch to the working tree
|
|
131
|
+
# repo.apply('fix.patch')
|
|
132
|
+
#
|
|
133
|
+
# @param file [String] path to the patch file to apply
|
|
134
|
+
#
|
|
135
|
+
# @return [String] git's stdout (usually empty on success)
|
|
136
|
+
#
|
|
137
|
+
# @return [nil] when `file` does not exist
|
|
138
|
+
#
|
|
139
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
140
|
+
#
|
|
141
|
+
def apply(file)
|
|
142
|
+
return unless File.exist?(file)
|
|
143
|
+
|
|
144
|
+
Git::Commands::Apply.new(@execution_context).call(file, chdir: @execution_context.git_work_dir).stdout
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Apply a series of patches from a mailbox file to the current branch
|
|
148
|
+
#
|
|
149
|
+
# Reads the mbox-format file in `file` and applies the patches via
|
|
150
|
+
# `git am`. If `file` does not exist, the method returns `nil` without
|
|
151
|
+
# calling git — preserving the 4.x `Git::Base#apply_mail` no-op contract.
|
|
152
|
+
#
|
|
153
|
+
# @example Apply patches from a mailbox
|
|
154
|
+
# repo.apply_mail('patches.mbox')
|
|
155
|
+
#
|
|
156
|
+
# @param file [String] path to the mbox patch file to apply
|
|
157
|
+
#
|
|
158
|
+
# @return [String] git's stdout (usually empty on success)
|
|
159
|
+
#
|
|
160
|
+
# @return [nil] when `file` does not exist
|
|
161
|
+
#
|
|
162
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
163
|
+
#
|
|
164
|
+
def apply_mail(file)
|
|
165
|
+
return unless File.exist?(file)
|
|
166
|
+
|
|
167
|
+
Git::Commands::Am::Apply.new(@execution_context).call(file, chdir: @execution_context.git_work_dir).stdout
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Option keys accepted by {#read_tree}
|
|
171
|
+
READ_TREE_ALLOWED_OPTS = %i[prefix].freeze
|
|
172
|
+
private_constant :READ_TREE_ALLOWED_OPTS
|
|
173
|
+
|
|
174
|
+
# Read tree information into the index
|
|
175
|
+
#
|
|
176
|
+
# Reads the named tree object into the index. This is a low-level plumbing
|
|
177
|
+
# operation used to stage the contents of a tree without updating the
|
|
178
|
+
# working tree. Typically called before {#checkout_index} or as part of
|
|
179
|
+
# custom merge flows.
|
|
180
|
+
#
|
|
181
|
+
# @example Read HEAD into the index
|
|
182
|
+
# repo.read_tree('HEAD')
|
|
183
|
+
#
|
|
184
|
+
# @example Read a tree under a prefix directory
|
|
185
|
+
# repo.read_tree('HEAD', { prefix: 'subdir/' })
|
|
186
|
+
#
|
|
187
|
+
# @param treeish [String] the tree-ish to read into the index
|
|
188
|
+
#
|
|
189
|
+
# @param opts [Hash] options for the read-tree command
|
|
190
|
+
#
|
|
191
|
+
# @option opts [String] :prefix (nil) keep the current index contents and
|
|
192
|
+
# read the named tree-ish under the directory at the given prefix
|
|
193
|
+
# (`--prefix=<prefix>`)
|
|
194
|
+
#
|
|
195
|
+
# @return [String] git's stdout (usually empty on success)
|
|
196
|
+
#
|
|
197
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
198
|
+
#
|
|
199
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
200
|
+
#
|
|
201
|
+
def read_tree(treeish, opts = {})
|
|
202
|
+
SharedPrivate.assert_valid_opts!(READ_TREE_ALLOWED_OPTS, **opts)
|
|
203
|
+
Git::Commands::ReadTree.new(@execution_context).call(treeish, **opts).stdout
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Option keys accepted by {#rm}
|
|
207
|
+
RM_ALLOWED_OPTS = %i[
|
|
208
|
+
force f dry_run n r cached ignore_unmatch sparse quiet q
|
|
209
|
+
pathspec_from_file pathspec_file_nul
|
|
210
|
+
].freeze
|
|
211
|
+
private_constant :RM_ALLOWED_OPTS
|
|
212
|
+
|
|
213
|
+
# Remove file(s) from the working tree and the index
|
|
214
|
+
#
|
|
215
|
+
# @example Remove a single file
|
|
216
|
+
# repo.rm('obsolete.txt', { force: true })
|
|
217
|
+
#
|
|
218
|
+
# @example Remove a directory recursively
|
|
219
|
+
# repo.rm('build', { r: true })
|
|
220
|
+
#
|
|
221
|
+
# @example Remove from the index only, keeping the working tree copy
|
|
222
|
+
# repo.rm('keep_me.txt', { cached: true })
|
|
223
|
+
#
|
|
224
|
+
# @param path [String, Array<String>] a file or files to remove (relative to
|
|
225
|
+
# the worktree root); defaults to `'.'` (all files)
|
|
226
|
+
#
|
|
227
|
+
# @param opts [Hash] options for the rm command
|
|
228
|
+
#
|
|
229
|
+
# @option opts [Boolean, nil] :force (nil) override the up-to-date check and
|
|
230
|
+
# remove files with local modifications (alias: `:f`)
|
|
231
|
+
#
|
|
232
|
+
# @option opts [Boolean, nil] :f (nil) alias for `:force`
|
|
233
|
+
#
|
|
234
|
+
# @option opts [Boolean, nil] :dry_run (nil) do not actually remove any files;
|
|
235
|
+
# only show what would be removed (alias: `:n`)
|
|
236
|
+
#
|
|
237
|
+
# @option opts [Boolean, nil] :n (nil) alias for `:dry_run`
|
|
238
|
+
#
|
|
239
|
+
# @option opts [Boolean, nil] :r (nil) allow recursive removal when a leading
|
|
240
|
+
# directory name is given
|
|
241
|
+
#
|
|
242
|
+
# @option opts [Boolean, nil] :cached (nil) only remove from the index, keeping
|
|
243
|
+
# the working tree files
|
|
244
|
+
#
|
|
245
|
+
# @option opts [Boolean, nil] :ignore_unmatch (nil) exit with a zero status even
|
|
246
|
+
# if no files matched
|
|
247
|
+
#
|
|
248
|
+
# @option opts [Boolean, nil] :sparse (nil) allow updating index entries outside
|
|
249
|
+
# of the sparse-checkout cone
|
|
250
|
+
#
|
|
251
|
+
# @option opts [Boolean, nil] :quiet (nil) suppress the one-line-per-file output
|
|
252
|
+
# (alias: `:q`)
|
|
253
|
+
#
|
|
254
|
+
# @option opts [Boolean, nil] :q (nil) alias for `:quiet`
|
|
255
|
+
#
|
|
256
|
+
# @option opts [String] :pathspec_from_file (nil) read pathspec from the given
|
|
257
|
+
# file, one pathspec element per line; pass `-` to read from standard input
|
|
258
|
+
#
|
|
259
|
+
# @option opts [Boolean, nil] :pathspec_file_nul (nil) when used with
|
|
260
|
+
# `:pathspec_from_file`, separate pathspec elements with NUL instead of newlines
|
|
261
|
+
#
|
|
262
|
+
# @return [String] git's stdout from the rm
|
|
263
|
+
#
|
|
264
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
265
|
+
#
|
|
266
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
267
|
+
#
|
|
268
|
+
def rm(path = '.', opts = {})
|
|
269
|
+
SharedPrivate.assert_valid_opts!(RM_ALLOWED_OPTS, **opts)
|
|
270
|
+
Git::Commands::Rm.new(@execution_context).call(*Array(path), **opts).stdout
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
alias remove rm
|
|
274
|
+
|
|
275
|
+
# Option keys accepted by {#mv}
|
|
276
|
+
MV_ALLOWED_OPTS = %i[force f dry_run n k].freeze
|
|
277
|
+
private_constant :MV_ALLOWED_OPTS
|
|
278
|
+
|
|
279
|
+
# Move or rename a file, directory, or symlink in the working tree
|
|
280
|
+
#
|
|
281
|
+
# Updates the index after successful completion, but the change must still
|
|
282
|
+
# be committed.
|
|
283
|
+
#
|
|
284
|
+
# @example Move a single file
|
|
285
|
+
# repo.mv('old.rb', 'new.rb')
|
|
286
|
+
#
|
|
287
|
+
# @example Move multiple files to a directory
|
|
288
|
+
# repo.mv(['file1.rb', 'file2.rb'], 'destination_dir/')
|
|
289
|
+
#
|
|
290
|
+
# @example Force overwrite if destination exists
|
|
291
|
+
# repo.mv('source.rb', 'dest.rb', force: true)
|
|
292
|
+
#
|
|
293
|
+
# @param source [String, Array<String>] one or more source file(s),
|
|
294
|
+
# directory(ies), or symlink(s) to move (relative to the worktree root)
|
|
295
|
+
#
|
|
296
|
+
# @param destination [String] the destination file or directory
|
|
297
|
+
#
|
|
298
|
+
# @param options [Hash] options for the mv command
|
|
299
|
+
#
|
|
300
|
+
# @option options [Boolean, nil] :force (nil) force renaming or moving even
|
|
301
|
+
# if the destination exists (alias: `:f`)
|
|
302
|
+
#
|
|
303
|
+
# @option options [Boolean, nil] :f (nil) alias for `:force`
|
|
304
|
+
#
|
|
305
|
+
# @option options [Boolean, nil] :dry_run (nil) do not actually move any
|
|
306
|
+
# files; only show what would happen (alias: `:n`)
|
|
307
|
+
#
|
|
308
|
+
# @option options [Boolean, nil] :n (nil) alias for `:dry_run`
|
|
309
|
+
#
|
|
310
|
+
# @option options [Boolean, nil] :k (nil) skip move or rename actions which
|
|
311
|
+
# would lead to an error
|
|
312
|
+
#
|
|
313
|
+
# @return [String] git's stdout from the mv command
|
|
314
|
+
#
|
|
315
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
316
|
+
#
|
|
317
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
318
|
+
#
|
|
319
|
+
def mv(source, destination, options = {})
|
|
320
|
+
SharedPrivate.assert_valid_opts!(MV_ALLOWED_OPTS, **options)
|
|
321
|
+
Git::Commands::Mv.new(@execution_context).call(*Array(source), destination, verbose: true, **options).stdout
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Option keys accepted by {#clean}
|
|
325
|
+
#
|
|
326
|
+
# The deprecated `:ff` and `:force_force` keys are handled by
|
|
327
|
+
# {Git::Repository::Staging::Private.migrate_clean_legacy_options} before this
|
|
328
|
+
# whitelist is enforced, so they are intentionally absent here.
|
|
329
|
+
CLEAN_ALLOWED_OPTS = %i[d force f dry_run n quiet q exclude e x X pathspec].freeze
|
|
330
|
+
private_constant :CLEAN_ALLOWED_OPTS
|
|
331
|
+
|
|
332
|
+
# Remove untracked files from the working tree
|
|
333
|
+
#
|
|
334
|
+
# @example Remove untracked files
|
|
335
|
+
# repo.clean({ force: true })
|
|
336
|
+
#
|
|
337
|
+
# @example Remove untracked files and directories
|
|
338
|
+
# repo.clean({ force: true, d: true })
|
|
339
|
+
#
|
|
340
|
+
# @example Remove untracked and ignored files
|
|
341
|
+
# repo.clean({ force: true, x: true })
|
|
342
|
+
#
|
|
343
|
+
# @param opts [Hash] options for the clean command
|
|
344
|
+
#
|
|
345
|
+
# @option opts [Boolean, nil] :d (nil) recurse into untracked directories
|
|
346
|
+
#
|
|
347
|
+
# @option opts [Boolean, Integer, nil] :force (nil) force the removal of
|
|
348
|
+
# untracked files; pass `2` to also remove untracked nested git repositories
|
|
349
|
+
# (alias: `:f`)
|
|
350
|
+
#
|
|
351
|
+
# @option opts [Boolean, Integer, nil] :f (nil) alias for `:force`
|
|
352
|
+
#
|
|
353
|
+
# @option opts [Boolean, nil] :dry_run (nil) do not actually remove anything,
|
|
354
|
+
# just show what would be done (alias: `:n`)
|
|
355
|
+
#
|
|
356
|
+
# @option opts [Boolean, nil] :n (nil) alias for `:dry_run`
|
|
357
|
+
#
|
|
358
|
+
# @option opts [Boolean, nil] :quiet (nil) be quiet, only report errors
|
|
359
|
+
# (alias: `:q`)
|
|
360
|
+
#
|
|
361
|
+
# @option opts [Boolean, nil] :q (nil) alias for `:quiet`
|
|
362
|
+
#
|
|
363
|
+
# @option opts [String, Array<String>] :exclude (nil) use the given exclude
|
|
364
|
+
# pattern in addition to the standard ignore rules (alias: `:e`)
|
|
365
|
+
#
|
|
366
|
+
# @option opts [String, Array<String>] :e (nil) alias for `:exclude`
|
|
367
|
+
#
|
|
368
|
+
# @option opts [Boolean, nil] :x (nil) don't use the standard ignore rules
|
|
369
|
+
#
|
|
370
|
+
# @option opts [Boolean, nil] :X (nil) remove only files ignored by git
|
|
371
|
+
#
|
|
372
|
+
# @option opts [String, Array<String>] :pathspec (nil) limit cleaning to files
|
|
373
|
+
# matching the given pathspec(s)
|
|
374
|
+
#
|
|
375
|
+
# @return [String] git's stdout from the clean
|
|
376
|
+
#
|
|
377
|
+
# @raise [ArgumentError] when unsupported options are provided, or when a
|
|
378
|
+
# deprecated `:ff`/`:force_force` value is not `true`, `false`, or `nil`
|
|
379
|
+
#
|
|
380
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
381
|
+
#
|
|
382
|
+
def clean(opts = {})
|
|
383
|
+
opts = Private.migrate_clean_legacy_options(opts)
|
|
384
|
+
SharedPrivate.assert_valid_opts!(CLEAN_ALLOWED_OPTS, **opts)
|
|
385
|
+
Git::Commands::Clean.new(@execution_context).call(**opts).stdout
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# List the files in the working tree that are ignored by git
|
|
389
|
+
#
|
|
390
|
+
# Runs `git ls-files --others --ignored --exclude-standard` and returns the
|
|
391
|
+
# ignored files as repository-relative paths.
|
|
392
|
+
#
|
|
393
|
+
# @example List ignored files
|
|
394
|
+
# repo.ignored_files #=> ["coverage/index.html", "tmp/cache.db"]
|
|
395
|
+
#
|
|
396
|
+
# @example No ignored files
|
|
397
|
+
# repo.ignored_files #=> []
|
|
398
|
+
#
|
|
399
|
+
# @return [Array<String>] repository-relative paths of ignored files; empty
|
|
400
|
+
# when there are none
|
|
401
|
+
#
|
|
402
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
403
|
+
#
|
|
404
|
+
def ignored_files
|
|
405
|
+
Git::Commands::LsFiles.new(@execution_context).call(
|
|
406
|
+
others: true, ignored: true, exclude_standard: true
|
|
407
|
+
).stdout.split("\n").map { |f| Private.unescape_quoted_path(f) }
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# Private helpers local to {Git::Repository::Staging}
|
|
411
|
+
#
|
|
412
|
+
# @api private
|
|
413
|
+
#
|
|
414
|
+
module Private
|
|
415
|
+
module_function
|
|
416
|
+
|
|
417
|
+
# Translate deprecated `git clean` option keys into their modern form
|
|
418
|
+
#
|
|
419
|
+
# Maps the legacy `:ff` and `:force_force` boolean options onto the
|
|
420
|
+
# `:force` option, emitting a deprecation warning for each.
|
|
421
|
+
#
|
|
422
|
+
# @param opts [Hash] the caller-provided clean options
|
|
423
|
+
#
|
|
424
|
+
# @return [Hash] a new options hash with deprecated keys translated
|
|
425
|
+
#
|
|
426
|
+
# @raise [ArgumentError] when a deprecated value is not `true`, `false`, or `nil`
|
|
427
|
+
#
|
|
428
|
+
def migrate_clean_legacy_options(opts)
|
|
429
|
+
opts = deprecate_clean_option(opts, :ff, ':ff option is deprecated. Use force: 2 instead.')
|
|
430
|
+
deprecate_clean_option(opts, :force_force, ':force_force option is deprecated. Use force: 2 instead.')
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# Translate a single deprecated clean option key onto `:force`
|
|
434
|
+
#
|
|
435
|
+
# @param opts [Hash] the clean options
|
|
436
|
+
#
|
|
437
|
+
# @param key [Symbol] the deprecated option key (`:ff` or `:force_force`)
|
|
438
|
+
#
|
|
439
|
+
# @param message [String] the deprecation message to emit
|
|
440
|
+
#
|
|
441
|
+
# @return [Hash] a new options hash with the deprecated key removed
|
|
442
|
+
#
|
|
443
|
+
# @raise [ArgumentError] when the deprecated value is not `true`, `false`,
|
|
444
|
+
# or `nil`
|
|
445
|
+
#
|
|
446
|
+
def deprecate_clean_option(opts, key, message)
|
|
447
|
+
return opts unless opts.key?(key)
|
|
448
|
+
|
|
449
|
+
opts = opts.dup
|
|
450
|
+
deprecated_value = opts.delete(key)
|
|
451
|
+
validate_deprecated_clean_option_value!(key, deprecated_value)
|
|
452
|
+
|
|
453
|
+
Git::Deprecation.warn(message)
|
|
454
|
+
return opts unless deprecated_value
|
|
455
|
+
|
|
456
|
+
opts[:force] = merge_clean_force_option(opts[:force], force_specified: force_option_specified?(opts))
|
|
457
|
+
opts
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
# Whether the caller explicitly set a non-nil `:force` value
|
|
461
|
+
#
|
|
462
|
+
# @param opts [Hash] the clean options
|
|
463
|
+
#
|
|
464
|
+
# @return [Boolean] true if `:force` was set to a non-nil value, false
|
|
465
|
+
# otherwise
|
|
466
|
+
#
|
|
467
|
+
def force_option_specified?(opts)
|
|
468
|
+
opts.key?(:force) && !opts[:force].nil?
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Validate the value passed to a deprecated clean option
|
|
472
|
+
#
|
|
473
|
+
# @param key [Symbol] the deprecated option key
|
|
474
|
+
#
|
|
475
|
+
# @param value [Object] the value provided for the deprecated key
|
|
476
|
+
#
|
|
477
|
+
# @return [void]
|
|
478
|
+
#
|
|
479
|
+
# @raise [ArgumentError] when `value` is not `true`, `false`, or `nil`
|
|
480
|
+
#
|
|
481
|
+
def validate_deprecated_clean_option_value!(key, value)
|
|
482
|
+
return if value.nil? || value == true || value == false
|
|
483
|
+
|
|
484
|
+
raise ArgumentError, "#{key} option only accepts true, false, or nil"
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# Merge a deprecated force request into the existing `:force` value
|
|
488
|
+
#
|
|
489
|
+
# @param existing_force [Boolean, Integer, nil] the caller's `:force` value
|
|
490
|
+
#
|
|
491
|
+
# @param force_specified [Boolean] whether the caller explicitly set `:force`
|
|
492
|
+
#
|
|
493
|
+
# @return [Integer] the resolved `:force` value
|
|
494
|
+
#
|
|
495
|
+
def merge_clean_force_option(existing_force, force_specified: false)
|
|
496
|
+
return 2 unless force_specified
|
|
497
|
+
|
|
498
|
+
normalized_force = normalize_clean_force_option(existing_force)
|
|
499
|
+
|
|
500
|
+
case normalized_force
|
|
501
|
+
when Integer then merge_integer_clean_force_option(normalized_force)
|
|
502
|
+
when false then 2
|
|
503
|
+
else normalized_force
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# Merge an integer `:force` value with the deprecated force request
|
|
508
|
+
#
|
|
509
|
+
# @param normalized_force [Integer] the caller's normalized `:force` value
|
|
510
|
+
#
|
|
511
|
+
# @return [Integer] the resolved `:force` value
|
|
512
|
+
#
|
|
513
|
+
def merge_integer_clean_force_option(normalized_force)
|
|
514
|
+
return normalized_force if normalized_force < 1
|
|
515
|
+
|
|
516
|
+
[normalized_force, 2].max
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
# Normalize a `:force` value, coercing `true` to the integer `1`
|
|
520
|
+
#
|
|
521
|
+
# @param value [Boolean, Integer, nil] the `:force` value
|
|
522
|
+
#
|
|
523
|
+
# @return [Integer, Boolean, nil] the normalized value
|
|
524
|
+
#
|
|
525
|
+
def normalize_clean_force_option(value)
|
|
526
|
+
case value
|
|
527
|
+
when true then 1
|
|
528
|
+
else value
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
# Unescape a git-quoted path
|
|
533
|
+
#
|
|
534
|
+
# Git wraps paths containing non-ASCII or special characters in
|
|
535
|
+
# double-quotes and octal-escapes each byte. This method strips the
|
|
536
|
+
# surrounding quotes and delegates unescaping to {Git::EscapedPath}.
|
|
537
|
+
#
|
|
538
|
+
# @param path [String] the path as it appears in git output
|
|
539
|
+
#
|
|
540
|
+
# @return [String] the unescaped path
|
|
541
|
+
#
|
|
542
|
+
def unescape_quoted_path(path)
|
|
543
|
+
if path.start_with?('"') && path.end_with?('"')
|
|
544
|
+
Git::EscapedPath.new(path[1..-2]).unescape
|
|
545
|
+
else
|
|
546
|
+
path
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
private_constant :Private
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
end
|