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