git 1.13.1 → 1.14.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/CHANGELOG.md +24 -0
- data/CONTRIBUTING.md +12 -0
- data/Rakefile +8 -4
- data/lib/git/base.rb +12 -6
- data/lib/git/command_line_result.rb +86 -0
- data/lib/git/escaped_path.rb +1 -1
- data/lib/git/failed_error.rb +51 -0
- data/lib/git/git_execute_error.rb +7 -0
- data/lib/git/lib.rb +103 -103
- data/lib/git/signaled_error.rb +50 -0
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +4 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 344c98cd98670d4afa26aae12680f28ad857f1fdbca4384a10c9cf7ed7937a8a
|
4
|
+
data.tar.gz: 9d857e44f2457f6c5208bebca6935991c2e88fbd82b2c482c570cd7afcca7c38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fd40652aa02ad36238522ee2210ad7c01ced240f0a1b91f2de3e6baefe93dd0a20fb22b80821ee45bf974d73a3cc346e4a5adbaa2322384b57e2bb0251d491d
|
7
|
+
data.tar.gz: 0c8d86fe09a9e4f8d06c1d8bb0abf05eff45a2746450253ccf751163e4340b873df4eff2dbfb0711aad30c61303e0c692802a378bceb46a26a1e17ba08927268
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,30 @@
|
|
5
5
|
|
6
6
|
# Change Log
|
7
7
|
|
8
|
+
## v1.14.0 (2023-02-25)
|
9
|
+
|
10
|
+
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.13.2..v1.14.0)
|
11
|
+
|
12
|
+
Changes since v1.13.2:
|
13
|
+
|
14
|
+
* 0f7c4a5 Allow the use of an array of path_limiters and add extended_regexp option to grep (#624)
|
15
|
+
* 8992701 Refactor error thrown when a git command fails (#622)
|
16
|
+
* cf74b91 Simplify how temp files are used when testing Git::Base#archive (#621)
|
17
|
+
* a8bfb9d Set init.defaultBranch when running tests if it is not already set (#620)
|
18
|
+
* 9ee7ca9 Create a null logger if a logger is not provided (#619)
|
19
|
+
* 872de4c Internal refactor of Git::Lib command (#618)
|
20
|
+
* 29e157d Simplify test running and fixture repo cloning (#615)
|
21
|
+
* 08d04ef Use dynamically-created repo for signed commits test (#614)
|
22
|
+
|
23
|
+
## v1.13.2 (2023-02-02)
|
24
|
+
|
25
|
+
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.13.1..v1.13.2)
|
26
|
+
|
27
|
+
Changes since v1.13.1:
|
28
|
+
|
29
|
+
* b6e031d Fix `Git::Lib#commit_data` for GPG-signed commits (#610)
|
30
|
+
* b12b820 Fix escaped path decoding (#612)
|
31
|
+
|
8
32
|
## v1.13.1 (2023-01-12)
|
9
33
|
|
10
34
|
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.13.0...v1.13.1)
|
data/CONTRIBUTING.md
CHANGED
@@ -81,6 +81,18 @@ In order to ensure high quality, all pull requests must meet these requirements:
|
|
81
81
|
* The entire test suite must pass when `bundle exec rake default` is run from the
|
82
82
|
project's local working copy.
|
83
83
|
|
84
|
+
While working on specific features you can run individual test files or
|
85
|
+
a group of tests using `bin/test`:
|
86
|
+
|
87
|
+
# run a single file:
|
88
|
+
$ bin/test tests/units/test_object.rb
|
89
|
+
|
90
|
+
# run multiple files:
|
91
|
+
$ bin/test tests/units/test_object.rb tests/units/test_archive.rb
|
92
|
+
|
93
|
+
# run all unit tests:
|
94
|
+
$ bin/test
|
95
|
+
|
84
96
|
### Continuous integration
|
85
97
|
* All tests must pass in the project's [GitHub Continuous Integration build](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
|
86
98
|
before the pull request will be merged.
|
data/Rakefile
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'English'
|
3
3
|
|
4
|
-
require
|
4
|
+
require 'git/version'
|
5
5
|
|
6
6
|
default_tasks = []
|
7
7
|
|
8
8
|
desc 'Run Unit Tests'
|
9
9
|
task :test do
|
10
|
-
sh '
|
11
|
-
sh 'git config --global user.name "GitExample"' if `git config user.name`.empty?
|
10
|
+
sh 'ruby bin/test'
|
12
11
|
|
13
|
-
|
12
|
+
# You can run individual test files (or multiple files) from the command
|
13
|
+
# line with:
|
14
|
+
#
|
15
|
+
# $ bin/test tests/units/test_archive.rb
|
16
|
+
#
|
17
|
+
# $ bin/test tests/units/test_archive.rb tests/units/test_object.rb
|
14
18
|
end
|
15
19
|
default_tasks << :test
|
16
20
|
|
data/lib/git/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'git/base/factory'
|
2
|
+
require 'logger'
|
2
3
|
|
3
4
|
module Git
|
4
5
|
# Git::Base is the main public interface for interacting with Git commands.
|
@@ -90,12 +91,8 @@ module Git
|
|
90
91
|
options[:repository] ||= File.join(working_dir, '.git')
|
91
92
|
options[:index] ||= File.join(options[:repository], 'index')
|
92
93
|
end
|
93
|
-
|
94
|
-
|
95
|
-
@logger.info("Starting Git")
|
96
|
-
else
|
97
|
-
@logger = nil
|
98
|
-
end
|
94
|
+
@logger = (options[:log] || Logger.new(nil))
|
95
|
+
@logger.info("Starting Git")
|
99
96
|
|
100
97
|
@working_directory = options[:working_directory] ? Git::WorkingDirectory.new(options[:working_directory]) : nil
|
101
98
|
@repository = options[:repository] ? Git::Repository.new(options[:repository]) : nil
|
@@ -212,6 +209,15 @@ module Git
|
|
212
209
|
# end
|
213
210
|
# end
|
214
211
|
#
|
212
|
+
# @param string [String] the string to search for
|
213
|
+
# @param path_limiter [String, Array] a path or array of paths to limit the search to or nil for no limit
|
214
|
+
# @param opts [Hash] options to pass to the underlying `git grep` command
|
215
|
+
#
|
216
|
+
# @option opts [Boolean] :ignore_case (false) ignore case when matching
|
217
|
+
# @option opts [Boolean] :invert_match (false) select non-matching lines
|
218
|
+
# @option opts [Boolean] :extended_regexp (false) use extended regular expressions
|
219
|
+
# @option opts [String] :object (HEAD) the object to search from
|
220
|
+
#
|
215
221
|
# @return [Hash<String, Array>] a hash of arrays
|
216
222
|
# ```Ruby
|
217
223
|
# {
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Git
|
4
|
+
# The result of running a git command
|
5
|
+
#
|
6
|
+
# This object stores the Git command executed and its status, stdout, and stderr.
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
#
|
10
|
+
class CommandLineResult
|
11
|
+
# Create a CommandLineResult object
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# `true`
|
15
|
+
# git_cmd = %w[git version]
|
16
|
+
# status = $?
|
17
|
+
# stdout = "git version 2.39.1\n"
|
18
|
+
# stderr = ""
|
19
|
+
# result = Git::CommandLineResult.new(git_cmd, status, stdout, stderr)
|
20
|
+
#
|
21
|
+
# @param git_cmd [Array<String>] the git command that was executed
|
22
|
+
# @param status [Process::Status] the status of the process
|
23
|
+
# @param stdout [String] the output of the process
|
24
|
+
# @param stderr [String] the error output of the process
|
25
|
+
#
|
26
|
+
def initialize(git_cmd, status, stdout, stderr)
|
27
|
+
@git_cmd = git_cmd
|
28
|
+
@status = status
|
29
|
+
@stdout = stdout
|
30
|
+
@stderr = stderr
|
31
|
+
end
|
32
|
+
|
33
|
+
# @attribute [r] git_cmd
|
34
|
+
#
|
35
|
+
# The git command that was executed
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# git_cmd = %w[git version]
|
39
|
+
# result = Git::CommandLineResult.new(git_cmd, $?, "", "")
|
40
|
+
# result.git_cmd #=> ["git", "version"]
|
41
|
+
#
|
42
|
+
# @return [Array<String>]
|
43
|
+
#
|
44
|
+
attr_reader :git_cmd
|
45
|
+
|
46
|
+
# @attribute [r] status
|
47
|
+
#
|
48
|
+
# The status of the process
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# `true`
|
52
|
+
# status = $?
|
53
|
+
# result = Git::CommandLineResult.new(status, "", "")
|
54
|
+
# result.status #=> #<Process::Status: pid 87859 exit 0>
|
55
|
+
#
|
56
|
+
# @return [Process::Status]
|
57
|
+
#
|
58
|
+
attr_reader :status
|
59
|
+
|
60
|
+
# @attribute [r] stdout
|
61
|
+
#
|
62
|
+
# The output of the process
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# stdout = "git version 2.39.1\n"
|
66
|
+
# result = Git::CommandLineResult.new($?, stdout, "")
|
67
|
+
# result.stdout #=> "git version 2.39.1\n"
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
#
|
71
|
+
attr_reader :stdout
|
72
|
+
|
73
|
+
# @attribute [r] stderr
|
74
|
+
#
|
75
|
+
# The error output of the process
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# stderr = "Tag not found\n"
|
79
|
+
# result = Git::CommandLineResult.new($?, "", stderr)
|
80
|
+
# result.stderr #=> "Tag not found\n"
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
#
|
84
|
+
attr_reader :stderr
|
85
|
+
end
|
86
|
+
end
|
data/lib/git/escaped_path.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git/git_execute_error'
|
4
|
+
|
5
|
+
module Git
|
6
|
+
# This error is raised when a git command fails
|
7
|
+
#
|
8
|
+
# The git command executed, status, stdout, and stderr are available from this
|
9
|
+
# object. The #message includes the git command, the status of the process, and
|
10
|
+
# the stderr of the process.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
class FailedError < Git::GitExecuteError
|
15
|
+
# Create a FailedError object
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# `exit 1` # set $? appropriately for this example
|
19
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, '', "failed")
|
20
|
+
# error = Git::FailedError.new(result)
|
21
|
+
# error.message #=>
|
22
|
+
# "[\"git\", \"status\"]\nstatus: pid 89784 exit 1\nstderr: \"failed\""
|
23
|
+
#
|
24
|
+
# @param result [Git::CommandLineResult] the result of the git command including
|
25
|
+
# the git command, status, stdout, and stderr
|
26
|
+
#
|
27
|
+
def initialize(result)
|
28
|
+
super("#{result.git_cmd}\nstatus: #{result.status}\nstderr: #{result.stderr.inspect}")
|
29
|
+
@result = result
|
30
|
+
end
|
31
|
+
|
32
|
+
# @attribute [r] result
|
33
|
+
#
|
34
|
+
# The result of the git command including the git command and its status and output
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# `exit 1` # set $? appropriately for this example
|
38
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, '', "failed")
|
39
|
+
# error = Git::FailedError.new(result)
|
40
|
+
# error.result #=>
|
41
|
+
# #<Git::CommandLineResult:0x00000001046bd488
|
42
|
+
# @git_cmd=["git", "status"],
|
43
|
+
# @status=#<Process::Status: pid 89784 exit 1>,
|
44
|
+
# @stderr="failed",
|
45
|
+
# @stdout="">
|
46
|
+
#
|
47
|
+
# @return [Git::CommandLineResult]
|
48
|
+
#
|
49
|
+
attr_reader :result
|
50
|
+
end
|
51
|
+
end
|
data/lib/git/lib.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
+
require 'git/failed_error'
|
2
|
+
require 'logger'
|
1
3
|
require 'tempfile'
|
2
4
|
require 'zlib'
|
3
5
|
|
4
6
|
module Git
|
5
|
-
|
6
|
-
class GitExecuteError < StandardError
|
7
|
-
end
|
8
|
-
|
9
7
|
class Lib
|
10
8
|
|
11
9
|
@@semaphore = Mutex.new
|
@@ -52,6 +50,7 @@ module Git
|
|
52
50
|
@git_index_file = nil
|
53
51
|
@git_work_dir = nil
|
54
52
|
@path = nil
|
53
|
+
@logger = logger || Logger.new(nil)
|
55
54
|
|
56
55
|
if base.is_a?(Git::Base)
|
57
56
|
@git_dir = base.repo.path
|
@@ -62,7 +61,6 @@ module Git
|
|
62
61
|
@git_index_file = base[:index]
|
63
62
|
@git_work_dir = base[:working_directory]
|
64
63
|
end
|
65
|
-
@logger = logger
|
66
64
|
end
|
67
65
|
|
68
66
|
# creates or reinitializes the repository
|
@@ -77,7 +75,7 @@ module Git
|
|
77
75
|
arr_opts << '--bare' if opts[:bare]
|
78
76
|
arr_opts << "--initial-branch=#{opts[:initial_branch]}" if opts[:initial_branch]
|
79
77
|
|
80
|
-
command('init', arr_opts)
|
78
|
+
command('init', *arr_opts)
|
81
79
|
end
|
82
80
|
|
83
81
|
# tries to clone the given repo
|
@@ -113,7 +111,7 @@ module Git
|
|
113
111
|
arr_opts << repository_url
|
114
112
|
arr_opts << clone_dir
|
115
113
|
|
116
|
-
command('clone', arr_opts)
|
114
|
+
command('clone', *arr_opts)
|
117
115
|
|
118
116
|
return_base_opts_from_clone(clone_dir, opts)
|
119
117
|
end
|
@@ -168,7 +166,7 @@ module Git
|
|
168
166
|
|
169
167
|
arr_opts << committish if committish
|
170
168
|
|
171
|
-
return command('describe', arr_opts)
|
169
|
+
return command('describe', *arr_opts)
|
172
170
|
end
|
173
171
|
|
174
172
|
def log_commits(opts={})
|
@@ -178,7 +176,7 @@ module Git
|
|
178
176
|
|
179
177
|
arr_opts += log_path_options(opts)
|
180
178
|
|
181
|
-
command_lines('log', arr_opts).map { |l| l.split.first }
|
179
|
+
command_lines('log', *arr_opts).map { |l| l.split.first }
|
182
180
|
end
|
183
181
|
|
184
182
|
def full_log_commits(opts={})
|
@@ -189,7 +187,7 @@ module Git
|
|
189
187
|
|
190
188
|
arr_opts += log_path_options(opts)
|
191
189
|
|
192
|
-
full_log = command_lines('log', arr_opts)
|
190
|
+
full_log = command_lines('log', *arr_opts)
|
193
191
|
|
194
192
|
process_commit_log_data(full_log)
|
195
193
|
end
|
@@ -221,54 +219,57 @@ module Git
|
|
221
219
|
def commit_data(sha)
|
222
220
|
sha = sha.to_s
|
223
221
|
cdata = command_lines('cat-file', 'commit', sha)
|
224
|
-
process_commit_data(cdata, sha
|
222
|
+
process_commit_data(cdata, sha)
|
225
223
|
end
|
226
224
|
|
227
|
-
def process_commit_data(data, sha
|
225
|
+
def process_commit_data(data, sha)
|
228
226
|
hsh = {
|
229
|
-
'sha'
|
230
|
-
'
|
231
|
-
'parent' => []
|
227
|
+
'sha' => sha,
|
228
|
+
'parent' => []
|
232
229
|
}
|
233
230
|
|
234
|
-
|
235
|
-
key, *value = data.shift.split
|
236
|
-
|
237
|
-
break if key.nil?
|
238
|
-
|
231
|
+
each_cat_file_header(data) do |key, value|
|
239
232
|
if key == 'parent'
|
240
|
-
hsh['parent'] << value
|
233
|
+
hsh['parent'] << value
|
241
234
|
else
|
242
|
-
hsh[key] = value
|
235
|
+
hsh[key] = value
|
243
236
|
end
|
244
237
|
end
|
245
238
|
|
246
|
-
hsh['message'] = data.
|
239
|
+
hsh['message'] = data.join("\n") + "\n"
|
247
240
|
|
248
241
|
return hsh
|
249
242
|
end
|
250
243
|
|
244
|
+
CAT_FILE_HEADER_LINE = /\A(?<key>\w+) (?<value>.*)\z/
|
245
|
+
|
246
|
+
def each_cat_file_header(data)
|
247
|
+
while (match = CAT_FILE_HEADER_LINE.match(data.shift))
|
248
|
+
key = match[:key]
|
249
|
+
value_lines = [match[:value]]
|
250
|
+
|
251
|
+
while data.first.start_with?(' ')
|
252
|
+
value_lines << data.shift.lstrip
|
253
|
+
end
|
254
|
+
|
255
|
+
yield key, value_lines.join("\n")
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
251
259
|
def tag_data(name)
|
252
260
|
sha = sha.to_s
|
253
261
|
tdata = command_lines('cat-file', 'tag', name)
|
254
|
-
process_tag_data(tdata, name
|
262
|
+
process_tag_data(tdata, name)
|
255
263
|
end
|
256
264
|
|
257
|
-
def process_tag_data(data, name
|
258
|
-
hsh = {
|
259
|
-
'name' => name,
|
260
|
-
'message' => ''
|
261
|
-
}
|
262
|
-
|
263
|
-
loop do
|
264
|
-
key, *value = data.shift.split
|
265
|
-
|
266
|
-
break if key.nil?
|
265
|
+
def process_tag_data(data, name)
|
266
|
+
hsh = { 'name' => name }
|
267
267
|
|
268
|
-
|
268
|
+
each_cat_file_header(data) do |key, value|
|
269
|
+
hsh[key] = value
|
269
270
|
end
|
270
271
|
|
271
|
-
hsh['message'] = data.
|
272
|
+
hsh['message'] = data.join("\n") + "\n"
|
272
273
|
|
273
274
|
return hsh
|
274
275
|
end
|
@@ -367,7 +368,7 @@ module Git
|
|
367
368
|
# HEAD b8c63206f8d10f57892060375a86ae911fad356e
|
368
369
|
# detached
|
369
370
|
#
|
370
|
-
command_lines('worktree',
|
371
|
+
command_lines('worktree', 'list', '--porcelain').each do |w|
|
371
372
|
s = w.split("\s")
|
372
373
|
directory = s[1] if s[0] == 'worktree'
|
373
374
|
arr << [directory, s[1]] if s[0] == 'HEAD'
|
@@ -376,16 +377,16 @@ module Git
|
|
376
377
|
end
|
377
378
|
|
378
379
|
def worktree_add(dir, commitish = nil)
|
379
|
-
return command('worktree',
|
380
|
-
command('worktree',
|
380
|
+
return command('worktree', 'add', dir, commitish) if !commitish.nil?
|
381
|
+
command('worktree', 'add', dir)
|
381
382
|
end
|
382
383
|
|
383
384
|
def worktree_remove(dir)
|
384
|
-
command('worktree',
|
385
|
+
command('worktree', 'remove', dir)
|
385
386
|
end
|
386
387
|
|
387
388
|
def worktree_prune
|
388
|
-
command('worktree',
|
389
|
+
command('worktree', 'prune')
|
389
390
|
end
|
390
391
|
|
391
392
|
def list_files(ref_dir)
|
@@ -400,7 +401,7 @@ module Git
|
|
400
401
|
end
|
401
402
|
|
402
403
|
def branch_contains(commit, branch_name="")
|
403
|
-
command("branch",
|
404
|
+
command("branch", branch_name, "--contains", commit)
|
404
405
|
end
|
405
406
|
|
406
407
|
# returns hash
|
@@ -412,13 +413,15 @@ module Git
|
|
412
413
|
grep_opts = ['-n']
|
413
414
|
grep_opts << '-i' if opts[:ignore_case]
|
414
415
|
grep_opts << '-v' if opts[:invert_match]
|
416
|
+
grep_opts << '-E' if opts[:extended_regexp]
|
415
417
|
grep_opts << '-e'
|
416
418
|
grep_opts << string
|
417
419
|
grep_opts << opts[:object] if opts[:object].is_a?(String)
|
418
|
-
grep_opts
|
420
|
+
grep_opts.push('--', opts[:path_limiter]) if opts[:path_limiter].is_a?(String)
|
421
|
+
grep_opts.push('--', *opts[:path_limiter]) if opts[:path_limiter].is_a?(Array)
|
419
422
|
|
420
423
|
hsh = {}
|
421
|
-
command_lines('grep', grep_opts).each do |line|
|
424
|
+
command_lines('grep', *grep_opts).each do |line|
|
422
425
|
if m = /(.*?)\:(\d+)\:(.*)/.match(line)
|
423
426
|
hsh[m[1]] ||= []
|
424
427
|
hsh[m[1]] << [m[2].to_i, m[3]]
|
@@ -433,7 +436,7 @@ module Git
|
|
433
436
|
diff_opts << obj2 if obj2.is_a?(String)
|
434
437
|
diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
|
435
438
|
|
436
|
-
command('diff', diff_opts)
|
439
|
+
command('diff', *diff_opts)
|
437
440
|
end
|
438
441
|
|
439
442
|
def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
|
@@ -444,7 +447,7 @@ module Git
|
|
444
447
|
|
445
448
|
hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}
|
446
449
|
|
447
|
-
command_lines('diff', diff_opts).each do |file|
|
450
|
+
command_lines('diff', *diff_opts).each do |file|
|
448
451
|
(insertions, deletions, filename) = file.split("\t")
|
449
452
|
hsh[:total][:insertions] += insertions.to_i
|
450
453
|
hsh[:total][:deletions] += deletions.to_i
|
@@ -463,7 +466,7 @@ module Git
|
|
463
466
|
|
464
467
|
opts_arr << '--' << opts[:path] if opts[:path]
|
465
468
|
|
466
|
-
command_lines('diff', opts_arr).inject({}) do |memo, line|
|
469
|
+
command_lines('diff', *opts_arr).inject({}) do |memo, line|
|
467
470
|
status, path = line.split("\t")
|
468
471
|
memo[path] = status
|
469
472
|
memo
|
@@ -496,11 +499,11 @@ module Git
|
|
496
499
|
|
497
500
|
def ls_remote(location=nil, opts={})
|
498
501
|
arr_opts = []
|
499
|
-
arr_opts <<
|
502
|
+
arr_opts << '--refs' if opts[:refs]
|
500
503
|
arr_opts << (location || '.')
|
501
504
|
|
502
505
|
Hash.new{ |h,k| h[k] = {} }.tap do |hsh|
|
503
|
-
command_lines('ls-remote', arr_opts).each do |line|
|
506
|
+
command_lines('ls-remote', *arr_opts).each do |line|
|
504
507
|
(sha, info) = line.split("\t")
|
505
508
|
(ref, type, name) = info.split('/', 3)
|
506
509
|
type ||= 'head'
|
@@ -581,7 +584,7 @@ module Git
|
|
581
584
|
|
582
585
|
arr_opts << (path ? "#{objectish}:#{path}" : objectish)
|
583
586
|
|
584
|
-
command('show', arr_opts.compact, chomp: false)
|
587
|
+
command('show', *arr_opts.compact, chomp: false)
|
585
588
|
end
|
586
589
|
|
587
590
|
## WRITE COMMANDS ##
|
@@ -622,7 +625,7 @@ module Git
|
|
622
625
|
|
623
626
|
arr_opts.flatten!
|
624
627
|
|
625
|
-
command('add', arr_opts)
|
628
|
+
command('add', *arr_opts)
|
626
629
|
end
|
627
630
|
|
628
631
|
def remove(path = '.', opts = {})
|
@@ -636,7 +639,7 @@ module Git
|
|
636
639
|
arr_opts << path
|
637
640
|
end
|
638
641
|
|
639
|
-
command('rm', arr_opts)
|
642
|
+
command('rm', *arr_opts)
|
640
643
|
end
|
641
644
|
|
642
645
|
# Takes the commit message with the options and executes the commit command
|
@@ -678,14 +681,14 @@ module Git
|
|
678
681
|
arr_opts << '--no-gpg-sign'
|
679
682
|
end
|
680
683
|
|
681
|
-
command('commit', arr_opts)
|
684
|
+
command('commit', *arr_opts)
|
682
685
|
end
|
683
686
|
|
684
687
|
def reset(commit, opts = {})
|
685
688
|
arr_opts = []
|
686
689
|
arr_opts << '--hard' if opts[:hard]
|
687
690
|
arr_opts << commit if commit
|
688
|
-
command('reset', arr_opts)
|
691
|
+
command('reset', *arr_opts)
|
689
692
|
end
|
690
693
|
|
691
694
|
def clean(opts = {})
|
@@ -695,7 +698,7 @@ module Git
|
|
695
698
|
arr_opts << '-d' if opts[:d]
|
696
699
|
arr_opts << '-x' if opts[:x]
|
697
700
|
|
698
|
-
command('clean', arr_opts)
|
701
|
+
command('clean', *arr_opts)
|
699
702
|
end
|
700
703
|
|
701
704
|
def revert(commitish, opts = {})
|
@@ -706,19 +709,19 @@ module Git
|
|
706
709
|
arr_opts << '--no-edit' if opts[:no_edit]
|
707
710
|
arr_opts << commitish
|
708
711
|
|
709
|
-
command('revert', arr_opts)
|
712
|
+
command('revert', *arr_opts)
|
710
713
|
end
|
711
714
|
|
712
715
|
def apply(patch_file)
|
713
716
|
arr_opts = []
|
714
717
|
arr_opts << '--' << patch_file if patch_file
|
715
|
-
command('apply', arr_opts)
|
718
|
+
command('apply', *arr_opts)
|
716
719
|
end
|
717
720
|
|
718
721
|
def apply_mail(patch_file)
|
719
722
|
arr_opts = []
|
720
723
|
arr_opts << '--' << patch_file if patch_file
|
721
|
-
command('am', arr_opts)
|
724
|
+
command('am', *arr_opts)
|
722
725
|
end
|
723
726
|
|
724
727
|
def stashes_all
|
@@ -736,24 +739,24 @@ module Git
|
|
736
739
|
end
|
737
740
|
|
738
741
|
def stash_save(message)
|
739
|
-
output = command('stash save', message)
|
742
|
+
output = command('stash', 'save', message)
|
740
743
|
output =~ /HEAD is now at/
|
741
744
|
end
|
742
745
|
|
743
746
|
def stash_apply(id = nil)
|
744
747
|
if id
|
745
|
-
command('stash apply', id)
|
748
|
+
command('stash', 'apply', id)
|
746
749
|
else
|
747
|
-
command('stash apply')
|
750
|
+
command('stash', 'apply')
|
748
751
|
end
|
749
752
|
end
|
750
753
|
|
751
754
|
def stash_clear
|
752
|
-
command('stash clear')
|
755
|
+
command('stash', 'clear')
|
753
756
|
end
|
754
757
|
|
755
758
|
def stash_list
|
756
|
-
command('stash list')
|
759
|
+
command('stash', 'list')
|
757
760
|
end
|
758
761
|
|
759
762
|
def branch_new(branch)
|
@@ -780,14 +783,14 @@ module Git
|
|
780
783
|
arr_opts << branch
|
781
784
|
arr_opts << opts[:start_point] if opts[:start_point] && arr_opts.include?('-b')
|
782
785
|
|
783
|
-
command('checkout', arr_opts)
|
786
|
+
command('checkout', *arr_opts)
|
784
787
|
end
|
785
788
|
|
786
789
|
def checkout_file(version, file)
|
787
790
|
arr_opts = []
|
788
791
|
arr_opts << version
|
789
792
|
arr_opts << file
|
790
|
-
command('checkout', arr_opts)
|
793
|
+
command('checkout', *arr_opts)
|
791
794
|
end
|
792
795
|
|
793
796
|
def merge(branch, message = nil, opts = {})
|
@@ -795,8 +798,8 @@ module Git
|
|
795
798
|
arr_opts << '--no-commit' if opts[:no_commit]
|
796
799
|
arr_opts << '--no-ff' if opts[:no_ff]
|
797
800
|
arr_opts << '-m' << message if message
|
798
|
-
arr_opts +=
|
799
|
-
command('merge', arr_opts)
|
801
|
+
arr_opts += Array(branch)
|
802
|
+
command('merge', *arr_opts)
|
800
803
|
end
|
801
804
|
|
802
805
|
def merge_base(*args)
|
@@ -811,7 +814,7 @@ module Git
|
|
811
814
|
|
812
815
|
arg_opts += args
|
813
816
|
|
814
|
-
command('merge-base', arg_opts).lines.map(&:strip)
|
817
|
+
command('merge-base', *arg_opts).lines.map(&:strip)
|
815
818
|
end
|
816
819
|
|
817
820
|
def unmerged
|
@@ -845,7 +848,7 @@ module Git
|
|
845
848
|
arr_opts << name
|
846
849
|
arr_opts << url
|
847
850
|
|
848
|
-
command('remote', arr_opts)
|
851
|
+
command('remote', *arr_opts)
|
849
852
|
end
|
850
853
|
|
851
854
|
def remote_set_url(name, url)
|
@@ -853,7 +856,7 @@ module Git
|
|
853
856
|
arr_opts << name
|
854
857
|
arr_opts << url
|
855
858
|
|
856
|
-
command('remote', arr_opts)
|
859
|
+
command('remote', *arr_opts)
|
857
860
|
end
|
858
861
|
|
859
862
|
def remote_remove(name)
|
@@ -890,7 +893,7 @@ module Git
|
|
890
893
|
arr_opts << '-m' << (opts[:m] || opts[:message])
|
891
894
|
end
|
892
895
|
|
893
|
-
command('tag', arr_opts)
|
896
|
+
command('tag', *arr_opts)
|
894
897
|
end
|
895
898
|
|
896
899
|
def fetch(remote, opts)
|
@@ -906,7 +909,7 @@ module Git
|
|
906
909
|
arr_opts << remote if remote
|
907
910
|
arr_opts << opts[:ref] if opts[:ref]
|
908
911
|
|
909
|
-
command('fetch', arr_opts)
|
912
|
+
command('fetch', *arr_opts)
|
910
913
|
end
|
911
914
|
|
912
915
|
def push(remote, branch = 'master', opts = {})
|
@@ -920,10 +923,10 @@ module Git
|
|
920
923
|
arr_opts << remote
|
921
924
|
|
922
925
|
if opts[:mirror]
|
923
|
-
command('push', arr_opts)
|
926
|
+
command('push', *arr_opts)
|
924
927
|
else
|
925
|
-
command('push', arr_opts
|
926
|
-
command('push',
|
928
|
+
command('push', *arr_opts, branch)
|
929
|
+
command('push', '--tags', *arr_opts) if opts[:tags]
|
927
930
|
end
|
928
931
|
end
|
929
932
|
|
@@ -951,7 +954,7 @@ module Git
|
|
951
954
|
arr_opts = []
|
952
955
|
arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
|
953
956
|
arr_opts += [treeish]
|
954
|
-
command('read-tree', arr_opts)
|
957
|
+
command('read-tree', *arr_opts)
|
955
958
|
end
|
956
959
|
|
957
960
|
def write_tree
|
@@ -968,7 +971,7 @@ module Git
|
|
968
971
|
arr_opts << tree
|
969
972
|
arr_opts << '-p' << opts[:parent] if opts[:parent]
|
970
973
|
arr_opts += [opts[:parents]].map { |p| ['-p', p] }.flatten if opts[:parents]
|
971
|
-
command('commit-tree', arr_opts, redirect: "< #{escape t.path}")
|
974
|
+
command('commit-tree', *arr_opts, redirect: "< #{escape t.path}")
|
972
975
|
end
|
973
976
|
|
974
977
|
def update_ref(branch, commit)
|
@@ -982,7 +985,7 @@ module Git
|
|
982
985
|
arr_opts << "--all" if opts[:all]
|
983
986
|
arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
|
984
987
|
|
985
|
-
command('checkout-index', arr_opts)
|
988
|
+
command('checkout-index', *arr_opts)
|
986
989
|
end
|
987
990
|
|
988
991
|
# creates an archive file
|
@@ -1014,7 +1017,7 @@ module Git
|
|
1014
1017
|
arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
|
1015
1018
|
arr_opts << sha
|
1016
1019
|
arr_opts << '--' << opts[:path] if opts[:path]
|
1017
|
-
command('archive', arr_opts, redirect: " > #{escape file}")
|
1020
|
+
command('archive', *arr_opts, redirect: " > #{escape file}")
|
1018
1021
|
if opts[:add_gzip]
|
1019
1022
|
file_content = File.read(file)
|
1020
1023
|
Zlib::GzipWriter.open(file) do |gz|
|
@@ -1103,52 +1106,46 @@ module Git
|
|
1103
1106
|
restore_git_system_env_variables()
|
1104
1107
|
end
|
1105
1108
|
|
1106
|
-
def command(cmd,
|
1109
|
+
def command(*cmd, redirect: '', chomp: true, &block)
|
1107
1110
|
Git::Lib.warn_if_old_command(self)
|
1108
1111
|
|
1109
|
-
|
1110
|
-
if opts.last.is_a?(Hash)
|
1111
|
-
command_opts.merge!(opts.pop)
|
1112
|
-
end
|
1113
|
-
command_opts.keys.each do |k|
|
1114
|
-
raise ArgumentError.new("Unsupported option: #{k}") unless [:chomp, :redirect].include?(k)
|
1115
|
-
end
|
1112
|
+
raise 'cmd can not include a nested array' if cmd.any? { |o| o.is_a? Array }
|
1116
1113
|
|
1117
1114
|
global_opts = []
|
1118
1115
|
global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
|
1119
1116
|
global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
|
1120
|
-
global_opts <<
|
1121
|
-
global_opts <<
|
1117
|
+
global_opts << '-c' << 'core.quotePath=true'
|
1118
|
+
global_opts << '-c' << 'color.ui=false'
|
1122
1119
|
|
1123
|
-
|
1120
|
+
escaped_cmd = cmd.map { |part| escape(part) }.join(' ')
|
1124
1121
|
|
1125
|
-
global_opts = global_opts.
|
1122
|
+
global_opts = global_opts.map { |s| escape(s) }.join(' ')
|
1126
1123
|
|
1127
|
-
git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{
|
1124
|
+
git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{escaped_cmd} #{redirect} 2>&1"
|
1128
1125
|
|
1129
1126
|
output = nil
|
1130
1127
|
|
1131
1128
|
command_thread = nil;
|
1132
1129
|
|
1133
|
-
|
1130
|
+
status = nil
|
1134
1131
|
|
1135
1132
|
with_custom_env_variables do
|
1136
1133
|
command_thread = Thread.new do
|
1137
1134
|
output = run_command(git_cmd, &block)
|
1138
|
-
|
1135
|
+
status = $?
|
1139
1136
|
end
|
1140
1137
|
command_thread.join
|
1141
1138
|
end
|
1142
1139
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
@logger.debug(output)
|
1146
|
-
end
|
1140
|
+
@logger.info(git_cmd)
|
1141
|
+
@logger.debug(output)
|
1147
1142
|
|
1148
|
-
|
1149
|
-
|
1143
|
+
if status.exitstatus > 1 || (status.exitstatus == 1 && output != '')
|
1144
|
+
result = Git::CommandLineResult.new(git_cmd, status, output, '')
|
1145
|
+
raise Git::FailedError.new(result)
|
1146
|
+
end
|
1150
1147
|
|
1151
|
-
output.chomp! if output &&
|
1148
|
+
output.chomp! if output && chomp && !block_given?
|
1152
1149
|
|
1153
1150
|
output
|
1154
1151
|
end
|
@@ -1161,7 +1158,7 @@ module Git
|
|
1161
1158
|
def diff_as_hash(diff_command, opts=[])
|
1162
1159
|
# update index before diffing to avoid spurious diffs
|
1163
1160
|
command('status')
|
1164
|
-
command_lines(diff_command, opts).inject({}) do |memo, line|
|
1161
|
+
command_lines(diff_command, *opts).inject({}) do |memo, line|
|
1165
1162
|
info, file = line.split("\t")
|
1166
1163
|
mode_src, mode_dest, sha_src, sha_dest, type = info.split
|
1167
1164
|
|
@@ -1205,7 +1202,10 @@ module Git
|
|
1205
1202
|
arr_opts = []
|
1206
1203
|
|
1207
1204
|
arr_opts << opts[:object] if opts[:object].is_a? String
|
1208
|
-
|
1205
|
+
if opts[:path_limiter]
|
1206
|
+
arr_opts << '--'
|
1207
|
+
arr_opts += Array(opts[:path_limiter])
|
1208
|
+
end
|
1209
1209
|
arr_opts
|
1210
1210
|
end
|
1211
1211
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git/git_execute_error'
|
4
|
+
|
5
|
+
module Git
|
6
|
+
# This error is raised when a git command exits because of an uncaught signal
|
7
|
+
#
|
8
|
+
# The git command executed, status, stdout, and stderr are available from this
|
9
|
+
# object. The #message includes the git command, the status of the process, and
|
10
|
+
# the stderr of the process.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
class SignaledError < Git::GitExecuteError
|
15
|
+
# Create a SignaledError object
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# `kill -9 $$` # set $? appropriately for this example
|
19
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, '', "killed")
|
20
|
+
# error = Git::SignaledError.new(result)
|
21
|
+
# error.message #=>
|
22
|
+
# "[\"git\", \"status\"]\nstatus: pid 88811 SIGKILL (signal 9)\nstderr: \"killed\""
|
23
|
+
#
|
24
|
+
# @param result [Git::CommandLineResult] the result of the git command including the git command, status, stdout, and stderr
|
25
|
+
#
|
26
|
+
def initialize(result)
|
27
|
+
super("#{result.git_cmd}\nstatus: #{result.status}\nstderr: #{result.stderr.inspect}")
|
28
|
+
@result = result
|
29
|
+
end
|
30
|
+
|
31
|
+
# @attribute [r] result
|
32
|
+
#
|
33
|
+
# The result of the git command including the git command, status, and output
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# `kill -9 $$` # set $? appropriately for this example
|
37
|
+
# result = Git::CommandLineResult.new(%w[git status], $?, '', "killed")
|
38
|
+
# error = Git::SignaledError.new(result)
|
39
|
+
# error.result #=>
|
40
|
+
# #<Git::CommandLineResult:0x000000010470f6e8
|
41
|
+
# @git_cmd=["git", "status"],
|
42
|
+
# @status=#<Process::Status: pid 88811 SIGKILL (signal 9)>,
|
43
|
+
# @stderr="killed",
|
44
|
+
# @stdout="">
|
45
|
+
#
|
46
|
+
# @return [Git::CommandLineResult]
|
47
|
+
#
|
48
|
+
attr_reader :result
|
49
|
+
end
|
50
|
+
end
|
data/lib/git/version.rb
CHANGED
data/lib/git.rb
CHANGED
@@ -7,10 +7,13 @@ require 'git/author'
|
|
7
7
|
require 'git/base'
|
8
8
|
require 'git/branch'
|
9
9
|
require 'git/branches'
|
10
|
+
require 'git/command_line_result'
|
10
11
|
require 'git/config'
|
11
12
|
require 'git/diff'
|
12
13
|
require 'git/encoding_utils'
|
13
14
|
require 'git/escaped_path'
|
15
|
+
require 'git/failed_error'
|
16
|
+
require 'git/git_execute_error'
|
14
17
|
require 'git/index'
|
15
18
|
require 'git/lib'
|
16
19
|
require 'git/log'
|
@@ -18,6 +21,7 @@ require 'git/object'
|
|
18
21
|
require 'git/path'
|
19
22
|
require 'git/remote'
|
20
23
|
require 'git/repository'
|
24
|
+
require 'git/signaled_error'
|
21
25
|
require 'git/status'
|
22
26
|
require 'git/stash'
|
23
27
|
require 'git/stashes'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Chacon and others
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -189,10 +189,13 @@ files:
|
|
189
189
|
- lib/git/base/factory.rb
|
190
190
|
- lib/git/branch.rb
|
191
191
|
- lib/git/branches.rb
|
192
|
+
- lib/git/command_line_result.rb
|
192
193
|
- lib/git/config.rb
|
193
194
|
- lib/git/diff.rb
|
194
195
|
- lib/git/encoding_utils.rb
|
195
196
|
- lib/git/escaped_path.rb
|
197
|
+
- lib/git/failed_error.rb
|
198
|
+
- lib/git/git_execute_error.rb
|
196
199
|
- lib/git/index.rb
|
197
200
|
- lib/git/lib.rb
|
198
201
|
- lib/git/log.rb
|
@@ -200,6 +203,7 @@ files:
|
|
200
203
|
- lib/git/path.rb
|
201
204
|
- lib/git/remote.rb
|
202
205
|
- lib/git/repository.rb
|
206
|
+
- lib/git/signaled_error.rb
|
203
207
|
- lib/git/stash.rb
|
204
208
|
- lib/git/stashes.rb
|
205
209
|
- lib/git/status.rb
|
@@ -231,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
235
|
version: '0'
|
232
236
|
requirements:
|
233
237
|
- git 1.6.0.0, or greater
|
234
|
-
rubygems_version: 3.
|
238
|
+
rubygems_version: 3.4.1
|
235
239
|
signing_key:
|
236
240
|
specification_version: 4
|
237
241
|
summary: An API to create, read, and manipulate Git repositories
|