git.rb 0.10.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 52833f20baf0598073541425701ec14677832f98aa5a5f10d6b6fabb647c6b5e
4
+ data.tar.gz: f579c6fcc86ad91fdb91983ab08c0acb2bdfe33f7c160693406daeccfc6a9b62
5
+ SHA512:
6
+ metadata.gz: 8eec775af216cf3e2a1c3d87eb23763d74c7e7f2f6f29e764f5e70ba6880533ea7245f5d7722c980c082e24a4463eebf274d617af5ce62779b1ef940cf6d477d
7
+ data.tar.gz: 74ccdf65e4842e68b17f5f9f64cb8c79eda27d5b4b12753ea5cc4965041e72a6e4d608387f02f390b7ffe9a594b46d9753f5c383cdc4093c9afd5985373d96b9
@@ -0,0 +1,7 @@
1
+ # Array/all_but_first.rb
2
+ # Array#all_but_first
3
+
4
+ # 20180804
5
+ # 0.1.0 (The same version number as the current version of Thoran/Array/AllButFirst.)
6
+
7
+ require 'Thoran/Array/AllButFirst/all_but_first'
@@ -0,0 +1,7 @@
1
+ # Array/all_but_last.rb
2
+ # Array#all_but_last
3
+
4
+ # 20180804
5
+ # 0.1.0 (The same version number as the current version of Thoran/Array/AllButLast.)
6
+
7
+ require 'Thoran/Array/AllButLast/all_but_last'
@@ -0,0 +1,13 @@
1
+ # Git.rb
2
+ # Git
3
+
4
+ # 20200127, 0128, 0202, 0207, 0208
5
+ # 0.10.0
6
+
7
+ lib_dir = File.expand_path(File.join(__FILE__, '..'))
8
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
9
+
10
+ require 'Git/Blame'
11
+ require 'Git/Branch'
12
+ require 'Git/Log'
13
+ require 'Git/Remote'
@@ -0,0 +1,125 @@
1
+ # Git/Blame.rb
2
+ # Git::Blame
3
+
4
+ # Examples:
5
+ #
6
+ # require 'Git/Blame'
7
+ #
8
+ # git_blame = Git::Blame.new('file/in/git/repository.rb')
9
+ # => #<Git::Blame @filename='file/in/git/repository.rb'>
10
+ #
11
+ # git_blame.entries
12
+ # => [#<Git::PorcelainEntry @porcelain_output='...', @line_number=1>, ...]
13
+ #
14
+ # line_number = 123
15
+ # git_blame_porcelain_entry = git_blame.find(line_number)
16
+ # => #<Git::PorcelainEntry @porcelain_output='...', @line_number=123>
17
+ #
18
+ # git_blame_porcelain_entry.commit_hash
19
+ # => "c9ab2bce79441f15d0a37e2af68017e7680b7e8d"
20
+ #
21
+ # git_blame_porcelain_entry.author
22
+ # => "thoran"
23
+
24
+ require 'Array/all_but_first'
25
+ require 'Array/all_but_last'
26
+
27
+ module Git
28
+ class Blame
29
+
30
+ class PorcelainEntry
31
+
32
+ class << self
33
+
34
+ def parse(porcelain_output)
35
+ new(porcelain_output).parse
36
+ end
37
+
38
+ end # class << self
39
+
40
+ attr_reader :line_number
41
+
42
+ def initialize(porcelain_output, line_number = nil)
43
+ @porcelain_output = porcelain_output
44
+ @line_number = line_number
45
+ end
46
+
47
+ def parse
48
+ lines_with_keys.each do |line|
49
+ variable_name = line.split.first.tr('-','_')
50
+ value = line.split.all_but_first.join(' ')
51
+ instance_variable_set("@#{variable_name}", value)
52
+ self.class.class_eval("attr_reader :#{variable_name}")
53
+ end
54
+ self
55
+ end
56
+
57
+ def commit_hash
58
+ lines.first.split.first
59
+ end
60
+
61
+ def previous_commit_hash
62
+ @previous.split.first
63
+ end
64
+
65
+ def code
66
+ lines.last
67
+ end
68
+
69
+ private
70
+
71
+ def lines
72
+ @lines ||= @porcelain_output.split("\n")
73
+ end
74
+
75
+ def lines_with_keys
76
+ @lines_with_keys ||= lines.all_but_first.all_but_last
77
+ end
78
+
79
+ end # class PorcelainEntry
80
+
81
+ def initialize(filename, line_number = nil)
82
+ @filename = filename
83
+ @line_number = line_number
84
+ end
85
+
86
+ def command_string
87
+ if @line_number
88
+ "git --no-pager blame -L #{@line_number},#{@line_number} #{@filename} --line-porcelain"
89
+ else
90
+ "git --no-pager blame #{@filename} --line-porcelain"
91
+ end
92
+ end
93
+
94
+ def blame_output
95
+ `#{command_string}`
96
+ end
97
+
98
+ def entries
99
+ line_count = 0
100
+ porcelain_entry_string = ''
101
+ entries = []
102
+ blame_array = blame_output.split("\n")
103
+ line_number = 0
104
+ i = -1
105
+ until i >= blame_array.size - 1
106
+ until blame_array[i].split.first == 'filename'
107
+ porcelain_entry_string << blame_array[i += 1]
108
+ porcelain_entry_string << "\n"
109
+ end
110
+ porcelain_entry_string << blame_array[i += 1]
111
+ porcelain_entry_string << "\n"
112
+ entries << PorcelainEntry.new(porcelain_entry_string, line_number += 1).parse
113
+ line_count = 0
114
+ porcelain_entry_string = ''
115
+ end
116
+ entries
117
+ end
118
+
119
+ def find(line_number)
120
+ @line_number = line_number
121
+ entries.detect{|entry| entry.line_number == @line_number}
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,130 @@
1
+ # Git/Branch.rb
2
+ # Git::Branch
3
+
4
+ # Examples:
5
+ #
6
+ # require 'Git/Branch'
7
+ #
8
+ # Git::Branch.local
9
+ # => Git::Branch
10
+ #
11
+ # Git::Branch.local.all, Git::Branch.all
12
+ # => [#<Git::Branch @name="master">, ...]
13
+ #
14
+ # Git::Branch.remote.all
15
+ # => [#<Git::Branch @name="master">, ...]
16
+ #
17
+ # Git::Branch.merged.all
18
+ # => [#<Git::Branch @name="master">, ...]
19
+ #
20
+ # Git::Branch.remote.merged.all
21
+ # => [#<Git::Branch @name="master">, ...]
22
+ #
23
+ # Git::Branch.current
24
+ # => #<Git::Branch @name="master">
25
+ #
26
+ # Git::Branch.current.master?
27
+ # => true
28
+ #
29
+ # git_branch = Git::Branch.new('branch_name')
30
+ # => #<Git::Branch @name="branch_name">
31
+ #
32
+ # git_branch.merged?
33
+ # => true/false
34
+ #
35
+ # git_branch.name, git_branch.to_s
36
+ # => "branch_name"
37
+ #
38
+ # git_branch = Git::Branch.new('branch_name', remote: 'remote_name')
39
+ # => #<Git::Branch @name="branch_name" @remote="remote_name">
40
+ #
41
+ # git_branch.remote
42
+ # => "remote_name"
43
+
44
+ require 'Array/all_but_first'
45
+
46
+ module Git
47
+ class Branch
48
+
49
+ @switches = []
50
+
51
+ class << self
52
+
53
+ def local
54
+ self
55
+ end
56
+
57
+ def remote
58
+ @switches << '--remote'
59
+ self
60
+ end
61
+
62
+ def merged
63
+ @switches << '--merged'
64
+ self
65
+ end
66
+
67
+ def command_string
68
+ command_string = ['git branch', @switches.join(' ')].join(' ').strip
69
+ @switches = []
70
+ command_string
71
+ end
72
+
73
+ def branch_output
74
+ `#{command_string}`
75
+ end
76
+
77
+ def all
78
+ result = branch_output.split("\n").collect do |branch|
79
+ if @switches.include?('--remote')
80
+ branch_parts = branch.split('/')
81
+ remote, branch_name = branch_parts.first.sub('*', '').strip, branch_parts.all_but_first.join('/')
82
+ new(branch_name, remote: remote)
83
+ else
84
+ branch_name = branch.sub('*', '').strip
85
+ new(branch_name)
86
+ end
87
+ end
88
+ result
89
+ end
90
+
91
+ def current
92
+ branch_name = branch_output.split("\n").detect{|branch| branch =~ /\*/}.sub('*', '').strip
93
+ new(branch_name)
94
+ end
95
+ alias_method :head, :current
96
+
97
+ end # class << self
98
+
99
+ attr_accessor :name
100
+ attr_accessor :remote
101
+
102
+ def initialize(name = nil, **args)
103
+ @name = name
104
+ @remote = args[:remote]
105
+ end
106
+
107
+ def merged?
108
+ if @remote
109
+ self.class.remote.merged.all.collect{|branch| branch.name}.include?(@remote + '/' + @name)
110
+ else
111
+ self.class.merged.all.collect{|branch| branch.name}.include?(@name)
112
+ end
113
+ end
114
+
115
+ def to_s
116
+ if @remote
117
+ @remote + '/' + @name
118
+ else
119
+ @name
120
+ end
121
+ end
122
+
123
+ def method_missing(method_name, *args, &block)
124
+ if method_name.to_s =~ /\?$/ && !self.class.instance_methods.include?(method_name)
125
+ @name == method_name.to_s.sub('?', '')
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,93 @@
1
+ # Git/Log.rb
2
+ # Git::Log
3
+
4
+ # Examples:
5
+ #
6
+ # require 'Git/Log'
7
+ #
8
+ # git_log = Git::Log.parse(`git log`)
9
+ # => [#<Git::Log @commits = [#<Git::Log::Commit @hash=..., @author="thoran", @date=..., @message=...>, ...]>
10
+ #
11
+ # git_log.commits
12
+ # => [#<Git::Log::Commit @hash=..., @author="thoran", @date=..., @message=...>, ...]
13
+ #
14
+ # git_log.commits.first
15
+ # => #<Git::Log::Commit @hash=..., @author="thoran", @date=..., @message=...>
16
+ #
17
+ # git_log.commits.first.author
18
+ # => "thoran"
19
+
20
+ require 'Ordinal/Array'
21
+
22
+ module Git
23
+ class Log
24
+
25
+ class Commit
26
+
27
+ class << self
28
+ def parse(commit_string)
29
+ parsed_commit_string = commit_string.split("\n").collect{|line| line.strip}.select{|line| !line.empty?}
30
+ Commit.new(
31
+ hash: parsed_commit_string.first.gsub(/^commit /, ''),
32
+ author: parsed_commit_string.second.gsub(/^Author: /, ''),
33
+ date: parsed_commit_string.third.gsub(/^Date: /, ''),
34
+ message: parsed_commit_string.fourth
35
+ )
36
+ end
37
+ end # class << self
38
+
39
+ attr_reader :hash
40
+ attr_reader :author
41
+ attr_reader :date
42
+ attr_reader :message
43
+
44
+ def initialize(values = {})
45
+ @hash = values[:hash]
46
+ @author = values[:author]
47
+ @date = values[:date]
48
+ @message = values[:message]
49
+ end
50
+
51
+ end # class Commit
52
+
53
+ @commits = []
54
+
55
+ class << self
56
+
57
+ attr_reader :commits
58
+
59
+ def parse(log_stream)
60
+ commit_log = Log.new
61
+ commit_string = ''
62
+ log_stream.each_line do |line|
63
+ line.lstrip!
64
+ if line =~ /^commit/ && !commit_string.empty?
65
+ commit_log.prepend(Commit.parse(commit_string))
66
+ commit_string = line
67
+ else
68
+ commit_string << line
69
+ end
70
+ end
71
+ commit_log.prepend(Commit.parse(commit_string))
72
+ commit_log
73
+ end
74
+
75
+ end # class << self
76
+
77
+ attr_reader :commits
78
+
79
+ def initialize(commits = [])
80
+ @commits = commits
81
+ end
82
+
83
+ def prepend(commit_object)
84
+ commits.unshift(commit_object)
85
+ end
86
+ alias_method :unshift, :prepend
87
+
88
+ def method_missing(method_name, *args, &block)
89
+ commits.send(method_name, *args, &block)
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,87 @@
1
+ # Git/Remote.rb
2
+ # Git::Remote
3
+
4
+ # Examples:
5
+ #
6
+ # require 'Git/Remote'
7
+ #
8
+ # Git::Remote.all
9
+ # => [#<Git::Remote @name='origin', @url='git@github.com:thoran/rails.git'>, #<Git::Remote @name='upstream', @url='git@github.com:rails/rails.git'>]
10
+ #
11
+ # Git::Remote.exist?('origin')
12
+ # => true
13
+ #
14
+ # git_remote = Git::Remote.find('origin')
15
+ # => #<Git::Remote @name="origin" @url="git@github.com:thoran/rails.git">
16
+ #
17
+ # git_remote.to_s
18
+ # => "origin git@github.com:thoran/rails.git"
19
+ #
20
+ # git_remote.name
21
+ # => "origin"
22
+
23
+ module Git
24
+ class Remote
25
+
26
+ class << self
27
+
28
+ def parse_line(remote_output_line)
29
+ name, url = remote_output_line.split
30
+ new(name: name, url: url)
31
+ end
32
+
33
+ def remote_output
34
+ `git remote --verbose`
35
+ end
36
+
37
+ def all
38
+ remote_output.split("\n").collect do |remote|
39
+ parse_line(remote)
40
+ end.uniq{|remote| remote.name}
41
+ end
42
+
43
+ def find(remote_name)
44
+ all.detect{|remote| remote.name == remote_name}
45
+ end
46
+
47
+ def add_command(remote_name, remote_url)
48
+ ['git remote add', remote_name, remote_url].join(' ')
49
+ end
50
+
51
+ def add(remote_name, remote_url)
52
+ system add_command(remote_name, remote_url)
53
+ end
54
+
55
+ def remove_command(remote_name)
56
+ ['git remote remove', remote_name].join(' ')
57
+ end
58
+
59
+ def remove(remote_name, remote_url)
60
+ system remove_command(remote_name)
61
+ end
62
+
63
+ def exist?(remote_name)
64
+ !!find(remote_name)
65
+ end
66
+
67
+ end # class << self
68
+
69
+ attr_accessor :name
70
+ attr_accessor :url
71
+
72
+ def initialize(name:, url:)
73
+ @name = name
74
+ @url = url
75
+ end
76
+
77
+ def remove
78
+ self.class.remove(@name, @url)
79
+ end
80
+ alias_method :delete, :remove
81
+
82
+ def to_s
83
+ "#{@name} #{@url}"
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Git
2
+ VERSION = '0.10.0'
3
+ end
@@ -0,0 +1,155 @@
1
+ # Ordinal.rb
2
+ # Ordinal
3
+
4
+ # 20140316
5
+ # 0.2.0
6
+
7
+ # Description: This is a collection of methods which relies upon an object having an entries method.
8
+
9
+ # Notes:
10
+ # 1. This was originally meant to be extensions on Enumerable, as can be seen in version 0.0.0, but I decided that any object which provides for an ordered list of entries by way of having an entries method should be able to make use of this.
11
+
12
+ # Changes since 0.1:
13
+ # 1. - require 'File/self.relative_path' from Ordinal/Array and replaced with require_relative.
14
+ # 2. - require 'File/self.relative_path' from Ordinal/Array and replaced with require_relative.
15
+
16
+ module Ordinal
17
+
18
+ def first
19
+ entries[0]
20
+ end
21
+
22
+ def second
23
+ entries[1]
24
+ end
25
+
26
+ def third
27
+ entries[2]
28
+ end
29
+
30
+ def fourth
31
+ entries[3]
32
+ end
33
+
34
+ def fifth
35
+ entries[4]
36
+ end
37
+
38
+ def sixth
39
+ entries[5]
40
+ end
41
+
42
+ def seventh
43
+ entries[6]
44
+ end
45
+
46
+ def eighth
47
+ entries[7]
48
+ end
49
+
50
+ def ninth
51
+ entries[8]
52
+ end
53
+
54
+ def tenth
55
+ entries[9]
56
+ end
57
+
58
+ def eleventh
59
+ entries[10]
60
+ end
61
+
62
+ def twelfth
63
+ entries[11]
64
+ end
65
+
66
+ def thirteenth
67
+ entries[12]
68
+ end
69
+
70
+ def fourteenth
71
+ entries[13]
72
+ end
73
+
74
+ def fifteenth
75
+ entries[14]
76
+ end
77
+
78
+ def sixteenth
79
+ entries[15]
80
+ end
81
+
82
+ def seventeenth
83
+ entries[16]
84
+ end
85
+
86
+ def eighteenth
87
+ entries[17]
88
+ end
89
+
90
+ def ninteenth
91
+ entries[18]
92
+ end
93
+
94
+ def twentieth
95
+ entries[19]
96
+ end
97
+
98
+ def tenth_last
99
+ entries[count - 10]
100
+ end
101
+
102
+ def ninth_last
103
+ entries[count - 9]
104
+ end
105
+
106
+ def eighth_last
107
+ entries[count - 8]
108
+ end
109
+
110
+ def seventh_last
111
+ entries[count - 7]
112
+ end
113
+
114
+ def sixth_last
115
+ entries[count - 6]
116
+ end
117
+
118
+ def fifth_last
119
+ entries[count - 5]
120
+ end
121
+
122
+ def fourth_last
123
+ entries[count - 4]
124
+ end
125
+
126
+ def third_last
127
+ entries[count - 3]
128
+ end
129
+
130
+ def second_last
131
+ entries[count - 2]
132
+ end
133
+
134
+ def last
135
+ entries[count - 1]
136
+ end
137
+ alias_method :first_last, :last
138
+
139
+ def all_but_first
140
+ entries.drop(1)
141
+ end
142
+
143
+ def all_but_last
144
+ entries.take(count - 1)
145
+ end
146
+
147
+ def all_but_first_and_last
148
+ entries.all_but_first.all_but_last
149
+ end
150
+
151
+ def first_and_last
152
+ [entries.first] + [entries.last]
153
+ end
154
+
155
+ end
@@ -0,0 +1,8 @@
1
+ # Ordinal/Array.rb
2
+ # Ordinal/Array
3
+
4
+ require_relative '../Ordinal'
5
+
6
+ class Array
7
+ include Ordinal
8
+ end
@@ -0,0 +1,28 @@
1
+ # Thoran/Array/AllButFirst/all_but_first.rb
2
+ # Thoran::Array::AllButFirst#all_but_first
3
+
4
+ # 20141223
5
+ # 0.1.0
6
+
7
+ # Description: This returns a copy of the receiving array with the first element removed.
8
+
9
+ # Changes:
10
+ # 1. + Thoran namespace.
11
+
12
+ require 'Thoran/Array/FirstX/firstX'
13
+
14
+ module Thoran
15
+ module Array
16
+ module AllButFirst
17
+
18
+ def all_but_first
19
+ d = self.dup
20
+ d.first!
21
+ d
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+
28
+ Array.send(:include, Thoran::Array::AllButFirst)
@@ -0,0 +1,28 @@
1
+ # Thoran/Array/AllButLast/all_but_last.rb
2
+ # Thoran::Array::AllButLast#all_but_last
3
+
4
+ # 20180804
5
+ # 0.1.0
6
+
7
+ # Description: This returns a copy of the receiving array with the last element removed.
8
+
9
+ # Changes:
10
+ # 1. + Thoran namespace.
11
+
12
+ require 'Thoran/Array/LastX/lastX'
13
+
14
+ module Thoran
15
+ module Array
16
+ module AllButLast
17
+
18
+ def all_but_last
19
+ d = self.dup
20
+ d.last!
21
+ d
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+
28
+ Array.send(:include, Thoran::Array::AllButLast)
@@ -0,0 +1,32 @@
1
+ # Thoran/Array/FirstX/firstX.rb
2
+ # Thoran::Array::FirstX#first!
3
+
4
+ # 20180804
5
+ # 0.3.3
6
+
7
+ # Description: Sometimes it makes more sense to treat arrays this way.
8
+
9
+ # Changes since 0.2:
10
+ # 1. Added the original version 0.1.0 of the implementation to the later 0.1.0!
11
+ # 0/1
12
+ # 2. Switched the tests to spec-style.
13
+ # 1/2
14
+ # 3. Added a test for the state of the array afterward, since this is meant to be an in place change.
15
+ # 2/3
16
+ # 4. Added tests for the extended functionality introduced in the first version 0.1.0.
17
+
18
+ module Thoran
19
+ module Array
20
+ module FirstX
21
+
22
+ def first!(n = 1)
23
+ return_value = []
24
+ n.times{return_value << self.shift}
25
+ return_value.size == 1 ? return_value[0] : return_value
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+
32
+ Array.send(:include, Thoran::Array::FirstX)
@@ -0,0 +1,33 @@
1
+ # Thoran/Array/LastX/lastX.rb
2
+ # Thoran::Array::LastX#last!
3
+
4
+ # 20180804
5
+ # 0.2.3
6
+
7
+ # Description: Sometimes it makes more sense to treat arrays this way.
8
+
9
+ # Changes since 0.1:
10
+ # 1. Added the complement of the extended version of Array#first!.
11
+ # 0/1
12
+ # 2. Switched the tests to spec-style.
13
+ # 1/2
14
+ # 3. Added a test for the state of the array afterward, since this is meant to be an in place change.
15
+ # 2/3
16
+ # 4. Added tests for the extended functionality introduced in the first version 0.1.0.
17
+ # 5. Fixed the implementation, so that the order is retained by unshifting the popped values rather than appending the shifted values as is the case with Array#first!.
18
+
19
+ module Thoran
20
+ module Array
21
+ module LastX
22
+
23
+ def last!(n = 1)
24
+ return_value = []
25
+ n.times{return_value.unshift(self.pop)}
26
+ return_value.size == 1 ? return_value[0] : return_value
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+
33
+ Array.send(:include, Thoran::Array::LastX)
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.0
5
+ platform: ruby
6
+ authors:
7
+ - thoran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Do stuff with git-blame, git-branch, git-log, and git-remote from Ruby.
14
+ email: code@thoran.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/Array/all_but_first.rb
20
+ - lib/Array/all_but_last.rb
21
+ - lib/Git.rb
22
+ - lib/Git/Blame.rb
23
+ - lib/Git/Branch.rb
24
+ - lib/Git/Log.rb
25
+ - lib/Git/Remote.rb
26
+ - lib/Git/VERSION.rb
27
+ - lib/Ordinal.rb
28
+ - lib/Ordinal/Array.rb
29
+ - lib/Thoran/AllButFirst/all_but_first.rb
30
+ - lib/Thoran/AllButLast/all_but_last.rb
31
+ - lib/Thoran/FirstX/firstX.rb
32
+ - lib/Thoran/LastX/lastX.rb
33
+ homepage: http://github.com/thoran/git.rb
34
+ licenses:
35
+ - MIT
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 1.9.3
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubygems_version: 3.1.2
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Do git stuff from Ruby.
56
+ test_files: []