git 4.4.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 -67
- data/.github/workflows/enforce_conventional_commits.yml +1 -1
- data/.github/workflows/experimental_continuous_integration.yml +2 -2
- data/.github/workflows/release.yml +3 -4
- data/.gitignore +8 -0
- data/.husky/pre-commit +13 -0
- data/.release-please-manifest.json +1 -1
- data/.rspec +3 -0
- data/.rubocop.yml +7 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -73
- data/CONTRIBUTING.md +694 -53
- data/README.md +17 -17
- data/Rakefile +61 -9
- data/commitlint.test +4 -0
- data/git.gemspec +14 -8
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/base.rb +485 -420
- 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/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,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,40 +268,44 @@ 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
311
|
def is_local_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -316,8 +318,7 @@ module Git
|
|
|
316
318
|
|
|
317
319
|
# returns +true+ if the branch exists remotely
|
|
318
320
|
def remote_branch?(branch)
|
|
319
|
-
|
|
320
|
-
branch_names.include?(branch)
|
|
321
|
+
facade_repository.remote_branch?(branch)
|
|
321
322
|
end
|
|
322
323
|
|
|
323
324
|
def is_remote_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -330,8 +331,7 @@ module Git
|
|
|
330
331
|
|
|
331
332
|
# returns +true+ if the branch exists
|
|
332
333
|
def branch?(branch)
|
|
333
|
-
|
|
334
|
-
branch_names.include?(branch)
|
|
334
|
+
facade_repository.branch?(branch)
|
|
335
335
|
end
|
|
336
336
|
|
|
337
337
|
def is_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
@@ -346,10 +346,20 @@ module Git
|
|
|
346
346
|
# actual 'git' forked system calls. At some point I hope to replace the Git::Lib
|
|
347
347
|
# class with one that uses native methods or libgit C bindings
|
|
348
348
|
def lib
|
|
349
|
-
@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
|
+
)
|
|
350
360
|
end
|
|
351
361
|
|
|
352
|
-
# Returns the per-instance git_ssh configuration value
|
|
362
|
+
# Returns the per-instance git_ssh configuration value
|
|
353
363
|
#
|
|
354
364
|
# This may be:
|
|
355
365
|
# * a [String] path when an explicit git_ssh command has been configured
|
|
@@ -360,6 +370,16 @@ module Git
|
|
|
360
370
|
# @api private
|
|
361
371
|
attr_reader :git_ssh
|
|
362
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
|
+
|
|
363
383
|
# Run a grep for 'string' on the HEAD of the git repository
|
|
364
384
|
#
|
|
365
385
|
# @example Limit grep's scope by calling grep() from a specific object:
|
|
@@ -378,9 +398,9 @@ module Git
|
|
|
378
398
|
# of paths to limit the search to or nil for no limit
|
|
379
399
|
# @param opts [Hash] options to pass to the underlying `git grep` command
|
|
380
400
|
#
|
|
381
|
-
# @option opts [Boolean] :ignore_case (
|
|
382
|
-
# @option opts [Boolean] :invert_match (
|
|
383
|
-
# @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
|
|
384
404
|
# @option opts [String] :object (HEAD) the object to search from
|
|
385
405
|
#
|
|
386
406
|
# @return [Hash<String, Array>] a hash of arrays
|
|
@@ -393,30 +413,38 @@ module Git
|
|
|
393
413
|
# ```
|
|
394
414
|
#
|
|
395
415
|
def grep(string, path_limiter = nil, opts = {})
|
|
396
|
-
object('HEAD')
|
|
416
|
+
opts = opts.merge(object: facade_repository.rev_parse('HEAD')) unless opts.key?(:object)
|
|
417
|
+
facade_repository.grep(string, path_limiter, opts)
|
|
397
418
|
end
|
|
398
419
|
|
|
399
420
|
# List the files in the worktree that are ignored by git
|
|
400
|
-
# @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
|
|
401
422
|
#
|
|
402
423
|
def ignored_files
|
|
403
|
-
|
|
424
|
+
facade_repository.ignored_files
|
|
404
425
|
end
|
|
405
426
|
|
|
406
427
|
# removes file(s) from the git repository
|
|
407
428
|
def rm(path = '.', opts = {})
|
|
408
|
-
|
|
429
|
+
facade_repository.rm(path, opts)
|
|
409
430
|
end
|
|
410
431
|
|
|
411
432
|
alias remove rm
|
|
412
433
|
|
|
413
434
|
# resets the working directory to the provided commitish
|
|
414
435
|
def reset(commitish = nil, opts = {})
|
|
415
|
-
|
|
436
|
+
facade_repository.reset(commitish, **opts)
|
|
416
437
|
end
|
|
417
438
|
|
|
418
439
|
# resets the working directory to the commitish with '--hard'
|
|
440
|
+
#
|
|
441
|
+
# @deprecated Use {#reset} with `hard: true` instead.
|
|
442
|
+
#
|
|
419
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
|
+
)
|
|
420
448
|
opts = { hard: true }.merge(opts)
|
|
421
449
|
lib.reset(commitish, opts)
|
|
422
450
|
end
|
|
@@ -429,7 +457,7 @@ module Git
|
|
|
429
457
|
# :ff
|
|
430
458
|
#
|
|
431
459
|
def clean(opts = {})
|
|
432
|
-
|
|
460
|
+
facade_repository.clean(opts)
|
|
433
461
|
end
|
|
434
462
|
|
|
435
463
|
# returns the most recent tag that is reachable from a commit
|
|
@@ -458,7 +486,7 @@ module Git
|
|
|
458
486
|
# :no_edit
|
|
459
487
|
#
|
|
460
488
|
def revert(commitish = nil, opts = {})
|
|
461
|
-
|
|
489
|
+
facade_repository.revert(commitish, **opts)
|
|
462
490
|
end
|
|
463
491
|
|
|
464
492
|
# commits all pending changes in the index file to the git repository
|
|
@@ -470,69 +498,71 @@ module Git
|
|
|
470
498
|
# :author
|
|
471
499
|
#
|
|
472
500
|
def commit(message, opts = {})
|
|
473
|
-
|
|
501
|
+
facade_repository.commit(message, **opts)
|
|
474
502
|
end
|
|
475
503
|
|
|
476
504
|
# commits all pending changes in the index file to the git repository,
|
|
477
505
|
# but automatically adds all modified files without having to explicitly
|
|
478
506
|
# calling @git.add() on them.
|
|
479
507
|
def commit_all(message, opts = {})
|
|
480
|
-
|
|
481
|
-
lib.commit(message, opts)
|
|
508
|
+
facade_repository.commit_all(message, **opts)
|
|
482
509
|
end
|
|
483
510
|
|
|
484
511
|
# checks out a branch as the new git working directory
|
|
485
512
|
def checkout(*, **)
|
|
486
|
-
|
|
513
|
+
facade_repository.checkout(*, **)
|
|
487
514
|
end
|
|
488
515
|
|
|
489
516
|
# checks out an old version of a file
|
|
490
517
|
def checkout_file(version, file)
|
|
491
|
-
|
|
518
|
+
facade_repository.checkout_file(version, file)
|
|
492
519
|
end
|
|
493
520
|
|
|
494
521
|
# fetches changes from a remote branch - this does not modify the working directory,
|
|
495
522
|
# it just gets the changes from the remote if there are any
|
|
496
523
|
def fetch(remote = 'origin', opts = {})
|
|
497
|
-
|
|
498
|
-
opts = remote
|
|
499
|
-
remote = nil
|
|
500
|
-
end
|
|
501
|
-
lib.fetch(remote, opts)
|
|
524
|
+
facade_repository.fetch(remote, opts)
|
|
502
525
|
end
|
|
503
526
|
|
|
504
527
|
# Push changes to a remote repository
|
|
505
528
|
#
|
|
506
529
|
# @overload push(remote = nil, branch = nil, options = {})
|
|
530
|
+
#
|
|
507
531
|
# @param remote [String] the remote repository to push to
|
|
532
|
+
#
|
|
508
533
|
# @param branch [String] the branch to push
|
|
534
|
+
#
|
|
509
535
|
# @param options [Hash] options to pass to the push command
|
|
510
536
|
#
|
|
511
|
-
# @option
|
|
512
|
-
#
|
|
513
|
-
# @option
|
|
514
|
-
#
|
|
515
|
-
# @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/
|
|
516
544
|
#
|
|
517
|
-
# @
|
|
545
|
+
# @option options [String, Array<String>] :push_option (nil) push options to transmit
|
|
546
|
+
#
|
|
547
|
+
# @return [String] the stdout output from the push command
|
|
518
548
|
#
|
|
519
549
|
# @raise [Git::FailedError] if the push fails
|
|
520
550
|
# @raise [ArgumentError] if a branch is given without a remote
|
|
521
551
|
#
|
|
522
552
|
def push(*, **)
|
|
523
|
-
|
|
553
|
+
facade_repository.push(*, **)
|
|
524
554
|
end
|
|
525
555
|
|
|
526
556
|
# merges one or more branches into the current working branch
|
|
527
557
|
#
|
|
528
558
|
# you can specify more than one branch to merge by passing an array of branches
|
|
529
559
|
def merge(branch, message = 'merge', opts = {})
|
|
530
|
-
|
|
560
|
+
facade_repository.merge(branch, message, opts)
|
|
531
561
|
end
|
|
532
562
|
|
|
533
563
|
# iterates over the files which are unmerged
|
|
534
|
-
def each_conflict(&)
|
|
535
|
-
|
|
564
|
+
def each_conflict(&)
|
|
565
|
+
facade_repository.each_conflict(&)
|
|
536
566
|
end
|
|
537
567
|
|
|
538
568
|
# Pulls the given branch from the given remote into the current branch
|
|
@@ -541,7 +571,7 @@ module Git
|
|
|
541
571
|
# @param branch [String] the branch to pull from
|
|
542
572
|
# @param opts [Hash] options to pass to the pull command
|
|
543
573
|
#
|
|
544
|
-
# @option opts [Boolean] :allow_unrelated_histories (
|
|
574
|
+
# @option opts [Boolean, nil] :allow_unrelated_histories (nil) merges histories of
|
|
545
575
|
# two projects that started their lives independently
|
|
546
576
|
# @example pulls from origin/master
|
|
547
577
|
# @git.pull
|
|
@@ -550,17 +580,17 @@ module Git
|
|
|
550
580
|
# @example pulls from upstream/develop
|
|
551
581
|
# @git.pull('upstream', 'develop')
|
|
552
582
|
#
|
|
553
|
-
# @return [
|
|
583
|
+
# @return [String] the stdout output from the pull command
|
|
554
584
|
#
|
|
555
585
|
# @raise [Git::FailedError] if the pull fails
|
|
556
586
|
# @raise [ArgumentError] if a branch is given without a remote
|
|
557
587
|
def pull(remote = nil, branch = nil, opts = {})
|
|
558
|
-
|
|
588
|
+
facade_repository.pull(remote, branch, opts)
|
|
559
589
|
end
|
|
560
590
|
|
|
561
591
|
# returns an array of Git:Remote objects
|
|
562
592
|
def remotes
|
|
563
|
-
|
|
593
|
+
facade_repository.remotes
|
|
564
594
|
end
|
|
565
595
|
|
|
566
596
|
# sets the url for a remote
|
|
@@ -569,9 +599,7 @@ module Git
|
|
|
569
599
|
# @git.set_remote_url('scotts_git', 'git://repo.or.cz/rubygit.git')
|
|
570
600
|
#
|
|
571
601
|
def set_remote_url(name, url)
|
|
572
|
-
|
|
573
|
-
lib.remote_set_url(name, url)
|
|
574
|
-
Git::Remote.new(self, name)
|
|
602
|
+
facade_repository.set_remote_url(name, url)
|
|
575
603
|
end
|
|
576
604
|
|
|
577
605
|
# Configures which branches are fetched for a remote
|
|
@@ -603,24 +631,19 @@ module Git
|
|
|
603
631
|
# the underlying git command fails
|
|
604
632
|
#
|
|
605
633
|
def remote_set_branches(name, *branches, add: false)
|
|
606
|
-
|
|
607
|
-
raise ArgumentError, 'branches are required' if branch_list.empty?
|
|
608
|
-
|
|
609
|
-
lib.remote_set_branches(name, branch_list, add: add)
|
|
610
|
-
|
|
611
|
-
nil
|
|
634
|
+
facade_repository.remote_set_branches(name, *branches, add: add)
|
|
612
635
|
end
|
|
613
636
|
|
|
614
637
|
# removes a remote from this repository
|
|
615
638
|
#
|
|
616
639
|
# @git.remove_remote('scott_git')
|
|
617
640
|
def remove_remote(name)
|
|
618
|
-
|
|
641
|
+
facade_repository.remove_remote(name)
|
|
619
642
|
end
|
|
620
643
|
|
|
621
|
-
# returns an array of all Git::Tag objects for this repository
|
|
644
|
+
# returns an array of all Git::Object::Tag objects for this repository
|
|
622
645
|
def tags
|
|
623
|
-
|
|
646
|
+
facade_repository.tags
|
|
624
647
|
end
|
|
625
648
|
|
|
626
649
|
# Create a new git tag
|
|
@@ -631,29 +654,53 @@ module Git
|
|
|
631
654
|
# repo.add_tag('tag_name', {:options => 'here'})
|
|
632
655
|
#
|
|
633
656
|
# @param [String] name The name of the tag to add
|
|
634
|
-
# @param [Hash] options
|
|
657
|
+
# @param [Hash] options Options to pass to `git tag`.
|
|
635
658
|
# See [git-tag](https://git-scm.com/docs/git-tag) for more details.
|
|
636
|
-
# @option options [
|
|
637
|
-
# @option options [
|
|
638
|
-
# @option options [
|
|
639
|
-
#
|
|
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)
|
|
640
666
|
# @option options [String] :message Use the given tag message
|
|
641
667
|
# @option options [String] :m An alias for the `:message` option
|
|
642
|
-
# @option options [
|
|
668
|
+
# @option options [Boolean, nil] :s (nil) make a GPG-signed tag
|
|
643
669
|
#
|
|
644
670
|
def add_tag(name, *options)
|
|
645
|
-
|
|
646
|
-
tag(name)
|
|
671
|
+
facade_repository.add_tag(name, *options)
|
|
647
672
|
end
|
|
648
673
|
|
|
649
674
|
# deletes a tag
|
|
650
675
|
def delete_tag(name)
|
|
651
|
-
|
|
676
|
+
facade_repository.delete_tag(name)
|
|
652
677
|
end
|
|
653
678
|
|
|
654
|
-
#
|
|
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
|
+
#
|
|
655
702
|
def archive(treeish, file = nil, opts = {})
|
|
656
|
-
|
|
703
|
+
facade_repository.archive(treeish, file, opts)
|
|
657
704
|
end
|
|
658
705
|
|
|
659
706
|
# repacks the repository
|
|
@@ -676,14 +723,14 @@ module Git
|
|
|
676
723
|
# references in the refs namespace, and all reflogs.
|
|
677
724
|
# @param [Hash] options options to pass to the underlying `git fsck` command
|
|
678
725
|
#
|
|
679
|
-
# @option options [Boolean] :unreachable print unreachable objects
|
|
680
|
-
# @option options [Boolean] :strict enable strict checking
|
|
681
|
-
# @option options [Boolean] :connectivity_only check only connectivity (faster)
|
|
682
|
-
# @option options [Boolean] :root report root nodes
|
|
683
|
-
# @option options [Boolean] :tags report tags
|
|
684
|
-
# @option options [Boolean] :cache consider objects in the index
|
|
685
|
-
# @option options [Boolean] :no_reflogs do not consider reflogs
|
|
686
|
-
# @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
|
|
687
734
|
# (note: this modifies the repository by creating files)
|
|
688
735
|
# @option options [Boolean, nil] :dangling print dangling objects (true/false/nil for default)
|
|
689
736
|
# @option options [Boolean, nil] :full check objects in alternate pools (true/false/nil for default)
|
|
@@ -694,10 +741,10 @@ module Git
|
|
|
694
741
|
#
|
|
695
742
|
# @example Check repository integrity
|
|
696
743
|
# result = git.fsck
|
|
697
|
-
# result.dangling.each { |obj| puts "#{obj.type}: #{obj.
|
|
744
|
+
# result.dangling.each { |obj| puts "#{obj.type}: #{obj.oid}" }
|
|
698
745
|
#
|
|
699
746
|
# @example Check with strict mode and suppress dangling output
|
|
700
|
-
# result = git.fsck(strict: true,
|
|
747
|
+
# result = git.fsck(strict: true, no_dangling: true)
|
|
701
748
|
#
|
|
702
749
|
# @example Check if repository has any issues
|
|
703
750
|
# result = git.fsck
|
|
@@ -705,14 +752,14 @@ module Git
|
|
|
705
752
|
#
|
|
706
753
|
# @example List root commits
|
|
707
754
|
# result = git.fsck(root: true)
|
|
708
|
-
# result.root.each { |obj| puts obj.
|
|
755
|
+
# result.root.each { |obj| puts obj.oid }
|
|
709
756
|
#
|
|
710
757
|
# @example Check specific objects
|
|
711
758
|
# result = git.fsck('abc1234', 'def5678')
|
|
712
759
|
#
|
|
713
760
|
# rubocop:disable Style/ArgumentsForwarding
|
|
714
761
|
def fsck(*objects, **opts)
|
|
715
|
-
|
|
762
|
+
facade_repository.fsck(*objects, **opts)
|
|
716
763
|
end
|
|
717
764
|
# rubocop:enable Style/ArgumentsForwarding
|
|
718
765
|
|
|
@@ -732,7 +779,7 @@ module Git
|
|
|
732
779
|
# @param [String|NilClass] path the path of the file to be shown
|
|
733
780
|
# @return [String] the object information
|
|
734
781
|
def show(objectish = nil, path = nil)
|
|
735
|
-
|
|
782
|
+
facade_repository.show(objectish, path)
|
|
736
783
|
end
|
|
737
784
|
|
|
738
785
|
## LOWER LEVEL INDEX OPERATIONS ##
|
|
@@ -761,7 +808,7 @@ module Git
|
|
|
761
808
|
end
|
|
762
809
|
|
|
763
810
|
def checkout_index(opts = {})
|
|
764
|
-
|
|
811
|
+
facade_repository.checkout_index(opts)
|
|
765
812
|
end
|
|
766
813
|
|
|
767
814
|
def read_tree(treeish, opts = {})
|
|
@@ -769,23 +816,22 @@ module Git
|
|
|
769
816
|
end
|
|
770
817
|
|
|
771
818
|
def write_tree
|
|
772
|
-
|
|
819
|
+
facade_repository.write_tree
|
|
773
820
|
end
|
|
774
821
|
|
|
775
822
|
def write_and_commit_tree(opts = {})
|
|
776
|
-
|
|
777
|
-
commit_tree(tree, opts)
|
|
823
|
+
Git::Object::Commit.new(self, facade_repository.write_and_commit_tree(**opts))
|
|
778
824
|
end
|
|
779
825
|
|
|
780
826
|
def update_ref(branch, commit)
|
|
781
|
-
|
|
827
|
+
facade_repository.update_ref(branch, commit)
|
|
782
828
|
end
|
|
783
829
|
|
|
784
830
|
def ls_files(location = nil)
|
|
785
|
-
|
|
831
|
+
facade_repository.ls_files(location)
|
|
786
832
|
end
|
|
787
833
|
|
|
788
|
-
def with_working(work_dir) # :yields: the
|
|
834
|
+
def with_working(work_dir) # :yields: the working directory Pathname
|
|
789
835
|
return_value = false
|
|
790
836
|
old_working = @working_directory
|
|
791
837
|
set_working(work_dir)
|
|
@@ -813,29 +859,58 @@ module Git
|
|
|
813
859
|
# git.rev_parse('v2.4:/doc/index.html')
|
|
814
860
|
#
|
|
815
861
|
def rev_parse(objectish)
|
|
816
|
-
|
|
862
|
+
facade_repository.rev_parse(objectish)
|
|
817
863
|
end
|
|
818
864
|
|
|
819
865
|
# For backwards compatibility
|
|
820
866
|
alias revparse rev_parse
|
|
821
867
|
|
|
822
|
-
|
|
823
|
-
|
|
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)
|
|
824
883
|
end
|
|
825
884
|
|
|
826
|
-
#
|
|
885
|
+
# Lists the objects in a git tree object
|
|
827
886
|
#
|
|
828
|
-
#
|
|
887
|
+
# @example List all top-level objects
|
|
888
|
+
# git.ls_tree('HEAD')
|
|
889
|
+
# # => { 'blob' => { 'README.md' => { mode: '100644', sha: '...' } }, ... }
|
|
829
890
|
#
|
|
830
|
-
# @param objectish [String]
|
|
831
|
-
# to the git object
|
|
891
|
+
# @param objectish [String] the tree-ish object to list
|
|
832
892
|
#
|
|
833
|
-
# @
|
|
893
|
+
# @param opts [Hash] additional options
|
|
834
894
|
#
|
|
835
|
-
# @
|
|
895
|
+
# @option opts [Boolean, nil] :recursive (nil) recurse into subtrees
|
|
836
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
|
+
|
|
837
912
|
def cat_file(objectish)
|
|
838
|
-
lib.
|
|
913
|
+
lib.cat_file(objectish)
|
|
839
914
|
end
|
|
840
915
|
|
|
841
916
|
# The name of the branch HEAD refers to or 'HEAD' if detached
|
|
@@ -847,59 +922,84 @@ module Git
|
|
|
847
922
|
# @return [String] the name of the branch HEAD refers to or 'HEAD' if detached
|
|
848
923
|
#
|
|
849
924
|
def current_branch
|
|
850
|
-
|
|
925
|
+
facade_repository.current_branch
|
|
851
926
|
end
|
|
852
927
|
|
|
853
928
|
# @return [Git::Branch] an object for branch_name
|
|
854
929
|
def branch(branch_name = current_branch)
|
|
855
|
-
|
|
930
|
+
facade_repository.branch(branch_name)
|
|
856
931
|
end
|
|
857
932
|
|
|
858
933
|
# @return [Git::Branches] a collection of all the branches in the repository.
|
|
859
934
|
# Each branch is represented as a {Git::Branch}.
|
|
860
935
|
def branches
|
|
861
|
-
|
|
936
|
+
facade_repository.branches
|
|
862
937
|
end
|
|
863
938
|
|
|
864
|
-
#
|
|
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
|
+
#
|
|
865
950
|
def worktree(dir, commitish = nil)
|
|
866
|
-
|
|
951
|
+
facade_repository.worktree(dir, commitish)
|
|
867
952
|
end
|
|
868
953
|
|
|
869
|
-
#
|
|
870
|
-
#
|
|
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
|
+
#
|
|
871
963
|
def worktrees
|
|
872
|
-
|
|
964
|
+
facade_repository.worktrees
|
|
873
965
|
end
|
|
874
966
|
|
|
875
967
|
# @return [Git::Object::Commit] a commit object
|
|
876
968
|
def commit_tree(tree = nil, opts = {})
|
|
877
|
-
Git::Object::Commit.new(self,
|
|
969
|
+
Git::Object::Commit.new(self, facade_repository.commit_tree(tree, **opts))
|
|
878
970
|
end
|
|
879
971
|
|
|
880
972
|
# @return [Git::Diff] a Git::Diff object
|
|
881
973
|
def diff(objectish = 'HEAD', obj2 = nil)
|
|
882
|
-
|
|
974
|
+
facade_repository.diff(objectish, obj2)
|
|
883
975
|
end
|
|
884
976
|
|
|
885
977
|
# @return [Git::Object] a Git object
|
|
886
978
|
def gblob(objectish)
|
|
887
|
-
|
|
979
|
+
facade_repository.gblob(objectish)
|
|
888
980
|
end
|
|
889
981
|
|
|
890
982
|
# @return [Git::Object] a Git object
|
|
891
983
|
def gcommit(objectish)
|
|
892
|
-
|
|
984
|
+
facade_repository.gcommit(objectish)
|
|
893
985
|
end
|
|
894
986
|
|
|
895
987
|
# @return [Git::Object] a Git object
|
|
896
988
|
def gtree(objectish)
|
|
897
|
-
|
|
989
|
+
facade_repository.gtree(objectish)
|
|
898
990
|
end
|
|
899
991
|
|
|
900
992
|
# @return [Git::Log] a log with the specified number of commits
|
|
901
993
|
def log(count = 30)
|
|
902
|
-
|
|
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)
|
|
903
1003
|
end
|
|
904
1004
|
|
|
905
1005
|
# returns a Git::Object of the appropriate type
|
|
@@ -913,22 +1013,22 @@ module Git
|
|
|
913
1013
|
#
|
|
914
1014
|
# @return [Git::Object] an instance of the appropriate type of Git::Object
|
|
915
1015
|
def object(objectish)
|
|
916
|
-
|
|
1016
|
+
facade_repository.object(objectish)
|
|
917
1017
|
end
|
|
918
1018
|
|
|
919
1019
|
# @return [Git::Remote] a remote of the specified name
|
|
920
1020
|
def remote(remote_name = 'origin')
|
|
921
|
-
|
|
1021
|
+
facade_repository.remote(remote_name)
|
|
922
1022
|
end
|
|
923
1023
|
|
|
924
1024
|
# @return [Git::Status] a status object
|
|
925
1025
|
def status
|
|
926
|
-
|
|
1026
|
+
facade_repository.status
|
|
927
1027
|
end
|
|
928
1028
|
|
|
929
1029
|
# @return [Git::Object::Tag] a tag object
|
|
930
1030
|
def tag(tag_name)
|
|
931
|
-
|
|
1031
|
+
facade_repository.tag(tag_name)
|
|
932
1032
|
end
|
|
933
1033
|
|
|
934
1034
|
# Find as good common ancestors as possible for a merge
|
|
@@ -936,204 +1036,169 @@ module Git
|
|
|
936
1036
|
#
|
|
937
1037
|
# @return [Array<Git::Object::Commit>] a collection of common ancestors
|
|
938
1038
|
def merge_base(*)
|
|
939
|
-
|
|
940
|
-
shas.map { |sha| gcommit(sha) }
|
|
1039
|
+
facade_repository.merge_base(*).map { |sha| gcommit(sha) }
|
|
941
1040
|
end
|
|
942
1041
|
|
|
943
|
-
# Returns
|
|
1042
|
+
# Returns the full unified diff patch text between two commits
|
|
944
1043
|
#
|
|
945
|
-
# @
|
|
946
|
-
#
|
|
947
|
-
# @param opts [Hash] Options to filter the diff.
|
|
948
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path_limiter Limit stats to specified path(s).
|
|
949
|
-
# @return [Git::DiffStats]
|
|
950
|
-
def diff_stats(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
951
|
-
Git::DiffStats.new(self, objectish, obj2, opts[:path_limiter])
|
|
952
|
-
end
|
|
953
|
-
|
|
954
|
-
# 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..."
|
|
955
1046
|
#
|
|
956
|
-
# @param
|
|
957
|
-
#
|
|
958
|
-
# @param opts [Hash] Options to filter the diff.
|
|
959
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path_limiter Limit status to specified path(s).
|
|
960
|
-
# @option opts [String, Pathname, Array<String, Pathname>] :path (deprecated) Legacy alias for :path_limiter.
|
|
961
|
-
# @return [Git::DiffPathStatus]
|
|
962
|
-
def diff_path_status(objectish = 'HEAD', obj2 = nil, opts = {})
|
|
963
|
-
path_limiter = if opts.key?(:path_limiter)
|
|
964
|
-
opts[:path_limiter]
|
|
965
|
-
elsif opts.key?(:path)
|
|
966
|
-
Git::Deprecation.warn(
|
|
967
|
-
'Git::Base#diff_path_status :path option is deprecated. Use :path_limiter instead.'
|
|
968
|
-
)
|
|
969
|
-
opts[:path]
|
|
970
|
-
end
|
|
971
|
-
|
|
972
|
-
Git::DiffPathStatus.new(self, objectish, obj2, path_limiter)
|
|
973
|
-
end
|
|
974
|
-
|
|
975
|
-
# Provided for backwards compatibility
|
|
976
|
-
alias diff_name_status diff_path_status
|
|
977
|
-
|
|
978
|
-
private
|
|
979
|
-
|
|
980
|
-
# 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'`
|
|
981
1049
|
#
|
|
982
|
-
#
|
|
983
|
-
# `normalize_paths`, making this a fallback. It avoids mutating the
|
|
984
|
-
# original options hash by returning a new one.
|
|
1050
|
+
# @param obj2 [String, nil] the second commit or object to compare
|
|
985
1051
|
#
|
|
986
|
-
#
|
|
987
|
-
# @return [Hash] a new options hash with defaults applied
|
|
988
|
-
def default_paths(options)
|
|
989
|
-
return options unless (working_dir = options[:working_directory])
|
|
990
|
-
|
|
991
|
-
options.dup.tap do |opts|
|
|
992
|
-
opts[:repository] ||= File.join(working_dir, '.git')
|
|
993
|
-
opts[:index] ||= File.join(opts[:repository], 'index')
|
|
994
|
-
end
|
|
995
|
-
end
|
|
996
|
-
|
|
997
|
-
# Initializes the logger from the provided options
|
|
998
|
-
# @param log_option [Logger, nil] The logger instance from options.
|
|
999
|
-
def setup_logger(log_option)
|
|
1000
|
-
@logger = log_option || Logger.new(nil)
|
|
1001
|
-
@logger.info('Starting Git')
|
|
1002
|
-
end
|
|
1003
|
-
|
|
1004
|
-
# Initializes the core git objects based on the provided options
|
|
1005
|
-
# @param options [Hash] The processed options hash.
|
|
1006
|
-
def initialize_components(options)
|
|
1007
|
-
@working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
|
|
1008
|
-
@repository = Git::Repository.new(options[:repository]) if options[:repository]
|
|
1009
|
-
@index = Git::Index.new(options[:index], must_exist: false) if options[:index]
|
|
1010
|
-
end
|
|
1011
|
-
|
|
1012
|
-
# Normalize options before they are sent to Git::Base.new
|
|
1052
|
+
# When `nil`, the comparison is against the index or working tree.
|
|
1013
1053
|
#
|
|
1014
|
-
#
|
|
1015
|
-
# * options[:working_directory]
|
|
1016
|
-
# * options[:repository]
|
|
1017
|
-
# * options[:index]
|
|
1054
|
+
# @param opts [Hash] options to filter the diff
|
|
1018
1055
|
#
|
|
1019
|
-
#
|
|
1020
|
-
#
|
|
1056
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path_limiter (nil)
|
|
1057
|
+
# limit the diff to the given path(s)
|
|
1021
1058
|
#
|
|
1022
|
-
|
|
1023
|
-
options, default_working_directory: nil, default_repository: nil, bare: false
|
|
1024
|
-
)
|
|
1025
|
-
normalize_working_directory(options, default: default_working_directory, bare: bare)
|
|
1026
|
-
normalize_repository(options, default: default_repository, bare: bare)
|
|
1027
|
-
normalize_index(options)
|
|
1028
|
-
end
|
|
1029
|
-
|
|
1030
|
-
# Normalize options[:working_directory]
|
|
1059
|
+
# @return [String] the unified diff patch output
|
|
1031
1060
|
#
|
|
1032
|
-
#
|
|
1033
|
-
#
|
|
1034
|
-
# 1. `options[:working_directory]`,
|
|
1035
|
-
# 2. the `default` parameter, or
|
|
1036
|
-
# 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.
|
|
1037
1063
|
#
|
|
1038
|
-
#
|
|
1039
|
-
# path relative to the current directory.
|
|
1064
|
+
# @raise [Git::FailedError] if git exits outside the allowed range (exit code > 1)
|
|
1040
1065
|
#
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
else
|
|
1046
|
-
File.expand_path(options[:working_directory] || default || Dir.pwd)
|
|
1047
|
-
end
|
|
1048
|
-
|
|
1049
|
-
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))
|
|
1050
1070
|
end
|
|
1051
1071
|
|
|
1052
|
-
#
|
|
1072
|
+
# Returns a lazy {Git::DiffStats} object for accessing diff statistics
|
|
1053
1073
|
#
|
|
1054
|
-
#
|
|
1055
|
-
#
|
|
1056
|
-
#
|
|
1057
|
-
#
|
|
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.
|
|
1058
1078
|
#
|
|
1059
|
-
#
|
|
1060
|
-
# 1. `options[:repository]`
|
|
1061
|
-
# 2. `.git`
|
|
1079
|
+
# **Comparing two commits**
|
|
1062
1080
|
#
|
|
1063
|
-
#
|
|
1064
|
-
#
|
|
1065
|
-
# working with a submodule or a secondary working tree (created with git worktree
|
|
1066
|
-
# add). In these cases the repository is actually contained/nested within the
|
|
1067
|
-
# parent's repository directory.
|
|
1081
|
+
# When both objectish and obj2 are provided, the comparison is between those two
|
|
1082
|
+
# refs (commits, tags, branches, etc.).
|
|
1068
1083
|
#
|
|
1069
|
-
#
|
|
1070
|
-
# path relative to:
|
|
1071
|
-
# 1. the current directory if working with a bare repository or
|
|
1072
|
-
# 2. the working directory if NOT working with a bare repository
|
|
1084
|
+
# **Comparing a commit against the working tree**
|
|
1073
1085
|
#
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
final_path = resolve_gitdir_if_present(initial_path, options[:working_directory])
|
|
1077
|
-
options[:repository] = final_path
|
|
1078
|
-
end
|
|
1079
|
-
|
|
1080
|
-
# 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.
|
|
1081
1088
|
#
|
|
1082
|
-
#
|
|
1083
|
-
# final repository location. For features like submodules or worktrees,
|
|
1084
|
-
# this path may point to a text file containing a `gitdir:` pointer to the
|
|
1085
|
-
# actual repository directory elsewhere. This initial path must be
|
|
1086
|
-
# subsequently resolved.
|
|
1089
|
+
# **Comparing the index against the working tree**
|
|
1087
1090
|
#
|
|
1088
|
-
#
|
|
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.
|
|
1089
1094
|
#
|
|
1090
|
-
# @
|
|
1095
|
+
# @example Get working tree stats since HEAD
|
|
1096
|
+
# repo.diff_stats.insertions #=> 3
|
|
1091
1097
|
#
|
|
1092
|
-
# @
|
|
1098
|
+
# @example Compare two specific commits
|
|
1099
|
+
# repo.diff_stats('abc1234', 'def5678')
|
|
1093
1100
|
#
|
|
1094
|
-
# @
|
|
1101
|
+
# @example Get unstaged stats (index vs. working tree)
|
|
1102
|
+
# repo.diff_stats(nil).insertions
|
|
1095
1103
|
#
|
|
1096
|
-
# @
|
|
1104
|
+
# @example Limit stats to a sub-path
|
|
1105
|
+
# repo.diff_stats('HEAD~1', 'HEAD', path_limiter: 'lib/')
|
|
1097
1106
|
#
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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))
|
|
1104
1130
|
end
|
|
1105
1131
|
|
|
1106
|
-
#
|
|
1132
|
+
# Returns the file path status between two commits
|
|
1107
1133
|
#
|
|
1108
|
-
#
|
|
1109
|
-
#
|
|
1110
|
-
# 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" }
|
|
1111
1136
|
#
|
|
1112
|
-
# @
|
|
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
|
|
1113
1141
|
#
|
|
1114
|
-
# @param
|
|
1142
|
+
# @param opts [Hash] options to filter the diff
|
|
1115
1143
|
#
|
|
1116
|
-
# @
|
|
1144
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path_limiter (nil)
|
|
1145
|
+
# limit the status report to specified path(s)
|
|
1117
1146
|
#
|
|
1118
|
-
# @
|
|
1147
|
+
# @option opts [String, Pathname, Array<String, Pathname>, nil] :path (nil)
|
|
1148
|
+
# deprecated; use `:path_limiter` instead
|
|
1119
1149
|
#
|
|
1120
|
-
|
|
1121
|
-
|
|
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
|
|
1122
1161
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
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
|
|
1127
1176
|
end
|
|
1128
1177
|
|
|
1129
|
-
#
|
|
1178
|
+
# Alias for {#diff_path_status}; provided for backward compatibility
|
|
1179
|
+
#
|
|
1180
|
+
# @return [Git::DiffPathStatus] the name-status report for the comparison
|
|
1130
1181
|
#
|
|
1131
|
-
#
|
|
1132
|
-
# directory relative to the repository directory
|
|
1182
|
+
# @deprecated Use {#diff_path_status} instead
|
|
1133
1183
|
#
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
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]
|
|
1137
1202
|
end
|
|
1138
1203
|
end
|
|
1139
1204
|
end
|