git 4.4.1 → 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 -67
- 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 -66
- data/CONTRIBUTING.md +694 -53
- data/README.md +17 -17
- 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 +488 -412
- data/lib/git/branch.rb +117 -59
- 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 -1085
- 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 +226 -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 +117 -56
- 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,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
module CommandLine
|
|
5
|
+
# The result of running a git command
|
|
6
|
+
#
|
|
7
|
+
# This object stores the Git command executed and its status, stdout, and stderr.
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
#
|
|
11
|
+
class Result
|
|
12
|
+
# Create a Result object
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# git_cmd = %w[git version]
|
|
16
|
+
# status = instance_double(ProcessExecuter::Result)
|
|
17
|
+
# stdout = "git version 2.39.1\n"
|
|
18
|
+
# stderr = ""
|
|
19
|
+
# result = Git::CommandLine::Result.new(git_cmd, status, stdout, stderr)
|
|
20
|
+
#
|
|
21
|
+
# @param git_cmd [Array<String>] the git command that was executed
|
|
22
|
+
#
|
|
23
|
+
# @param status [ProcessExecuter::Result] the process result object returned
|
|
24
|
+
# by `ProcessExecuter.run` or `ProcessExecuter.run_with_capture`.
|
|
25
|
+
# Responds to `timed_out?`, `signaled?`, and `success?`.
|
|
26
|
+
#
|
|
27
|
+
# @param stdout [String] the processed stdout of the process
|
|
28
|
+
#
|
|
29
|
+
# @param stderr [String] the processed stderr of the process
|
|
30
|
+
#
|
|
31
|
+
def initialize(git_cmd, status, stdout, stderr)
|
|
32
|
+
@git_cmd = git_cmd
|
|
33
|
+
@status = status
|
|
34
|
+
@stdout = stdout
|
|
35
|
+
@stderr = stderr
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @attribute [r] git_cmd
|
|
39
|
+
#
|
|
40
|
+
# The git command that was executed
|
|
41
|
+
#
|
|
42
|
+
# @example
|
|
43
|
+
# git_cmd = %w[git version]
|
|
44
|
+
# result = Git::CommandLine::Result.new(git_cmd, nil, '', '')
|
|
45
|
+
# result.git_cmd #=> ["git", "version"]
|
|
46
|
+
#
|
|
47
|
+
# @return [Array<String>]
|
|
48
|
+
#
|
|
49
|
+
attr_reader :git_cmd
|
|
50
|
+
|
|
51
|
+
# @attribute [r] status
|
|
52
|
+
#
|
|
53
|
+
# The process result object returned by ProcessExecuter
|
|
54
|
+
#
|
|
55
|
+
# In practice this is a `ProcessExecuter::ResultWithCapture` (from
|
|
56
|
+
# {Git::CommandLine::Capturing}) or a `ProcessExecuter::Result` (from
|
|
57
|
+
# {Git::CommandLine::Streaming}). Both respond to `success?`, `timed_out?`,
|
|
58
|
+
# and `signaled?`.
|
|
59
|
+
#
|
|
60
|
+
# @example
|
|
61
|
+
# status = instance_double(ProcessExecuter::Result, success?: true)
|
|
62
|
+
# result = Git::CommandLine::Result.new(%w[git version], status, '', '')
|
|
63
|
+
# result.status == status #=> true
|
|
64
|
+
#
|
|
65
|
+
# @return [ProcessExecuter::Result]
|
|
66
|
+
#
|
|
67
|
+
attr_reader :status
|
|
68
|
+
|
|
69
|
+
# @attribute [r] stdout
|
|
70
|
+
#
|
|
71
|
+
# The output of the process
|
|
72
|
+
#
|
|
73
|
+
# @example
|
|
74
|
+
# stdout = "git version 2.39.1\n"
|
|
75
|
+
# result = Git::CommandLine::Result.new([], nil, stdout, '')
|
|
76
|
+
# result.stdout #=> "git version 2.39.1\n"
|
|
77
|
+
#
|
|
78
|
+
# @return [String]
|
|
79
|
+
#
|
|
80
|
+
attr_reader :stdout
|
|
81
|
+
|
|
82
|
+
# @attribute [r] stderr
|
|
83
|
+
#
|
|
84
|
+
# The error output of the process
|
|
85
|
+
#
|
|
86
|
+
# @example
|
|
87
|
+
# stderr = "Tag not found\n"
|
|
88
|
+
# result = Git::CommandLine::Result.new([], nil, '', stderr)
|
|
89
|
+
# result.stderr #=> "Tag not found\n"
|
|
90
|
+
#
|
|
91
|
+
# @return [String]
|
|
92
|
+
#
|
|
93
|
+
attr_reader :stderr
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/command_line'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
|
|
6
|
+
module Git
|
|
7
|
+
module CommandLine
|
|
8
|
+
# Executes a git command in streaming mode without buffering stdout in memory
|
|
9
|
+
#
|
|
10
|
+
# {Git::CommandLine::Streaming} is the non-buffering strategy: it calls
|
|
11
|
+
# `ProcessExecuter.run` and streams stdout directly to the caller-supplied `out:`
|
|
12
|
+
# IO object. Stderr is always captured internally in a `StringIO` for error
|
|
13
|
+
# diagnostics and is available as `result.stderr`.
|
|
14
|
+
#
|
|
15
|
+
# Use this class (via {Git::Lib#command_streaming}) for commands such as
|
|
16
|
+
# `cat-file -p <blob>` whose stdout may be too large to buffer in memory.
|
|
17
|
+
#
|
|
18
|
+
# {Git::CommandLine::Capturing} is the complementary strategy for the common case
|
|
19
|
+
# where buffering stdout is acceptable.
|
|
20
|
+
#
|
|
21
|
+
# @example Stream a blob to a file
|
|
22
|
+
# streaming = Git::CommandLine::Streaming.new(
|
|
23
|
+
# {}, '/usr/bin/git', %w[--git-dir /repo/.git], Logger.new($stdout)
|
|
24
|
+
# )
|
|
25
|
+
# File.open('/tmp/blob', 'wb') do |f|
|
|
26
|
+
# streaming.run('cat-file', 'blob', sha, out: f)
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# @see Git::Lib#command_streaming
|
|
30
|
+
#
|
|
31
|
+
# @see Git::CommandLine::Capturing
|
|
32
|
+
#
|
|
33
|
+
class Streaming < Git::CommandLine::Base
|
|
34
|
+
# Default options accepted by {#run}
|
|
35
|
+
#
|
|
36
|
+
# @api private
|
|
37
|
+
RUN_OPTION_DEFAULTS = {
|
|
38
|
+
in: nil,
|
|
39
|
+
out: nil,
|
|
40
|
+
err: nil,
|
|
41
|
+
chdir: nil,
|
|
42
|
+
timeout: nil,
|
|
43
|
+
raise_on_failure: true,
|
|
44
|
+
env: {}
|
|
45
|
+
}.freeze
|
|
46
|
+
|
|
47
|
+
# Execute a git command in streaming mode and return the result
|
|
48
|
+
#
|
|
49
|
+
# Unlike {Git::CommandLine::Capturing#run}, this method does **not** buffer
|
|
50
|
+
# stdout in memory. Stdout is written only to the IO object provided via the
|
|
51
|
+
# `out:` option. Stderr is captured internally via a `StringIO` for error
|
|
52
|
+
# diagnostics.
|
|
53
|
+
#
|
|
54
|
+
# Use this entry point for commands that stream large content (e.g. blobs)
|
|
55
|
+
# where capturing stdout in memory would be unacceptable.
|
|
56
|
+
#
|
|
57
|
+
# @example Stream a blob to a file
|
|
58
|
+
# file = File.open('/tmp/blob', 'wb')
|
|
59
|
+
# streaming.run('cat-file', 'blob', sha, out: file)
|
|
60
|
+
#
|
|
61
|
+
# @param options_hash [Hash] the options to pass to the command
|
|
62
|
+
#
|
|
63
|
+
# @option options_hash [IO, nil] :in the IO object to use as stdin for the
|
|
64
|
+
# command, or nil to inherit the parent process stdin. Must be a real IO
|
|
65
|
+
# object with a file descriptor (not StringIO).
|
|
66
|
+
#
|
|
67
|
+
# @option options_hash [#write, nil] :out the IO/object to stream stdout into.
|
|
68
|
+
# Stdout is NOT buffered in the returned result; this is the only way to
|
|
69
|
+
# read it.
|
|
70
|
+
#
|
|
71
|
+
# @option options_hash [#write, nil] :err an optional additional destination to
|
|
72
|
+
# receive stderr output in real time (e.g. `$stderr` or a `File`). Stderr is
|
|
73
|
+
# always captured internally in a `StringIO` for error diagnostics. When
|
|
74
|
+
# `err:` is provided, writes are teed to both the internal buffer and this
|
|
75
|
+
# destination. `result.stderr` always reflects what was captured in the
|
|
76
|
+
# internal buffer, regardless of whether `err:` is supplied.
|
|
77
|
+
#
|
|
78
|
+
# @option options_hash [String, nil] :chdir the directory to run the command in
|
|
79
|
+
#
|
|
80
|
+
# @option options_hash [Numeric, nil] :timeout the maximum seconds to wait for
|
|
81
|
+
# the command to complete. Zero means no timeout. A timeout kills the
|
|
82
|
+
# process via `SIGKILL` and raises {Git::TimeoutError}.
|
|
83
|
+
#
|
|
84
|
+
# @option options_hash [Boolean] :raise_on_failure (true) whether to raise
|
|
85
|
+
# {Git::FailedError} on non-zero exit status.
|
|
86
|
+
# {Git::TimeoutError} and {Git::SignaledError} are always raised regardless.
|
|
87
|
+
#
|
|
88
|
+
# @option options_hash [Hash] :env ({}) additional environment variable
|
|
89
|
+
# overrides for this command. String keys map to String values (to set) or
|
|
90
|
+
# `nil` (to unset).
|
|
91
|
+
#
|
|
92
|
+
# @return [Git::CommandLineResult] the result of the command
|
|
93
|
+
#
|
|
94
|
+
# `result.stdout` will always be `''` (empty) — stdout was streamed to `out:`.
|
|
95
|
+
# `result.stderr` contains any stderr output captured for diagnostics.
|
|
96
|
+
#
|
|
97
|
+
# @raise [ArgumentError] if `args` contains an array or an unknown option is
|
|
98
|
+
# passed
|
|
99
|
+
#
|
|
100
|
+
# @raise [Git::SignaledError] if the command was terminated by an uncaught signal
|
|
101
|
+
#
|
|
102
|
+
# @raise [Git::FailedError] if the command returned a non-zero exit status
|
|
103
|
+
#
|
|
104
|
+
# @raise [Git::ProcessIOError] if an exception was raised while collecting
|
|
105
|
+
# subprocess output
|
|
106
|
+
#
|
|
107
|
+
# @raise [Git::TimeoutError] if the command times out
|
|
108
|
+
#
|
|
109
|
+
def run(*, **options_hash)
|
|
110
|
+
options = merge_and_validate_options(RUN_OPTION_DEFAULTS, options_hash)
|
|
111
|
+
|
|
112
|
+
internal_err = StringIO.new
|
|
113
|
+
# Tee stderr to the caller-provided destination (if any) AND the internal
|
|
114
|
+
# StringIO. This ensures result.stderr is always available even when err:
|
|
115
|
+
# is a non-StringIO IO object.
|
|
116
|
+
err_dest = options[:err] ? build_stderr_tee(internal_err, options[:err]) : internal_err
|
|
117
|
+
result = execute(*, err_io: err_dest, **options)
|
|
118
|
+
process_result(result, internal_err, options)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
# @return [ProcessExecuter::Result] the result of running the command (non-capturing)
|
|
124
|
+
#
|
|
125
|
+
# @api private
|
|
126
|
+
def execute(*args, err_io:, **options_hash)
|
|
127
|
+
git_cmd = build_git_cmd(args)
|
|
128
|
+
options = execute_options(err_io:, **options_hash)
|
|
129
|
+
run_process_executer do
|
|
130
|
+
ProcessExecuter.run(merged_env(options_hash), *git_cmd, **options)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Build the ProcessExecuter options hash for a streaming run
|
|
135
|
+
#
|
|
136
|
+
# @return [Hash]
|
|
137
|
+
#
|
|
138
|
+
# @api private
|
|
139
|
+
def execute_options(err_io:, **options_hash)
|
|
140
|
+
chdir = options_hash[:chdir] || :not_set
|
|
141
|
+
timeout_after = options_hash[:timeout]
|
|
142
|
+
|
|
143
|
+
{ chdir:, timeout_after:, raise_errors: false, err: err_io }.tap do |options|
|
|
144
|
+
options[:in] = options_hash[:in] unless options_hash[:in].nil?
|
|
145
|
+
options[:out] = options_hash[:out] unless options_hash[:out].nil?
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Build a tee writer that forwards #write calls to two destinations simultaneously.
|
|
150
|
+
#
|
|
151
|
+
# Used to capture stderr in an internal StringIO while also streaming to a
|
|
152
|
+
# caller-provided destination.
|
|
153
|
+
#
|
|
154
|
+
# @param primary [StringIO] the internal capture buffer
|
|
155
|
+
#
|
|
156
|
+
# @param secondary [#write] the caller-supplied destination
|
|
157
|
+
#
|
|
158
|
+
# @return [#write] an object whose #write method delegates to both destinations
|
|
159
|
+
#
|
|
160
|
+
# @api private
|
|
161
|
+
def build_stderr_tee(primary, secondary)
|
|
162
|
+
::Object.new.tap do |tee|
|
|
163
|
+
tee.define_singleton_method(:write) do |data|
|
|
164
|
+
primary.write(data)
|
|
165
|
+
secondary.write(data)
|
|
166
|
+
data.bytesize
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Process the result of a streaming command and return a Git::CommandLineResult
|
|
172
|
+
#
|
|
173
|
+
# Constructs stdout as `''` (not captured) and stderr from the internal StringIO.
|
|
174
|
+
#
|
|
175
|
+
# @param result [ProcessExecuter::Result] the raw process result
|
|
176
|
+
#
|
|
177
|
+
# @param err_io [StringIO] the internal StringIO that captured stderr
|
|
178
|
+
#
|
|
179
|
+
# @param options [Hash] the merged run options
|
|
180
|
+
#
|
|
181
|
+
# @return [Git::CommandLineResult]
|
|
182
|
+
#
|
|
183
|
+
# @api private
|
|
184
|
+
def process_result(result, err_io, options)
|
|
185
|
+
command = result.command
|
|
186
|
+
stderr = err_io.string
|
|
187
|
+
log_result(result, command, '', stderr)
|
|
188
|
+
command_line_result(
|
|
189
|
+
command, result, '', stderr, options[:timeout], options[:raise_on_failure]
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
data/lib/git/command_line.rb
CHANGED
|
@@ -1,330 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/base'
|
|
4
|
-
require 'git/command_line_result'
|
|
5
|
-
require 'git/errors'
|
|
6
|
-
require 'stringio'
|
|
7
|
-
|
|
8
3
|
module Git
|
|
9
|
-
#
|
|
4
|
+
# Namespace module for git command-line execution strategies
|
|
5
|
+
#
|
|
6
|
+
# This module groups the classes responsible for invoking git subprocesses
|
|
7
|
+
# and handling their output. Choose a concrete class based on your buffering
|
|
8
|
+
# needs:
|
|
9
|
+
#
|
|
10
|
+
# * {Git::CommandLine::Capturing} — buffers stdout and stderr in memory.
|
|
11
|
+
# Use this for the vast majority of git commands whose output fits in memory.
|
|
12
|
+
#
|
|
13
|
+
# * {Git::CommandLine::Streaming} — streams stdout to a caller-supplied IO.
|
|
14
|
+
# Use this for commands (e.g. `cat-file -p <blob>`) whose output may be
|
|
15
|
+
# too large to buffer.
|
|
16
|
+
#
|
|
17
|
+
# Both classes inherit from {Git::CommandLine::Base} and are instantiated
|
|
18
|
+
# via factory helpers in {Git::Lib}: {Git::Lib#command_capturing} and
|
|
19
|
+
# {Git::Lib#command_streaming}.
|
|
20
|
+
#
|
|
21
|
+
# Results are returned as {Git::CommandLine::Result} objects (also accessible
|
|
22
|
+
# as {Git::CommandLineResult} for backward compatibility).
|
|
10
23
|
#
|
|
11
24
|
# @api public
|
|
12
25
|
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@logger = logger
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# @attribute [r] env
|
|
36
|
-
#
|
|
37
|
-
# Variables to set (or unset) in the git command's environment
|
|
38
|
-
#
|
|
39
|
-
# @example
|
|
40
|
-
# env = { 'GIT_DIR' => '/path/to/git/dir' }
|
|
41
|
-
# command_line = Git::CommandLine.new(env, '/usr/bin/git', [], Logger.new(STDOUT))
|
|
42
|
-
# command_line.env #=> { 'GIT_DIR' => '/path/to/git/dir' }
|
|
43
|
-
#
|
|
44
|
-
# @return [Hash<String, String>]
|
|
45
|
-
#
|
|
46
|
-
# @see https://ruby-doc.org/3.2.1/Process.html#method-c-spawn Process.spawn
|
|
47
|
-
# for details on how to set environment variables using the `env` parameter
|
|
48
|
-
#
|
|
49
|
-
attr_reader :env
|
|
50
|
-
|
|
51
|
-
# @attribute [r] binary_path
|
|
52
|
-
#
|
|
53
|
-
# The path to the command line binary to run
|
|
54
|
-
#
|
|
55
|
-
# @example
|
|
56
|
-
# binary_path = '/usr/bin/git'
|
|
57
|
-
# command_line = Git::CommandLine.new({}, binary_path, ['version'], Logger.new(STDOUT))
|
|
58
|
-
# command_line.binary_path #=> '/usr/bin/git'
|
|
59
|
-
#
|
|
60
|
-
# @return [String]
|
|
61
|
-
#
|
|
62
|
-
attr_reader :binary_path
|
|
63
|
-
|
|
64
|
-
# @attribute [r] global_opts
|
|
65
|
-
#
|
|
66
|
-
# The global options to pass to git
|
|
67
|
-
#
|
|
68
|
-
# These are options that are passed to git before the command name and
|
|
69
|
-
# arguments. For example, in `git --git-dir /path/to/git/dir version`, the
|
|
70
|
-
# global options are %w[--git-dir /path/to/git/dir].
|
|
71
|
-
#
|
|
72
|
-
# @example
|
|
73
|
-
# env = {}
|
|
74
|
-
# global_opts = %w[--git-dir /path/to/git/dir]
|
|
75
|
-
# logger = Logger.new(nil)
|
|
76
|
-
# cli = CommandLine.new(env, '/usr/bin/git', global_opts, logger)
|
|
77
|
-
# cli.global_opts #=> %w[--git-dir /path/to/git/dir]
|
|
78
|
-
#
|
|
79
|
-
# @return [Array<String>]
|
|
80
|
-
#
|
|
81
|
-
attr_reader :global_opts
|
|
82
|
-
|
|
83
|
-
# @attribute [r] logger
|
|
84
|
-
#
|
|
85
|
-
# The logger to use for logging git commands and results
|
|
86
|
-
#
|
|
87
|
-
# @example
|
|
88
|
-
# env = {}
|
|
89
|
-
# global_opts = %w[]
|
|
90
|
-
# logger = Logger.new(STDOUT)
|
|
91
|
-
# cli = CommandLine.new(env, '/usr/bin/git', global_opts, logger)
|
|
92
|
-
# cli.logger == logger #=> true
|
|
93
|
-
#
|
|
94
|
-
# @return [Logger]
|
|
95
|
-
#
|
|
96
|
-
attr_reader :logger
|
|
97
|
-
|
|
98
|
-
# Execute a git command, wait for it to finish, and return the result
|
|
99
|
-
#
|
|
100
|
-
# Non-option the command line arguements to pass to git. If you collect
|
|
101
|
-
# the command line arguments in an array, make sure you splat the array
|
|
102
|
-
# into the parameter list.
|
|
103
|
-
#
|
|
104
|
-
# NORMALIZATION
|
|
105
|
-
#
|
|
106
|
-
# The command output is returned as a Unicde string containing the binary output
|
|
107
|
-
# from the command. If the binary output is not valid UTF-8, the output will
|
|
108
|
-
# cause problems because the encoding will be invalid.
|
|
109
|
-
#
|
|
110
|
-
# Normalization is a process that trys to convert the binary output to a valid
|
|
111
|
-
# UTF-8 string. It uses the `rchardet` gem to detect the encoding of the binary
|
|
112
|
-
# output and then converts it to UTF-8.
|
|
113
|
-
#
|
|
114
|
-
# Normalization is not enabled by default. Pass `normalize: true` to Git::CommandLine#run
|
|
115
|
-
# to enable it. Normalization will only be performed on stdout and only if the `out:`` option
|
|
116
|
-
# is nil or is a StringIO object. If the out: option is set to a file or other IO object,
|
|
117
|
-
# the normalize option will be ignored.
|
|
118
|
-
#
|
|
119
|
-
# @example Run a command and return the output
|
|
120
|
-
# cli.run('version') #=> "git version 2.39.1\n"
|
|
121
|
-
#
|
|
122
|
-
# @example The args array should be splatted into the parameter list
|
|
123
|
-
# args = %w[log -n 1 --oneline]
|
|
124
|
-
# cli.run(*args) #=> "f5baa11 beginning of Ruby/Git project\n"
|
|
125
|
-
#
|
|
126
|
-
# @example Run a command and return the chomped output
|
|
127
|
-
# cli.run('version', chomp: true) #=> "git version 2.39.1"
|
|
128
|
-
#
|
|
129
|
-
# @example Run a command and without normalizing the output
|
|
130
|
-
# cli.run('version', normalize: false) #=> "git version 2.39.1\n"
|
|
131
|
-
#
|
|
132
|
-
# @example Capture stdout in a temporary file
|
|
133
|
-
# require 'tempfile'
|
|
134
|
-
# tempfile = Tempfile.create('git') do |file|
|
|
135
|
-
# cli.run('version', out: file)
|
|
136
|
-
# file.rewind
|
|
137
|
-
# file.read #=> "git version 2.39.1\n"
|
|
138
|
-
# end
|
|
139
|
-
#
|
|
140
|
-
# @example Capture stderr in a StringIO object
|
|
141
|
-
# require 'stringio'
|
|
142
|
-
# stderr = StringIO.new
|
|
143
|
-
# begin
|
|
144
|
-
# cli.run('log', 'nonexistent-branch', err: stderr)
|
|
145
|
-
# rescue Git::FailedError => e
|
|
146
|
-
# stderr.string #=> "unknown revision or path not in the working tree.\n"
|
|
147
|
-
# end
|
|
148
|
-
#
|
|
149
|
-
# @param options_hash [Hash] the options to pass to the command
|
|
150
|
-
#
|
|
151
|
-
# @option options_hash [#write, nil] :out the object to write stdout to or nil to ignore stdout
|
|
152
|
-
#
|
|
153
|
-
# If this is a 'StringIO' object, then `stdout_writer.string` will be returned.
|
|
154
|
-
#
|
|
155
|
-
# In general, only specify a `stdout_writer` object when you want to redirect
|
|
156
|
-
# stdout to a file or some other object that responds to `#write`. The default
|
|
157
|
-
# behavior will return the output of the command.
|
|
158
|
-
#
|
|
159
|
-
# @option options_hash [#write, nil] :err the object to write stderr to or nil to ignore stderr
|
|
160
|
-
#
|
|
161
|
-
# If this is a 'StringIO' object and `merged_output` is `true`, then
|
|
162
|
-
# `stderr_writer.string` will be merged into the output returned by this method.
|
|
163
|
-
#
|
|
164
|
-
# @option options_hash [Boolean] :normalize whether to normalize the output of stdout and stderr
|
|
165
|
-
#
|
|
166
|
-
# @option options_hash [Boolean] :chomp whether to chomp both stdout and stderr output
|
|
167
|
-
#
|
|
168
|
-
# @option options_hash [Boolean] :merge whether to merge stdout and stderr in the string returned
|
|
169
|
-
#
|
|
170
|
-
# @option options_hash [String, nil] :chdir the directory to run the command in
|
|
171
|
-
#
|
|
172
|
-
# @option options_hash [Numeric, nil] :timeout the maximum seconds to wait for the command to complete
|
|
173
|
-
#
|
|
174
|
-
# If timeout is zero, the timeout will not be enforced.
|
|
175
|
-
#
|
|
176
|
-
# If the command times out, it is killed via a `SIGKILL` signal and `Git::TimeoutError` is raised.
|
|
177
|
-
#
|
|
178
|
-
# If the command does not respond to SIGKILL, it will hang this method.
|
|
179
|
-
#
|
|
180
|
-
# @return [Git::CommandLineResult] the output of the command
|
|
181
|
-
#
|
|
182
|
-
# This result of running the command.
|
|
183
|
-
#
|
|
184
|
-
# @raise [ArgumentError] if `args` is not an array of strings
|
|
185
|
-
#
|
|
186
|
-
# @raise [Git::SignaledError] if the command was terminated because of an uncaught signal
|
|
187
|
-
#
|
|
188
|
-
# @raise [Git::FailedError] if the command returned a non-zero exitstatus
|
|
189
|
-
#
|
|
190
|
-
# @raise [Git::ProcessIOError] if an exception was raised while collecting subprocess output
|
|
191
|
-
#
|
|
192
|
-
# @raise [Git::TimeoutError] if the command times out
|
|
193
|
-
#
|
|
194
|
-
def run(*, **options_hash)
|
|
195
|
-
options_hash = RUN_ARGS.merge(options_hash)
|
|
196
|
-
extra_options = options_hash.keys - RUN_ARGS.keys
|
|
197
|
-
raise ArgumentError, "Unknown options: #{extra_options.join(', ')}" if extra_options.any?
|
|
198
|
-
|
|
199
|
-
result = run_with_capture(*, **options_hash)
|
|
200
|
-
process_result(result, options_hash[:normalize], options_hash[:chomp], options_hash[:timeout])
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
# @return [Git::CommandLineResult] the result of running the command
|
|
204
|
-
#
|
|
205
|
-
# @api private
|
|
206
|
-
#
|
|
207
|
-
def run_with_capture(*args, **options_hash)
|
|
208
|
-
git_cmd = build_git_cmd(args)
|
|
209
|
-
options = run_with_capture_options(**options_hash)
|
|
210
|
-
ProcessExecuter.run_with_capture(env, *git_cmd, **options)
|
|
211
|
-
rescue ProcessExecuter::ProcessIOError => e
|
|
212
|
-
raise Git::ProcessIOError.new(e.message), cause: e.exception.cause
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def run_with_capture_options(**options_hash)
|
|
216
|
-
chdir = options_hash[:chdir] || :not_set
|
|
217
|
-
timeout_after = options_hash[:timeout]
|
|
218
|
-
out = options_hash[:out]
|
|
219
|
-
err = options_hash[:err]
|
|
220
|
-
merge_output = options_hash[:merge] || false
|
|
221
|
-
|
|
222
|
-
{ chdir:, timeout_after:, merge_output:, raise_errors: false }.tap do |options|
|
|
223
|
-
options[:out] = out unless out.nil?
|
|
224
|
-
options[:err] = err unless err.nil?
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
RUN_ARGS = {
|
|
229
|
-
normalize: false,
|
|
230
|
-
chomp: false,
|
|
231
|
-
merge: false,
|
|
232
|
-
out: nil,
|
|
233
|
-
err: nil,
|
|
234
|
-
chdir: nil,
|
|
235
|
-
timeout: nil
|
|
236
|
-
}.freeze
|
|
237
|
-
|
|
238
|
-
private
|
|
239
|
-
|
|
240
|
-
# Build the git command line from the available sources to send to `Process.spawn`
|
|
241
|
-
# @return [Array<String>]
|
|
242
|
-
# @api private
|
|
243
|
-
#
|
|
244
|
-
def build_git_cmd(args)
|
|
245
|
-
raise ArgumentError, 'The args array can not contain an array' if args.any?(Array)
|
|
246
|
-
|
|
247
|
-
[binary_path, *global_opts, *args].map(&:to_s)
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
# Process the result of the command and return a Git::CommandLineResult
|
|
251
|
-
#
|
|
252
|
-
# Post process output, log the command and result, and raise an error if the
|
|
253
|
-
# command failed.
|
|
254
|
-
#
|
|
255
|
-
# @param result [ProcessExecuter::Command::Result] the result it is a
|
|
256
|
-
# Process::Status and include command, stdout, and stderr
|
|
257
|
-
#
|
|
258
|
-
# @param normalize [Boolean] whether to normalize the output of each writer
|
|
259
|
-
#
|
|
260
|
-
# @param chomp [Boolean] whether to chomp the output of each writer
|
|
261
|
-
#
|
|
262
|
-
# @param timeout [Numeric, nil] the maximum seconds to wait for the command to
|
|
263
|
-
# complete
|
|
264
|
-
#
|
|
265
|
-
# @return [Git::CommandLineResult] the result of the command to return to the
|
|
266
|
-
# caller
|
|
267
|
-
#
|
|
268
|
-
# @raise [Git::FailedError] if the command failed
|
|
269
|
-
#
|
|
270
|
-
# @raise [Git::SignaledError] if the command was signaled
|
|
271
|
-
#
|
|
272
|
-
# @raise [Git::TimeoutError] if the command times out
|
|
273
|
-
#
|
|
274
|
-
# @raise [Git::ProcessIOError] if an exception was raised while collecting
|
|
275
|
-
# subprocess output
|
|
276
|
-
#
|
|
277
|
-
# @api private
|
|
278
|
-
#
|
|
279
|
-
def process_result(result, normalize, chomp, timeout)
|
|
280
|
-
command = result.command
|
|
281
|
-
processed_out, processed_err = post_process_output(result, normalize, chomp)
|
|
282
|
-
log_result(result, command, processed_out, processed_err)
|
|
283
|
-
command_line_result(command, result, processed_out, processed_err, timeout)
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
def log_result(result, command, processed_out, processed_err)
|
|
287
|
-
logger.info { "#{command} exited with status #{result}" }
|
|
288
|
-
logger.debug { "stdout:\n#{processed_out.inspect}\nstderr:\n#{processed_err.inspect}" }
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def command_line_result(command, result, processed_out, processed_err, timeout)
|
|
292
|
-
Git::CommandLineResult.new(command, result, processed_out, processed_err).tap do |processed_result|
|
|
293
|
-
raise Git::TimeoutError.new(processed_result, timeout) if result.timeout?
|
|
294
|
-
|
|
295
|
-
raise Git::SignaledError, processed_result if result.signaled?
|
|
296
|
-
|
|
297
|
-
raise Git::FailedError, processed_result unless result.success?
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
# Post-process and return an array of raw output strings
|
|
302
|
-
#
|
|
303
|
-
# For each raw output string:
|
|
304
|
-
#
|
|
305
|
-
# * If normalize: is true, normalize the encoding by transcoding each line from
|
|
306
|
-
# the detected encoding to UTF-8.
|
|
307
|
-
# * If chomp: is true chomp the output after normalization.
|
|
308
|
-
#
|
|
309
|
-
# Even if no post-processing is done based on the options, the strings returned
|
|
310
|
-
# are a copy of the raw output strings. The raw output strings are not modified.
|
|
311
|
-
#
|
|
312
|
-
# @param result [ProcessExecuter::ResultWithCapture] the command's output to post-process
|
|
313
|
-
#
|
|
314
|
-
# @param normalize [Boolean] whether to normalize the output of each writer
|
|
315
|
-
# @param chomp [Boolean] whether to chomp the output of each writer
|
|
316
|
-
#
|
|
317
|
-
# @return [Array<String>]
|
|
318
|
-
#
|
|
319
|
-
# @api private
|
|
320
|
-
#
|
|
321
|
-
def post_process_output(result, normalize, chomp)
|
|
322
|
-
[result.stdout, result.stderr].map do |raw_output|
|
|
323
|
-
output = raw_output.dup
|
|
324
|
-
output = output.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join if normalize
|
|
325
|
-
output.chomp! if chomp
|
|
326
|
-
output
|
|
327
|
-
end
|
|
328
|
-
end
|
|
26
|
+
# @example Buffered command via Git::CommandLine::Capturing
|
|
27
|
+
# cli = Git::CommandLine::Capturing.new(
|
|
28
|
+
# {}, '/usr/bin/git', [], Logger.new(nil)
|
|
29
|
+
# )
|
|
30
|
+
# result = cli.run('version')
|
|
31
|
+
# result.stdout #=> "git version 2.39.1\n"
|
|
32
|
+
#
|
|
33
|
+
# @example Streaming command via Git::CommandLine::Streaming
|
|
34
|
+
# cli = Git::CommandLine::Streaming.new(
|
|
35
|
+
# {}, '/usr/bin/git', [], Logger.new(nil)
|
|
36
|
+
# )
|
|
37
|
+
# File.open('/tmp/blob', 'wb') do |f|
|
|
38
|
+
# cli.run('cat-file', 'blob', sha, out: f)
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
# @see Git::CommandLine::Base
|
|
42
|
+
# @see Git::CommandLine::Result
|
|
43
|
+
#
|
|
44
|
+
module CommandLine
|
|
329
45
|
end
|
|
330
46
|
end
|
|
47
|
+
|
|
48
|
+
require 'git/command_line/result'
|
|
49
|
+
require 'git/command_line/base'
|
|
50
|
+
require 'git/command_line/capturing'
|
|
51
|
+
require 'git/command_line/streaming'
|