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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.commitlintrc.yml +38 -0
  3. data/.github/pull_request_template.md +8 -0
  4. data/.github/workflows/continuous_integration.yml +19 -21
  5. data/.github/workflows/enforce_conventional_commits.yml +28 -0
  6. data/.github/workflows/experimental_continuous_integration.yml +50 -0
  7. data/.github/workflows/release.yml +52 -0
  8. data/.gitignore +3 -0
  9. data/.husky/commit-msg +1 -0
  10. data/.release-please-manifest.json +3 -0
  11. data/.yardopts +0 -1
  12. data/CHANGELOG.md +211 -0
  13. data/CONTRIBUTING.md +290 -102
  14. data/README.md +180 -62
  15. data/Rakefile +7 -0
  16. data/git.gemspec +11 -11
  17. data/lib/git/author.rb +3 -2
  18. data/lib/git/base.rb +222 -59
  19. data/lib/git/branch.rb +2 -0
  20. data/lib/git/branches.rb +15 -14
  21. data/lib/git/command_line.rb +287 -0
  22. data/lib/git/config.rb +7 -1
  23. data/lib/git/diff.rb +2 -0
  24. data/lib/git/errors.rb +206 -0
  25. data/lib/git/escaped_path.rb +1 -1
  26. data/lib/git/index.rb +2 -1
  27. data/lib/git/lib.rb +604 -234
  28. data/lib/git/log.rb +74 -6
  29. data/lib/git/object.rb +80 -76
  30. data/lib/git/path.rb +9 -8
  31. data/lib/git/remote.rb +2 -0
  32. data/lib/git/repository.rb +2 -0
  33. data/lib/git/stash.rb +7 -6
  34. data/lib/git/stashes.rb +11 -10
  35. data/lib/git/status.rb +135 -25
  36. data/lib/git/version.rb +3 -1
  37. data/lib/git/working_directory.rb +2 -0
  38. data/lib/git/worktree.rb +2 -0
  39. data/lib/git/worktrees.rb +2 -0
  40. data/lib/git.rb +21 -7
  41. data/package.json +10 -0
  42. data/release-please-config.json +36 -0
  43. metadata +52 -38
  44. data/.github/stale.yml +0 -25
  45. data/Dockerfile.changelog-rs +0 -12
  46. data/PULL_REQUEST_TEMPLATE.md +0 -9
  47. data/RELEASING.md +0 -70
  48. data/lib/git/base/factory.rb +0 -99
  49. data/lib/git/failed_error.rb +0 -53
  50. data/lib/git/git_execute_error.rb +0 -7
  51. data/lib/git/signaled_error.rb +0 -50
  52. /data/{ISSUE_TEMPLATE.md → .github/issue_template.md} +0 -0
data/lib/git/log.rb CHANGED
@@ -1,15 +1,78 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
4
 
3
- # object that holds the last X commits on given branch
5
+ # Return the last n commits that match the specified criteria
6
+ #
7
+ # @example The last (default number) of commits
8
+ # git = Git.open('.')
9
+ # Git::Log.new(git) #=> Enumerable of the last 30 commits
10
+ #
11
+ # @example The last n commits
12
+ # Git::Log.new(git).max_commits(50) #=> Enumerable of last 50 commits
13
+ #
14
+ # @example All commits returned by `git log`
15
+ # Git::Log.new(git).max_count(:all) #=> Enumerable of all commits
16
+ #
17
+ # @example All commits that match complex criteria
18
+ # Git::Log.new(git)
19
+ # .max_count(:all)
20
+ # .object('README.md')
21
+ # .since('10 years ago')
22
+ # .between('v1.0.7', 'HEAD')
23
+ #
24
+ # @api public
25
+ #
4
26
  class Log
5
27
  include Enumerable
6
28
 
