git 2.0.0.pre2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +8 -0
- data/.github/workflows/continuous_integration.yml +0 -10
- data/.github/workflows/experimental_continuous_integration.yml +43 -0
- data/CHANGELOG.md +35 -0
- data/CONTRIBUTING.md +22 -67
- data/README.md +63 -70
- data/git.gemspec +2 -0
- data/lib/git/base.rb +21 -8
- data/lib/git/command_line.rb +21 -12
- data/lib/git/errors.rb +206 -0
- data/lib/git/lib.rb +42 -19
- data/lib/git/object.rb +69 -67
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +7 -10
- metadata +37 -15
- data/.github/stale.yml +0 -25
- data/Dockerfile.changelog-rs +0 -12
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/lib/git/command_line_error.rb +0 -59
- data/lib/git/error.rb +0 -7
- data/lib/git/failed_error.rb +0 -14
- data/lib/git/git_execute_error.rb +0 -14
- data/lib/git/signaled_error.rb +0 -14
- data/lib/git/timeout_error.rb +0 -60
- /data/{ISSUE_TEMPLATE.md → .github/issue_template.md} +0 -0
data/lib/git/errors.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Git
|
4
|
+
# Base class for all custom git module errors
|
5
|
+
#
|
6
|
+
# The git gem will only raise an `ArgumentError` or an error that is a subclass of
|
7
|
+
# `Git::Error`. It does not explicitly raise any other types of errors.
|
8
|
+
#
|
9
|
+
# It is recommended to rescue `Git::Error` to catch any runtime error raised by
|
10
|
+
# this gem unless you need more specific error handling.
|
11
|
+
#
|
12
|
+
# Git's custom errors are arranged in the following class heirarchy:
|
13
|
+
#
|
14
|
+
# ```text
|
15
|
+
# StandardError
|
16
|
+
# └─> Git::Error
|
17
|
+
# ├─> Git::CommandLineError
|
18
|
+
# │ ├─> Git::FailedError
|
19
|
+
# │ └─> Git::SignaledError
|
20
|
+
# │ └─> Git::TimeoutError
|
21
|
+
# ├─> Git::ProcessIOError
|
22
|
+
# └─> Git::UnexpectedResultError
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
# | Error Class | Description |
|
26
|
+
# | --- | --- |
|
27
|
+
# | `Error` | This catch-all error serves as the base class for other custom errors raised by the git gem. |
|
28
|
+
# | `CommandLineError` | A subclass of this error is raised when there is a problem executing the git command line. |
|
29
|
+
# | `FailedError` | This error is raised when the git command line exits with a non-zero status code that is not expected by the git gem. |
|
30
|
+
# | `SignaledError` | This error is raised when the git command line is terminated as a result of receiving a signal. This could happen if the process is forcibly terminated or if there is a serious system error. |
|
31
|
+
# | `TimeoutError` | This is a specific type of `SignaledError` that is raised when the git command line operation times out and is killed via the SIGKILL signal. This happens if the operation takes longer than the timeout duration configured in `Git.config.timeout` or via the `:timeout` parameter given in git methods that support timeouts. |
|
32
|
+
# | `ProcessIOError` | An error was encountered reading or writing to a subprocess. |
|
33
|
+
# | `UnexpectedResultError` | The command line ran without error but did not return the expected results. |
|
34
|
+
#
|
35
|
+
# @example Rescuing a generic error
|
36
|
+
# begin
|
37
|
+
# # some git operation
|
38
|
+
# rescue Git::Error => e
|
39
|
+
# puts "An error occurred: #{e.message}"
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# @example Rescuing a timeout error
|
43
|
+
# begin
|
44
|
+
# timeout_duration = 0.001 # seconds
|
45
|
+
# repo = Git.clone('https://github.com/ruby-git/ruby-git', 'ruby-git-temp', timeout: timeout_duration)
|
46
|
+
# rescue Git::TimeoutError => e # Catch the more specific error first!
|
47
|
+
# puts "Git clone took too long and timed out #{e}"
|
48
|
+
# rescue Git::Error => e
|
49
|
+
# puts "Received the following error: #{e}"
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# @see Git::CommandLineError
|
53
|
+
# @see Git::FailedError
|
54
|
+
# @see Git::SignaledError
|
55
|
+
# @see Git::TimeoutError
|
56
|
+
# @see Git::ProcessIOError
|
57
|
+
# @see Git::UnexpectedResultError
|
58
|
+
#
|
59
|
+
# @api public
|
60
|
+
#
|
61
|
+
class Error < StandardError; end
|
62
|
+
|
63
|
+
# An alias for Git::Error
|
64
|
+
#
|
65
|
+
# Git::GitExecuteError error class is an alias for Git::Error for backwards
|
66
|
+
# compatibility. It is recommended to use Git::Error directly.
|
67
|
+
#
|
68
|
+
# @deprecated Use Git::Error instead
|
69
|
+
#
|
70
|
+
GitExecuteError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Git::GitExecuteError', 'Git::Error', Git::Deprecation)
|
71
|
+
|
72
|
+
# Raised when a git command fails or exits because of an uncaught signal
|
73
|
+
#
|
74
|
+
# The git command executed, status, stdout, and stderr are available from this
|
75
|
+
# object.
|
76
|
+
#
|
77
|
+
# The Gem will raise a more specific error for each type of failure:
|
78
|
+
#
|
79
|
+
# * {Git::FailedError}: when the git command exits with a non-zero status
|
80
|
+
# * {Git::SignaledError}: when the git command exits because of an uncaught signal
|
81
|
+
# * {Git::TimeoutError}: when the git command times out
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
#
|
85
|
+
class CommandLineError < Git::Error
|
86
|
+
# Create a CommandLineError object
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# `exit 1` # set $? appropriately for this example
|
90
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, 'stdout', 'stderr')
|
91
|
+
# error = Git::CommandLineError.new(result)
|
92
|
+
# error.to_s #=> '["git", "status"], status: pid 89784 exit 1, stderr: "stderr"'
|
93
|
+
#
|
94
|
+
# @param result [Git::CommandLineResult] the result of the git command including
|
95
|
+
# the git command, status, stdout, and stderr
|
96
|
+
#
|
97
|
+
def initialize(result)
|
98
|
+
@result = result
|
99
|
+
super(error_message)
|
100
|
+
end
|
101
|
+
|
102
|
+
# The human readable representation of this error
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# error.error_message #=> '["git", "status"], status: pid 89784 exit 1, stderr: "stderr"'
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
#
|
109
|
+
def error_message = <<~MESSAGE.chomp
|
110
|
+
#{result.git_cmd}, status: #{result.status}, stderr: #{result.stderr.inspect}
|
111
|
+
MESSAGE
|
112
|
+
|
113
|
+
# @attribute [r] result
|
114
|
+
#
|
115
|
+
# The result of the git command including the git command and its status and output
|
116
|
+
#
|
117
|
+
# @example
|
118
|
+
# error.result #=> #<Git::CommandLineResult:0x00000001046bd488 ...>
|
119
|
+
#
|
120
|
+
# @return [Git::CommandLineResult]
|
121
|
+
#
|
122
|
+
attr_reader :result
|
123
|
+
end
|
124
|
+
|
125
|
+
# This error is raised when a git command returns a non-zero exitstatus
|
126
|
+
#
|
127
|
+
# The git command executed, status, stdout, and stderr are available from this
|
128
|
+
# object.
|
129
|
+
#
|
130
|
+
# @api public
|
131
|
+
#
|
132
|
+
class FailedError < Git::CommandLineError; end
|
133
|
+
|
134
|
+
# This error is raised when a git command exits because of an uncaught signal
|
135
|
+
#
|
136
|
+
# @api public
|
137
|
+
#
|
138
|
+
class SignaledError < Git::CommandLineError; end
|
139
|
+
|
140
|
+
# This error is raised when a git command takes longer than the configured timeout
|
141
|
+
#
|
142
|
+
# The git command executed, status, stdout, and stderr, and the timeout duration
|
143
|
+
# are available from this object.
|
144
|
+
#
|
145
|
+
# result.status.timeout? will be `true`
|
146
|
+
#
|
147
|
+
# @api public
|
148
|
+
#
|
149
|
+
class TimeoutError < Git::SignaledError
|
150
|
+
# Create a TimeoutError object
|
151
|
+
#
|
152
|
+
# @example
|
153
|
+
# command = %w[sleep 10]
|
154
|
+
# timeout_duration = 1
|
155
|
+
# status = ProcessExecuter.spawn(*command, timeout: timeout_duration)
|
156
|
+
# result = Git::CommandLineResult.new(command, status, 'stdout', 'err output')
|
157
|
+
# error = Git::TimeoutError.new(result, timeout_duration)
|
158
|
+
# error.error_message #=> '["sleep", "10"], status: pid 70144 SIGKILL (signal 9), stderr: "err output", timed out after 1s'
|
159
|
+
#
|
160
|
+
# @param result [Git::CommandLineResult] the result of the git command including
|
161
|
+
# the git command, status, stdout, and stderr
|
162
|
+
#
|
163
|
+
# @param timeout_duration [Numeric] the amount of time the subprocess was allowed
|
164
|
+
# to run before being killed
|
165
|
+
#
|
166
|
+
def initialize(result, timeout_duration)
|
167
|
+
@timeout_duration = timeout_duration
|
168
|
+
super(result)
|
169
|
+
end
|
170
|
+
|
171
|
+
# The human readable representation of this error
|
172
|
+
#
|
173
|
+
# @example
|
174
|
+
# error.error_message #=> '["sleep", "10"], status: pid 88811 SIGKILL (signal 9), stderr: "err output", timed out after 1s'
|
175
|
+
#
|
176
|
+
# @return [String]
|
177
|
+
#
|
178
|
+
def error_message = <<~MESSAGE.chomp
|
179
|
+
#{super}, timed out after #{timeout_duration}s
|
180
|
+
MESSAGE
|
181
|
+
|
182
|
+
# The amount of time the subprocess was allowed to run before being killed
|
183
|
+
#
|
184
|
+
# @example
|
185
|
+
# `kill -9 $$` # set $? appropriately for this example
|
186
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, '', "killed")
|
187
|
+
# error = Git::TimeoutError.new(result, 10)
|
188
|
+
# error.timeout_duration #=> 10
|
189
|
+
#
|
190
|
+
# @return [Numeric]
|
191
|
+
#
|
192
|
+
attr_reader :timeout_duration
|
193
|
+
end
|
194
|
+
|
195
|
+
# Raised when the output of a git command can not be read
|
196
|
+
#
|
197
|
+
# @api public
|
198
|
+
#
|
199
|
+
class ProcessIOError < Git::Error; end
|
200
|
+
|
201
|
+
# Raised when the git command result was not as expected
|
202
|
+
#
|
203
|
+
# @api public
|
204
|
+
#
|
205
|
+
class UnexpectedResultError < Git::Error; end
|
206
|
+
end
|
data/lib/git/lib.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'git/failed_error'
|
2
1
|
require 'git/command_line'
|
2
|
+
require 'git/errors'
|
3
3
|
require 'logger'
|
4
4
|
require 'pp'
|
5
5
|
require 'process_executer'
|
@@ -80,22 +80,34 @@ module Git
|
|
80
80
|
command('init', *arr_opts)
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
83
|
+
# Clones a repository into a newly created directory
|
84
84
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
# :remote:: name of remote (rather than 'origin')
|
93
|
-
# :recursive:: after the clone is created, initialize all submodules within, using their default settings.
|
85
|
+
# @param [String] repository_url the URL of the repository to clone
|
86
|
+
# @param [String, nil] directory the directory to clone into
|
87
|
+
#
|
88
|
+
# If nil, the repository is cloned into a directory with the same name as
|
89
|
+
# the repository.
|
90
|
+
#
|
91
|
+
# @param [Hash] opts the options for this command
|
94
92
|
#
|
95
|
-
#
|
93
|
+
# @option opts [Boolean] :bare (false) if true, clone as a bare repository
|
94
|
+
# @option opts [String] :branch the branch to checkout
|
95
|
+
# @option opts [String, Array] :config one or more configuration options to set
|
96
|
+
# @option opts [Integer] :depth the number of commits back to pull
|
97
|
+
# @option opts [String] :filter specify partial clone
|
98
|
+
# @option opts [String] :mirror set up a mirror of the source repository
|
99
|
+
# @option opts [String] :origin the name of the remote
|
100
|
+
# @option opts [String] :path an optional prefix for the directory parameter
|
101
|
+
# @option opts [String] :remote the name of the remote
|
102
|
+
# @option opts [Boolean] :recursive after the clone is created, initialize all submodules within, using their default settings
|
103
|
+
# @option opts [Numeric, nil] :timeout the number of seconds to wait for the command to complete
|
104
|
+
#
|
105
|
+
# See {Git::Lib#command} for more information about :timeout
|
96
106
|
#
|
97
107
|
# @return [Hash] the options to pass to {Git::Base.new}
|
98
108
|
#
|
109
|
+
# @todo make this work with SSH password or auth_key
|
110
|
+
#
|
99
111
|
def clone(repository_url, directory, opts = {})
|
100
112
|
@path = opts[:path] || '.'
|
101
113
|
clone_dir = opts[:path] ? File.join(@path, directory) : directory
|
@@ -143,7 +155,7 @@ module Git
|
|
143
155
|
match_data = output.match(%r{^ref: refs/heads/(?<default_branch>[^\t]+)\tHEAD$})
|
144
156
|
return match_data[:default_branch] if match_data
|
145
157
|
|
146
|
-
raise 'Unable to determine the default branch'
|
158
|
+
raise Git::UnexpectedResultError, 'Unable to determine the default branch'
|
147
159
|
end
|
148
160
|
|
149
161
|
## READ COMMANDS ##
|
@@ -408,7 +420,7 @@ module Git
|
|
408
420
|
def branches_all
|
409
421
|
command_lines('branch', '-a').map do |line|
|
410
422
|
match_data = line.match(BRANCH_LINE_REGEXP)
|
411
|
-
raise
|
423
|
+
raise Git::UnexpectedResultError, 'Unexpected branch line format' unless match_data
|
412
424
|
next nil if match_data[:not_a_branch] || match_data[:detached_ref]
|
413
425
|
[
|
414
426
|
match_data[:refname],
|
@@ -933,7 +945,7 @@ module Git
|
|
933
945
|
opts = opts.last.instance_of?(Hash) ? opts.last : {}
|
934
946
|
|
935
947
|
if (opts[:a] || opts[:annotate]) && !(opts[:m] || opts[:message])
|
936
|
-
raise
|
948
|
+
raise ArgumentError, 'Cannot create an annotated tag without a message.'
|
937
949
|
end
|
938
950
|
|
939
951
|
arr_opts = []
|
@@ -1006,10 +1018,11 @@ module Git
|
|
1006
1018
|
end
|
1007
1019
|
end
|
1008
1020
|
|
1009
|
-
def pull(remote = nil, branch = nil)
|
1021
|
+
def pull(remote = nil, branch = nil, opts = {})
|
1010
1022
|
raise ArgumentError, "You must specify a remote if a branch is specified" if remote.nil? && !branch.nil?
|
1011
1023
|
|
1012
1024
|
arr_opts = []
|
1025
|
+
arr_opts << '--allow-unrelated-histories' if opts[:allow_unrelated_histories]
|
1013
1026
|
arr_opts << remote if remote
|
1014
1027
|
arr_opts << branch if branch
|
1015
1028
|
command('pull', *arr_opts)
|
@@ -1214,15 +1227,25 @@ module Git
|
|
1214
1227
|
#
|
1215
1228
|
# @param chdir [String, nil] the directory to run the command in
|
1216
1229
|
#
|
1217
|
-
# @param timeout [Numeric, nil] the maximum
|
1218
|
-
#
|
1230
|
+
# @param timeout [Numeric, nil] the maximum seconds to wait for the command to complete
|
1231
|
+
#
|
1232
|
+
# If timeout is nil, the global timeout from {Git::Config} is used.
|
1233
|
+
#
|
1234
|
+
# If timeout is zero, the timeout will not be enforced.
|
1235
|
+
#
|
1236
|
+
# If the command times out, it is killed via a `SIGKILL` signal and `Git::TimeoutError` is raised.
|
1237
|
+
#
|
1238
|
+
# If the command does not respond to SIGKILL, it will hang this method.
|
1219
1239
|
#
|
1220
1240
|
# @see Git::CommandLine#run
|
1221
1241
|
#
|
1222
1242
|
# @return [String] the command's stdout (or merged stdout and stderr if `merge`
|
1223
1243
|
# is true)
|
1224
1244
|
#
|
1225
|
-
# @raise [Git::
|
1245
|
+
# @raise [Git::FailedError] if the command failed
|
1246
|
+
# @raise [Git::SignaledError] if the command was signaled
|
1247
|
+
# @raise [Git::TimeoutError] if the command times out
|
1248
|
+
# @raise [Git::ProcessIOError] if an exception was raised while collecting subprocess output
|
1226
1249
|
#
|
1227
1250
|
# The exception's `result` attribute is a {Git::CommandLineResult} which will
|
1228
1251
|
# contain the result of the command including the exit status, stdout, and
|
data/lib/git/object.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
require 'git/author'
|
2
|
+
require 'git/diff'
|
3
|
+
require 'git/errors'
|
4
|
+
require 'git/log'
|
5
|
+
|
1
6
|
module Git
|
2
|
-
|
3
|
-
class GitTagNameDoesNotExist< StandardError
|
4
|
-
end
|
5
|
-
|
7
|
+
|
6
8
|
# represents a git object
|
7
9
|
class Object
|
8
|
-
|
10
|
+
|
9
11
|
class AbstractObject
|
10
12
|
attr_accessor :objectish, :type, :mode
|
11
13
|
|
12
14
|
attr_writer :size
|
13
|
-
|
15
|
+
|
14
16
|
def initialize(base, objectish)
|
15
17
|
@base = base
|
16
18
|
@objectish = objectish.to_s
|
@@ -23,11 +25,11 @@ module Git
|
|
23
25
|
def sha
|
24
26
|
@sha ||= @base.lib.revparse(@objectish)
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
def size
|
28
30
|
@size ||= @base.lib.object_size(@objectish)
|
29
31
|
end
|
30
|
-
|
32
|
+
|
31
33
|
# Get the object's contents.
|
32
34
|
# If no block is given, the contents are cached in memory and returned as a string.
|
33
35
|
# If a block is given, it yields an IO object (via IO::popen) which could be used to
|
@@ -41,108 +43,108 @@ module Git
|
|
41
43
|
@contents ||= @base.lib.object_contents(@objectish)
|
42
44
|
end
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
def contents_array
|
46
48
|
self.contents.split("\n")
|
47
49
|
end
|
48
|
-
|
50
|
+
|
49
51
|
def to_s
|
50
52
|
@objectish
|
51
53
|
end
|
52
|
-
|
54
|
+
|
53
55
|
def grep(string, path_limiter = nil, opts = {})
|
54
56
|
opts = {:object => sha, :path_limiter => path_limiter}.merge(opts)
|
55
57
|
@base.lib.grep(string, opts)
|
56
58
|
end
|
57
|
-
|
59
|
+
|
58
60
|
def diff(objectish)
|
59
61
|
Git::Diff.new(@base, @objectish, objectish)
|
60
62
|
end
|
61
|
-
|
63
|
+
|
62
64
|
def log(count = 30)
|
63
65
|
Git::Log.new(@base, count).object(@objectish)
|
64
66
|
end
|
65
|
-
|
67
|
+
|
66
68
|
# creates an archive of this object (tree)
|
67
69
|
def archive(file = nil, opts = {})
|
68
70
|
@base.lib.archive(@objectish, file, opts)
|
69
71
|
end
|
70
|
-
|
72
|
+
|
71
73
|
def tree?; false; end
|
72
|
-
|
74
|
+
|
73
75
|
def blob?; false; end
|
74
|
-
|
76
|
+
|
75
77
|
def commit?; false; end
|
76
78
|
|
77
79
|
def tag?; false; end
|
78
|
-
|
80
|
+
|
79
81
|
end
|
80
|
-
|
81
|
-
|
82
|
+
|
83
|
+
|
82
84
|
class Blob < AbstractObject
|
83
|
-
|
85
|
+
|
84
86
|
def initialize(base, sha, mode = nil)
|
85
87
|
super(base, sha)
|
86
88
|
@mode = mode
|
87
89
|
end
|
88
|
-
|
90
|
+
|
89
91
|
def blob?
|
90
92
|
true
|
91
93
|
end
|
92
94
|
|
93
95
|
end
|
94
|
-
|
96
|
+
|
95
97
|
class Tree < AbstractObject
|
96
|
-
|
98
|
+
|
97
99
|
def initialize(base, sha, mode = nil)
|
98
100
|
super(base, sha)
|
99
101
|
@mode = mode
|
100
102
|
@trees = nil
|
101
103
|
@blobs = nil
|
102
104
|
end
|
103
|
-
|
105
|
+
|
104
106
|
def children
|
105
107
|
blobs.merge(subtrees)
|
106
108
|
end
|
107
|
-
|
109
|
+
|
108
110
|
def blobs
|
109
111
|
@blobs ||= check_tree[:blobs]
|
110
112
|
end
|
111
113
|
alias_method :files, :blobs
|
112
|
-
|
114
|
+
|
113
115
|
def trees
|
114
116
|
@trees ||= check_tree[:trees]
|
115
117
|
end
|
116
118
|
alias_method :subtrees, :trees
|
117
119
|
alias_method :subdirectories, :trees
|
118
|
-
|
120
|
+
|
119
121
|
def full_tree
|
120
122
|
@base.lib.full_tree(@objectish)
|
121
123
|
end
|
122
|
-
|
124
|
+
|
123
125
|
def depth
|
124
126
|
@base.lib.tree_depth(@objectish)
|
125
127
|
end
|
126
|
-
|
128
|
+
|
127
129
|
def tree?
|
128
130
|
true
|
129
131
|
end
|
130
|
-
|
132
|
+
|
131
133
|
private
|
132
134
|
|
133
135
|
# actually run the git command
|
134
136
|
def check_tree
|
135
137
|
@trees = {}
|
136
138
|
@blobs = {}
|
137
|
-
|
139
|
+
|
138
140
|
data = @base.lib.ls_tree(@objectish)
|
139
141
|
|
140
|
-
data['tree'].each do |key, tree|
|
141
|
-
@trees[key] = Git::Object::Tree.new(@base, tree[:sha], tree[:mode])
|
142
|
+
data['tree'].each do |key, tree|
|
143
|
+
@trees[key] = Git::Object::Tree.new(@base, tree[:sha], tree[:mode])
|
142
144
|
end
|
143
|
-
|
144
|
-
data['blob'].each do |key, blob|
|
145
|
-
@blobs[key] = Git::Object::Blob.new(@base, blob[:sha], blob[:mode])
|
145
|
+
|
146
|
+
data['blob'].each do |key, blob|
|
147
|
+
@blobs[key] = Git::Object::Blob.new(@base, blob[:sha], blob[:mode])
|
146
148
|
end
|
147
149
|
|
148
150
|
{
|
@@ -150,11 +152,11 @@ module Git
|
|
150
152
|
:blobs => @blobs
|
151
153
|
}
|
152
154
|
end
|
153
|
-
|
155
|
+
|
154
156
|
end
|
155
|
-
|
157
|
+
|
156
158
|
class Commit < AbstractObject
|
157
|
-
|
159
|
+
|
158
160
|
def initialize(base, sha, init = nil)
|
159
161
|
super(base, sha)
|
160
162
|
@tree = nil
|
@@ -166,48 +168,48 @@ module Git
|
|
166
168
|
set_commit(init)
|
167
169
|
end
|
168
170
|
end
|
169
|
-
|
171
|
+
|
170
172
|
def message
|
171
173
|
check_commit
|
172
174
|
@message
|
173
175
|
end
|
174
|
-
|
176
|
+
|
175
177
|
def name
|
176
178
|
@base.lib.namerev(sha)
|
177
179
|
end
|
178
|
-
|
180
|
+
|
179
181
|
def gtree
|
180
182
|
check_commit
|
181
183
|
Tree.new(@base, @tree)
|
182
184
|
end
|
183
|
-
|
185
|
+
|
184
186
|
def parent
|
185
187
|
parents.first
|
186
188
|
end
|
187
|
-
|
189
|
+
|
188
190
|
# array of all parent commits
|
189
191
|
def parents
|
190
192
|
check_commit
|
191
|
-
@parents
|
193
|
+
@parents
|
192
194
|
end
|
193
|
-
|
195
|
+
|
194
196
|
# git author
|
195
|
-
def author
|
197
|
+
def author
|
196
198
|
check_commit
|
197
199
|
@author
|
198
200
|
end
|
199
|
-
|
201
|
+
|
200
202
|
def author_date
|
201
203
|
author.date
|
202
204
|
end
|
203
|
-
|
205
|
+
|
204
206
|
# git author
|
205
207
|
def committer
|
206
208
|
check_commit
|
207
209
|
@committer
|
208
210
|
end
|
209
|
-
|
210
|
-
def committer_date
|
211
|
+
|
212
|
+
def committer_date
|
211
213
|
committer.date
|
212
214
|
end
|
213
215
|
alias_method :date, :committer_date
|
@@ -215,7 +217,7 @@ module Git
|
|
215
217
|
def diff_parent
|
216
218
|
diff(parent)
|
217
219
|
end
|
218
|
-
|
220
|
+
|
219
221
|
def set_commit(data)
|
220
222
|
@sha ||= data['sha']
|
221
223
|
@committer = Git::Author.new(data['committer'])
|
@@ -224,26 +226,26 @@ module Git
|
|
224
226
|
@parents = data['parent'].map{ |sha| Git::Object::Commit.new(@base, sha) }
|
225
227
|
@message = data['message'].chomp
|
226
228
|
end
|
227
|
-
|
229
|
+
|
228
230
|
def commit?
|
229
231
|
true
|
230
232
|
end
|
231
233
|
|
232
234
|
private
|
233
|
-
|
235
|
+
|
234
236
|
# see if this object has been initialized and do so if not
|
235
237
|
def check_commit
|
236
238
|
return if @tree
|
237
|
-
|
239
|
+
|
238
240
|
data = @base.lib.commit_data(@objectish)
|
239
241
|
set_commit(data)
|
240
242
|
end
|
241
|
-
|
243
|
+
|
242
244
|
end
|
243
|
-
|
245
|
+
|
244
246
|
class Tag < AbstractObject
|
245
247
|
attr_accessor :name
|
246
|
-
|
248
|
+
|
247
249
|
def initialize(base, sha, name)
|
248
250
|
super(base, sha)
|
249
251
|
@name = name
|
@@ -259,7 +261,7 @@ module Git
|
|
259
261
|
check_tag()
|
260
262
|
return @message
|
261
263
|
end
|
262
|
-
|
264
|
+
|
263
265
|
def tag?
|
264
266
|
true
|
265
267
|
end
|
@@ -274,7 +276,7 @@ module Git
|
|
274
276
|
def check_tag
|
275
277
|
return if @loaded
|
276
278
|
|
277
|
-
if !self.annotated?
|
279
|
+
if !self.annotated?
|
278
280
|
@message = @tagger = nil
|
279
281
|
else
|
280
282
|
tdata = @base.lib.tag_data(@name)
|
@@ -284,29 +286,29 @@ module Git
|
|
284
286
|
|
285
287
|
@loaded = true
|
286
288
|
end
|
287
|
-
|
289
|
+
|
288
290
|
end
|
289
|
-
|
291
|
+
|
290
292
|
# if we're calling this, we don't know what type it is yet
|
291
293
|
# so this is our little factory method
|
292
294
|
def self.new(base, objectish, type = nil, is_tag = false)
|
293
295
|
if is_tag
|
294
296
|
sha = base.lib.tag_sha(objectish)
|
295
297
|
if sha == ''
|
296
|
-
raise Git::
|
298
|
+
raise Git::UnexpectedResultError.new("Tag '#{objectish}' does not exist.")
|
297
299
|
end
|
298
300
|
return Git::Object::Tag.new(base, sha, objectish)
|
299
301
|
end
|
300
|
-
|
302
|
+
|
301
303
|
type ||= base.lib.object_type(objectish)
|
302
304
|
klass =
|
303
305
|
case type
|
304
|
-
when /blob/ then Blob
|
306
|
+
when /blob/ then Blob
|
305
307
|
when /commit/ then Commit
|
306
308
|
when /tree/ then Tree
|
307
309
|
end
|
308
310
|
klass.new(base, objectish)
|
309
311
|
end
|
310
|
-
|
312
|
+
|
311
313
|
end
|
312
314
|
end
|
data/lib/git/version.rb
CHANGED