git 4.3.2 → 5.0.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/copilot-instructions.md +67 -2705
- data/.github/pull_request_template.md +3 -1
- data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
- data/.github/skills/command-implementation/REFERENCE.md +993 -0
- data/.github/skills/command-implementation/SKILL.md +229 -0
- data/.github/skills/command-test-conventions/SKILL.md +660 -0
- data/.github/skills/command-yard-documentation/SKILL.md +426 -0
- data/.github/skills/dependency-management/SKILL.md +72 -0
- data/.github/skills/development-workflow/SKILL.md +506 -0
- data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +586 -0
- data/.github/skills/facade-implementation/REFERENCE.md +840 -0
- data/.github/skills/facade-implementation/SKILL.md +260 -0
- data/.github/skills/facade-test-conventions/SKILL.md +380 -0
- data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
- data/.github/skills/make-skill-template/SKILL.md +176 -0
- data/.github/skills/pr-readiness-review/SKILL.md +185 -0
- data/.github/skills/project-context/SKILL.md +313 -0
- data/.github/skills/pull-request-review/SKILL.md +168 -0
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
- data/.github/skills/release-management/SKILL.md +125 -0
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
- data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
- data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
- data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
- data/.github/skills/reviewing-skills/SKILL.md +189 -0
- data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
- data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
- data/.github/skills/test-debugging/SKILL.md +160 -0
- data/.github/skills/yard-documentation/SKILL.md +793 -0
- data/.github/workflows/continuous_integration.yml +3 -2
- data/.github/workflows/enforce_conventional_commits.yml +1 -1
- data/.github/workflows/experimental_continuous_integration.yml +2 -2
- data/.github/workflows/release.yml +3 -4
- data/.gitignore +8 -0
- data/.husky/pre-commit +13 -0
- data/.release-please-manifest.json +1 -1
- data/.rspec +3 -0
- data/.rubocop.yml +7 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -40
- data/CONTRIBUTING.md +694 -53
- data/README.md +17 -5
- data/Rakefile +61 -9
- data/commitlint.test +4 -0
- data/git.gemspec +14 -8
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/base.rb +486 -410
- data/lib/git/branch.rb +380 -43
- data/lib/git/branch_delete_failure.rb +31 -0
- data/lib/git/branch_delete_result.rb +63 -0
- data/lib/git/branch_info.rb +178 -0
- data/lib/git/branches.rb +130 -24
- data/lib/git/command_line/base.rb +245 -0
- data/lib/git/command_line/capturing.rb +249 -0
- data/lib/git/command_line/result.rb +96 -0
- data/lib/git/command_line/streaming.rb +194 -0
- data/lib/git/command_line.rb +43 -322
- data/lib/git/command_line_result.rb +4 -88
- data/lib/git/commands/add.rb +131 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +252 -0
- data/lib/git/commands/am/continue.rb +43 -0
- data/lib/git/commands/am/quit.rb +43 -0
- data/lib/git/commands/am/retry.rb +47 -0
- data/lib/git/commands/am/show_current_patch.rb +64 -0
- data/lib/git/commands/am/skip.rb +42 -0
- data/lib/git/commands/am.rb +33 -0
- data/lib/git/commands/apply.rb +237 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +140 -0
- data/lib/git/commands/arguments.rb +3510 -0
- data/lib/git/commands/base.rb +403 -0
- data/lib/git/commands/branch/copy.rb +94 -0
- data/lib/git/commands/branch/create.rb +173 -0
- data/lib/git/commands/branch/delete.rb +80 -0
- data/lib/git/commands/branch/list.rb +162 -0
- data/lib/git/commands/branch/move.rb +94 -0
- data/lib/git/commands/branch/set_upstream.rb +86 -0
- data/lib/git/commands/branch/show_current.rb +49 -0
- data/lib/git/commands/branch/unset_upstream.rb +57 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +364 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +210 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +151 -0
- data/lib/git/commands/checkout/files.rb +115 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +105 -0
- data/lib/git/commands/clean.rb +100 -0
- data/lib/git/commands/clone.rb +240 -0
- data/lib/git/commands/commit.rb +272 -0
- data/lib/git/commands/commit_tree.rb +100 -0
- data/lib/git/commands/config_option_syntax/add.rb +83 -0
- data/lib/git/commands/config_option_syntax/get.rb +117 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +102 -0
- data/lib/git/commands/config_option_syntax/list.rb +107 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
- data/lib/git/commands/config_option_syntax/set.rb +114 -0
- data/lib/git/commands/config_option_syntax/unset.rb +89 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +155 -0
- data/lib/git/commands/diff.rb +656 -0
- data/lib/git/commands/diff_files.rb +518 -0
- data/lib/git/commands/diff_index.rb +496 -0
- data/lib/git/commands/fetch.rb +352 -0
- data/lib/git/commands/fsck.rb +136 -0
- data/lib/git/commands/gc.rb +132 -0
- data/lib/git/commands/grep.rb +338 -0
- data/lib/git/commands/init.rb +99 -0
- data/lib/git/commands/log.rb +632 -0
- data/lib/git/commands/ls_files.rb +191 -0
- data/lib/git/commands/ls_remote.rb +155 -0
- data/lib/git/commands/ls_tree.rb +131 -0
- data/lib/git/commands/maintenance/register.rb +75 -0
- data/lib/git/commands/maintenance/run.rb +104 -0
- data/lib/git/commands/maintenance/start.rb +66 -0
- data/lib/git/commands/maintenance/stop.rb +55 -0
- data/lib/git/commands/maintenance/unregister.rb +79 -0
- data/lib/git/commands/maintenance.rb +31 -0
- data/lib/git/commands/merge/abort.rb +44 -0
- data/lib/git/commands/merge/continue.rb +44 -0
- data/lib/git/commands/merge/quit.rb +46 -0
- data/lib/git/commands/merge/start.rb +245 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +86 -0
- data/lib/git/commands/mv.rb +77 -0
- data/lib/git/commands/name_rev.rb +114 -0
- data/lib/git/commands/pull.rb +377 -0
- data/lib/git/commands/push.rb +246 -0
- data/lib/git/commands/read_tree.rb +149 -0
- data/lib/git/commands/remote/add.rb +91 -0
- data/lib/git/commands/remote/get_url.rb +66 -0
- data/lib/git/commands/remote/list.rb +54 -0
- data/lib/git/commands/remote/prune.rb +61 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +69 -0
- data/lib/git/commands/remote/set_branches.rb +63 -0
- data/lib/git/commands/remote/set_head.rb +82 -0
- data/lib/git/commands/remote/set_url.rb +71 -0
- data/lib/git/commands/remote/set_url_add.rb +61 -0
- data/lib/git/commands/remote/set_url_delete.rb +64 -0
- data/lib/git/commands/remote/show.rb +71 -0
- data/lib/git/commands/remote/update.rb +72 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +277 -0
- data/lib/git/commands/reset.rb +147 -0
- data/lib/git/commands/rev_parse.rb +297 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +57 -0
- data/lib/git/commands/revert/quit.rb +47 -0
- data/lib/git/commands/revert/skip.rb +44 -0
- data/lib/git/commands/revert/start.rb +153 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +114 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
- data/lib/git/commands/show_ref/exists.rb +78 -0
- data/lib/git/commands/show_ref/list.rb +145 -0
- data/lib/git/commands/show_ref/verify.rb +120 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +75 -0
- data/lib/git/commands/stash/branch.rb +65 -0
- data/lib/git/commands/stash/clear.rb +41 -0
- data/lib/git/commands/stash/create.rb +58 -0
- data/lib/git/commands/stash/drop.rb +67 -0
- data/lib/git/commands/stash/list.rb +39 -0
- data/lib/git/commands/stash/pop.rb +78 -0
- data/lib/git/commands/stash/push.rb +103 -0
- data/lib/git/commands/stash/show.rb +149 -0
- data/lib/git/commands/stash/store.rb +63 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +169 -0
- data/lib/git/commands/symbolic_ref/delete.rb +68 -0
- data/lib/git/commands/symbolic_ref/read.rb +95 -0
- data/lib/git/commands/symbolic_ref/update.rb +76 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +139 -0
- data/lib/git/commands/tag/delete.rb +55 -0
- data/lib/git/commands/tag/list.rb +143 -0
- data/lib/git/commands/tag/verify.rb +71 -0
- data/lib/git/commands/tag.rb +26 -0
- data/lib/git/commands/update_ref/batch.rb +140 -0
- data/lib/git/commands/update_ref/delete.rb +92 -0
- data/lib/git/commands/update_ref/update.rb +106 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +52 -0
- data/lib/git/commands/worktree/add.rb +140 -0
- data/lib/git/commands/worktree/list.rb +64 -0
- data/lib/git/commands/worktree/lock.rb +58 -0
- data/lib/git/commands/worktree/management_base.rb +51 -0
- data/lib/git/commands/worktree/move.rb +66 -0
- data/lib/git/commands/worktree/prune.rb +67 -0
- data/lib/git/commands/worktree/remove.rb +63 -0
- data/lib/git/commands/worktree/repair.rb +76 -0
- data/lib/git/commands/worktree/unlock.rb +47 -0
- data/lib/git/commands/worktree.rb +43 -0
- data/lib/git/commands/write_tree.rb +68 -0
- data/lib/git/commands.rb +89 -0
- data/lib/git/detached_head_info.rb +54 -0
- data/lib/git/diff.rb +297 -7
- data/lib/git/diff_file_numstat_info.rb +29 -0
- data/lib/git/diff_file_patch_info.rb +134 -0
- data/lib/git/diff_file_raw_info.rb +127 -0
- data/lib/git/diff_info.rb +169 -0
- data/lib/git/diff_path_status.rb +78 -19
- data/lib/git/diff_result.rb +32 -0
- data/lib/git/diff_stats.rb +59 -14
- data/lib/git/dirstat_info.rb +86 -0
- data/lib/git/errors.rb +65 -2
- data/lib/git/execution_context/global.rb +56 -0
- data/lib/git/execution_context/repository.rb +147 -0
- data/lib/git/execution_context.rb +482 -0
- data/lib/git/file_ref.rb +74 -0
- data/lib/git/fsck_object.rb +9 -9
- data/lib/git/fsck_result.rb +1 -1
- data/lib/git/lib.rb +1606 -1028
- data/lib/git/log.rb +15 -2
- data/lib/git/object.rb +92 -22
- data/lib/git/parsers/branch.rb +224 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/diff.rb +585 -0
- data/lib/git/parsers/fsck.rb +133 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/stash.rb +208 -0
- data/lib/git/parsers/tag.rb +257 -0
- data/lib/git/remote.rb +133 -9
- data/lib/git/repository/branching.rb +572 -0
- data/lib/git/repository/committing.rb +191 -0
- data/lib/git/repository/configuring.rb +156 -0
- data/lib/git/repository/diffing.rb +775 -0
- data/lib/git/repository/inspecting.rb +153 -0
- data/lib/git/repository/logging.rb +247 -0
- data/lib/git/repository/merging.rb +295 -0
- data/lib/git/repository/object_operations.rb +1101 -0
- data/lib/git/repository/path_resolver.rb +207 -0
- data/lib/git/repository/remote_operations.rb +753 -0
- data/lib/git/repository/shared_private.rb +51 -0
- data/lib/git/repository/staging.rb +390 -0
- data/lib/git/repository/stashing.rb +107 -0
- data/lib/git/repository/status_operations.rb +180 -0
- data/lib/git/repository/worktree_operations.rb +159 -0
- data/lib/git/repository.rb +264 -1
- data/lib/git/stash.rb +85 -4
- data/lib/git/stash_info.rb +104 -0
- data/lib/git/stashes.rb +130 -13
- data/lib/git/status.rb +224 -18
- data/lib/git/tag_delete_failure.rb +31 -0
- data/lib/git/tag_delete_result.rb +63 -0
- data/lib/git/tag_info.rb +105 -0
- data/lib/git/version.rb +109 -2
- data/lib/git/version_constraint.rb +81 -0
- data/lib/git/worktree.rb +120 -5
- data/lib/git/worktrees.rb +107 -7
- data/lib/git.rb +114 -18
- data/redesign/1_architecture_existing.md +54 -18
- data/redesign/2_architecture_redesign.md +365 -46
- data/redesign/3_architecture_implementation.md +1451 -54
- data/tasks/gem_tasks.rake +4 -0
- data/tasks/npm_tasks.rake +7 -0
- data/tasks/rspec.rake +48 -0
- data/tasks/test.rake +13 -1
- data/tasks/yard.rake +34 -7
- metadata +349 -20
- data/lib/git/index.rb +0 -6
- data/lib/git/path.rb +0 -38
- data/lib/git/working_directory.rb +0 -6
- /data/{release-please-config.json → .release-please-config.json} +0 -0
data/lib/git/base.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'logger'
|
|
4
|
-
require '
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'git/repository/path_resolver'
|
|
5
6
|
|
|
6
7
|
module Git
|
|
7
8
|
# The main public interface for interacting with Git commands
|
|
@@ -15,17 +16,22 @@ module Git
|
|
|
15
16
|
class Base
|
|
16
17
|
# (see Git.bare)
|
|
17
18
|
def self.bare(git_dir, options = {})
|
|
18
|
-
|
|
19
|
-
new(options)
|
|
19
|
+
paths = Git::Repository::PathResolver.resolve_paths(repository: git_dir, bare: true)
|
|
20
|
+
new(options.merge(paths))
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
# (see Git.clone)
|
|
23
24
|
def self.clone(repository_url, directory, options = {})
|
|
24
25
|
lib_options = {}
|
|
25
26
|
lib_options[:git_ssh] = options[:git_ssh] if options.key?(:git_ssh)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
clone_result = Git::Lib.new(lib_options, options[:log]).clone(repository_url, directory, options)
|
|
28
|
+
bare = options[:bare] || options[:mirror]
|
|
29
|
+
paths = Git::Repository::PathResolver.resolve_paths(
|
|
30
|
+
working_directory: clone_result[:working_directory],
|
|
31
|
+
repository: clone_result[:repository],
|
|
32
|
+
bare: bare
|
|
33
|
+
)
|
|
34
|
+
new(options.merge(paths))
|
|
29
35
|
end
|
|
30
36
|
|
|
31
37
|
# (see Git.default_branch)
|
|
@@ -40,84 +46,32 @@ module Git
|
|
|
40
46
|
@config ||= Config.new
|
|
41
47
|
end
|
|
42
48
|
|
|
49
|
+
# @deprecated Use {Git.git_version} instead, which returns a {Git::Version} (not an Array).
|
|
50
|
+
# For the legacy array shape, call: `Git.git_version.to_a`
|
|
51
|
+
#
|
|
43
52
|
def self.binary_version(binary_path)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
parse_version_string(result)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
private_class_method def self.execute_git_version(binary_path)
|
|
52
|
-
Open3.capture2e(
|
|
53
|
-
binary_path,
|
|
54
|
-
'-c', 'core.quotePath=true',
|
|
55
|
-
'-c', 'color.ui=false',
|
|
56
|
-
'version'
|
|
53
|
+
Git::Deprecation.warn(
|
|
54
|
+
'Git::Base.binary_version is deprecated and will be removed in 6.0. ' \
|
|
55
|
+
'Use Git.git_version instead, which returns a Git::Version ' \
|
|
56
|
+
'(not an Array). For the legacy array shape, call: Git.git_version.to_a'
|
|
57
57
|
)
|
|
58
|
-
|
|
59
|
-
raise "Failed to get git version: #{binary_path} not found"
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
private_class_method def self.parse_version_string(raw_string)
|
|
63
|
-
version_match = raw_string.match(/\d+(\.\d+)+/)
|
|
64
|
-
return [0, 0, 0] unless version_match
|
|
65
|
-
|
|
66
|
-
version_parts = version_match[0].split('.').map(&:to_i)
|
|
67
|
-
version_parts.fill(0, version_parts.length...3)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# (see Git.init)
|
|
71
|
-
def self.init(directory = '.', options = {})
|
|
72
|
-
normalize_paths(options, default_working_directory: directory, default_repository: directory,
|
|
73
|
-
bare: options[:bare])
|
|
74
|
-
|
|
75
|
-
init_options = {
|
|
76
|
-
bare: options[:bare],
|
|
77
|
-
initial_branch: options[:initial_branch]
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
directory = options[:bare] ? options[:repository] : options[:working_directory]
|
|
81
|
-
FileUtils.mkdir_p(directory)
|
|
82
|
-
|
|
83
|
-
# TODO: this dance seems awkward: this creates a Git::Lib so we can call
|
|
84
|
-
# init so we can create a new Git::Base which in turn (ultimately)
|
|
85
|
-
# creates another/different Git::Lib.
|
|
86
|
-
#
|
|
87
|
-
# TODO: maybe refactor so this Git::Bare.init does this:
|
|
88
|
-
# self.new(opts).init(init_opts) and move all/some of this code into
|
|
89
|
-
# Git::Bare#init. This way the init method can be called on any
|
|
90
|
-
# repository you have a Git::Base instance for. This would not
|
|
91
|
-
# change the existing interface (other than adding to it).
|
|
92
|
-
#
|
|
93
|
-
Git::Lib.new(options).init(init_options)
|
|
94
|
-
|
|
95
|
-
new(options)
|
|
58
|
+
Git.git_version(binary_path).to_a
|
|
96
59
|
end
|
|
97
60
|
|
|
61
|
+
# Find the root of the working tree that contains `working_dir`
|
|
62
|
+
#
|
|
63
|
+
# Delegates to {Git::Repository::PathResolver.root_of_worktree}, using the
|
|
64
|
+
# global config for `binary_path` and `git_ssh`.
|
|
65
|
+
#
|
|
66
|
+
# @param working_dir [String] a path inside the working tree
|
|
67
|
+
#
|
|
68
|
+
# @return [String] the absolute path to the root of the working tree
|
|
69
|
+
#
|
|
70
|
+
# @raise [ArgumentError] if `working_dir` does not exist or is not inside a
|
|
71
|
+
# git working tree
|
|
72
|
+
#
|
|
98
73
|
def self.root_of_worktree(working_dir)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
result, status = execute_rev_parse_toplevel(working_dir)
|
|
102
|
-
process_rev_parse_result(result, status, working_dir)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
private_class_method def self.execute_rev_parse_toplevel(working_dir)
|
|
106
|
-
Open3.capture2e(
|
|
107
|
-
Git::Base.config.binary_path,
|
|
108
|
-
'-c', 'core.quotePath=true',
|
|
109
|
-
'-c', 'color.ui=false',
|
|
110
|
-
'rev-parse', '--show-toplevel',
|
|
111
|
-
chdir: File.expand_path(working_dir)
|
|
112
|
-
)
|
|
113
|
-
rescue Errno::ENOENT
|
|
114
|
-
raise ArgumentError, 'Failed to find the root of the worktree: git binary not found'
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
private_class_method def self.process_rev_parse_result(result, status, working_dir)
|
|
118
|
-
raise ArgumentError, "'#{working_dir}' is not in a git working tree" unless status.success?
|
|
119
|
-
|
|
120
|
-
result.chomp
|
|
74
|
+
Git::Repository::PathResolver.root_of_worktree(working_dir)
|
|
121
75
|
end
|
|
122
76
|
|
|
123
77
|
# (see Git.open)
|
|
@@ -126,9 +80,13 @@ module Git
|
|
|
126
80
|
|
|
127
81
|
working_dir = root_of_worktree(working_dir) unless options[:repository]
|
|
128
82
|
|
|
129
|
-
|
|
83
|
+
paths = Git::Repository::PathResolver.resolve_paths(
|
|
84
|
+
working_directory: working_dir,
|
|
85
|
+
repository: options[:repository],
|
|
86
|
+
index: options[:index]
|
|
87
|
+
)
|
|
130
88
|
|
|
131
|
-
new(options)
|
|
89
|
+
new(options.merge(paths))
|
|
132
90
|
end
|
|
133
91
|
|
|
134
92
|
# Create an object that executes Git commands in the context of a working
|
|
@@ -137,51 +95,100 @@ module Git
|
|
|
137
95
|
# @param [Hash] options The options for this command (see list of valid
|
|
138
96
|
# options below)
|
|
139
97
|
#
|
|
140
|
-
# @option options [Pathname] :
|
|
141
|
-
# directory
|
|
98
|
+
# @option options [Pathname] :working_directory the path to the root of the working
|
|
99
|
+
# directory or `nil` if executing commands on a bare repository
|
|
142
100
|
#
|
|
143
101
|
# @option options [Pathname] :repository used to specify a non-standard path to
|
|
144
|
-
# the repository directory
|
|
102
|
+
# the repository directory
|
|
103
|
+
#
|
|
104
|
+
# The default is `"<working_directory>/.git"`.
|
|
145
105
|
#
|
|
146
106
|
# @option options [Pathname] :index used to specify a non-standard path to an
|
|
147
|
-
# index file
|
|
107
|
+
# index file
|
|
108
|
+
#
|
|
109
|
+
# The default is `"<working_directory>/.git/index"`
|
|
110
|
+
#
|
|
111
|
+
# @option options [Logger] :log A logger to use for Git operations
|
|
148
112
|
#
|
|
149
|
-
#
|
|
150
|
-
# commands are logged at the `:info` level. Additional logging is done
|
|
113
|
+
# Git commands are logged at the `:info` level. Additional logging is done
|
|
151
114
|
# at the `:debug` level.
|
|
152
115
|
#
|
|
153
|
-
# @option options [String, nil] :git_ssh Path to a custom SSH executable or script
|
|
116
|
+
# @option options [String, nil] :git_ssh Path to a custom SSH executable or script
|
|
117
|
+
#
|
|
154
118
|
# Controls how SSH is configured for this {Git::Base} instance:
|
|
155
119
|
# - If this option is not provided, the global Git::Base.config.git_ssh setting is used.
|
|
156
120
|
# - If this option is explicitly set to nil, SSH is disabled for this instance.
|
|
157
121
|
# - If this option is a non-empty String, that value is used as the SSH command for
|
|
158
122
|
# this instance, overriding the global Git::Base.config.git_ssh setting.
|
|
159
123
|
#
|
|
160
|
-
# @
|
|
161
|
-
#
|
|
124
|
+
# @option options [String, :use_global_config] :binary_path Path to the git binary
|
|
125
|
+
#
|
|
126
|
+
# Controls which git binary is used for commands routed through
|
|
127
|
+
# {Git::ExecutionContext} (i.e., commands already migrated to
|
|
128
|
+
# +Git::Commands::*+ classes). Commands still delegating through +Git::Lib+
|
|
129
|
+
# continue to use the global `Git::Base.config.binary_path` setting.
|
|
130
|
+
#
|
|
131
|
+
# This limitation will be resolved when the architectural migration to
|
|
132
|
+
# +Git::Repository+ is complete.
|
|
133
|
+
#
|
|
134
|
+
# - If this option is not provided, the global Git::Base.config.binary_path setting is used.
|
|
135
|
+
# - If this option is a String, that value is used as the git binary path for
|
|
136
|
+
# migrated commands, overriding the global Git::Base.config.binary_path setting.
|
|
137
|
+
# - Passing `nil` raises ArgumentError — there is no "unset the binary" semantic.
|
|
138
|
+
#
|
|
139
|
+
# @return [Git::Base] an object that can execute git commands on a working copy or
|
|
140
|
+
# bare repository
|
|
141
|
+
#
|
|
142
|
+
# @raise [ArgumentError] if `binary_path` is `nil`
|
|
162
143
|
#
|
|
163
144
|
def initialize(options = {})
|
|
164
|
-
options = default_paths(options)
|
|
165
145
|
setup_logger(options[:log])
|
|
166
146
|
@git_ssh = options.key?(:git_ssh) ? options[:git_ssh] : :use_global_config
|
|
147
|
+
if options.key?(:binary_path)
|
|
148
|
+
raise ArgumentError, 'binary_path must not be nil' if options[:binary_path].nil?
|
|
149
|
+
|
|
150
|
+
@binary_path = options[:binary_path]
|
|
151
|
+
else
|
|
152
|
+
@binary_path = :use_global_config
|
|
153
|
+
end
|
|
167
154
|
initialize_components(options)
|
|
168
155
|
end
|
|
169
156
|
|
|
170
|
-
# Update the index from the current worktree to prepare
|
|
157
|
+
# Update the index from the current worktree to prepare for the next commit
|
|
171
158
|
#
|
|
172
|
-
# @
|
|
173
|
-
# lib.add('path/to/file')
|
|
174
|
-
# lib.add(['path/to/file1','path/to/file2'])
|
|
175
|
-
# lib.add(all: true)
|
|
159
|
+
# @overload add(paths = '.', **options)
|
|
176
160
|
#
|
|
177
|
-
#
|
|
178
|
-
#
|
|
161
|
+
# @example Stage all changed files
|
|
162
|
+
# git.add
|
|
179
163
|
#
|
|
180
|
-
#
|
|
181
|
-
#
|
|
164
|
+
# @example Stage a specific file
|
|
165
|
+
# git.add('path/to/file.rb')
|
|
182
166
|
#
|
|
183
|
-
|
|
184
|
-
|
|
167
|
+
# @example Stage multiple files
|
|
168
|
+
# git.add(['path/to/file1.rb', 'path/to/file2.rb'])
|
|
169
|
+
#
|
|
170
|
+
# @example Stage all changes including deletions
|
|
171
|
+
# git.add(all: true)
|
|
172
|
+
#
|
|
173
|
+
# @param paths [String, Array<String>] a file or files to add (relative to
|
|
174
|
+
# the worktree root); defaults to `'.'` (all files)
|
|
175
|
+
#
|
|
176
|
+
# @param options [Hash] options for the add command
|
|
177
|
+
#
|
|
178
|
+
# @option options [Boolean, nil] :all (nil) add, modify, and remove index
|
|
179
|
+
# entries to match the worktree
|
|
180
|
+
#
|
|
181
|
+
# @option options [Boolean, nil] :force (nil) allow adding otherwise ignored
|
|
182
|
+
# files
|
|
183
|
+
#
|
|
184
|
+
# @return [String] git's stdout from the add
|
|
185
|
+
#
|
|
186
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
187
|
+
#
|
|
188
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
189
|
+
#
|
|
190
|
+
def add(paths = '.', **)
|
|
191
|
+
facade_repository.add(paths, **)
|
|
185
192
|
end
|
|
186
193
|
|
|
187
194
|
# adds a new remote to this repository
|
|
@@ -195,9 +202,7 @@ module Git
|
|
|
195
202
|
# :fetch => true
|
|
196
203
|
# :track => <branch_name>
|
|
197
204
|
def add_remote(name, url, opts = {})
|
|
198
|
-
|
|
199
|
-
lib.remote_add(name, url, opts)
|
|
200
|
-
Git::Remote.new(self, name)
|
|
205
|
+
facade_repository.add_remote(name, url, opts)
|
|
201
206
|
end
|
|
202
207
|
|
|
203
208
|
# changes current working directory for a block
|
|
@@ -209,42 +214,46 @@ module Git
|
|
|
209
214
|
# @git.add
|
|
210
215
|
# @git.commit('message')
|
|
211
216
|
# end
|
|
212
|
-
def chdir # :yields: the
|
|
217
|
+
def chdir # :yields: the working directory Pathname
|
|
213
218
|
Dir.chdir(dir.to_s) do
|
|
214
|
-
yield dir
|
|
219
|
+
yield dir
|
|
215
220
|
end
|
|
216
221
|
end
|
|
217
222
|
|
|
218
223
|
# g.config('user.name', 'Scott Chacon') # sets value
|
|
219
224
|
# g.config('user.email', 'email@email.com') # sets value
|
|
220
|
-
# g.config('user.email', 'email@email.com', file: 'path/to/custom/config) # sets value in file
|
|
225
|
+
# g.config('user.email', 'email@email.com', file: 'path/to/custom/config') # sets value in file
|
|
221
226
|
# g.config('user.name') # returns 'Scott Chacon'
|
|
222
227
|
# g.config # returns whole config hash
|
|
223
228
|
def config(name = nil, value = nil, options = {})
|
|
224
|
-
|
|
225
|
-
# set value
|
|
226
|
-
lib.config_set(name, value, options)
|
|
227
|
-
elsif name
|
|
228
|
-
# return value
|
|
229
|
-
lib.config_get(name)
|
|
230
|
-
else
|
|
231
|
-
# return hash
|
|
232
|
-
lib.config_list
|
|
233
|
-
end
|
|
229
|
+
facade_repository.config(name, value, options)
|
|
234
230
|
end
|
|
235
231
|
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
232
|
+
# Returns a reference to the working directory
|
|
233
|
+
#
|
|
234
|
+
# @example
|
|
235
|
+
# @git.dir.to_s
|
|
236
|
+
# @git.dir.writable?
|
|
237
|
+
#
|
|
238
|
+
# @return [Pathname] the working directory path
|
|
239
|
+
#
|
|
239
240
|
def dir
|
|
240
241
|
@working_directory
|
|
241
242
|
end
|
|
242
243
|
|
|
243
|
-
#
|
|
244
|
+
# Returns a reference to the git index file
|
|
245
|
+
#
|
|
246
|
+
# @return [Pathname] the index file path
|
|
247
|
+
#
|
|
244
248
|
attr_reader :index
|
|
245
249
|
|
|
246
|
-
#
|
|
247
|
-
#
|
|
250
|
+
# Returns a reference to the git repository directory
|
|
251
|
+
#
|
|
252
|
+
# @example
|
|
253
|
+
# @git.repo.to_s
|
|
254
|
+
#
|
|
255
|
+
# @return [Pathname] the repository directory path
|
|
256
|
+
#
|
|
248
257
|
def repo
|
|
249
258
|
@repository
|
|
250
259
|
end
|
|
@@ -259,40 +268,44 @@ module Git
|
|
|
259
268
|
.sum { |file| File.stat(file).size.to_i }
|
|
260
269
|
end
|
|
261
270
|
|
|
262
|
-
|
|
271
|
+
private
|
|
272
|
+
|
|
273
|
+
def deprecate_check_argument(check, must_exist)
|
|
263
274
|
unless check.nil?
|
|
264
275
|
Git::Deprecation.warn(
|
|
265
276
|
'The "check" argument is deprecated and will be removed in a future version. ' \
|
|
266
277
|
'Use "must_exist:" instead.'
|
|
267
278
|
)
|
|
268
279
|
end
|
|
269
|
-
|
|
270
280
|
# default is true
|
|
271
|
-
must_exist
|
|
272
|
-
|
|
273
|
-
@lib = nil
|
|
274
|
-
@index = Git::Index.new(index_file.to_s, must_exist:)
|
|
281
|
+
must_exist.nil? && check.nil? ? true : must_exist | check
|
|
275
282
|
end
|
|
276
283
|
|
|
277
|
-
def
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
'The "check" argument is deprecated and will be removed in a future version. ' \
|
|
281
|
-
'Use "must_exist:" instead.'
|
|
282
|
-
)
|
|
284
|
+
def validate_path(path, must_exist)
|
|
285
|
+
Pathname.new(File.expand_path(path.to_s)).tap do |expanded_path|
|
|
286
|
+
raise ArgumentError, "path does not exist: #{expanded_path}" if must_exist && !expanded_path.exist?
|
|
283
287
|
end
|
|
288
|
+
end
|
|
284
289
|
|
|
285
|
-
|
|
286
|
-
|
|
290
|
+
public
|
|
291
|
+
|
|
292
|
+
def set_index(index_file, check = nil, must_exist: nil)
|
|
293
|
+
must_exist = deprecate_check_argument(check, must_exist)
|
|
294
|
+
@lib = nil
|
|
295
|
+
@facade_repository = nil
|
|
296
|
+
@index = validate_path(index_file, must_exist)
|
|
297
|
+
end
|
|
287
298
|
|
|
299
|
+
def set_working(work_dir, check = nil, must_exist: nil)
|
|
300
|
+
must_exist = deprecate_check_argument(check, must_exist)
|
|
288
301
|
@lib = nil
|
|
289
|
-
@
|
|
302
|
+
@facade_repository = nil
|
|
303
|
+
@working_directory = validate_path(work_dir, must_exist)
|
|
290
304
|
end
|
|
291
305
|
|
|
292
306
|
# returns +true+ if the branch exists locally
|
|
293
307
|
def local_branch?(branch)
|
|
294
|
-
|
|
295
|
-
branch_names.include?(branch)
|
|
308
|
+
facade_repository.local_branch?(branch)
|
|
296
309
|
end
|
|
297
310
|
|
|
298
311
|
def is_local_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -305,8 +318,7 @@ module Git
|
|
|
305
318
|
|
|
306
319
|
# returns +true+ if the branch exists remotely
|
|
307
320
|
def remote_branch?(branch)
|
|
308
|
-
|
|
309
|
-
branch_names.include?(branch)
|
|
321
|
+
facade_repository.remote_branch?(branch)
|
|
310
322
|
end
|
|
311
323
|
|
|
312
324
|
def is_remote_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -319,8 +331,7 @@ module Git
|
|
|
319
331
|
|
|
320
332
|
# returns +true+ if the branch exists
|
|
321
333
|
def branch?(branch)
|
|
322
|
-
|
|
323
|
-
branch_names.include?(branch)
|
|
334
|
+
facade_repository.branch?(branch)
|
|
324
335
|
end
|
|
325
336
|
|
|
326
337
|
def is_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -338,7 +349,17 @@ module Git
|
|
|
338
349
|
@lib ||= Git::Lib.new(self, @logger)
|
|
339
350
|
end
|
|
340
351
|
|
|
341
|
-
# Returns the
|
|
352
|
+
# Returns the {Git::Repository} facade for this repository
|
|
353
|
+
#
|
|
354
|
+
# @return [Git::Repository]
|
|
355
|
+
# @api private
|
|
356
|
+
def facade_repository
|
|
357
|
+
@facade_repository ||= Git::Repository.new(
|
|
358
|
+
execution_context: Git::ExecutionContext::Repository.from_base(self, logger: @logger)
|
|
359
|
+
)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Returns the per-instance git_ssh configuration value
|
|
342
363
|
#
|
|
343
364
|
# This may be:
|
|
344
365
|
# * a [String] path when an explicit git_ssh command has been configured
|
|
@@ -349,6 +370,16 @@ module Git
|
|
|
349
370
|
# @api private
|
|
350
371
|
attr_reader :git_ssh
|
|
351
372
|
|
|
373
|
+
# Returns the per-instance git binary path configuration value
|
|
374
|
+
#
|
|
375
|
+
# This may be:
|
|
376
|
+
# * a [String] path when an explicit binary path has been configured
|
|
377
|
+
# * the Symbol `:use_global_config` when this instance is using the global config
|
|
378
|
+
#
|
|
379
|
+
# @return [String, Symbol] the binary_path configuration value for this instance
|
|
380
|
+
# @api private
|
|
381
|
+
attr_reader :binary_path
|
|
382
|
+
|
|
352
383
|
# Run a grep for 'string' on the HEAD of the git repository
|
|
353
384
|
#
|
|
354
385
|
# @example Limit grep's scope by calling grep() from a specific object:
|
|
@@ -367,9 +398,9 @@ module Git
|
|
|
367
398
|
# of paths to limit the search to or nil for no limit
|
|
368
399
|
# @param opts [Hash] options to pass to the underlying `git grep` command
|
|
369
400
|
#
|
|
370
|
-
# @option opts [Boolean] :ignore_case (
|
|
371
|
-
# @option opts [Boolean] :invert_match (
|
|
372
|
-
# @option opts [Boolean] :extended_regexp (
|
|
401
|
+
# @option opts [Boolean, nil] :ignore_case (nil) ignore case when matching
|
|
402
|
+
# @option opts [Boolean, nil] :invert_match (nil) select non-matching lines
|
|
403
|
+
# @option opts [Boolean, nil] :extended_regexp (nil) use extended regular expressions
|
|
373
404
|
# @option opts [String] :object (HEAD) the object to search from
|
|
374
405
|
#
|
|
375
406
|
# @return [Hash<String, Array>] a hash of arrays
|
|
@@ -382,30 +413,38 @@ module Git
|
|
|
382
413
|
# ```
|
|
383
414
|
#
|
|
384
415
|
def grep(string, path_limiter = nil, opts = {})
|
|
385
|
-
object('HEAD')
|
|
416
|
+
opts = opts.merge(object: facade_repository.rev_parse('HEAD')) unless opts.key?(:object)
|
|
417
|
+
facade_repository.grep(string, path_limiter, opts)
|
|
386
418
|
end
|
|
387
419
|
|
|
388
420
|
# List the files in the worktree that are ignored by git
|
|
389
|
-
# @return [Array<String>] the list of ignored files relative to
|
|
421
|
+
# @return [Array<String>] the list of ignored files relative to the root of the worktree
|
|
390
422
|
#
|
|
391
423
|
def ignored_files
|
|
392
|
-
|
|
424
|
+
facade_repository.ignored_files
|
|
393
425
|
end
|
|
394
426
|
|
|
395
427
|
# removes file(s) from the git repository
|
|
396
428
|
def rm(path = '.', opts = {})
|
|
397
|
-
|
|
429
|
+
facade_repository.rm(path, opts)
|
|
398
430
|
end
|
|
399
431
|
|
|
400
432
|
alias remove rm
|
|
401
433
|
|
|
402
434
|
# resets the working directory to the provided commitish
|
|
403
435
|
def reset(commitish = nil, opts = {})
|
|
404
|
-
|
|
436
|
+
facade_repository.reset(commitish, **opts)
|
|
405
437
|
end
|
|
406
438
|
|
|
407
439
|
# resets the working directory to the commitish with '--hard'
|
|
440
|
+
#
|
|
441
|
+
# @deprecated Use {#reset} with `hard: true` instead.
|
|
442
|
+
#
|
|
408
443
|
def reset_hard(commitish = nil, opts = {})
|
|
444
|
+
Git::Deprecation.warn(
|
|
445
|
+
'Git::Base#reset_hard is deprecated and will be removed in a future version. ' \
|
|
446
|
+
'Use Git::Base#reset(commitish, hard: true) instead.'
|
|
447
|
+
)
|
|
409
448
|
opts = { hard: true }.merge(opts)
|
|
410
449
|
lib.reset(commitish, opts)
|
|
411
450
|
end
|
|
@@ -418,7 +457,7 @@ module Git
|
|
|
418
457
|
# :ff
|
|
419
458
|
#
|
|
420
459
|
def clean(opts = {})
|
|
421
|
-
|
|
460
|
+
facade_repository.clean(opts)
|
|
422
461
|
end
|
|
423
462
|
|
|
424
463
|
# returns the most recent tag that is reachable from a commit
|
|
@@ -447,7 +486,7 @@ module Git
|
|
|
447
486
|
# :no_edit
|
|
448
487
|
#
|
|
449
488
|
def revert(commitish = nil, opts = {})
|
|
450
|
-
|
|
489
|
+
facade_repository.revert(commitish, **opts)
|
|
451
490
|
end
|
|
452
491
|
|
|
453
492
|
# commits all pending changes in the index file to the git repository
|
|
@@ -459,69 +498,71 @@ module Git
|
|
|
459
498
|
# :author
|
|
460
499
|
#
|
|
461
500
|
def commit(message, opts = {})
|
|
462
|
-
|
|
501
|
+
facade_repository.commit(message, **opts)
|
|
463
502
|
end
|
|
464
503
|
|
|
465
504
|
# commits all pending changes in the index file to the git repository,
|
|
466
505
|
# but automatically adds all modified files without having to explicitly
|
|
467
506
|
# calling @git.add() on them.
|
|
468
507
|
def commit_all(message, opts = {})
|
|
469
|
-
|
|
470
|
-
lib.commit(message, opts)
|
|
508
|
+
facade_repository.commit_all(message, **opts)
|
|
471
509
|
end
|
|
472
510
|
|
|
473
511
|
# checks out a branch as the new git working directory
|
|
474
512
|
def checkout(*, **)
|
|
475
|
-
|
|
513
|
+
facade_repository.checkout(*, **)
|
|
476
514
|
end
|
|
477
515
|
|
|
478
516
|
# checks out an old version of a file
|
|
479
517
|
def checkout_file(version, file)
|
|
480
|
-
|
|
518
|
+
facade_repository.checkout_file(version, file)
|
|
481
519
|
end
|
|
482
520
|
|
|
483
521
|
# fetches changes from a remote branch - this does not modify the working directory,
|
|
484
522
|
# it just gets the changes from the remote if there are any
|
|
485
523
|
def fetch(remote = 'origin', opts = {})
|
|
486
|
-
|
|
487
|
-
opts = remote
|
|
488
|
-
remote = nil
|
|
489
|
-
end
|
|
490
|
-
lib.fetch(remote, opts)
|
|
524
|
+
facade_repository.fetch(remote, opts)
|
|
491
525
|
end
|
|
492
526
|
|
|
493
527
|
# Push changes to a remote repository
|
|
494
528
|
#
|
|
495
529
|
# @overload push(remote = nil, branch = nil, options = {})
|
|
530
|
+
#
|
|
496
531
|
# @param remote [String] the remote repository to push to
|
|
532
|
+
#
|
|
497
533
|
# @param branch [String] the branch to push
|
|
534
|
+
#
|
|
498
535
|
# @param options [Hash] options to pass to the push command
|
|
499
536
|
#
|
|
500
|
-
# @option
|
|
501
|
-
#
|
|
502
|
-
# @option
|
|
503
|
-
# @option opts [Boolean] :tags (false) Push all refs under refs/tags/
|
|
504
|
-
# @option opts [Array, String] :push_options (nil) Push options to transmit
|
|
537
|
+
# @option options [Boolean, nil] :mirror (nil) push all refs under refs/heads/, refs/tags/ and refs/remotes/
|
|
538
|
+
#
|
|
539
|
+
# @option options [Boolean, nil] :delete (nil) delete refs that don't exist on the remote
|
|
505
540
|
#
|
|
506
|
-
# @
|
|
541
|
+
# @option options [Boolean, nil] :force (nil) force updates
|
|
542
|
+
#
|
|
543
|
+
# @option options [Boolean, nil] :tags (nil) push all refs under refs/tags/
|
|
544
|
+
#
|
|
545
|
+
# @option options [String, Array<String>] :push_option (nil) push options to transmit
|
|
546
|
+
#
|
|
547
|
+
# @return [String] the stdout output from the push command
|
|
507
548
|
#
|
|
508
549
|
# @raise [Git::FailedError] if the push fails
|
|
509
550
|
# @raise [ArgumentError] if a branch is given without a remote
|
|
510
551
|
#
|
|
511
552
|
def push(*, **)
|
|
512
|
-
|
|
553
|
+
facade_repository.push(*, **)
|
|
513
554
|
end
|
|
514
555
|
|
|
515
556
|
# merges one or more branches into the current working branch
|
|
516
557
|
#
|
|
517
558
|
# you can specify more than one branch to merge by passing an array of branches
|
|
518
559
|
def merge(branch, message = 'merge', opts = {})
|
|
519
|
-
|
|
560
|
+
facade_repository.merge(branch, message, opts)
|
|
520
561
|
end
|
|
521
562
|
|
|
522
563
|
# iterates over the files which are unmerged
|
|
523
|
-
def each_conflict(&)
|
|
524
|
-
|
|
564
|
+
def each_conflict(&)
|
|
565
|
+
facade_repository.each_conflict(&)
|
|
525
566
|
end
|
|
526
567
|
|
|
527
568
|
# Pulls the given branch from the given remote into the current branch
|
|
@@ -530,7 +571,7 @@ module Git
|
|
|
530
571
|
# @param branch [String] the branch to pull from
|
|
531
572
|
# @param opts [Hash] options to pass to the pull command
|
|
532
573
|
#
|
|
533
|
-
# @option opts [Boolean] :allow_unrelated_histories (
|
|
574
|
+
# @option opts [Boolean, nil] :allow_unrelated_histories (nil) merges histories of
|
|
534
575
|
# two projects that started their lives independently
|
|
535
576
|
# @example pulls from origin/master
|
|
536
577
|
# @git.pull
|
|
@@ -539,17 +580,17 @@ module Git
|
|
|
539
580
|
# @example pulls from upstream/develop
|
|
540
581
|
# @git.pull('upstream', 'develop')
|
|
541
582
|
#
|
|
542
|
-
# @return [
|
|
583
|
+
# @return [String] the stdout output from the pull command
|
|
543
584
|
#
|
|
544
585
|
# @raise [Git::FailedError] if the pull fails
|
|
545
586
|
# @raise [ArgumentError] if a branch is given without a remote
|
|
546
587
|
def pull(remote = nil, branch = nil, opts = {})
|
|
547
|
-
|
|
588
|
+
facade_repository.pull(remote, branch, opts)
|
|
548
589
|
end
|
|
549
590
|
|
|
550
591
|
# returns an array of Git:Remote objects
|
|
551
592
|
def remotes
|
|
552
|
-
|
|
593
|
+
facade_repository.remotes
|
|
553
594
|
end
|
|
554
595
|
|
|
555
596
|
# sets the url for a remote
|
|
@@ -558,9 +599,7 @@ module Git
|
|
|
558
599
|
# @git.set_remote_url('scotts_git', 'git://repo.or.cz/rubygit.git')
|
|
559
600
|
#
|
|
560
601
|
def set_remote_url(name, url)
|
|
561
|
-
|
|
562
|
-
lib.remote_set_url(name, url)
|
|
563
|
-
Git::Remote.new(self, name)
|
|
602
|
+
facade_repository.set_remote_url(name, url)
|
|
564
603
|
end
|
|
565
604
|
|
|
566
605
|
# Configures which branches are fetched for a remote
|
|
@@ -592,24 +631,19 @@ module Git
|
|
|
592
631
|
# the underlying git command fails
|
|
593
632
|
#
|
|
594
633
|
def remote_set_branches(name, *branches, add: false)
|
|
595
|
-
|
|
596
|
-
raise ArgumentError, 'branches are required' if branch_list.empty?
|
|
597
|
-
|
|
598
|
-
lib.remote_set_branches(name, branch_list, add: add)
|
|
599
|
-
|
|
600
|
-
nil
|
|
634
|
+
facade_repository.remote_set_branches(name, *branches, add: add)
|
|
601
635
|
end
|
|
602
636
|
|
|
603
637
|
# removes a remote from this repository
|
|
604
638
|
#
|
|
605
639
|
# @git.remove_remote('scott_git')
|
|
606
640
|
def remove_remote(name)
|
|
607
|
-
|
|
641
|
+
facade_repository.remove_remote(name)
|
|
608
642
|
end
|
|
609
643
|
|
|
610
|
-
# returns an array of all Git::Tag objects for this repository
|
|
644
|
+
# returns an array of all Git::Object::Tag objects for this repository
|
|
611
645
|
def tags
|
|
612
|
-
|
|
646
|
+
facade_repository.tags
|
|
613
647
|
end
|
|
614
648
|
|
|
615
649
|
# Create a new git tag
|
|
@@ -620,29 +654,53 @@ module Git
|
|
|
620
654
|
# repo.add_tag('tag_name', {:options => 'here'})
|
|
621
655
|
#
|
|
622
656
|
# @param [String] name The name of the tag to add
|
|
623
|
-
# @param [Hash] options
|
|
657
|
+
# @param [Hash] options Options to pass to `git tag`.
|
|
624
658
|
# See [git-tag](https://git-scm.com/docs/git-tag) for more details.
|
|
625
|
-
# @option options [
|
|
626
|
-
# @option options [
|
|
627
|
-
# @option options [
|
|
628
|
-
#
|
|
659
|
+
# @option options [Boolean, nil] :annotate (nil) make an unsigned, annotated tag object
|
|
660
|
+
# @option options [Boolean, nil] :a (nil) an alias for the `:annotate` option
|
|
661
|
+
# @option options [Boolean, nil] :d (nil) delete existing tag with the given name —
|
|
662
|
+
# deprecated; use {#delete_tag} instead (alias: `:delete`)
|
|
663
|
+
# @option options [Boolean, nil] :delete (nil) delete existing tag with the given name —
|
|
664
|
+
# deprecated; use {#delete_tag} instead (alias: `:d`)
|
|
665
|
+
# @option options [Boolean, nil] :f (nil) replace an existing tag with the given name (instead of failing)
|
|
629
666
|
# @option options [String] :message Use the given tag message
|
|
630
667
|
# @option options [String] :m An alias for the `:message` option
|
|
631
|
-
# @option options [
|
|
668
|
+
# @option options [Boolean, nil] :s (nil) make a GPG-signed tag
|
|
632
669
|
#
|
|
633
670
|
def add_tag(name, *options)
|
|
634
|
-
|
|
635
|
-
tag(name)
|
|
671
|
+
facade_repository.add_tag(name, *options)
|
|
636
672
|
end
|
|
637
673
|
|
|
638
674
|
# deletes a tag
|
|
639
675
|
def delete_tag(name)
|
|
640
|
-
|
|
676
|
+
facade_repository.delete_tag(name)
|
|
641
677
|
end
|
|
642
678
|
|
|
643
|
-
#
|
|
679
|
+
# Creates an archive of the given tree-ish and writes it to a file
|
|
680
|
+
#
|
|
681
|
+
# @api public
|
|
682
|
+
#
|
|
683
|
+
# @param treeish [String] the commit, tag, branch, or tree to archive
|
|
684
|
+
#
|
|
685
|
+
# @param file [String, nil] destination file path; a temp file is created
|
|
686
|
+
# if `nil`
|
|
687
|
+
#
|
|
688
|
+
# @param opts [Hash] archive options (see {Git::Repository::ObjectOperations#archive})
|
|
689
|
+
#
|
|
690
|
+
# @return [String] the path to the written archive file
|
|
691
|
+
#
|
|
692
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
693
|
+
#
|
|
694
|
+
# @raise [ArgumentError] if `file` is an existing directory
|
|
695
|
+
#
|
|
696
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
697
|
+
#
|
|
698
|
+
# @example Archive HEAD to a zip file
|
|
699
|
+
# git.archive('HEAD', '/tmp/release.zip', format: 'zip')
|
|
700
|
+
# #=> "/tmp/release.zip"
|
|
701
|
+
#
|
|
644
702
|
def archive(treeish, file = nil, opts = {})
|
|
645
|
-
|
|
703
|
+
facade_repository.archive(treeish, file, opts)
|
|
646
704
|
end
|
|
647
705
|
|
|
648
706
|
# repacks the repository
|
|
@@ -665,14 +723,14 @@ module Git
|
|
|
665
723
|
# references in the refs namespace, and all reflogs.
|
|
666
724
|
# @param [Hash] options options to pass to the underlying `git fsck` command
|
|
667
725
|
#
|
|
668
|
-
# @option options [Boolean] :unreachable print unreachable objects
|
|
669
|
-
# @option options [Boolean] :strict enable strict checking
|
|
670
|
-
# @option options [Boolean] :connectivity_only check only connectivity (faster)
|
|
671
|
-
# @option options [Boolean] :root report root nodes
|
|
672
|
-
# @option options [Boolean] :tags report tags
|
|
673
|
-
# @option options [Boolean] :cache consider objects in the index
|
|
674
|
-
# @option options [Boolean] :no_reflogs do not consider reflogs
|
|
675
|
-
# @option options [Boolean] :lost_found write dangling objects to .git/lost-found
|
|
726
|
+
# @option options [Boolean, nil] :unreachable (nil) print unreachable objects
|
|
727
|
+
# @option options [Boolean, nil] :strict (nil) enable strict checking
|
|
728
|
+
# @option options [Boolean, nil] :connectivity_only (nil) check only connectivity (faster)
|
|
729
|
+
# @option options [Boolean, nil] :root (nil) report root nodes
|
|
730
|
+
# @option options [Boolean, nil] :tags (nil) report tags
|
|
731
|
+
# @option options [Boolean, nil] :cache (nil) consider objects in the index
|
|
732
|
+
# @option options [Boolean, nil] :no_reflogs (nil) do not consider reflogs
|
|
733
|
+
# @option options [Boolean, nil] :lost_found (nil) write dangling objects to .git/lost-found
|
|
676
734
|
# (note: this modifies the repository by creating files)
|
|
677
735
|
# @option options [Boolean, nil] :dangling print dangling objects (true/false/nil for default)
|
|
678
736
|
# @option options [Boolean, nil] :full check objects in alternate pools (true/false/nil for default)
|
|
@@ -683,10 +741,10 @@ module Git
|
|
|
683
741
|
#
|
|
684
742
|
# @example Check repository integrity
|
|
685
743
|
# result = git.fsck
|
|
686
|
-
# result.dangling.each { |obj| puts "#{obj.type}: #{obj.
|
|
744
|
+
# result.dangling.each { |obj| puts "#{obj.type}: #{obj.oid}" }
|
|
687
745
|
#
|
|
688
746
|
# @example Check with strict mode and suppress dangling output
|
|
689
|
-
# result = git.fsck(strict: true,
|
|
747
|
+
# result = git.fsck(strict: true, no_dangling: true)
|
|
690
748
|
#
|
|
691
749
|
# @example Check if repository has any issues
|
|
692
750
|
# result = git.fsck
|
|
@@ -694,14 +752,14 @@ module Git
|
|
|
694
752
|
#
|
|
695
753
|
# @example List root commits
|
|
696
754
|
# result = git.fsck(root: true)
|
|
697
|
-
# result.root.each { |obj| puts obj.
|
|
755
|
+
# result.root.each { |obj| puts obj.oid }
|
|
698
756
|
#
|
|
699
757
|
# @example Check specific objects
|
|
700
758
|
# result = git.fsck('abc1234', 'def5678')
|
|
701
759
|
#
|
|
702
760
|
# rubocop:disable Style/ArgumentsForwarding
|
|
703
761
|
def fsck(*objects, **opts)
|
|
704
|
-
|
|
762
|
+
facade_repository.fsck(*objects, **opts)
|
|
705
763
|
end
|
|
706
764
|
# rubocop:enable Style/ArgumentsForwarding
|
|
707
765
|
|
|
@@ -721,7 +779,7 @@ module Git
|
|
|
721
779
|
# @param [String|NilClass] path the path of the file to be shown
|
|
722
780
|
# @return [String] the object information
|
|
723
781
|
def show(objectish = nil, path = nil)
|
|
724
|
-
|
|
782
|
+
facade_repository.show(objectish, path)
|
|
725
783
|
end
|
|
726
784
|
|
|
727
785
|
## LOWER LEVEL INDEX OPERATIONS ##
|
|
@@ -750,7 +808,7 @@ module Git
|
|
|
750
808
|
end
|
|
751
809
|
|
|
752
810
|
def checkout_index(opts = {})
|
|
753
|
-
|
|
811
|
+
facade_repository.checkout_index(opts)
|
|
754
812
|
end
|
|
755
813
|
|
|
756
814
|
def read_tree(treeish, opts = {})
|
|
@@ -758,23 +816,22 @@ module Git
|
|
|
758
816
|
end
|
|
759
817
|
|
|
760
818
|
def write_tree
|
|
761
|
-
|
|
819
|
+
facade_repository.write_tree
|
|
762
820
|
end
|
|
763
821
|
|
|
764
822
|
def write_and_commit_tree(opts = {})
|
|
765
|
-
|
|
766
|
-
commit_tree(tree, opts)
|
|
823
|
+
Git::Object::Commit.new(self, facade_repository.write_and_commit_tree(**opts))
|
|
767
824
|
end
|
|
768
825
|
|
|
769
826
|
def update_ref(branch, commit)
|
|
770
|
-
|
|
827
|
+
facade_repository.update_ref(branch, commit)
|
|
771
828
|
end
|
|
772
829
|
|
|
773
830
|
def ls_files(location = nil)
|
|
774
|
-
|
|
831
|
+
facade_repository.ls_files(location)
|
|
775
832
|
end
|
|
776
833
|
|
|
777
|
-
def with_working(work_dir) # :yields: the
|
|
834
|
+
def with_working(work_dir) # :yields: the working directory Pathname
|
|
778
835
|
return_value = false
|
|
779
836
|
old_working = @working_directory
|
|
780
837
|
set_working(work_dir)
|
|
@@ -802,29 +859,58 @@ module Git
|
|
|
802
859
|
# git.rev_parse('v2.4:/doc/index.html')
|
|
803
860
|
#
|
|
804
861
|
def rev_parse(objectish)
|
|
805
|
-
|
|
862
|
+
facade_repository.rev_parse(objectish)
|
|
806
863
|
end
|
|
807
864
|
|
|
808
865
|
# For backwards compatibility
|
|
809
866
|
alias revparse rev_parse
|
|
810
867
|
|
|
811
|
-
|
|
812
|
-
|
|
868
|
+
# Returns the number of entries in a git tree object
|
|
869
|
+
#
|
|
870
|
+
# @example Count recursive entries in the HEAD tree
|
|
871
|
+
# git.tree_depth('HEAD^{tree}') #=> 42
|
|
872
|
+
#
|
|
873
|
+
# @param objectish [String] the tree-ish object to recurse into
|
|
874
|
+
#
|
|
875
|
+
# @return [Integer] the number of entries in the recursive tree listing
|
|
876
|
+
#
|
|
877
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
878
|
+
#
|
|
879
|
+
# @see Git::Repository::ObjectOperations#tree_depth
|
|
880
|
+
#
|
|
881
|
+
def tree_depth(objectish)
|
|
882
|
+
facade_repository.tree_depth(objectish)
|
|
813
883
|
end
|
|
814
884
|
|
|
815
|
-
#
|
|
885
|
+
# Lists the objects in a git tree object
|
|
886
|
+
#
|
|
887
|
+
# @example List all top-level objects
|
|
888
|
+
# git.ls_tree('HEAD')
|
|
889
|
+
# # => { 'blob' => { 'README.md' => { mode: '100644', sha: '...' } }, ... }
|
|
890
|
+
#
|
|
891
|
+
# @param objectish [String] the tree-ish object to list
|
|
816
892
|
#
|
|
817
|
-
#
|
|
893
|
+
# @param opts [Hash] additional options
|
|
818
894
|
#
|
|
819
|
-
# @
|
|
820
|
-
# to the git object
|
|
895
|
+
# @option opts [Boolean, nil] :recursive (nil) recurse into subtrees
|
|
821
896
|
#
|
|
822
|
-
# @
|
|
897
|
+
# @option opts [String, Array<String>] :path (nil) limit the listing to
|
|
898
|
+
# the given path or array of paths
|
|
823
899
|
#
|
|
824
|
-
# @
|
|
900
|
+
# @return [Hash<String, Hash<String, Hash>>] a three-level Hash keyed by
|
|
901
|
+
# object type (`'blob'`, `'tree'`, `'commit'`), then by filename, then
|
|
902
|
+
# holding `:mode` and `:sha` values
|
|
825
903
|
#
|
|
904
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
905
|
+
#
|
|
906
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
907
|
+
#
|
|
908
|
+
def ls_tree(objectish, opts = {})
|
|
909
|
+
facade_repository.ls_tree(objectish, opts)
|
|
910
|
+
end
|
|
911
|
+
|
|
826
912
|
def cat_file(objectish)
|
|
827
|
-
lib.
|
|
913
|
+
lib.cat_file(objectish)
|
|
828
914
|
end
|
|
829
915
|
|
|
830
916
|
# The name of the branch HEAD refers to or 'HEAD' if detached
|
|
@@ -836,59 +922,84 @@ module Git
|
|
|
836
922
|
# @return [String] the name of the branch HEAD refers to or 'HEAD' if detached
|
|
837
923
|
#
|
|
838
924
|
def current_branch
|
|
839
|
-
|
|
925
|
+
facade_repository.current_branch
|
|
840
926
|
end
|
|
841
927
|
|
|
842
928
|
# @return [Git::Branch] an object for branch_name
|
|
843
929
|
def branch(branch_name = current_branch)
|
|
844
|
-
|
|
930
|
+
facade_repository.branch(branch_name)
|
|
845
931
|
end
|
|
846
932
|
|
|
847
933
|
# @return [Git::Branches] a collection of all the branches in the repository.
|
|
848
934
|
# Each branch is represented as a {Git::Branch}.
|
|
849
935
|
def branches
|
|
850
|
-
|
|
936
|
+
facade_repository.branches
|
|
851
937
|
end
|
|
852
938
|
|
|
853
|
-
#
|
|
939
|
+
# Returns a {Git::Worktree} object for the given path and optional commitish
|
|
940
|
+
#
|
|
941
|
+
# @example Create a worktree object for an existing path
|
|
942
|
+
# worktree = repo.worktree('/path/to/worktree')
|
|
943
|
+
#
|
|
944
|
+
# @param dir [String] filesystem path of the worktree
|
|
945
|
+
#
|
|
946
|
+
# @param commitish [String, nil] branch, tag, or commit to check out
|
|
947
|
+
#
|
|
948
|
+
# @return [Git::Worktree] worktree object for the given path
|
|
949
|
+
#
|
|
854
950
|
def worktree(dir, commitish = nil)
|
|
855
|
-
|
|
951
|
+
facade_repository.worktree(dir, commitish)
|
|
856
952
|
end
|
|
857
953
|
|
|
858
|
-
#
|
|
859
|
-
#
|
|
954
|
+
# Returns a {Git::Worktrees} collection of all worktrees in the repository
|
|
955
|
+
#
|
|
956
|
+
# @example List paths for all worktrees
|
|
957
|
+
# repo.worktrees.each { |wt| puts wt.dir }
|
|
958
|
+
#
|
|
959
|
+
# @return [Git::Worktrees] all linked and main worktrees
|
|
960
|
+
#
|
|
961
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
962
|
+
#
|
|
860
963
|
def worktrees
|
|
861
|
-
|
|
964
|
+
facade_repository.worktrees
|
|
862
965
|
end
|
|
863
966
|
|
|
864
967
|
# @return [Git::Object::Commit] a commit object
|
|
865
968
|
def commit_tree(tree = nil, opts = {})
|
|
866
|
-
Git::Object::Commit.new(self,
|
|
969
|
+
Git::Object::Commit.new(self, facade_repository.commit_tree(tree, **opts))
|
|
867
970
|
end
|
|
868
971
|
|
|
869
972
|
# @return [Git::Diff] a Git::Diff object
|
|
870
973
|
def diff(objectish = 'HEAD', obj2 = nil)
|
|
871
|
-
|
|
974
|
+
facade_repository.diff(objectish, obj2)
|
|
872
975
|
end
|
|
873
976
|
|
|
874
977
|
# @return [Git::Object] a Git object
|
|
875
978
|
def gblob(objectish)
|
|
876
|
-
|
|
979
|
+
facade_repository.gblob(objectish)
|
|
877
980
|
end
|
|
878
981
|
|
|
879
982
|
# @return [Git::Object] a Git object
|
|
880
983
|
def gcommit(objectish)
|
|
881
|
-
|
|
984
|
+
facade_repository.gcommit(objectish)
|
|
882
985
|
end
|
|
883
986
|
|
|
884
987
|
# @return [Git::Object] a Git object
|
|
885
988
|
def gtree(objectish)
|
|
886
|
-
|
|
989
|
+
facade_repository.gtree(objectish)
|
|
887
990
|
end
|
|
888
991
|
|
|
889
992
|
# @return [Git::Log] a log with the specified number of commits
|
|
890
993
|
def log(count = 30)
|
|
891
|
-
|
|
994
|
+
facade_repository.log(count)
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
# Return commits that are within the given revision range
|
|
998
|
+
#
|
|
999
|
+
# @param opts [Hash] options for the log query
|
|
1000
|
+
# @return [Array<Hash>] the parsed raw log output for each commit
|
|
1001
|
+
def full_log_commits(opts = {})
|
|
1002
|
+
facade_repository.full_log_commits(opts)
|
|
892
1003
|
end
|
|
893
1004
|
|
|
894
1005
|
# returns a Git::Object of the appropriate type
|
|
@@ -902,22 +1013,22 @@ module Git
|
|
|
902
1013
|
#
|
|
903
1014
|
# @return [Git::Object] an instance of the appropriate type of Git::Object
|
|
904
1015
|
def object(objectish)
|
|
905
|
-
|
|
1016
|
+
facade_repository.object(objectish)
|
|
906
1017
|
end
|
|
907
1018
|
|
|
908
1019
|
# @return [Git::Remote] a remote of the specified name
|
|
909
1020
|
def remote(remote_name = 'origin')
|
|
910
|
-
|
|
1021
|
+
facade_repository.remote(remote_name)
|
|
911
1022
|
end
|
|
912
1023
|
|
|
913
1024
|
# @return [Git::Status] a status object
|
|
914
1025
|
def status
|
|
915
|
-
|
|
1026
|
+
facade_repository.status
|
|
916
1027
|
end
|
|
917
1028
|
|
|
918
1029
|
# @return [Git::Object::Tag] a tag object
|
|
919
1030
|
def tag(tag_name)
|
|
920
|
-
|
|
1031
|
+
facade_repository.tag(tag_name)
|
|
921
1032
|
end
|
|
922
1033
|
|
|
923
1034
|
# Find as good common ancestors as possible for a merge
|
|
@@ -925,204 +1036,169 @@ module Git
|
|
|
925
1036
|
#
|
|
926
1037
|
# @return [Array<Git::Object::Commit>] a collection of common ancestors
|
|
927
1038
|
def merge_base(*)
|
|
928
|
-
|
|
929
|
-
shas.map { |sha| gcommit(sha) }
|
|
1039
|
+
facade_repository.merge_base(*).map { |sha| gcommit(sha) }
|
|
930
1040
|
end
|
|
931
1041
|
|
|
932
|
-
# Returns
|
|
1042
|
+
# Returns the full unified diff patch text between two commits
|
|
933
1043
|
#
|
|
934
|
-
# @
|
|
935
|
-
#
|
|
936
|
-
# @param opts [Hash] Options to filter the diff.
|
|
937
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path_limiter Limit stats to specified path(s).
|
|
938
|
-
# @return [Git::DiffStats]
|
|
939
|
-
def diff_stats(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
940
|
-
Git::DiffStats.new(self, objectish, obj2, opts[:path_limiter])
|
|
941
|
-
end
|
|
942
|
-
|
|
943
|
-
# Returns a Git::Diff::PathStatus object for accessing the name-status report.
|
|
1044
|
+
# @example Get the patch for the most recent commit
|
|
1045
|
+
# repo.diff_full #=> "diff --git a/lib/foo.rb b/lib/foo.rb\n..."
|
|
944
1046
|
#
|
|
945
|
-
# @param
|
|
946
|
-
#
|
|
947
|
-
# @param opts [Hash] Options to filter the diff.
|
|
948
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path_limiter Limit status to specified path(s).
|
|
949
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path (deprecated) Legacy alias for :path_limiter.
|
|
950
|
-
# @return [Git::DiffPathStatus]
|
|
951
|
-
def diff_path_status(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
952
|
-
path_limiter = if opts.key?(:path_limiter)
|
|
953
|
-
opts[:path_limiter]
|
|
954
|
-
elsif opts.key?(:path)
|
|
955
|
-
Git::Deprecation.warn(
|
|
956
|
-
'Git::Base#diff_path_status :path option is deprecated. Use :path_limiter instead.'
|
|
957
|
-
)
|
|
958
|
-
opts[:path]
|
|
959
|
-
end
|
|
960
|
-
|
|
961
|
-
Git::DiffPathStatus.new(self, objectish, obj2, path_limiter)
|
|
962
|
-
end
|
|
963
|
-
|
|
964
|
-
# Provided for backwards compatibility
|
|
965
|
-
alias diff_name_status diff_path_status
|
|
966
|
-
|
|
967
|
-
private
|
|
968
|
-
|
|
969
|
-
# Sets default paths in the options hash for direct `Git::Base.new` calls
|
|
1047
|
+
# @param obj1 [String] the first commit or object to compare; defaults to
|
|
1048
|
+
# `'HEAD'`
|
|
970
1049
|
#
|
|
971
|
-
#
|
|
972
|
-
# `normalize_paths`, making this a fallback. It avoids mutating the
|
|
973
|
-
# original options hash by returning a new one.
|
|
1050
|
+
# @param obj2 [String, nil] the second commit or object to compare
|
|
974
1051
|
#
|
|
975
|
-
#
|
|
976
|
-
# @return [Hash] a new options hash with defaults applied
|
|
977
|
-
def default_paths(options)
|
|
978
|
-
return options unless (working_dir = options[:working_directory])
|
|
979
|
-
|
|
980
|
-
options.dup.tap do |opts|
|
|
981
|
-
opts[:repository] ||= File.join(working_dir, '.git')
|
|
982
|
-
opts[:index] ||= File.join(opts[:repository], 'index')
|
|
983
|
-
end
|
|
984
|
-
end
|
|
985
|
-
|
|
986
|
-
# Initializes the logger from the provided options
|
|
987
|
-
# @param log_option [Logger, nil] The logger instance from options.
|
|
988
|
-
def setup_logger(log_option)
|
|
989
|
-
@logger = log_option || Logger.new(nil)
|
|
990
|
-
@logger.info('Starting Git')
|
|
991
|
-
end
|
|
992
|
-
|
|
993
|
-
# Initializes the core git objects based on the provided options
|
|
994
|
-
# @param options [Hash] The processed options hash.
|
|
995
|
-
def initialize_components(options)
|
|
996
|
-
@working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
|
|
997
|
-
@repository = Git::Repository.new(options[:repository]) if options[:repository]
|
|
998
|
-
@index = Git::Index.new(options[:index], must_exist: false) if options[:index]
|
|
999
|
-
end
|
|
1000
|
-
|
|
1001
|
-
# Normalize options before they are sent to Git::Base.new
|
|
1052
|
+
# When `nil`, the comparison is against the index or working tree.
|
|
1002
1053
|
#
|
|
1003
|
-
#
|
|
1004
|
-
# * options[:working_directory]
|
|
1005
|
-
# * options[:repository]
|
|
1006
|
-
# * options[:index]
|
|
1054
|
+
# @param opts [Hash] options to filter the diff
|
|
1007
1055
|
#
|
|
1008
|
-
#
|
|
1009
|
-
#
|
|
1056
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path_limiter (nil)
|
|
1057
|
+
# limit the diff to the given path(s)
|
|
1010
1058
|
#
|
|
1011
|
-
|
|
1012
|
-
options, default_working_directory: nil, default_repository: nil, bare: false
|
|
1013
|
-
)
|
|
1014
|
-
normalize_working_directory(options, default: default_working_directory, bare: bare)
|
|
1015
|
-
normalize_repository(options, default: default_repository, bare: bare)
|
|
1016
|
-
normalize_index(options)
|
|
1017
|
-
end
|
|
1018
|
-
|
|
1019
|
-
# Normalize options[:working_directory]
|
|
1059
|
+
# @return [String] the unified diff patch output
|
|
1020
1060
|
#
|
|
1021
|
-
#
|
|
1022
|
-
#
|
|
1023
|
-
# 1. `options[:working_directory]`,
|
|
1024
|
-
# 2. the `default` parameter, or
|
|
1025
|
-
# 3. the current working directory
|
|
1061
|
+
# @note Unknown option keys are silently ignored for backward compatibility;
|
|
1062
|
+
# only `:path_limiter` is forwarded to the underlying command.
|
|
1026
1063
|
#
|
|
1027
|
-
#
|
|
1028
|
-
# path relative to the current directory.
|
|
1064
|
+
# @raise [Git::FailedError] if git exits outside the allowed range (exit code > 1)
|
|
1029
1065
|
#
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
else
|
|
1035
|
-
File.expand_path(options[:working_directory] || default || Dir.pwd)
|
|
1036
|
-
end
|
|
1037
|
-
|
|
1038
|
-
options[:working_directory] = working_directory
|
|
1066
|
+
# @see Git::Repository::Diffing#diff_full
|
|
1067
|
+
#
|
|
1068
|
+
def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
|
|
1069
|
+
facade_repository.diff_full(obj1, obj2, opts.slice(:path_limiter))
|
|
1039
1070
|
end
|
|
1040
1071
|
|
|
1041
|
-
#
|
|
1072
|
+
# Returns a lazy {Git::DiffStats} object for accessing diff statistics
|
|
1042
1073
|
#
|
|
1043
|
-
#
|
|
1044
|
-
#
|
|
1045
|
-
#
|
|
1046
|
-
#
|
|
1074
|
+
# Compares (1) two commits, (2) a commit against the working tree, or (3) the
|
|
1075
|
+
# index against the working tree and constructs a lazy {Git::DiffStats} that
|
|
1076
|
+
# computes per-file insertion and deletion counts on demand when its accessor
|
|
1077
|
+
# methods are called.
|
|
1047
1078
|
#
|
|
1048
|
-
#
|
|
1049
|
-
# 1. `options[:repository]`
|
|
1050
|
-
# 2. `.git`
|
|
1079
|
+
# **Comparing two commits**
|
|
1051
1080
|
#
|
|
1052
|
-
#
|
|
1053
|
-
#
|
|
1054
|
-
# working with a submodule or a secondary working tree (created with git worktree
|
|
1055
|
-
# add). In these cases the repository is actually contained/nested within the
|
|
1056
|
-
# parent's repository directory.
|
|
1081
|
+
# When both objectish and obj2 are provided, the comparison is between those two
|
|
1082
|
+
# refs (commits, tags, branches, etc.).
|
|
1057
1083
|
#
|
|
1058
|
-
#
|
|
1059
|
-
# path relative to:
|
|
1060
|
-
# 1. the current directory if working with a bare repository or
|
|
1061
|
-
# 2. the working directory if NOT working with a bare repository
|
|
1084
|
+
# **Comparing a commit against the working tree**
|
|
1062
1085
|
#
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
final_path = resolve_gitdir_if_present(initial_path, options[:working_directory])
|
|
1066
|
-
options[:repository] = final_path
|
|
1067
|
-
end
|
|
1068
|
-
|
|
1069
|
-
# Determines the initial, potential path to the repository directory
|
|
1086
|
+
# When only objectish is provided (and isn't nil), the comparison is between
|
|
1087
|
+
# objectish and the working tree; the stats reflect all changes since objectish.
|
|
1070
1088
|
#
|
|
1071
|
-
#
|
|
1072
|
-
# final repository location. For features like submodules or worktrees,
|
|
1073
|
-
# this path may point to a text file containing a `gitdir:` pointer to the
|
|
1074
|
-
# actual repository directory elsewhere. This initial path must be
|
|
1075
|
-
# subsequently resolved.
|
|
1089
|
+
# **Comparing the index against the working tree**
|
|
1076
1090
|
#
|
|
1077
|
-
#
|
|
1091
|
+
# When objectish is explicitly `nil` then obj2 must be omitted or `nil`. In this
|
|
1092
|
+
# case, the comparison is between the index and the working tree; the stats reflect
|
|
1093
|
+
# unstaged changes.
|
|
1078
1094
|
#
|
|
1079
|
-
# @
|
|
1095
|
+
# @example Get working tree stats since HEAD
|
|
1096
|
+
# repo.diff_stats.insertions #=> 3
|
|
1080
1097
|
#
|
|
1081
|
-
# @
|
|
1098
|
+
# @example Compare two specific commits
|
|
1099
|
+
# repo.diff_stats('abc1234', 'def5678')
|
|
1082
1100
|
#
|
|
1083
|
-
# @
|
|
1101
|
+
# @example Get unstaged stats (index vs. working tree)
|
|
1102
|
+
# repo.diff_stats(nil).insertions
|
|
1084
1103
|
#
|
|
1085
|
-
# @
|
|
1104
|
+
# @example Limit stats to a sub-path
|
|
1105
|
+
# repo.diff_stats('HEAD~1', 'HEAD', path_limiter: 'lib/')
|
|
1086
1106
|
#
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1107
|
+
# @param objectish [String, nil] the first commit or object to compare; defaults to
|
|
1108
|
+
# `'HEAD'`; pass `nil` to compare the index against the working tree
|
|
1109
|
+
#
|
|
1110
|
+
# @param obj2 [String, nil] the second commit or object to compare
|
|
1111
|
+
#
|
|
1112
|
+
# @param opts [Hash] options to filter the diff
|
|
1113
|
+
#
|
|
1114
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path_limiter (nil)
|
|
1115
|
+
# limit the stats to the given path(s)
|
|
1116
|
+
#
|
|
1117
|
+
# @return [Git::DiffStats] a lazy stats object for the comparison
|
|
1118
|
+
#
|
|
1119
|
+
# @note Unknown option keys are silently ignored for backward compatibility;
|
|
1120
|
+
# only `:path_limiter` is forwarded to the underlying command.
|
|
1121
|
+
#
|
|
1122
|
+
# @raise [ArgumentError] if `objectish` or `obj2` starts with `"-"`
|
|
1123
|
+
#
|
|
1124
|
+
# @raise [ArgumentError] if `objectish` is `nil` but `obj2` is not
|
|
1125
|
+
#
|
|
1126
|
+
# @see Git::Repository::Diffing#diff_stats
|
|
1127
|
+
#
|
|
1128
|
+
def diff_stats(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
1129
|
+
facade_repository.diff_stats(objectish, obj2, opts.slice(:path_limiter))
|
|
1093
1130
|
end
|
|
1094
1131
|
|
|
1095
|
-
#
|
|
1132
|
+
# Returns the file path status between two commits
|
|
1096
1133
|
#
|
|
1097
|
-
#
|
|
1098
|
-
#
|
|
1099
|
-
# path. Otherwise, it returns the original path.
|
|
1134
|
+
# @example Get all changed files between HEAD and the previous commit
|
|
1135
|
+
# repo.diff_path_status.to_h #=> { "README.md" => "M", "lib/foo.rb" => "A" }
|
|
1100
1136
|
#
|
|
1101
|
-
# @
|
|
1137
|
+
# @param objectish [String] the first commit or object to compare; defaults to
|
|
1138
|
+
# `'HEAD'`
|
|
1102
1139
|
#
|
|
1103
|
-
# @param
|
|
1140
|
+
# @param obj2 [String, nil] the second commit or object to compare
|
|
1104
1141
|
#
|
|
1105
|
-
# @param
|
|
1142
|
+
# @param opts [Hash] options to filter the diff
|
|
1106
1143
|
#
|
|
1107
|
-
# @
|
|
1144
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path_limiter (nil)
|
|
1145
|
+
# limit the status report to specified path(s)
|
|
1108
1146
|
#
|
|
1109
|
-
|
|
1110
|
-
|
|
1147
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path (nil)
|
|
1148
|
+
# deprecated; use `:path_limiter` instead
|
|
1149
|
+
#
|
|
1150
|
+
# @return [Git::DiffPathStatus] the name-status report for the comparison
|
|
1151
|
+
#
|
|
1152
|
+
# @raise [ArgumentError] if `objectish` or `obj2` starts with `"-"`
|
|
1153
|
+
#
|
|
1154
|
+
# @raise [Git::FailedError] if git exits outside the allowed range (exit code > 1)
|
|
1155
|
+
#
|
|
1156
|
+
# @see Git::Repository::Diffing#diff_path_status
|
|
1157
|
+
#
|
|
1158
|
+
def diff_path_status(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
1159
|
+
facade_repository.diff_path_status(objectish, obj2, opts.slice(:path_limiter, :path))
|
|
1160
|
+
end
|
|
1111
1161
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1162
|
+
# Compares the index and the working directory
|
|
1163
|
+
#
|
|
1164
|
+
# @example List all files with unstaged changes
|
|
1165
|
+
# repo.diff_files #=> { "lib/foo.rb" => { mode_index: "100644", ... } }
|
|
1166
|
+
#
|
|
1167
|
+
# @return [Hash{String => Hash}] a hash keyed by file path; see
|
|
1168
|
+
# {Git::Repository::Diffing#diff_files} for the full key list
|
|
1169
|
+
#
|
|
1170
|
+
# @raise [Git::FailedError] if git exits outside the allowed range (exit code > 1)
|
|
1171
|
+
#
|
|
1172
|
+
# @see Git::Repository::Diffing#diff_files
|
|
1173
|
+
#
|
|
1174
|
+
def diff_files
|
|
1175
|
+
facade_repository.diff_files
|
|
1116
1176
|
end
|
|
1117
1177
|
|
|
1118
|
-
#
|
|
1178
|
+
# Alias for {#diff_path_status}; provided for backward compatibility
|
|
1179
|
+
#
|
|
1180
|
+
# @return [Git::DiffPathStatus] the name-status report for the comparison
|
|
1119
1181
|
#
|
|
1120
|
-
#
|
|
1121
|
-
# directory relative to the repository directory
|
|
1182
|
+
# @deprecated Use {#diff_path_status} instead
|
|
1122
1183
|
#
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1184
|
+
# @see #diff_path_status
|
|
1185
|
+
alias diff_name_status diff_path_status
|
|
1186
|
+
|
|
1187
|
+
private
|
|
1188
|
+
|
|
1189
|
+
# Initializes the logger from the provided options
|
|
1190
|
+
# @param log_option [Logger, nil] The logger instance from options.
|
|
1191
|
+
def setup_logger(log_option)
|
|
1192
|
+
@logger = log_option || Logger.new(nil)
|
|
1193
|
+
@logger.info('Starting Git')
|
|
1194
|
+
end
|
|
1195
|
+
|
|
1196
|
+
# Initializes the core git objects based on the provided options
|
|
1197
|
+
# @param options [Hash] The processed options hash.
|
|
1198
|
+
def initialize_components(options)
|
|
1199
|
+
@working_directory = Pathname.new(options[:working_directory]) if options[:working_directory]
|
|
1200
|
+
@repository = Pathname.new(options[:repository]) if options[:repository]
|
|
1201
|
+
@index = Pathname.new(options[:index]) if options[:index]
|
|
1126
1202
|
end
|
|
1127
1203
|
end
|
|
1128
1204
|
end
|