7
- def initialize(base, count = 30)
29
+ # Create a new Git::Log object
30
+ #
31
+ # @example
32
+ # git = Git.open('.')
33
+ # Git::Log.new(git)
34
+ #
35
+ # @param base [Git::Base] the git repository object
36
+ # @param max_count [Integer, Symbol, nil] the number of commits to return, or
37
+ # `:all` or `nil` to return all
38
+ #
39
+ # Passing max_count to {#initialize} is equivalent to calling {#max_count} on the object.
40
+ #
41
+ def initialize(base, max_count = 30)
8
42
  dirty_log
9
43
  @base = base
10
- @count = count
44
+ max_count(max_count)
45
+ end
46
+
47
+ # The maximum number of commits to return
48
+ #
49
+ # @example All commits returned by `git log`
50
+ # git = Git.open('.')
51
+ # Git::Log.new(git).max_count(:all)
52
+ #
53
+ # @param num_or_all [Integer, Symbol, nil] the number of commits to return, or
54
+ # `:all` or `nil` to return all
55
+ #
56
+ # @return [self]
57
+ #
58
+ def max_count(num_or_all)
59
+ dirty_log
60
+ @max_count = (num_or_all == :all) ? nil : num_or_all
61
+ self
11
62
  end
12
63
 
64
+ # Adds the --all flag to the git log command
65
+ #
66
+ # This asks for the logs of all refs (basically all commits reachable by HEAD,
67
+ # branches, and tags). This does not control the maximum number of commits
68
+ # returned. To control how many commits are returned, call {#max_count}.
69
+ #
70
+ # @example Return the last 50 commits reachable by all refs
71
+ # git = Git.open('.')
72
+ # Git::Log.new(git).max_count(50).all
73
+ #
74
+ # @return [self]
75
+ #
13
76
  def all
14
77
  dirty_log
15
78
  @all = true
@@ -70,11 +133,16 @@ module Git
70
133
  return self
71
134
  end
72
135
 
136
+ def merges
137
+ dirty_log
138
+ @merges = true
139
+ return self
140
+ end
141
+
73
142
  def to_s
74
143
  self.map { |c| c.to_s }.join("\n")
75
144
  end
76
145
 
77
-
78
146
  # forces git log to run
79
147
 
80
148
  def size
@@ -119,9 +187,9 @@ module Git
119
187
  # actually run the 'git log' command
120
188
  def run_log
121
189
  log = @base.lib.full_log_commits(
122
- count: @count, all: @all, object: @object, path_limiter: @path, since: @since,
190
+ count: @max_count, all: @all, object: @object, path_limiter: @path, since: @since,
123
191
  author: @author, grep: @grep, skip: @skip, until: @until, between: @between,
124
- cherry: @cherry
192
+ cherry: @cherry, merges: @merges
125
193
  )
126
194
  @commits = log.map { |c| Git::Object::Commit.new(@base, c['sha'], c) }
127
195
  end
data/lib/git/object.rb CHANGED
@@ -1,16 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/author'
4
+ require 'git/diff'
5
+ require 'git/errors'
6
+ require 'git/log'
7
+
1
8
  module Git
2
-
3
- class GitTagNameDoesNotExist< StandardError
4
- end
5
-
9
+
6
10
  # represents a git object
7
11
  class Object
8
-
12
+
9
13
  class AbstractObject
10
14
  attr_accessor :objectish, :type, :mode
11
15
 
12
16
  attr_writer :size
13
-
17
+
14
18
  def initialize(base, objectish)
15
19
  @base = base
16
20
  @objectish = objectish.to_s
@@ -21,13 +25,13 @@ module Git
21
25
  end
22
26
 
23
27
  def sha
24
- @sha ||= @base.lib.revparse(@objectish)
28
+ @sha ||= @base.lib.rev_parse(@objectish)
25
29
  end
26
-
30
+
27
31
  def size
28
- @size ||= @base.lib.object_size(@objectish)
32
+ @size ||= @base.lib.cat_file_size(@objectish)
29
33
  end
30
-
34
+
31
35
  # Get the object's contents.
32
36
  # If no block is given, the contents are cached in memory and returned as a string.
33
37
  # If a block is given, it yields an IO object (via IO::popen) which could be used to
