git 1.19.1 → 3.1.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/.commitlintrc.yml +38 -0
- data/.github/pull_request_template.md +8 -0
- data/.github/workflows/continuous_integration.yml +19 -21
- data/.github/workflows/enforce_conventional_commits.yml +28 -0
- data/.github/workflows/experimental_continuous_integration.yml +50 -0
- data/.github/workflows/release.yml +52 -0
- data/.gitignore +3 -0
- data/.husky/commit-msg +1 -0
- data/.release-please-manifest.json +3 -0
- data/.yardopts +0 -1
- data/CHANGELOG.md +211 -0
- data/CONTRIBUTING.md +290 -102
- data/README.md +180 -62
- data/Rakefile +7 -0
- data/git.gemspec +11 -11
- data/lib/git/author.rb +3 -2
- data/lib/git/base.rb +222 -59
- data/lib/git/branch.rb +2 -0
- data/lib/git/branches.rb +15 -14
- data/lib/git/command_line.rb +287 -0
- data/lib/git/config.rb +7 -1
- data/lib/git/diff.rb +2 -0
- data/lib/git/errors.rb +206 -0
- data/lib/git/escaped_path.rb +1 -1
- data/lib/git/index.rb +2 -1
- data/lib/git/lib.rb +604 -234
- data/lib/git/log.rb +74 -6
- data/lib/git/object.rb +80 -76
- data/lib/git/path.rb +9 -8
- data/lib/git/remote.rb +2 -0
- data/lib/git/repository.rb +2 -0
- data/lib/git/stash.rb +7 -6
- data/lib/git/stashes.rb +11 -10
- data/lib/git/status.rb +135 -25
- data/lib/git/version.rb +3 -1
- data/lib/git/working_directory.rb +2 -0
- data/lib/git/worktree.rb +2 -0
- data/lib/git/worktrees.rb +2 -0
- data/lib/git.rb +21 -7
- data/package.json +10 -0
- data/release-please-config.json +36 -0
- metadata +52 -38
- data/.github/stale.yml +0 -25
- data/Dockerfile.changelog-rs +0 -12
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/RELEASING.md +0 -70
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/signaled_error.rb +0 -50
- /data/{ISSUE_TEMPLATE.md → .github/issue_template.md} +0 -0
data/lib/git/base.rb
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'logger'
|
|
3
4
|
require 'open3'
|
|
4
5
|
|
|
5
6
|
module Git
|
|
6
|
-
#
|
|
7
|
+
# The main public interface for interacting with Git commands
|
|
7
8
|
#
|
|
8
9
|
# Instead of creating a Git::Base directly, obtain a Git::Base instance by
|
|
9
10
|
# calling one of the follow {Git} class methods: {Git.open}, {Git.init},
|
|
10
11
|
# {Git.clone}, or {Git.bare}.
|
|
11
12
|
#
|
|
13
|
+
# @api public
|
|
14
|
+
#
|
|
12
15
|
class Base
|
|
13
|
-
include Git::Base::Factory
|
|
14
|
-
|
|
15
16
|
# (see Git.bare)
|
|
16
17
|
def self.bare(git_dir, options = {})
|
|
17
18
|
normalize_paths(options, default_repository: git_dir, bare: true)
|
|
@@ -37,6 +38,26 @@ module Git
|
|
|
37
38
|
@@config ||= Config.new
|
|
38
39
|
end
|
|
39
40
|
|
|
41
|
+
def self.binary_version(binary_path)
|
|
42
|
+
result = nil
|
|
43
|
+
status = nil
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
result, status = Open3.capture2e(binary_path, "-c", "core.quotePath=true", "-c", "color.ui=false", "version")
|
|
47
|
+
result = result.chomp
|
|
48
|
+
rescue Errno::ENOENT
|
|
49
|
+
raise RuntimeError, "Failed to get git version: #{binary_path} not found"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if status.success?
|
|
53
|
+
version = result[/\d+(\.\d+)+/]
|
|
54
|
+
version_parts = version.split('.').collect { |i| i.to_i }
|
|
55
|
+
version_parts.fill(0, version_parts.length...3)
|
|
56
|
+
else
|
|
57
|
+
raise RuntimeError, "Failed to get git version: #{status}\n#{result}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
40
61
|
# (see Git.init)
|
|
41
62
|
def self.init(directory = '.', options = {})
|
|
42
63
|
normalize_paths(options, default_working_directory: directory, default_repository: directory, bare: options[:bare])
|
|
@@ -68,9 +89,14 @@ module Git
|
|
|
68
89
|
result = working_dir
|
|
69
90
|
status = nil
|
|
70
91
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
92
|
+
raise ArgumentError, "'#{working_dir}' does not exist" unless Dir.exist?(working_dir)
|
|
93
|
+
|
|
94
|
+
begin
|
|
95
|
+
result, status = Open3.capture2e(Git::Base.config.binary_path, "-c", "core.quotePath=true", "-c", "color.ui=false", "rev-parse", "--show-toplevel", chdir: File.expand_path(working_dir))
|
|
96
|
+
result = result.chomp
|
|
97
|
+
rescue Errno::ENOENT
|
|
98
|
+
raise ArgumentError, "Failed to find the root of the worktree: git binary not found"
|
|
99
|
+
end
|
|
74
100
|
|
|
75
101
|
raise ArgumentError, "'#{working_dir}' is not in a git working tree" unless status.success?
|
|
76
102
|
result
|
|
@@ -122,6 +148,62 @@ module Git
|
|
|
122
148
|
@index = options[:index] ? Git::Index.new(options[:index], false) : nil
|
|
123
149
|
end
|
|
124
150
|
|
|
151
|
+
# Update the index from the current worktree to prepare the for the next commit
|
|
152
|
+
#
|
|
153
|
+
# @example
|
|
154
|
+
# lib.add('path/to/file')
|
|
155
|
+
# lib.add(['path/to/file1','path/to/file2'])
|
|
156
|
+
# lib.add(all: true)
|
|
157
|
+
#
|
|
158
|
+
# @param [String, Array<String>] paths a file or files to be added to the repository (relative to the worktree root)
|
|
159
|
+
# @param [Hash] options
|
|
160
|
+
#
|
|
161
|
+
# @option options [Boolean] :all Add, modify, and remove index entries to match the worktree
|
|
162
|
+
# @option options [Boolean] :force Allow adding otherwise ignored files
|
|
163
|
+
#
|
|
164
|
+
def add(paths = '.', **options)
|
|
165
|
+
self.lib.add(paths, options)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# adds a new remote to this repository
|
|
169
|
+
# url can be a git url or a Git::Base object if it's a local reference
|
|
170
|
+
#
|
|
171
|
+
# @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
|
|
172
|
+
# @git.fetch('scotts_git')
|
|
173
|
+
# @git.merge('scotts_git/master')
|
|
174
|
+
#
|
|
175
|
+
# Options:
|
|
176
|
+
# :fetch => true
|
|
177
|
+
# :track => <branch_name>
|
|
178
|
+
def add_remote(name, url, opts = {})
|
|
179
|
+
url = url.repo.path if url.is_a?(Git::Base)
|
|
180
|
+
self.lib.remote_add(name, url, opts)
|
|
181
|
+
Git::Remote.new(self, name)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Create a new git tag
|
|
185
|
+
#
|
|
186
|
+
# @example
|
|
187
|
+
# repo.add_tag('tag_name', object_reference)
|
|
188
|
+
# repo.add_tag('tag_name', object_reference, {:options => 'here'})
|
|
189
|
+
# repo.add_tag('tag_name', {:options => 'here'})
|
|
190
|
+
#
|
|
191
|
+
# @param [String] name The name of the tag to add
|
|
192
|
+
# @param [Hash] options Opstions to pass to `git tag`.
|
|
193
|
+
# See [git-tag](https://git-scm.com/docs/git-tag) for more details.
|
|
194
|
+
# @option options [boolean] :annotate Make an unsigned, annotated tag object
|
|
195
|
+
# @option options [boolean] :a An alias for the `:annotate` option
|
|
196
|
+
# @option options [boolean] :d Delete existing tag with the given names.
|
|
197
|
+
# @option options [boolean] :f Replace an existing tag with the given name (instead of failing)
|
|
198
|
+
# @option options [String] :message Use the given tag message
|
|
199
|
+
# @option options [String] :m An alias for the `:message` option
|
|
200
|
+
# @option options [boolean] :s Make a GPG-signed tag.
|
|
201
|
+
#
|
|
202
|
+
def add_tag(name, *options)
|
|
203
|
+
self.lib.tag(name, *options)
|
|
204
|
+
self.tag(name)
|
|
205
|
+
end
|
|
206
|
+
|
|
125
207
|
# changes current working directory for a block
|
|
126
208
|
# to the git working directory
|
|
127
209
|
#
|
|
@@ -254,27 +336,11 @@ module Git
|
|
|
254
336
|
self.object('HEAD').grep(string, path_limiter, opts)
|
|
255
337
|
end
|
|
256
338
|
|
|
257
|
-
#
|
|
258
|
-
#
|
|
259
|
-
# @example
|
|
260
|
-
# git.add
|
|
261
|
-
# git.add('path/to/file')
|
|
262
|
-
# git.add(['path/to/file1','path/to/file2'])
|
|
263
|
-
# git.add(:all => true)
|
|
264
|
-
#
|
|
265
|
-
# options:
|
|
266
|
-
# :all => true
|
|
267
|
-
#
|
|
268
|
-
# @param [String,Array] paths files paths to be added (optional, default='.')
|
|
269
|
-
# @param [Hash] options
|
|
270
|
-
# @option options [boolean] :all
|
|
271
|
-
# Update the index not only where the working tree has a file matching
|
|
272
|
-
# <pathspec> but also where the index already has an entry.
|
|
273
|
-
# See [the --all option to git-add](https://git-scm.com/docs/git-add#Documentation/git-add.txt--A)
|
|
274
|
-
# for more details.
|
|
339
|
+
# List the files in the worktree that are ignored by git
|
|
340
|
+
# @return [Array<String>] the list of ignored files relative to teh root of the worktree
|
|
275
341
|
#
|
|
276
|
-
def
|
|
277
|
-
self.lib.
|
|
342
|
+
def ignored_files
|
|
343
|
+
self.lib.ignored_files
|
|
278
344
|
end
|
|
279
345
|
|
|
280
346
|
# removes file(s) from the git repository
|
|
@@ -409,14 +475,27 @@ module Git
|
|
|
409
475
|
self.lib.conflicts(&block)
|
|
410
476
|
end
|
|
411
477
|
|
|
412
|
-
#
|
|
478
|
+
# Pulls the given branch from the given remote into the current branch
|
|
479
|
+
#
|
|
480
|
+
# @param remote [String] the remote repository to pull from
|
|
481
|
+
# @param branch [String] the branch to pull from
|
|
482
|
+
# @param opts [Hash] options to pass to the pull command
|
|
413
483
|
#
|
|
414
|
-
#
|
|
415
|
-
#
|
|
416
|
-
#
|
|
484
|
+
# @option opts [Boolean] :allow_unrelated_histories (false) Merges histories of two projects that started their
|
|
485
|
+
# lives independently
|
|
486
|
+
# @example pulls from origin/master
|
|
487
|
+
# @git.pull
|
|
488
|
+
# @example pulls from upstream/master
|
|
489
|
+
# @git.pull('upstream')
|
|
490
|
+
# @example pulls from upstream/develop
|
|
491
|
+
# @git.pull('upstream', 'develop')
|
|
417
492
|
#
|
|
418
|
-
|
|
419
|
-
|
|
493
|
+
# @return [Void]
|
|
494
|
+
#
|
|
495
|
+
# @raise [Git::FailedError] if the pull fails
|
|
496
|
+
# @raise [ArgumentError] if a branch is given without a remote
|
|
497
|
+
def pull(remote = nil, branch = nil, opts = {})
|
|
498
|
+
self.lib.pull(remote, branch, opts)
|
|
420
499
|
end
|
|
421
500
|
|
|
422
501
|
# returns an array of Git:Remote objects
|
|
@@ -424,22 +503,6 @@ module Git
|
|
|
424
503
|
self.lib.remotes.map { |r| Git::Remote.new(self, r) }
|
|
425
504
|
end
|
|
426
505
|
|
|
427
|
-
# adds a new remote to this repository
|
|
428
|
-
# url can be a git url or a Git::Base object if it's a local reference
|
|
429
|
-
#
|
|
430
|
-
# @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
|
|
431
|
-
# @git.fetch('scotts_git')
|
|
432
|
-
# @git.merge('scotts_git/master')
|
|
433
|
-
#
|
|
434
|
-
# Options:
|
|
435
|
-
# :fetch => true
|
|
436
|
-
# :track => <branch_name>
|
|
437
|
-
def add_remote(name, url, opts = {})
|
|
438
|
-
url = url.repo.path if url.is_a?(Git::Base)
|
|
439
|
-
self.lib.remote_add(name, url, opts)
|
|
440
|
-
Git::Remote.new(self, name)
|
|
441
|
-
end
|
|
442
|
-
|
|
443
506
|
# sets the url for a remote
|
|
444
507
|
# url can be a git url or a Git::Base object if it's a local reference
|
|
445
508
|
#
|
|
@@ -463,7 +526,7 @@ module Git
|
|
|
463
526
|
self.lib.tags.map { |r| tag(r) }
|
|
464
527
|
end
|
|
465
528
|
|
|
466
|
-
#
|
|
529
|
+
# Create a new git tag
|
|
467
530
|
#
|
|
468
531
|
# @example
|
|
469
532
|
# repo.add_tag('tag_name', object_reference)
|
|
@@ -598,27 +661,127 @@ module Git
|
|
|
598
661
|
# runs git rev-parse to convert the objectish to a full sha
|
|
599
662
|
#
|
|
600
663
|
# @example
|
|
601
|
-
# git.
|
|
602
|
-
# git.
|
|
603
|
-
# git.
|
|
664
|
+
# git.rev_parse("HEAD^^")
|
|
665
|
+
# git.rev_parse('v2.4^{tree}')
|
|
666
|
+
# git.rev_parse('v2.4:/doc/index.html')
|
|
604
667
|
#
|
|
605
|
-
def
|
|
606
|
-
self.lib.
|
|
668
|
+
def rev_parse(objectish)
|
|
669
|
+
self.lib.rev_parse(objectish)
|
|
607
670
|
end
|
|
608
671
|
|
|
609
|
-
|
|
610
|
-
|
|
672
|
+
# For backwards compatibility
|
|
673
|
+
alias revparse rev_parse
|
|
674
|
+
|
|
675
|
+
def ls_tree(objectish, opts = {})
|
|
676
|
+
self.lib.ls_tree(objectish, opts)
|
|
611
677
|
end
|
|
612
678
|
|
|
613
679
|
def cat_file(objectish)
|
|
614
|
-
self.lib.
|
|
680
|
+
self.lib.cat_file(objectish)
|
|
615
681
|
end
|
|
616
682
|
|
|
617
|
-
#
|
|
683
|
+
# The name of the branch HEAD refers to or 'HEAD' if detached
|
|
684
|
+
#
|
|
685
|
+
# Returns one of the following:
|
|
686
|
+
# * The branch name that HEAD refers to (even if it is an unborn branch)
|
|
687
|
+
# * 'HEAD' if in a detached HEAD state
|
|
688
|
+
#
|
|
689
|
+
# @return [String] the name of the branch HEAD refers to or 'HEAD' if detached
|
|
690
|
+
#
|
|
618
691
|
def current_branch
|
|
619
692
|
self.lib.branch_current
|
|
620
693
|
end
|
|
621
694
|
|
|
695
|
+
# @return [Git::Branch] an object for branch_name
|
|
696
|
+
def branch(branch_name = self.current_branch)
|
|
697
|
+
Git::Branch.new(self, branch_name)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
# @return [Git::Branches] a collection of all the branches in the repository.
|
|
701
|
+
# Each branch is represented as a {Git::Branch}.
|
|
702
|
+
def branches
|
|
703
|
+
Git::Branches.new(self)
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
# returns a Git::Worktree object for dir, commitish
|
|
707
|
+
def worktree(dir, commitish = nil)
|
|
708
|
+
Git::Worktree.new(self, dir, commitish)
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
# returns a Git::worktrees object of all the Git::Worktrees
|
|
712
|
+
# objects for this repo
|
|
713
|
+
def worktrees
|
|
714
|
+
Git::Worktrees.new(self)
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
# @return [Git::Object::Commit] a commit object
|
|
718
|
+
def commit_tree(tree = nil, opts = {})
|
|
719
|
+
Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
# @return [Git::Diff] a Git::Diff object
|
|
723
|
+
def diff(objectish = 'HEAD', obj2 = nil)
|
|
724
|
+
Git::Diff.new(self, objectish, obj2)
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
# @return [Git::Object] a Git object
|
|
728
|
+
def gblob(objectish)
|
|
729
|
+
Git::Object.new(self, objectish, 'blob')
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
# @return [Git::Object] a Git object
|
|
733
|
+
def gcommit(objectish)
|
|
734
|
+
Git::Object.new(self, objectish, 'commit')
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
# @return [Git::Object] a Git object
|
|
738
|
+
def gtree(objectish)
|
|
739
|
+
Git::Object.new(self, objectish, 'tree')
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
# @return [Git::Log] a log with the specified number of commits
|
|
743
|
+
def log(count = 30)
|
|
744
|
+
Git::Log.new(self, count)
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
# returns a Git::Object of the appropriate type
|
|
748
|
+
# you can also call @git.gtree('tree'), but that's
|
|
749
|
+
# just for readability. If you call @git.gtree('HEAD') it will
|
|
750
|
+
# still return a Git::Object::Commit object.
|
|
751
|
+
#
|
|
752
|
+
# object calls a method that will run a rev-parse
|
|
753
|
+
# on the objectish and determine the type of the object and return
|
|
754
|
+
# an appropriate object for that type
|
|
755
|
+
#
|
|
756
|
+
# @return [Git::Object] an instance of the appropriate type of Git::Object
|
|
757
|
+
def object(objectish)
|
|
758
|
+
Git::Object.new(self, objectish)
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
# @return [Git::Remote] a remote of the specified name
|
|
762
|
+
def remote(remote_name = 'origin')
|
|
763
|
+
Git::Remote.new(self, remote_name)
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
# @return [Git::Status] a status object
|
|
767
|
+
def status
|
|
768
|
+
Git::Status.new(self)
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
# @return [Git::Object::Tag] a tag object
|
|
772
|
+
def tag(tag_name)
|
|
773
|
+
Git::Object.new(self, tag_name, 'tag', true)
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
# Find as good common ancestors as possible for a merge
|
|
777
|
+
# example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true)
|
|
778
|
+
#
|
|
779
|
+
# @return [Array<Git::Object::Commit>] a collection of common ancestors
|
|
780
|
+
def merge_base(*args)
|
|
781
|
+
shas = self.lib.merge_base(*args)
|
|
782
|
+
shas.map { |sha| gcommit(sha) }
|
|
783
|
+
end
|
|
784
|
+
|
|
622
785
|
private
|
|
623
786
|
|
|
624
787
|
# Normalize options before they are sent to Git::Base.new
|
data/lib/git/branch.rb
CHANGED
data/lib/git/branches.rb
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Git
|
|
2
|
-
|
|
4
|
+
|
|
3
5
|
# object that holds all the available branches
|
|
4
6
|
class Branches
|
|
5
7
|
|
|
6
8
|
include Enumerable
|
|
7
|
-
|
|
9
|
+
|
|
8
10
|
def initialize(base)
|
|
9
11
|
@branches = {}
|
|
10
|
-
|
|
12
|
+
|
|
11
13
|
@base = base
|
|
12
|
-
|
|
14
|
+
|
|
13
15
|
@base.lib.branches_all.each do |b|
|
|
14
16
|
@branches[b[0]] = Git::Branch.new(@base, b[0])
|
|
15
17
|
end
|
|
@@ -18,21 +20,21 @@ module Git
|
|
|
18
20
|
def local
|
|
19
21
|
self.select { |b| !b.remote }
|
|
20
22
|
end
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
def remote
|
|
23
25
|
self.select { |b| b.remote }
|
|
24
26
|
end
|
|
25
|
-
|
|
27
|
+
|
|
26
28
|
# array like methods
|
|
27
29
|
|
|
28
30
|
def size
|
|
29
31
|
@branches.size
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
+
end
|
|
33
|
+
|
|
32
34
|
def each(&block)
|
|
33
35
|
@branches.values.each(&block)
|
|
34
36
|
end
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
# Returns the target branch
|
|
37
39
|
#
|
|
38
40
|
# Example:
|
|
@@ -50,14 +52,14 @@ module Git
|
|
|
50
52
|
@branches.values.inject(@branches) do |branches, branch|
|
|
51
53
|
branches[branch.full] ||= branch
|
|
52
54
|
|
|
53
|
-
# This is how Git (version 1.7.9.5) works.
|
|
54
|
-
# Lets you ignore the 'remotes' if its at the beginning of the branch full name (even if is not a real remote branch).
|
|
55
|
+
# This is how Git (version 1.7.9.5) works.
|
|
56
|
+
# Lets you ignore the 'remotes' if its at the beginning of the branch full name (even if is not a real remote branch).
|
|
55
57
|
branches[branch.full.sub('remotes/', '')] ||= branch if branch.full =~ /^remotes\/.+/
|
|
56
|
-
|
|
58
|
+
|
|
57
59
|
branches
|
|
58
60
|
end[branch_name.to_s]
|
|
59
61
|
end
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
def to_s
|
|
62
64
|
out = ''
|
|
63
65
|
@branches.each do |k, b|
|
|
@@ -65,7 +67,6 @@ module Git
|
|
|
65
67
|
end
|
|
66
68
|
out
|
|
67
69
|
end
|
|
68
|
-
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
end
|