git 3.1.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/continuous_integration.yml +11 -3
- data/.github/workflows/experimental_continuous_integration.yml +9 -0
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +19 -0
- data/README.md +19 -0
- data/git.gemspec +2 -2
- data/lib/git/base.rb +21 -0
- data/lib/git/command_line.rb +11 -10
- data/lib/git/command_line_result.rb +9 -3
- data/lib/git/diff.rb +80 -81
- data/lib/git/diff_path_status.rb +45 -0
- data/lib/git/diff_stats.rb +59 -0
- data/lib/git/lib.rb +7 -7
- data/lib/git/log.rb +94 -14
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93f63d19e697e7cc1f9d6f8fed0a34ff32015c5ed24357f183f2493dca636953
|
4
|
+
data.tar.gz: 8e7619c86fee8af92c11d60c6af450e3814bbf77d456fcb3c6d3c914d985403f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f003e0ea707da5dc4a164c041407802650390e6a03b496d1960994dfd79cae393ab16da3ed062b0cbeaa6839e7d21931d8e9954d7c19fb8ec25cbbfb0f46fa7
|
7
|
+
data.tar.gz: 552efec7c3d8b2e09cfa1c943666e72a3d8aaa336a64252c7d955412cef092c5aede3e87ca7f17df0e8f673a9ed3b35cafcfcf04912b5c8e65ad0082ac415f46
|
@@ -22,18 +22,26 @@ jobs:
|
|
22
22
|
fail-fast: false
|
23
23
|
matrix:
|
24
24
|
# Only the latest versions of JRuby and TruffleRuby are tested
|
25
|
-
ruby: ["3.
|
25
|
+
ruby: ["3.2", "3.3", "3.4", "truffleruby-24.2.1", "jruby-10.0.0.1"]
|
26
26
|
operating-system: [ubuntu-latest]
|
27
27
|
experimental: [No]
|
28
|
+
java_version: [""]
|
28
29
|
include:
|
29
|
-
-
|
30
|
-
ruby: 3.1
|
30
|
+
- ruby: 3.2
|
31
31
|
operating-system: windows-latest
|
32
|
+
experimental: No
|
32
33
|
|
33
34
|
steps:
|
34
35
|
- name: Checkout Code
|
35
36
|
uses: actions/checkout@v4
|
36
37
|
|
38
|
+
- name: Setup Java
|
39
|
+
if: matrix.java_version != ''
|
40
|
+
uses: actions/setup-java@v4
|
41
|
+
with:
|
42
|
+
distribution: 'temurin'
|
43
|
+
java-version: ${{ matrix.java_version }}
|
44
|
+
|
37
45
|
- name: Setup Ruby
|
38
46
|
uses: ruby/setup-ruby@v1
|
39
47
|
with:
|
@@ -27,16 +27,25 @@ jobs:
|
|
27
27
|
ruby: head
|
28
28
|
operating-system: ubuntu-latest
|
29
29
|
experimental: Yes
|
30
|
+
java_version: ""
|
30
31
|
|
31
32
|
- # Since JRuby on Windows is known to not work, consider this experimental
|
32
33
|
ruby: jruby-head
|
33
34
|
operating-system: windows-latest
|
34
35
|
experimental: Yes
|
36
|
+
java_version: "21"
|
35
37
|
|
36
38
|
steps:
|
37
39
|
- name: Checkout Code
|
38
40
|
uses: actions/checkout@v4
|
39
41
|
|
42
|
+
- name: Setup Java
|
43
|
+
if: matrix.java_version != ''
|
44
|
+
uses: actions/setup-java@v4
|
45
|
+
with:
|
46
|
+
distribution: 'temurin'
|
47
|
+
java-version: ${{ matrix.java_version }}
|
48
|
+
|
40
49
|
- name: Setup Ruby
|
41
50
|
uses: ruby/setup-ruby@v1
|
42
51
|
with:
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,25 @@
|
|
5
5
|
|
6
6
|
# Change Log
|
7
7
|
|
8
|
+
## [4.0.0](https://github.com/ruby-git/ruby-git/compare/v3.1.1...v4.0.0) (2025-07-02)
|
9
|
+
|
10
|
+
|
11
|
+
### ⚠ BREAKING CHANGES
|
12
|
+
|
13
|
+
* Users will need to be on Ruby 3.2 or greater
|
14
|
+
|
15
|
+
### Features
|
16
|
+
|
17
|
+
* Add Log#execute to run the log and return an immutable result ([ded54c4](https://github.com/ruby-git/ruby-git/commit/ded54c4b551aefb7de35b9505ce14f2061d1708c))
|
18
|
+
* **diff:** Refactor Git::Diff to separate concerns and improve AP ([e22eb10](https://github.com/ruby-git/ruby-git/commit/e22eb10bf2e4049f1a0fb325341ef7489f25e66e))
|
19
|
+
* Upgrade minimally supported Ruby to 3.2 ([fb93ef1](https://github.com/ruby-git/ruby-git/commit/fb93ef14def222d6eca29f49a5f810a3d6de5787))
|
20
|
+
|
21
|
+
|
22
|
+
### Other Changes
|
23
|
+
|
24
|
+
* Remove unneeded explicit return statements ([28e07ae](https://github.com/ruby-git/ruby-git/commit/28e07ae2e91a8defd52549393bf6f3fcbede122e))
|
25
|
+
* Upgrade to ProcessExecuter 4.x ([5b00d3b](https://github.com/ruby-git/ruby-git/commit/5b00d3b9c4063c9988d844eec9ddedddb8c26446))
|
26
|
+
|
8
27
|
## [3.1.1](https://github.com/ruby-git/ruby-git/compare/v3.1.0...v3.1.1) (2025-07-02)
|
9
28
|
|
10
29
|
|
data/README.md
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
- [Major Objects](#major-objects)
|
19
19
|
- [Errors Raised By This Gem](#errors-raised-by-this-gem)
|
20
20
|
- [Specifying And Handling Timeouts](#specifying-and-handling-timeouts)
|
21
|
+
- [Deprecations](#deprecations)
|
21
22
|
- [Examples](#examples)
|
22
23
|
- [Ruby version support policy](#ruby-version-support-policy)
|
23
24
|
- [License](#license)
|
@@ -202,6 +203,24 @@ rescue Git::TimeoutError => e
|
|
202
203
|
end
|
203
204
|
```
|
204
205
|
|
206
|
+
## Deprecations
|
207
|
+
|
208
|
+
This gem uses ActiveSupport's deprecation mechanism to report deprecation warnings.
|
209
|
+
|
210
|
+
You can silence deprecation warnings by adding this line to your source code:
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
Git::Deprecation.behavior = :silence
|
214
|
+
```
|
215
|
+
|
216
|
+
See [the Active Support Deprecation
|
217
|
+
documentation](https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html)
|
218
|
+
for more details.
|
219
|
+
|
220
|
+
If deprecation warnings are silenced, you should reenable them before upgrading the
|
221
|
+
git gem to the next major version. This will make it easier to identify changes
|
222
|
+
needed for the upgrade.
|
223
|
+
|
205
224
|
## Examples
|
206
225
|
|
207
226
|
Here are a bunch of examples of how to use the Ruby/Git package.
|
data/git.gemspec
CHANGED
@@ -24,12 +24,12 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}"
|
25
25
|
|
26
26
|
s.require_paths = ['lib']
|
27
|
-
s.required_ruby_version = '>= 3.
|
27
|
+
s.required_ruby_version = '>= 3.2.0'
|
28
28
|
s.requirements = ['git 2.28.0 or greater']
|
29
29
|
|
30
30
|
s.add_runtime_dependency 'activesupport', '>= 5.0'
|
31
31
|
s.add_runtime_dependency 'addressable', '~> 2.8'
|
32
|
-
s.add_runtime_dependency 'process_executer', '~>
|
32
|
+
s.add_runtime_dependency 'process_executer', '~> 4.0'
|
33
33
|
s.add_runtime_dependency 'rchardet', '~> 1.9'
|
34
34
|
|
35
35
|
s.add_development_dependency 'create_github_release', '~> 2.1'
|
data/lib/git/base.rb
CHANGED
@@ -782,6 +782,27 @@ module Git
|
|
782
782
|
shas.map { |sha| gcommit(sha) }
|
783
783
|
end
|
784
784
|
|
785
|
+
# Returns a Git::Diff::Stats object for accessing diff statistics.
|
786
|
+
#
|
787
|
+
# @param objectish [String] The first commit or object to compare. Defaults to 'HEAD'.
|
788
|
+
# @param obj2 [String, nil] The second commit or object to compare.
|
789
|
+
# @return [Git::Diff::Stats]
|
790
|
+
def diff_stats(objectish = 'HEAD', obj2 = nil)
|
791
|
+
Git::DiffStats.new(self, objectish, obj2)
|
792
|
+
end
|
793
|
+
|
794
|
+
# Returns a Git::Diff::PathStatus object for accessing the name-status report.
|
795
|
+
#
|
796
|
+
# @param objectish [String] The first commit or object to compare. Defaults to 'HEAD'.
|
797
|
+
# @param obj2 [String, nil] The second commit or object to compare.
|
798
|
+
# @return [Git::Diff::PathStatus]
|
799
|
+
def diff_path_status(objectish = 'HEAD', obj2 = nil)
|
800
|
+
Git::DiffPathStatus.new(self, objectish, obj2)
|
801
|
+
end
|
802
|
+
|
803
|
+
# Provided for backwards compatibility
|
804
|
+
alias diff_name_status diff_path_status
|
805
|
+
|
785
806
|
private
|
786
807
|
|
787
808
|
# Normalize options before they are sent to Git::Base.new
|
data/lib/git/command_line.rb
CHANGED
@@ -192,8 +192,13 @@ module Git
|
|
192
192
|
def run(*args, out: nil, err: nil, normalize:, chomp:, merge:, chdir: nil, timeout: nil)
|
193
193
|
git_cmd = build_git_cmd(args)
|
194
194
|
begin
|
195
|
-
|
196
|
-
|
195
|
+
options = { chdir: (chdir || :not_set), timeout_after: timeout, raise_errors: false }
|
196
|
+
options[:out] = out unless out.nil?
|
197
|
+
options[:err] = err unless err.nil?
|
198
|
+
options[:merge_output] = merge unless merge.nil?
|
199
|
+
|
200
|
+
result = ProcessExecuter.run_with_capture(env, *git_cmd, **options)
|
201
|
+
rescue ProcessExecuter::ProcessIOError => e
|
197
202
|
raise Git::ProcessIOError.new(e.message), cause: e.exception.cause
|
198
203
|
end
|
199
204
|
process_result(result, normalize, chomp, timeout)
|
@@ -274,14 +279,10 @@ module Git
|
|
274
279
|
# @api private
|
275
280
|
#
|
276
281
|
def post_process(raw_output, normalize, chomp)
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
output
|
282
|
-
else
|
283
|
-
nil
|
284
|
-
end
|
282
|
+
output = raw_output.dup
|
283
|
+
output = output.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join if normalize
|
284
|
+
output.chomp! if chomp
|
285
|
+
output
|
285
286
|
end
|
286
287
|
end
|
287
288
|
end
|
@@ -19,15 +19,21 @@ module Git
|
|
19
19
|
# result = Git::CommandLineResult.new(git_cmd, status, stdout, stderr)
|
20
20
|
#
|
21
21
|
# @param git_cmd [Array<String>] the git command that was executed
|
22
|
-
# @param status [
|
23
|
-
# @param stdout [String] the
|
24
|
-
# @param stderr [String] the
|
22
|
+
# @param status [ProcessExecuter::ResultWithCapture] the status of the process
|
23
|
+
# @param stdout [String] the processed stdout of the process
|
24
|
+
# @param stderr [String] the processed stderr of the process
|
25
25
|
#
|
26
26
|
def initialize(git_cmd, status, stdout, stderr)
|
27
27
|
@git_cmd = git_cmd
|
28
28
|
@status = status
|
29
29
|
@stdout = stdout
|
30
30
|
@stderr = stderr
|
31
|
+
|
32
|
+
# ProcessExecuter::ResultWithCapture changed the timeout? method to timed_out?
|
33
|
+
# in version 4.x. This is a compatibility layer to maintain the old method name
|
34
|
+
# for backward compatibility.
|
35
|
+
#
|
36
|
+
status.define_singleton_method(:timeout?) { timed_out? }
|
31
37
|
end
|
32
38
|
|
33
39
|
# @attribute [r] git_cmd
|
data/lib/git/diff.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'diff_path_status'
|
4
|
+
require_relative 'diff_stats'
|
4
5
|
|
5
|
-
|
6
|
+
module Git
|
7
|
+
# object that holds the diff between two commits
|
6
8
|
class Diff
|
7
9
|
include Enumerable
|
8
10
|
|
@@ -12,63 +14,68 @@ module Git
|
|
12
14
|
@to = to && to.to_s
|
13
15
|
|
14
16
|
@path = nil
|
15
|
-
@full_diff = nil
|
16
17
|
@full_diff_files = nil
|
17
|
-
@stats = nil
|
18
18
|
end
|
19
19
|
attr_reader :from, :to
|
20
20
|
|
21
|
-
def name_status
|
22
|
-
cache_name_status
|
23
|
-
end
|
24
|
-
|
25
21
|
def path(path)
|
26
22
|
@path = path
|
27
|
-
|
23
|
+
self
|
28
24
|
end
|
29
25
|
|
30
|
-
def
|
31
|
-
|
32
|
-
@stats[:total][:files]
|
26
|
+
def patch
|
27
|
+
@base.lib.diff_full(@from, @to, { path_limiter: @path })
|
33
28
|
end
|
29
|
+
alias_method :to_s, :patch
|
34
30
|
|
35
|
-
def
|
36
|
-
|
37
|
-
@
|
31
|
+
def [](key)
|
32
|
+
process_full
|
33
|
+
@full_diff_files.assoc(key)[1]
|
38
34
|
end
|
39
35
|
|
40
|
-
def
|
41
|
-
|
42
|
-
@
|
36
|
+
def each(&block)
|
37
|
+
process_full
|
38
|
+
@full_diff_files.map { |file| file[1] }.each(&block)
|
43
39
|
end
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
#
|
42
|
+
# DEPRECATED METHODS
|
43
|
+
#
|
44
|
+
|
45
|
+
def name_status
|
46
|
+
Git::Deprecation.warn("Git::Diff#name_status is deprecated. Use Git::Base#diff_path_status instead.")
|
47
|
+
path_status_provider.to_h
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
50
|
+
def size
|
51
|
+
Git::Deprecation.warn("Git::Diff#size is deprecated. Use Git::Base#diff_stats(...).total[:files] instead.")
|
52
|
+
stats_provider.total[:files]
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
|
56
|
+
|
57
|
+
def lines
|
58
|
+
Git::Deprecation.warn("Git::Diff#lines is deprecated. Use Git::Base#diff_stats(...).lines instead.")
|
59
|
+
stats_provider.lines
|
59
60
|
end
|
60
|
-
alias_method :to_s, :patch
|
61
61
|
|
62
|
-
|
62
|
+
def deletions
|
63
|
+
Git::Deprecation.warn("Git::Diff#deletions is deprecated. Use Git::Base#diff_stats(...).deletions instead.")
|
64
|
+
stats_provider.deletions
|
65
|
+
end
|
63
66
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
+
def insertions
|
68
|
+
Git::Deprecation.warn("Git::Diff#insertions is deprecated. Use Git::Base#diff_stats(...).insertions instead.")
|
69
|
+
stats_provider.insertions
|
67
70
|
end
|
68
71
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
+
def stats
|
73
|
+
Git::Deprecation.warn("Git::Diff#stats is deprecated. Use Git::Base#diff_stats instead.")
|
74
|
+
# CORRECTED: Re-create the original hash structure for backward compatibility
|
75
|
+
{
|
76
|
+
files: stats_provider.files,
|
77
|
+
total: stats_provider.total
|
78
|
+
}
|
72
79
|
end
|
73
80
|
|
74
81
|
class DiffFile
|
@@ -102,56 +109,48 @@ module Git
|
|
102
109
|
|
103
110
|
private
|
104
111
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def process_full
|
110
|
-
return if @full_diff_files
|
111
|
-
cache_full
|
112
|
-
@full_diff_files = process_full_diff
|
113
|
-
end
|
112
|
+
def process_full
|
113
|
+
return if @full_diff_files
|
114
|
+
@full_diff_files = process_full_diff
|
115
|
+
end
|
114
116
|
|
115
|
-
|
116
|
-
|
117
|
-
|
117
|
+
# CORRECTED: Pass the @path variable to the new objects
|
118
|
+
def path_status_provider
|
119
|
+
@path_status_provider ||= Git::DiffPathStatus.new(@base, @from, @to, @path)
|
120
|
+
end
|
118
121
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
+
# CORRECTED: Pass the @path variable to the new objects
|
123
|
+
def stats_provider
|
124
|
+
@stats_provider ||= Git::DiffStats.new(@base, @from, @to, @path)
|
125
|
+
end
|
122
126
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
}
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
if m =
|
135
|
-
current_file =
|
136
|
-
final[current_file] =
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
final[current_file][:mode] = m[2]
|
146
|
-
end
|
147
|
-
if m = /^Binary files /.match(line)
|
148
|
-
final[current_file][:binary] = true
|
149
|
-
end
|
150
|
-
final[current_file][:patch] << "\n" + line
|
127
|
+
def process_full_diff
|
128
|
+
defaults = {
|
129
|
+
mode: '', src: '', dst: '', type: 'modified'
|
130
|
+
}
|
131
|
+
final = {}
|
132
|
+
current_file = nil
|
133
|
+
patch.split("\n").each do |line|
|
134
|
+
if m = %r{\Adiff --git ("?)a/(.+?)\1 ("?)b/(.+?)\3\z}.match(line)
|
135
|
+
current_file = Git::EscapedPath.new(m[2]).unescape
|
136
|
+
final[current_file] = defaults.merge({ patch: line, path: current_file })
|
137
|
+
else
|
138
|
+
if m = /^index ([0-9a-f]{4,40})\.\.([0-9a-f]{4,40})( ......)*/.match(line)
|
139
|
+
final[current_file][:src] = m[1]
|
140
|
+
final[current_file][:dst] = m[2]
|
141
|
+
final[current_file][:mode] = m[3].strip if m[3]
|
142
|
+
end
|
143
|
+
if m = /^([[:alpha:]]*?) file mode (......)/.match(line)
|
144
|
+
final[current_file][:type] = m[1]
|
145
|
+
final[current_file][:mode] = m[2]
|
146
|
+
end
|
147
|
+
if m = /^Binary files /.match(line)
|
148
|
+
final[current_file][:binary] = true
|
151
149
|
end
|
150
|
+
final[current_file][:patch] << "\n" + line
|
152
151
|
end
|
153
|
-
final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
|
154
152
|
end
|
155
|
-
|
153
|
+
final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
|
154
|
+
end
|
156
155
|
end
|
157
156
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Git
|
4
|
+
class DiffPathStatus
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# @private
|
8
|
+
def initialize(base, from, to, path_limiter = nil)
|
9
|
+
# Eagerly check for invalid arguments
|
10
|
+
[from, to].compact.each do |arg|
|
11
|
+
raise ArgumentError, "Invalid argument: '#{arg}'" if arg.start_with?('-')
|
12
|
+
end
|
13
|
+
|
14
|
+
@base = base
|
15
|
+
@from = from
|
16
|
+
@to = to
|
17
|
+
@path_limiter = path_limiter
|
18
|
+
@path_status = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Iterates over each file's status.
|
22
|
+
#
|
23
|
+
# @yield [path, status]
|
24
|
+
def each(&block)
|
25
|
+
fetch_path_status.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the name-status report as a Hash.
|
29
|
+
#
|
30
|
+
# @return [Hash<String, String>] A hash where keys are file paths
|
31
|
+
# and values are their status codes.
|
32
|
+
def to_h
|
33
|
+
fetch_path_status
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Lazily fetches and caches the path status from the git lib.
|
39
|
+
def fetch_path_status
|
40
|
+
@path_status ||= @base.lib.diff_path_status(
|
41
|
+
@from, @to, { path: @path_limiter }
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Git
|
4
|
+
# Provides access to the statistics of a diff between two commits,
|
5
|
+
# including insertions, deletions, and file-level details.
|
6
|
+
class DiffStats
|
7
|
+
# @private
|
8
|
+
def initialize(base, from, to, path_limiter = nil)
|
9
|
+
# Eagerly check for invalid arguments
|
10
|
+
[from, to].compact.each do |arg|
|
11
|
+
raise ArgumentError, "Invalid argument: '#{arg}'" if arg.start_with?('-')
|
12
|
+
end
|
13
|
+
|
14
|
+
@base = base
|
15
|
+
@from = from
|
16
|
+
@to = to
|
17
|
+
@path_limiter = path_limiter
|
18
|
+
@stats = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the total number of lines deleted.
|
22
|
+
def deletions
|
23
|
+
fetch_stats[:total][:deletions]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the total number of lines inserted.
|
27
|
+
def insertions
|
28
|
+
fetch_stats[:total][:insertions]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the total number of lines changed (insertions + deletions).
|
32
|
+
def lines
|
33
|
+
fetch_stats[:total][:lines]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a hash of statistics for each file in the diff.
|
37
|
+
#
|
38
|
+
# @return [Hash<String, {insertions: Integer, deletions: Integer}>]
|
39
|
+
def files
|
40
|
+
fetch_stats[:files]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns a hash of the total statistics for the diff.
|
44
|
+
#
|
45
|
+
# @return [{insertions: Integer, deletions: Integer, lines: Integer, files: Integer}]
|
46
|
+
def total
|
47
|
+
fetch_stats[:total]
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Lazily fetches and caches the stats from the git lib.
|
53
|
+
def fetch_stats
|
54
|
+
@stats ||= @base.lib.diff_stats(
|
55
|
+
@from, @to, { path_limiter: @path_limiter }
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/git/lib.rb
CHANGED
@@ -217,7 +217,7 @@ module Git
|
|
217
217
|
|
218
218
|
arr_opts << commit_ish if commit_ish
|
219
219
|
|
220
|
-
|
220
|
+
command('describe', *arr_opts)
|
221
221
|
end
|
222
222
|
|
223
223
|
# Return the commits that are within the given revision range
|
@@ -472,7 +472,7 @@ module Git
|
|
472
472
|
|
473
473
|
hsh['message'] = data.join("\n") + "\n"
|
474
474
|
|
475
|
-
|
475
|
+
hsh
|
476
476
|
end
|
477
477
|
|
478
478
|
CAT_FILE_HEADER_LINE = /\A(?<key>\w+) (?<value>.*)\z/
|
@@ -543,7 +543,7 @@ module Git
|
|
543
543
|
|
544
544
|
hsh['message'] = data.join("\n") + "\n"
|
545
545
|
|
546
|
-
|
546
|
+
hsh
|
547
547
|
end
|
548
548
|
|
549
549
|
def process_commit_log_data(data)
|
@@ -584,7 +584,7 @@ module Git
|
|
584
584
|
|
585
585
|
hsh_array << hsh if hsh
|
586
586
|
|
587
|
-
|
587
|
+
hsh_array
|
588
588
|
end
|
589
589
|
|
590
590
|
def ls_tree(sha, opts = {})
|
@@ -758,7 +758,7 @@ module Git
|
|
758
758
|
:unborn
|
759
759
|
end
|
760
760
|
|
761
|
-
|
761
|
+
HeadState.new(state, branch_name)
|
762
762
|
end
|
763
763
|
|
764
764
|
def branch_current
|
@@ -848,7 +848,7 @@ module Git
|
|
848
848
|
hsh
|
849
849
|
end
|
850
850
|
|
851
|
-
def
|
851
|
+
def diff_path_status(reference1 = nil, reference2 = nil, opts = {})
|
852
852
|
assert_args_are_not_options('commit or commit range', reference1, reference2)
|
853
853
|
|
854
854
|
opts_arr = ['--name-status']
|
@@ -1488,7 +1488,7 @@ module Git
|
|
1488
1488
|
gz.write(file_content)
|
1489
1489
|
end
|
1490
1490
|
end
|
1491
|
-
|
1491
|
+
file
|
1492
1492
|
end
|
1493
1493
|
|
1494
1494
|
# returns the current version of git, as an Array of Fixnums.
|
data/lib/git/log.rb
CHANGED
@@ -6,13 +6,13 @@ module Git
|
|
6
6
|
#
|
7
7
|
# @example The last (default number) of commits
|
8
8
|
# git = Git.open('.')
|
9
|
-
# Git::Log.new(git) #=> Enumerable of the last 30 commits
|
9
|
+
# Git::Log.new(git).execute #=> Enumerable of the last 30 commits
|
10
10
|
#
|
11
11
|
# @example The last n commits
|
12
|
-
# Git::Log.new(git).max_commits(50) #=> Enumerable of last 50 commits
|
12
|
+
# Git::Log.new(git).max_commits(50).execute #=> Enumerable of last 50 commits
|
13
13
|
#
|
14
14
|
# @example All commits returned by `git log`
|
15
|
-
# Git::Log.new(git).max_count(:all) #=> Enumerable of all commits
|
15
|
+
# Git::Log.new(git).max_count(:all).execute #=> Enumerable of all commits
|
16
16
|
#
|
17
17
|
# @example All commits that match complex criteria
|
18
18
|
# Git::Log.new(git)
|
@@ -20,12 +20,62 @@ module Git
|
|
20
20
|
# .object('README.md')
|
21
21
|
# .since('10 years ago')
|
22
22
|
# .between('v1.0.7', 'HEAD')
|
23
|
+
# .execute
|
23
24
|
#
|
24
25
|
# @api public
|
25
26
|
#
|
26
27
|
class Log
|
27
28
|
include Enumerable
|
28
29
|
|
30
|
+
# An immutable collection of commits returned by Git::Log#execute
|
31
|
+
#
|
32
|
+
# This object is an Enumerable that contains Git::Object::Commit objects.
|
33
|
+
# It provides methods to access the commit data without executing any
|
34
|
+
# further git commands.
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
class Result
|
38
|
+
include Enumerable
|
39
|
+
|
40
|
+
# @private
|
41
|
+
def initialize(commits)
|
42
|
+
@commits = commits
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Integer] the number of commits in the result set
|
46
|
+
def size
|
47
|
+
@commits.size
|
48
|
+
end
|
49
|
+
|
50
|
+
# Iterates over each commit in the result set
|
51
|
+
#
|
52
|
+
# @yield [Git::Object::Commit]
|
53
|
+
def each(&block)
|
54
|
+
@commits.each(&block)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Git::Object::Commit, nil] the first commit in the result set
|
58
|
+
def first
|
59
|
+
@commits.first
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Git::Object::Commit, nil] the last commit in the result set
|
63
|
+
def last
|
64
|
+
@commits.last
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param index [Integer] the index of the commit to return
|
68
|
+
# @return [Git::Object::Commit, nil] the commit at the given index
|
69
|
+
def [](index)
|
70
|
+
@commits[index]
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [String] a string representation of the log
|
74
|
+
def to_s
|
75
|
+
map { |c| c.to_s }.join("\n")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
29
79
|
# Create a new Git::Log object
|
30
80
|
#
|
31
81
|
# @example
|
@@ -44,6 +94,25 @@ module Git
|
|
44
94
|
max_count(max_count)
|
45
95
|
end
|
46
96
|
|
97
|
+
# Executes the git log command and returns an immutable result object.
|
98
|
+
#
|
99
|
+
# This is the preferred way to get log data. It separates the query
|
100
|
+
# building from the execution, making the API more predictable.
|
101
|
+
#
|
102
|
+
# @example
|
103
|
+
# query = g.log.since('2 weeks ago').author('Scott')
|
104
|
+
# results = query.execute
|
105
|
+
# puts "Found #{results.size} commits"
|
106
|
+
# results.each do |commit|
|
107
|
+
# # ...
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# @return [Git::Log::Result] an object containing the log results
|
111
|
+
def execute
|
112
|
+
run_log
|
113
|
+
Result.new(@commits)
|
114
|
+
end
|
115
|
+
|
47
116
|
# The maximum number of commits to return
|
48
117
|
#
|
49
118
|
# @example All commits returned by `git log`
|
@@ -82,90 +151,97 @@ module Git
|
|
82
151
|
def object(objectish)
|
83
152
|
dirty_log
|
84
153
|
@object = objectish
|
85
|
-
|
154
|
+
self
|
86
155
|
end
|
87
156
|
|
88
157
|
def author(regex)
|
89
158
|
dirty_log
|
90
159
|
@author = regex
|
91
|
-
|
160
|
+
self
|
92
161
|
end
|
93
162
|
|
94
163
|
def grep(regex)
|
95
164
|
dirty_log
|
96
165
|
@grep = regex
|
97
|
-
|
166
|
+
self
|
98
167
|
end
|
99
168
|
|
100
169
|
def path(path)
|
101
170
|
dirty_log
|
102
171
|
@path = path
|
103
|
-
|
172
|
+
self
|
104
173
|
end
|
105
174
|
|
106
175
|
def skip(num)
|
107
176
|
dirty_log
|
108
177
|
@skip = num
|
109
|
-
|
178
|
+
self
|
110
179
|
end
|
111
180
|
|
112
181
|
def since(date)
|
113
182
|
dirty_log
|
114
183
|
@since = date
|
115
|
-
|
184
|
+
self
|
116
185
|
end
|
117
186
|
|
118
187
|
def until(date)
|
119
188
|
dirty_log
|
120
189
|
@until = date
|
121
|
-
|
190
|
+
self
|
122
191
|
end
|
123
192
|
|
124
193
|
def between(sha1, sha2 = nil)
|
125
194
|
dirty_log
|
126
195
|
@between = [sha1, sha2]
|
127
|
-
|
196
|
+
self
|
128
197
|
end
|
129
198
|
|
130
199
|
def cherry
|
131
200
|
dirty_log
|
132
201
|
@cherry = true
|
133
|
-
|
202
|
+
self
|
134
203
|
end
|
135
204
|
|
136
205
|
def merges
|
137
206
|
dirty_log
|
138
207
|
@merges = true
|
139
|
-
|
208
|
+
self
|
140
209
|
end
|
141
210
|
|
142
211
|
def to_s
|
143
|
-
|
212
|
+
deprecate_method(__method__)
|
213
|
+
check_log
|
214
|
+
@commits.map { |c| c.to_s }.join("\n")
|
144
215
|
end
|
145
216
|
|
146
217
|
# forces git log to run
|
147
218
|
|
148
219
|
def size
|
220
|
+
deprecate_method(__method__)
|
149
221
|
check_log
|
150
222
|
@commits.size rescue nil
|
151
223
|
end
|
152
224
|
|
153
225
|
def each(&block)
|
226
|
+
deprecate_method(__method__)
|
154
227
|
check_log
|
155
228
|
@commits.each(&block)
|
156
229
|
end
|
157
230
|
|
158
231
|
def first
|
232
|
+
deprecate_method(__method__)
|
159
233
|
check_log
|
160
234
|
@commits.first rescue nil
|
161
235
|
end
|
162
236
|
|
163
237
|
def last
|
238
|
+
deprecate_method(__method__)
|
164
239
|
check_log
|
165
240
|
@commits.last rescue nil
|
166
241
|
end
|
167
242
|
|
168
243
|
def [](index)
|
244
|
+
deprecate_method(__method__)
|
169
245
|
check_log
|
170
246
|
@commits[index] rescue nil
|
171
247
|
end
|
@@ -173,6 +249,10 @@ module Git
|
|
173
249
|
|
174
250
|
private
|
175
251
|
|
252
|
+
def deprecate_method(method_name)
|
253
|
+
Git::Deprecation.warn("Calling Git::Log##{method_name} is deprecated and will be removed in a future version. Call #execute and then ##{method_name} on the result object.")
|
254
|
+
end
|
255
|
+
|
176
256
|
def dirty_log
|
177
257
|
@dirty_flag = true
|
178
258
|
end
|
data/lib/git/version.rb
CHANGED
data/lib/git.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Chacon and others
|
@@ -43,14 +43,14 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '4.0'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '4.0'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: rchardet
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -222,6 +222,8 @@ files:
|
|
222
222
|
- lib/git/command_line_result.rb
|
223
223
|
- lib/git/config.rb
|
224
224
|
- lib/git/diff.rb
|
225
|
+
- lib/git/diff_path_status.rb
|
226
|
+
- lib/git/diff_stats.rb
|
225
227
|
- lib/git/encoding_utils.rb
|
226
228
|
- lib/git/errors.rb
|
227
229
|
- lib/git/escaped_path.rb
|
@@ -248,8 +250,8 @@ licenses:
|
|
248
250
|
metadata:
|
249
251
|
homepage_uri: http://github.com/ruby-git/ruby-git
|
250
252
|
source_code_uri: http://github.com/ruby-git/ruby-git
|
251
|
-
changelog_uri: https://rubydoc.info/gems/git/
|
252
|
-
documentation_uri: https://rubydoc.info/gems/git/
|
253
|
+
changelog_uri: https://rubydoc.info/gems/git/4.0.0/file/CHANGELOG.md
|
254
|
+
documentation_uri: https://rubydoc.info/gems/git/4.0.0
|
253
255
|
rdoc_options: []
|
254
256
|
require_paths:
|
255
257
|
- lib
|
@@ -257,7 +259,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
257
259
|
requirements:
|
258
260
|
- - ">="
|
259
261
|
- !ruby/object:Gem::Version
|
260
|
-
version: 3.
|
262
|
+
version: 3.2.0
|
261
263
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
262
264
|
requirements:
|
263
265
|
- - ">="
|