@@ -36,113 +40,113 @@ module Git
36
40
  # Use this for large files so that they are not held in memory.
37
41
  def contents(&block)
38
42
  if block_given?
39
- @base.lib.object_contents(@objectish, &block)
43
+ @base.lib.cat_file_contents(@objectish, &block)
40
44
  else
41
- @contents ||= @base.lib.object_contents(@objectish)
45
+ @contents ||= @base.lib.cat_file_contents(@objectish)
42
46
  end
43
47
  end
44
-
48
+
45
49
  def contents_array
46
50
  self.contents.split("\n")
47
51
  end
48
-
52
+
49
53
  def to_s
50
54
  @objectish
51
55
  end
52
-
56
+
53
57
  def grep(string, path_limiter = nil, opts = {})
54
58
  opts = {:object => sha, :path_limiter => path_limiter}.merge(opts)
55
59
  @base.lib.grep(string, opts)
56
60
  end
57
-
61
+
58
62
  def diff(objectish)
59
63
  Git::Diff.new(@base, @objectish, objectish)
60
64
  end
61
-
65
+
62
66
  def log(count = 30)
63
67
  Git::Log.new(@base, count).object(@objectish)
64
68
  end
65
-
69
+
66
70
  # creates an archive of this object (tree)
67
71
  def archive(file = nil, opts = {})
68
72
  @base.lib.archive(@objectish, file, opts)
69
73
  end
70
-
74
+
71
75
  def tree?; false; end
72
-
76
+
73
77
  def blob?; false; end
74
-
78
+
75
79
  def commit?; false; end
76
80
 
77
81
  def tag?; false; end
78
-
82
+
79
83
  end
80
-
81
-
84
+
85
+
82
86
  class Blob < AbstractObject
83
-
87
+
84
88
  def initialize(base, sha, mode = nil)
85
89
  super(base, sha)
86
90
  @mode = mode
87
91
  end
88
-
92
+
89
93
  def blob?
90
94
  true
91
95
  end
92
96
 
93
97
  end
94
-
98
+
95
99
  class Tree < AbstractObject
96
-
100
+
97
101
  def initialize(base, sha, mode = nil)
98
102
  super(base, sha)
99
103
  @mode = mode
100
104
  @trees = nil
101
105
  @blobs = nil
102
106
  end
103
-
107
+
104
108
  def children
105
109
  blobs.merge(subtrees)
106
110
  end
107
-
111
+
108
112
  def blobs
109
113
  @blobs ||= check_tree[:blobs]
110
114
  end
111
115
  alias_method :files, :blobs
112
-
116
+
113
117
  def trees
114
118
  @trees ||= check_tree[:trees]
115
119
  end
116
120
  alias_method :subtrees, :trees
117
121
  alias_method :subdirectories, :trees
118
-
122
+
119
123
  def full_tree
120
124
  @base.lib.full_tree(@objectish)
121
125
  end
122
-
126
+
123
127
  def depth
124
128
  @base.lib.tree_depth(@objectish)
125
129
  end
126
-
130
+
127
131
  def tree?
128
132
  true
129
133
  end
130
-
134
+
131
135
  private
132
136
 
133
137
  # actually run the git command
134
138
  def check_tree
135
139
  @trees = {}
136
140
  @blobs = {}
137
-
141
+
138
142
  data = @base.lib.ls_tree(@objectish)
139
143
 
140
- data['tree'].each do |key, tree|
141
- @trees[key] = Git::Object::Tree.new(@base, tree[:sha], tree[:mode])
144
+ data['tree'].each do |key, tree|
145
+ @trees[key] = Git::Object::Tree.new(@base, tree[:sha], tree[:mode])
142
146
  end
143
-
144
- data['blob'].each do |key, blob|
145
- @blobs[key] = Git::Object::Blob.new(@base, blob[:sha], blob[:mode])
147
+
148
+ data['blob'].each do |key, blob|
149
+ @blobs[key] = Git::Object::Blob.new(@base, blob[:sha], blob[:mode])
146
150
  end
