git 1.19.1 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +5 -1
- data/AI_POLICY.md +24 -0
- data/CHANGELOG.md +689 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/CONTRIBUTING.md +1175 -97
- data/GOVERNANCE.md +106 -0
- data/LICENSE +1 -1
- data/MAINTAINERS.md +17 -4
- data/README.md +476 -320
- data/UPGRADING.md +1138 -0
- data/git.gemspec +124 -36
- data/lib/git/author.rb +39 -7
- data/lib/git/author_info.rb +66 -0
- data/lib/git/branch.rb +615 -65
- data/lib/git/branch_delete_failure.rb +34 -0
- data/lib/git/branch_delete_result.rb +66 -0
- data/lib/git/branch_info.rb +237 -0
- data/lib/git/branches.rb +167 -44
- data/lib/git/command_line/base.rb +247 -0
- data/lib/git/command_line/capturing.rb +308 -0
- data/lib/git/command_line/result.rb +88 -0
- data/lib/git/command_line/streaming.rb +236 -0
- data/lib/git/command_line.rb +52 -0
- data/lib/git/commands/add.rb +139 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +263 -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 +49 -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 +242 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +145 -0
- data/lib/git/commands/arguments.rb +4521 -0
- data/lib/git/commands/base.rb +502 -0
- data/lib/git/commands/branch/copy.rb +102 -0
- data/lib/git/commands/branch/create.rb +177 -0
- data/lib/git/commands/branch/delete.rb +88 -0
- data/lib/git/commands/branch/list.rb +178 -0
- data/lib/git/commands/branch/move.rb +102 -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 +53 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +385 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +271 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +153 -0
- data/lib/git/commands/checkout/files.rb +116 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +106 -0
- data/lib/git/commands/clean.rb +102 -0
- data/lib/git/commands/clone.rb +241 -0
- data/lib/git/commands/commit.rb +273 -0
- data/lib/git/commands/commit_tree.rb +101 -0
- data/lib/git/commands/config_option_syntax/add.rb +86 -0
- data/lib/git/commands/config_option_syntax/get.rb +121 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
- data/lib/git/commands/config_option_syntax/list.rb +111 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
- data/lib/git/commands/config_option_syntax/set.rb +119 -0
- data/lib/git/commands/config_option_syntax/unset.rb +92 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +156 -0
- data/lib/git/commands/diff.rb +657 -0
- data/lib/git/commands/diff_files.rb +519 -0
- data/lib/git/commands/diff_index.rb +499 -0
- data/lib/git/commands/fetch.rb +354 -0
- data/lib/git/commands/fsck.rb +138 -0
- data/lib/git/commands/gc.rb +134 -0
- data/lib/git/commands/grep.rb +339 -0
- data/lib/git/commands/init.rb +101 -0
- data/lib/git/commands/log.rb +634 -0
- data/lib/git/commands/ls_files.rb +195 -0
- data/lib/git/commands/ls_remote.rb +161 -0
- data/lib/git/commands/ls_tree.rb +135 -0
- data/lib/git/commands/maintenance/register.rb +77 -0
- data/lib/git/commands/maintenance/run.rb +109 -0
- data/lib/git/commands/maintenance/start.rb +71 -0
- data/lib/git/commands/maintenance/stop.rb +60 -0
- data/lib/git/commands/maintenance/unregister.rb +84 -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 +250 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +91 -0
- data/lib/git/commands/mv.rb +82 -0
- data/lib/git/commands/name_rev.rb +119 -0
- data/lib/git/commands/pull.rb +382 -0
- data/lib/git/commands/push.rb +251 -0
- data/lib/git/commands/read_tree.rb +154 -0
- data/lib/git/commands/remote/add.rb +96 -0
- data/lib/git/commands/remote/get_url.rb +68 -0
- data/lib/git/commands/remote/list.rb +56 -0
- data/lib/git/commands/remote/prune.rb +63 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +76 -0
- data/lib/git/commands/remote/set_branches.rb +70 -0
- data/lib/git/commands/remote/set_head.rb +89 -0
- data/lib/git/commands/remote/set_url.rb +78 -0
- data/lib/git/commands/remote/set_url_add.rb +70 -0
- data/lib/git/commands/remote/set_url_delete.rb +71 -0
- data/lib/git/commands/remote/show.rb +77 -0
- data/lib/git/commands/remote/update.rb +79 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +281 -0
- data/lib/git/commands/reset.rb +154 -0
- data/lib/git/commands/rev_parse.rb +304 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +62 -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 +158 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +113 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
- data/lib/git/commands/show_ref/exists.rb +80 -0
- data/lib/git/commands/show_ref/list.rb +149 -0
- data/lib/git/commands/show_ref/verify.rb +122 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +81 -0
- data/lib/git/commands/stash/branch.rb +67 -0
- data/lib/git/commands/stash/clear.rb +43 -0
- data/lib/git/commands/stash/create.rb +60 -0
- data/lib/git/commands/stash/drop.rb +73 -0
- data/lib/git/commands/stash/list.rb +43 -0
- data/lib/git/commands/stash/pop.rb +87 -0
- data/lib/git/commands/stash/push.rb +112 -0
- data/lib/git/commands/stash/show.rb +158 -0
- data/lib/git/commands/stash/store.rb +72 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +174 -0
- data/lib/git/commands/symbolic_ref/delete.rb +72 -0
- data/lib/git/commands/symbolic_ref/read.rb +99 -0
- data/lib/git/commands/symbolic_ref/update.rb +79 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +142 -0
- data/lib/git/commands/tag/delete.rb +57 -0
- data/lib/git/commands/tag/list.rb +146 -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 +145 -0
- data/lib/git/commands/update_ref/delete.rb +90 -0
- data/lib/git/commands/update_ref/update.rb +103 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +60 -0
- data/lib/git/commands/worktree/add.rb +139 -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 +88 -0
- data/lib/git/config.rb +72 -5
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +795 -0
- data/lib/git/detached_head_info.rb +57 -0
- data/lib/git/diff.rb +437 -86
- data/lib/git/diff_file_numstat_info.rb +31 -0
- data/lib/git/diff_file_patch_info.rb +136 -0
- data/lib/git/diff_file_raw_info.rb +129 -0
- data/lib/git/diff_info.rb +162 -0
- data/lib/git/diff_path_status.rb +107 -0
- data/lib/git/diff_result.rb +34 -0
- data/lib/git/diff_stats.rb +111 -0
- data/lib/git/dirstat_info.rb +102 -0
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +285 -0
- data/lib/git/escaped_path.rb +57 -5
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +151 -0
- data/lib/git/execution_context.rb +559 -0
- data/lib/git/factories.rb +813 -0
- data/lib/git/file_ref.rb +77 -0
- data/lib/git/fsck_object.rb +56 -0
- data/lib/git/fsck_result.rb +132 -0
- data/lib/git/log.rb +306 -90
- data/lib/git/object.rb +563 -141
- data/lib/git/parsers/branch.rb +240 -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 +792 -0
- data/lib/git/parsers/fsck.rb +144 -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/remote.rb +162 -0
- data/lib/git/parsers/stash.rb +292 -0
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/tag.rb +341 -0
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/path_resolver.rb +206 -0
- data/lib/git/remote.rb +165 -12
- data/lib/git/remote_info.rb +203 -0
- data/lib/git/repository/branching.rb +964 -0
- data/lib/git/repository/committing.rb +246 -0
- data/lib/git/repository/context_helpers.rb +293 -0
- data/lib/git/repository/diffing.rb +785 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +410 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +451 -0
- data/lib/git/repository/object_operations.rb +1551 -0
- data/lib/git/repository/remote_operations.rb +984 -0
- data/lib/git/repository/shared_private.rb +120 -0
- data/lib/git/repository/staging.rb +587 -0
- data/lib/git/repository/stashing.rb +623 -0
- data/lib/git/repository/status_operations.rb +249 -0
- data/lib/git/repository/worktree_operations.rb +339 -0
- data/lib/git/repository.rb +484 -2
- data/lib/git/stash.rb +109 -12
- data/lib/git/stash_info.rb +102 -0
- data/lib/git/stashes.rb +169 -26
- data/lib/git/status.rb +308 -122
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_delete_failure.rb +34 -0
- data/lib/git/tag_delete_result.rb +66 -0
- data/lib/git/tag_info.rb +99 -0
- data/lib/git/url.rb +15 -8
- data/lib/git/version.rb +113 -2
- data/lib/git/version_constraint.rb +85 -0
- data/lib/git/worktree.rb +150 -8
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +118 -13
- data/lib/git.rb +632 -234
- metadata +369 -54
- data/.github/stale.yml +0 -25
- data/.github/workflows/continuous_integration.yml +0 -49
- data/.gitignore +0 -10
- data/Dockerfile.changelog-rs +0 -12
- data/Gemfile +0 -5
- data/ISSUE_TEMPLATE.md +0 -15
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/RELEASING.md +0 -70
- data/Rakefile +0 -60
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/base.rb +0 -711
- data/lib/git/command_line_result.rb +0 -86
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/index.rb +0 -5
- data/lib/git/lib.rb +0 -1328
- data/lib/git/path.rb +0 -31
- data/lib/git/signaled_error.rb +0 -50
- data/lib/git/working_directory.rb +0 -4
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/base'
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
module Commands
|
|
7
|
+
module Branch
|
|
8
|
+
# Implements the `git branch --unset-upstream` command for removing upstream tracking
|
|
9
|
+
#
|
|
10
|
+
# This command removes the upstream tracking information for the given branch
|
|
11
|
+
# (or current branch if not specified).
|
|
12
|
+
#
|
|
13
|
+
# @example Unset upstream for current branch
|
|
14
|
+
# unset_upstream = Git::Commands::Branch::UnsetUpstream.new(execution_context)
|
|
15
|
+
# unset_upstream.call
|
|
16
|
+
#
|
|
17
|
+
# @example Unset upstream for a specific branch
|
|
18
|
+
# unset_upstream = Git::Commands::Branch::UnsetUpstream.new(execution_context)
|
|
19
|
+
# unset_upstream.call('feature')
|
|
20
|
+
#
|
|
21
|
+
# @note `arguments` block audited against https://git-scm.com/docs/git-branch/2.53.0
|
|
22
|
+
#
|
|
23
|
+
# @see Git::Commands::Branch
|
|
24
|
+
#
|
|
25
|
+
# @see https://git-scm.com/docs/git-branch git-branch
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
class UnsetUpstream < Git::Commands::Base
|
|
30
|
+
# NOTE: The --unset-upstream flag is always present.
|
|
31
|
+
# The branch_name positional is optional; if omitted, git uses the current branch.
|
|
32
|
+
arguments do
|
|
33
|
+
literal 'branch'
|
|
34
|
+
literal '--unset-upstream'
|
|
35
|
+
operand :branch_name
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @!method call(*)
|
|
39
|
+
#
|
|
40
|
+
# @overload call(branch_name = nil)
|
|
41
|
+
#
|
|
42
|
+
# Execute the `git branch --unset-upstream` command
|
|
43
|
+
#
|
|
44
|
+
# @param branch_name [String, nil] the branch to remove upstream tracking for
|
|
45
|
+
# (defaults to current branch if omitted)
|
|
46
|
+
#
|
|
47
|
+
# @return [Git::CommandLine::Result] the result of calling `git branch --unset-upstream`
|
|
48
|
+
#
|
|
49
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'branch/copy'
|
|
4
|
+
require_relative 'branch/create'
|
|
5
|
+
require_relative 'branch/delete'
|
|
6
|
+
require_relative 'branch/list'
|
|
7
|
+
require_relative 'branch/move'
|
|
8
|
+
require_relative 'branch/set_upstream'
|
|
9
|
+
require_relative 'branch/show_current'
|
|
10
|
+
require_relative 'branch/unset_upstream'
|
|
11
|
+
|
|
12
|
+
module Git
|
|
13
|
+
module Commands
|
|
14
|
+
# Commands for managing branches via `git branch`
|
|
15
|
+
#
|
|
16
|
+
# This module contains command classes split by branch operation:
|
|
17
|
+
#
|
|
18
|
+
# - {Branch::Create} — create a new branch
|
|
19
|
+
# - {Branch::Delete} — delete one or more branches (`--delete` / `--delete --force`)
|
|
20
|
+
# - {Branch::List} — list branches with optional filtering
|
|
21
|
+
# - {Branch::Move} — rename a branch (`--move` / `--move --force`)
|
|
22
|
+
# - {Branch::Copy} — copy a branch (`--copy` / `--copy --force`)
|
|
23
|
+
# - {Branch::ShowCurrent} — print the current branch name (`--show-current`)
|
|
24
|
+
# - {Branch::SetUpstream} — set upstream tracking (`--set-upstream-to`)
|
|
25
|
+
# - {Branch::UnsetUpstream} — remove upstream tracking (`--unset-upstream`)
|
|
26
|
+
#
|
|
27
|
+
# @see https://git-scm.com/docs/git-branch git-branch documentation
|
|
28
|
+
#
|
|
29
|
+
# @api private
|
|
30
|
+
#
|
|
31
|
+
module Branch
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/base'
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
module Commands
|
|
7
|
+
module CatFile
|
|
8
|
+
# Queries one or more git objects via the batch stdin streaming protocol
|
|
9
|
+
#
|
|
10
|
+
# Accepts object names (or commands) written to stdin. Three output modes are
|
|
11
|
+
# available, selected by passing exactly one of `batch:`, `batch_check:`, or
|
|
12
|
+
# `batch_command:` as a keyword argument:
|
|
13
|
+
#
|
|
14
|
+
# - **`batch: true`** (`--batch`) — for each named object, write a header line
|
|
15
|
+
# `<sha> <type> <size>` followed by the raw content bytes and a newline
|
|
16
|
+
# separator; missing objects are reported inline as `<name> missing`
|
|
17
|
+
# - **`batch_check: true`** (`--batch-check`) — for each named object, write
|
|
18
|
+
# one metadata line `<sha> <type> <size>`; missing objects as `<name> missing`
|
|
19
|
+
# - **`batch_command: true`** (`--batch-command`) — enter command-dispatch mode;
|
|
20
|
+
# stdin carries named verbs (`contents <object>`, `info <object>`, `flush`),
|
|
21
|
+
# allowing content and metadata requests to be interleaved in a single process
|
|
22
|
+
#
|
|
23
|
+
# All three modes accept a format string instead of `true` to customise the
|
|
24
|
+
# per-object output line (e.g. `batch: "%(objectname) %(objecttype) %(objectsize)"`)
|
|
25
|
+
#
|
|
26
|
+
# When `batch_all_objects: true` is given instead of object names, git enumerates
|
|
27
|
+
# the entire object database itself and stdin is not read (incompatible with
|
|
28
|
+
# `batch_command:`).
|
|
29
|
+
#
|
|
30
|
+
# Missing objects never cause a non-zero exit — they are reported inline.
|
|
31
|
+
#
|
|
32
|
+
# For single-object queries, use {CatFile::Raw}.
|
|
33
|
+
# For filter-processed content, use {CatFile::Filtered}.
|
|
34
|
+
#
|
|
35
|
+
# @note `arguments` block audited against https://git-scm.com/docs/git-cat-file/2.53.0
|
|
36
|
+
#
|
|
37
|
+
# @see Git::Commands::CatFile
|
|
38
|
+
#
|
|
39
|
+
# @see https://git-scm.com/docs/git-cat-file git-cat-file documentation
|
|
40
|
+
#
|
|
41
|
+
# @api private
|
|
42
|
+
#
|
|
43
|
+
class Batch < Base
|
|
44
|
+
arguments do
|
|
45
|
+
literal 'cat-file'
|
|
46
|
+
|
|
47
|
+
# Full content mode: header + raw bytes + newline separator per object;
|
|
48
|
+
# accepts a format string to customise the per-object output header
|
|
49
|
+
# (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
|
|
50
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch
|
|
51
|
+
flag_or_value_option :batch, inline: true
|
|
52
|
+
|
|
53
|
+
# Metadata-only mode: one `<sha> <type> <size>` line per object;
|
|
54
|
+
# accepts a format string to customise the per-object output line
|
|
55
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-check
|
|
56
|
+
flag_or_value_option :batch_check, inline: true
|
|
57
|
+
|
|
58
|
+
# Command-dispatch mode: stdin carries `contents`/`info`/`flush` verbs;
|
|
59
|
+
# accepts a format string to customise the output of `info` and `contents` commands
|
|
60
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-command
|
|
61
|
+
flag_or_value_option :batch_command, inline: true
|
|
62
|
+
|
|
63
|
+
# Enumerate all objects in the repository without reading stdin.
|
|
64
|
+
# Incompatible with `batch_command:`.
|
|
65
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-all-objects
|
|
66
|
+
flag_option :batch_all_objects
|
|
67
|
+
|
|
68
|
+
# Use normal stdio buffering; enables explicit `flush` semantics when used
|
|
69
|
+
# with `batch_command:` and improves throughput with `batch_check:`
|
|
70
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---buffer
|
|
71
|
+
flag_option :buffer
|
|
72
|
+
|
|
73
|
+
# Follow symlinks inside the repository when traversing tree objects
|
|
74
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---follow-symlinks
|
|
75
|
+
flag_option :follow_symlinks
|
|
76
|
+
|
|
77
|
+
# Allow `--batch-all-objects` to output objects in an arbitrary, potentially
|
|
78
|
+
# faster order
|
|
79
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---unordered
|
|
80
|
+
flag_option :unordered
|
|
81
|
+
|
|
82
|
+
# Apply textconv filters to blob content (combine with `batch_command:`)
|
|
83
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---textconv
|
|
84
|
+
flag_option :textconv
|
|
85
|
+
|
|
86
|
+
# Apply the full working-tree filter pipeline (combine with `batch_command:`)
|
|
87
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filters
|
|
88
|
+
flag_option :filters
|
|
89
|
+
|
|
90
|
+
# Map committer/author identities through mailmap for all batch modes
|
|
91
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---use-mailmap
|
|
92
|
+
flag_option :use_mailmap, negatable: true
|
|
93
|
+
|
|
94
|
+
# Omit objects matching the filter spec from the output (batched modes only)
|
|
95
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filterltfilter-specgt
|
|
96
|
+
value_option :filter, inline: true
|
|
97
|
+
|
|
98
|
+
# Use NUL-delimited input/output instead of newline-delimited
|
|
99
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--Z
|
|
100
|
+
flag_option :Z
|
|
101
|
+
|
|
102
|
+
# Stream stdout to this IO object instead of buffering in memory.
|
|
103
|
+
# When provided, {#call} dispatches to the streaming execution path.
|
|
104
|
+
execution_option :out
|
|
105
|
+
|
|
106
|
+
# Abort the command after this many seconds.
|
|
107
|
+
execution_option :timeout
|
|
108
|
+
|
|
109
|
+
# Object names (or batch-command lines) are written to stdin, not argv.
|
|
110
|
+
# Using skip_cli: true because these values are fed via stdin — git never
|
|
111
|
+
# sees them as CLI arguments so Ruby must enforce the cross-argument
|
|
112
|
+
# constraints below.
|
|
113
|
+
operand :object, repeatable: true, skip_cli: true
|
|
114
|
+
|
|
115
|
+
conflicts :object, :batch_all_objects
|
|
116
|
+
requires_one_of :object, :batch_all_objects
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Execute `git cat-file` in batch stdin-streaming mode.
|
|
120
|
+
#
|
|
121
|
+
# Exactly one of `batch:`, `batch_check:`, or `batch_command:` must be selected.
|
|
122
|
+
# Pass `batch_all_objects: true` instead of object names to enumerate the entire
|
|
123
|
+
# object database without reading stdin.
|
|
124
|
+
#
|
|
125
|
+
# @overload call(*objects, batch: true, **options)
|
|
126
|
+
# Stream one or more named objects; return header + content per object
|
|
127
|
+
#
|
|
128
|
+
# @param objects [Array<String>] object names written to stdin
|
|
129
|
+
#
|
|
130
|
+
# @param batch [Boolean, String] enable `--batch` mode; pass a format string
|
|
131
|
+
# to customise the per-object output header
|
|
132
|
+
# (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
|
|
133
|
+
#
|
|
134
|
+
# @param options [Hash] command options
|
|
135
|
+
#
|
|
136
|
+
# @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
|
|
137
|
+
#
|
|
138
|
+
# @option options [Boolean, nil] :follow_symlinks (nil) follow symlinks in trees
|
|
139
|
+
#
|
|
140
|
+
# @option options [Boolean, nil] :unordered (nil) output in arbitrary order
|
|
141
|
+
#
|
|
142
|
+
# @option options [Boolean, nil] :textconv (nil) apply textconv filters
|
|
143
|
+
#
|
|
144
|
+
# @option options [Boolean, nil] :filters (nil) apply full working-tree filters
|
|
145
|
+
#
|
|
146
|
+
# @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
|
|
147
|
+
#
|
|
148
|
+
# @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
|
|
149
|
+
#
|
|
150
|
+
# @option options [String] :filter (nil) omit objects matching the given filter spec
|
|
151
|
+
#
|
|
152
|
+
# @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
|
|
153
|
+
#
|
|
154
|
+
# @option options [#write, nil] :out (nil) stream stdout to this IO object
|
|
155
|
+
# instead of buffering in memory; when given, `result.stdout` will be `''`
|
|
156
|
+
#
|
|
157
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
158
|
+
#
|
|
159
|
+
# Stdout contains the batch output stream (or `''` when `out:` is given)
|
|
160
|
+
#
|
|
161
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
162
|
+
#
|
|
163
|
+
# @raise [Git::FailedError] if git exits non-zero (catastrophic failure only;
|
|
164
|
+
# missing objects are reported inline)
|
|
165
|
+
#
|
|
166
|
+
# @overload call(*objects, batch_check: true, **options)
|
|
167
|
+
# Stream one or more named objects; return one metadata line per object
|
|
168
|
+
#
|
|
169
|
+
# @param objects [Array<String>] object names written to stdin
|
|
170
|
+
#
|
|
171
|
+
# @param batch_check [Boolean, String] enable `--batch-check` mode; pass a
|
|
172
|
+
# format string to customise the per-object output line
|
|
173
|
+
# (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
|
|
174
|
+
#
|
|
175
|
+
# @param options [Hash] command options
|
|
176
|
+
#
|
|
177
|
+
# @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better
|
|
178
|
+
# throughput when processing large numbers of objects
|
|
179
|
+
#
|
|
180
|
+
# @option options [Boolean, nil] :follow_symlinks (nil) follow symlinks in trees
|
|
181
|
+
#
|
|
182
|
+
# @option options [Boolean, nil] :unordered (nil) output in arbitrary order
|
|
183
|
+
#
|
|
184
|
+
# @option options [Boolean, nil] :textconv (nil) apply textconv filters
|
|
185
|
+
#
|
|
186
|
+
# @option options [Boolean, nil] :filters (nil) apply full working-tree filters
|
|
187
|
+
#
|
|
188
|
+
# @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
|
|
189
|
+
#
|
|
190
|
+
# @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
|
|
191
|
+
#
|
|
192
|
+
# @option options [String] :filter (nil) omit objects matching the given filter spec
|
|
193
|
+
#
|
|
194
|
+
# @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
|
|
195
|
+
#
|
|
196
|
+
# @option options [#write, nil] :out (nil) stream stdout to this IO object
|
|
197
|
+
# instead of buffering in memory; when given, `result.stdout` will be `''`
|
|
198
|
+
#
|
|
199
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
200
|
+
#
|
|
201
|
+
# Stdout contains one metadata line per object (or `''` when `out:` is given)
|
|
202
|
+
#
|
|
203
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
204
|
+
#
|
|
205
|
+
# @raise [Git::FailedError] if git exits non-zero (catastrophic failure only;
|
|
206
|
+
# missing objects are reported inline)
|
|
207
|
+
#
|
|
208
|
+
# @overload call(*objects, batch_command: true, **options)
|
|
209
|
+
# Dispatch mixed `contents`/`info`/`flush` commands via stdin
|
|
210
|
+
#
|
|
211
|
+
# Each element of `objects` is written verbatim as a stdin line — the caller
|
|
212
|
+
# is responsible for prefixing lines with the appropriate verb
|
|
213
|
+
# (`contents <object>`, `info <object>`, or `flush`).
|
|
214
|
+
#
|
|
215
|
+
# @param objects [Array<String>] pre-formatted command lines to write to stdin
|
|
216
|
+
#
|
|
217
|
+
# @param batch_command [Boolean, String] enable `--batch-command` mode; pass
|
|
218
|
+
# a format string to customise the output of `info` and `contents` commands
|
|
219
|
+
#
|
|
220
|
+
# @param options [Hash] command options
|
|
221
|
+
#
|
|
222
|
+
# @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
|
|
223
|
+
#
|
|
224
|
+
# @option options [Boolean, nil] :textconv (nil) apply textconv filters
|
|
225
|
+
#
|
|
226
|
+
# @option options [Boolean, nil] :filters (nil) apply full working-tree filters
|
|
227
|
+
#
|
|
228
|
+
# @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
|
|
229
|
+
#
|
|
230
|
+
# @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
|
|
231
|
+
#
|
|
232
|
+
# @option options [String] :filter (nil) omit objects matching the given filter spec
|
|
233
|
+
#
|
|
234
|
+
# @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
|
|
235
|
+
#
|
|
236
|
+
# @option options [#write, nil] :out (nil) stream stdout to this IO object
|
|
237
|
+
# instead of buffering in memory; when given, `result.stdout` will be `''`
|
|
238
|
+
#
|
|
239
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
240
|
+
#
|
|
241
|
+
# Stdout contains the interleaved command output (or `''` when `out:` is given)
|
|
242
|
+
#
|
|
243
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
244
|
+
#
|
|
245
|
+
# @raise [Git::FailedError] if git exits non-zero
|
|
246
|
+
#
|
|
247
|
+
# @overload call(batch_all_objects: true, batch: true, **options)
|
|
248
|
+
# Enumerate all objects in the repository with full content
|
|
249
|
+
#
|
|
250
|
+
# @param batch_all_objects [Boolean] enumerate all objects; stdin is not read
|
|
251
|
+
#
|
|
252
|
+
# @param batch [Boolean, String] enable `--batch` mode; pass a format string
|
|
253
|
+
# to customise the per-object output header
|
|
254
|
+
#
|
|
255
|
+
# @param options [Hash] command options
|
|
256
|
+
#
|
|
257
|
+
# @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
|
|
258
|
+
#
|
|
259
|
+
# @option options [Boolean, nil] :unordered (nil) output in arbitrary order
|
|
260
|
+
#
|
|
261
|
+
# @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap for
|
|
262
|
+
# commit and tag objects (`--use-mailmap`)
|
|
263
|
+
#
|
|
264
|
+
# @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
|
|
265
|
+
#
|
|
266
|
+
# @option options [String] :filter (nil) omit objects matching the given filter spec
|
|
267
|
+
#
|
|
268
|
+
# @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
|
|
269
|
+
#
|
|
270
|
+
# @option options [#write, nil] :out (nil) stream stdout to this IO object
|
|
271
|
+
# instead of buffering in memory; when given, `result.stdout` will be `''`
|
|
272
|
+
#
|
|
273
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
274
|
+
#
|
|
275
|
+
# Stdout contains the full batch output (or `''` when `out:` is given)
|
|
276
|
+
#
|
|
277
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
278
|
+
#
|
|
279
|
+
# @raise [Git::FailedError] if git exits non-zero
|
|
280
|
+
#
|
|
281
|
+
# @overload call(batch_all_objects: true, batch_check: true, **options)
|
|
282
|
+
# Enumerate all objects in the repository with metadata only
|
|
283
|
+
#
|
|
284
|
+
# @param batch_all_objects [Boolean] enumerate all objects; stdin is not read
|
|
285
|
+
#
|
|
286
|
+
# @param batch_check [Boolean, String] enable `--batch-check` mode; pass a
|
|
287
|
+
# format string to customise the per-object output line
|
|
288
|
+
#
|
|
289
|
+
# @param options [Hash] command options
|
|
290
|
+
#
|
|
291
|
+
# @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better
|
|
292
|
+
# throughput when processing large numbers of objects
|
|
293
|
+
#
|
|
294
|
+
# @option options [Boolean, nil] :unordered (nil) output in arbitrary order
|
|
295
|
+
#
|
|
296
|
+
# @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap for
|
|
297
|
+
# commit and tag objects (`--use-mailmap`)
|
|
298
|
+
#
|
|
299
|
+
# @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
|
|
300
|
+
#
|
|
301
|
+
# @option options [String] :filter (nil) omit objects matching the given filter spec
|
|
302
|
+
#
|
|
303
|
+
# @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
|
|
304
|
+
#
|
|
305
|
+
# @option options [#write, nil] :out (nil) stream stdout to this IO object
|
|
306
|
+
# instead of buffering in memory; when given, `result.stdout` will be `''`
|
|
307
|
+
#
|
|
308
|
+
# @option options [Numeric, nil] :timeout (nil) abort the command after this many seconds
|
|
309
|
+
#
|
|
310
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
311
|
+
#
|
|
312
|
+
# Stdout contains one metadata line per object (or `''` when `out:` is given)
|
|
313
|
+
#
|
|
314
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
315
|
+
#
|
|
316
|
+
# @raise [Git::FailedError] if git exits non-zero
|
|
317
|
+
def call(*objects, **)
|
|
318
|
+
bound = args_definition.bind(*objects, **)
|
|
319
|
+
validate_version!(bound.execution_options)
|
|
320
|
+
# `-Z` puts git into NUL I/O mode: input objects must be NUL-terminated.
|
|
321
|
+
# Without `-Z`, the standard newline delimiter is used.
|
|
322
|
+
delimiter = bound.Z? ? "\0" : "\n"
|
|
323
|
+
stdin = Array(bound.object).map { |o| "#{o}#{delimiter}" }.join
|
|
324
|
+
with_stdin(stdin) { |reader| run_batch(bound, reader) }
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
private
|
|
328
|
+
|
|
329
|
+
# Run the bound command with stdin connected to the reader end of the pipe
|
|
330
|
+
#
|
|
331
|
+
# @param bound [Git::Commands::Arguments::Bound] bound argument list
|
|
332
|
+
#
|
|
333
|
+
# @param reader [IO] read end of the stdin pipe
|
|
334
|
+
#
|
|
335
|
+
# @return [Git::CommandLine::Result]
|
|
336
|
+
#
|
|
337
|
+
def run_batch(bound, reader)
|
|
338
|
+
result = if bound.execution_options.key?(:out)
|
|
339
|
+
run_batch_streaming(bound, reader)
|
|
340
|
+
else
|
|
341
|
+
run_batch_capturing(bound, reader)
|
|
342
|
+
end
|
|
343
|
+
validate_exit_status!(result)
|
|
344
|
+
result
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Run the bound command using the streaming execution path
|
|
348
|
+
#
|
|
349
|
+
# @param bound [Git::Commands::Arguments::Bound] bound argument list
|
|
350
|
+
#
|
|
351
|
+
# @param reader [IO] read end of the stdin pipe
|
|
352
|
+
#
|
|
353
|
+
# @return [Git::CommandLine::Result] the command result
|
|
354
|
+
#
|
|
355
|
+
def run_batch_streaming(bound, reader)
|
|
356
|
+
@execution_context.command_streaming(
|
|
357
|
+
*bound,
|
|
358
|
+
in: reader,
|
|
359
|
+
**bound.execution_options,
|
|
360
|
+
raise_on_failure: false
|
|
361
|
+
)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Run the bound command using the capturing execution path
|
|
365
|
+
#
|
|
366
|
+
# @param bound [Git::Commands::Arguments::Bound] bound argument list
|
|
367
|
+
#
|
|
368
|
+
# @param reader [IO] read end of the stdin pipe
|
|
369
|
+
#
|
|
370
|
+
# @return [Git::CommandLine::Result] the command result
|
|
371
|
+
#
|
|
372
|
+
def run_batch_capturing(bound, reader)
|
|
373
|
+
@execution_context.command_capturing(
|
|
374
|
+
*bound,
|
|
375
|
+
in: reader,
|
|
376
|
+
**bound.execution_options,
|
|
377
|
+
normalize: false,
|
|
378
|
+
chomp: false,
|
|
379
|
+
raise_on_failure: false
|
|
380
|
+
)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/base'
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
module Commands
|
|
7
|
+
module CatFile
|
|
8
|
+
# Retrieves a single git object after applying working-tree filter processing
|
|
9
|
+
#
|
|
10
|
+
# Runs `git cat-file` with `--textconv` or `--filters`. Both modes require the
|
|
11
|
+
# caller to identify the object by revision **and** path so that git can look up
|
|
12
|
+
# the applicable `.gitattributes` rules:
|
|
13
|
+
#
|
|
14
|
+
# - **`--textconv`** — apply only the textconv filter (binary-to-text conversion
|
|
15
|
+
# defined by `diff.<driver>.textconv` in `.gitattributes`); intended for
|
|
16
|
+
# human-readable display
|
|
17
|
+
# - **`--filters`** — apply the full working-tree pipeline: smudge filter, EOL
|
|
18
|
+
# conversion, and textconv; returns the content exactly as `git checkout`
|
|
19
|
+
# would write it to disk
|
|
20
|
+
#
|
|
21
|
+
# The object can be identified as a combined `<rev>:<path>` string passed as the
|
|
22
|
+
# `rev` operand, or as a bare `<rev>` with `--path=<path>` supplied separately.
|
|
23
|
+
#
|
|
24
|
+
# For unfiltered object access, use {CatFile::Raw}.
|
|
25
|
+
# For batch queries across multiple objects, use {CatFile::Batch}.
|
|
26
|
+
#
|
|
27
|
+
# @note `arguments` block audited against https://git-scm.com/docs/git-cat-file/2.53.0
|
|
28
|
+
#
|
|
29
|
+
# @see Git::Commands::CatFile
|
|
30
|
+
#
|
|
31
|
+
# @see https://git-scm.com/docs/git-cat-file git-cat-file documentation
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
#
|
|
35
|
+
class Filtered < Base
|
|
36
|
+
arguments do
|
|
37
|
+
literal 'cat-file'
|
|
38
|
+
|
|
39
|
+
# Apply only the textconv filter (binary-to-text conversion)
|
|
40
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---textconv
|
|
41
|
+
flag_option :textconv
|
|
42
|
+
|
|
43
|
+
# Apply the full working-tree filter pipeline (smudge, EOL, textconv)
|
|
44
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filters
|
|
45
|
+
flag_option :filters
|
|
46
|
+
|
|
47
|
+
# Specify the path separately when the rev is passed as a bare revision.
|
|
48
|
+
# When used, the `rev` operand must be a plain revision (not `<rev>:<path>`).
|
|
49
|
+
# See https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---pathltpathgt
|
|
50
|
+
value_option :path, inline: true
|
|
51
|
+
|
|
52
|
+
end_of_options
|
|
53
|
+
|
|
54
|
+
# Revision identifying the object — either a combined `<rev>:<path>` string
|
|
55
|
+
# (e.g. `HEAD:README.md`) or a bare revision when `--path` is also given
|
|
56
|
+
operand :rev, required: true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @!method call(*)
|
|
60
|
+
#
|
|
61
|
+
# @overload call(rev, textconv: true, **options)
|
|
62
|
+
# Apply the textconv filter to a single object
|
|
63
|
+
#
|
|
64
|
+
# @param rev [String] combined `<rev>:<path>` identifier (e.g. `HEAD:README.md`),
|
|
65
|
+
# or a bare revision when `path:` is also given
|
|
66
|
+
#
|
|
67
|
+
# @param textconv [Boolean] enable textconv mode
|
|
68
|
+
#
|
|
69
|
+
# @param options [Hash] command options
|
|
70
|
+
#
|
|
71
|
+
# @option options [String] :path (nil)
|
|
72
|
+
# path to the blob when `rev` is a bare revision
|
|
73
|
+
#
|
|
74
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
75
|
+
#
|
|
76
|
+
# Stdout contains the textconv-processed content
|
|
77
|
+
#
|
|
78
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
79
|
+
#
|
|
80
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
81
|
+
#
|
|
82
|
+
# @overload call(rev, filters: true, **options)
|
|
83
|
+
# Apply the full working-tree filter pipeline to a single object
|
|
84
|
+
#
|
|
85
|
+
# @param rev [String] combined `<rev>:<path>` identifier (e.g. `HEAD:README.md`),
|
|
86
|
+
# or a bare revision when `path:` is also given
|
|
87
|
+
#
|
|
88
|
+
# @param filters [Boolean] enable full filter pipeline mode
|
|
89
|
+
#
|
|
90
|
+
# @param options [Hash] command options
|
|
91
|
+
#
|
|
92
|
+
# @option options [String] :path (nil)
|
|
93
|
+
# path to the blob when `rev` is a bare revision
|
|
94
|
+
#
|
|
95
|
+
# @return [Git::CommandLine::Result] the result of calling `git cat-file`
|
|
96
|
+
#
|
|
97
|
+
# Stdout contains the filter-processed content
|
|
98
|
+
#
|
|
99
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
100
|
+
#
|
|
101
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|