147
151
 
148
152
  {
@@ -150,11 +154,11 @@ module Git
150
154
  :blobs => @blobs
151
155
  }
152
156
  end
153
-
157
+
154
158
  end
155
-
159
+
156
160
  class Commit < AbstractObject
157
-
161
+
158
162
  def initialize(base, sha, init = nil)
159
163
  super(base, sha)
160
164
  @tree = nil
@@ -166,48 +170,48 @@ module Git
166
170
  set_commit(init)
167
171
  end
168
172
  end
169
-
173
+
170
174
  def message
171
175
  check_commit
172
176
  @message
173
177
  end
174
-
178
+
175
179
  def name
176
- @base.lib.namerev(sha)
180
+ @base.lib.name_rev(sha)
177
181
  end
178
-
182
+
179
183
  def gtree
180
184
  check_commit
181
185
  Tree.new(@base, @tree)
182
186
  end
183
-
187
+
184
188
  def parent
185
189
  parents.first
186
190
  end
187
-
191
+
188
192
  # array of all parent commits
189
193
  def parents
190
194
  check_commit
191
- @parents
195
+ @parents
192
196
  end
193
-
197
+
194
198
  # git author
195
- def author
199
+ def author
196
200
  check_commit
197
201
  @author
198
202
  end
199
-
203
+
200
204
  def author_date
201
205
  author.date
202
206
  end
203
-
207
+
204
208
  # git author
205
209
  def committer
206
210
  check_commit
207
211
  @committer
208
212
  end
209
-
210
- def committer_date
213
+
214
+ def committer_date
211
215
  committer.date
212
216
  end
213
217
  alias_method :date, :committer_date
@@ -215,7 +219,7 @@ module Git
215
219
  def diff_parent
216
220
  diff(parent)
217
221
  end
218
-
222
+
219
223
  def set_commit(data)
220
224
  @sha ||= data['sha']
221
225
  @committer = Git::Author.new(data['committer'])
@@ -224,26 +228,26 @@ module Git
224
228
  @parents = data['parent'].map{ |sha| Git::Object::Commit.new(@base, sha) }
225
229
  @message = data['message'].chomp
226
230
  end
227
-
231
+
228
232
  def commit?
229
233
  true
230
234
  end
231
235
 
232
236
  private
233
-
237
+
234
238
  # see if this object has been initialized and do so if not
235
239
  def check_commit
236
240
  return if @tree
237
-
238
- data = @base.lib.commit_data(@objectish)
241
+
242
+ data = @base.lib.cat_file_commit(@objectish)
239
243
  set_commit(data)
240
244
  end
241
-
245
+
242
246
  end
243
-
247
+
244
248
  class Tag < AbstractObject
245
249
  attr_accessor :name
246
-
250
+
247
251
  def initialize(base, sha, name)
248
252
  super(base, sha)
249
253
  @name = name
@@ -252,14 +256,14 @@ module Git
252
256
  end
253
257
 
254
258
  def annotated?
255
- @annotated ||= (@base.lib.object_type(self.name) == 'tag')
259
+ @annotated ||= (@base.lib.cat_file_type(self.name) == 'tag')
256
260
  end
257
261
 
258
262
  def message
259
263
  check_tag()
260
264
  return @message
261
265
  end
262
-
266
+
263
267
  def tag?
264
268
  true
265
269
  end
@@ -274,39 +278,39 @@ module Git
274
278
  def check_tag
275
279
  return if @loaded
276
280
 
277
- if !self.annotated?
281
+ if !self.annotated?
278
282
  @message = @tagger = nil
279
283
  else
280
- tdata = @base.lib.tag_data(@name)
284
+ tdata = @base.lib.cat_file_tag(@name)
281
285
  @message = tdata['message'].chomp
282
286
  @tagger = Git::Author.new(tdata['tagger'])
283
287
  end
284
288
 
285
289
  @loaded = true
286
290
  end
287
-
291
+
288
292
  end
289
-
293
+
290
294
  # if we're calling this, we don't know what type it is yet
291
295
  # so this is our little factory method
292
296
  def self.new(base, objectish, type = nil, is_tag = false)
293
297
  if is_tag
294
298
  sha = base.lib.tag_sha(objectish)
295
299
  if sha == ''
296
- raise Git::GitTagNameDoesNotExist.new(objectish)
300
+ raise Git::UnexpectedResultError.new("Tag '#{objectish}' does not exist.")
297
301
  end
298
302
  return Git::Object::Tag.new(base, sha, objectish)
299
303
  end
300
-
301
- type ||= base.lib.object_type(objectish)
304
+
305
+ type ||= base.lib.cat_file_type(objectish)
302
306
  klass =
303
307
  case type
304
- when /blob/ then Blob
308
+ when /blob/ then Blob
305
309
  when /commit/ then Commit
306
310
  when /tree/ then Tree
307
311
  end
308
312
  klass.new(base, objectish)
309
313
  end
310
-
314
+
311
315
  end
312
316
  end
data/lib/git/path.rb CHANGED
@@ -1,19 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
-
4
+
3
5
  class Path
4
-
6
+
5
7
  attr_accessor :path
6
-
8
+
7
9
  def initialize(path, check_path=true)
8
10
  path = File.expand_path(path)
9
-
11
+
10
12
  if check_path && !File.exist?(path)
11
13
  raise ArgumentError, 'path does not exist', [path]
12
14
  end
13
-
15
+
14
16
  @path = path
15
17
  end
16
-
18
+
17
19
  def readable?
18
20
  File.readable?(@path)
19
21
  end
@@ -21,11 +23,10 @@ module Git
21
23
  def writable?
22
24
  File.writable?(@path)
23
25
  end
24
-
26
+
25
27
  def to_s
26
28
  @path
27
29
  end
28
-
29
30
  end
30
31
 
31
32
  end
data/lib/git/remote.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
4
  class Remote < Path
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
4
 
3
5
  class Repository < Path
data/lib/git/stash.rb CHANGED
@@ -1,27 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
4
  class Stash
3
-
5
+
4
6
  def initialize(base, message, existing=false)
5
7
  @base = base
6
8
  @message = message
7
9
  save unless existing
8
10
  end
9
-
11
+
10
12
  def save
11
13
  @saved = @base.lib.stash_save(@message)
12
14
  end
13
-
15
+
14
16
  def saved?
15
17
  @saved
16
18
  end
17
-
19
+
18
20
  def message
19
21
  @message
20
22
  end
21
-
23
+
22
24
  def to_s
23
25
  message
24
26
  end
25
-
26
27
  end
27
28
  end
data/lib/git/stashes.rb CHANGED
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
2
-
4
+
3
5
  # object that holds all the available stashes
4
6
  class Stashes
5
7
  include Enumerable
6
-
8
+
7
9
  def initialize(base)
8
10
  @stashes = []
9
-
11
+
10
12
  @base = base
11
-
13
+
12
14
  @base.lib.stashes_all.each do |id, message|
13
15
  @stashes.unshift(Git::Stash.new(@base, message, true))
14
16
  end
@@ -24,16 +26,16 @@ module Git
24
26
  def all
25
27
  @base.lib.stashes_all
26
28
  end
27
-
29
+
28
30
  def save(message)
29
31
  s = Git::Stash.new(@base, message)
30
32
  @stashes.unshift(s) if s.saved?
31
33
  end
32
-
34
+
33
35
  def apply(index=nil)
34
36
  @base.lib.stash_apply(index)
35
37
  end
36
-
38
+
37
39
  def clear
38
40
  @base.lib.stash_clear
39
41
  @stashes = []
@@ -42,14 +44,13 @@ module Git
42
44
  def size
43
45
  @stashes.size
44
46
  end
45
-
47
+
46
48
  def each(&block)
47
49
  @stashes.each(&block)
48
50
  end
49
-
51
+
50
52
  def [](index)
51
53
  @stashes[index.to_i]
52
54
  end
53
-
54
55
  end
55
56
  end