git 1.13.2 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29b8c6b76f613f41bcddf2786fe9b164ef2168f265f3b8fdccb9f8f4ead52669
4
- data.tar.gz: b0f66b11fd1a2eba3640bfa42ff842dcfbd52ab30455026b97ebecad8fd86f0c
3
+ metadata.gz: 344c98cd98670d4afa26aae12680f28ad857f1fdbca4384a10c9cf7ed7937a8a
4
+ data.tar.gz: 9d857e44f2457f6c5208bebca6935991c2e88fbd82b2c482c570cd7afcca7c38
5
5
  SHA512:
6
- metadata.gz: bb85d50e45a905b7e71617da29f6194e478b17aed237237e0dd53066a5182c328d4e992494a3b7d26df47223c0e601733400e62d04b7e9fffdf8993c22cd2fb5
7
- data.tar.gz: ee9d9edbd87615caee4cc073acd2df9a047b46d5ba117997f193a98d28374d214e2994018d3bed10c0e4acad7cd913ba39da25ecc2b0fd973863930f19d0f129
6
+ metadata.gz: 6fd40652aa02ad36238522ee2210ad7c01ced240f0a1b91f2de3e6baefe93dd0a20fb22b80821ee45bf974d73a3cc346e4a5adbaa2322384b57e2bb0251d491d
7
+ data.tar.gz: 0c8d86fe09a9e4f8d06c1d8bb0abf05eff45a2746450253ccf751163e4340b873df4eff2dbfb0711aad30c61303e0c692802a378bceb46a26a1e17ba08927268
data/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@
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
+
8
23
  ## v1.13.2 (2023-02-02)
9
24
 
10
25
  [Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.13.1..v1.13.2)
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 "#{File.expand_path(File.dirname(__FILE__))}/lib/git/version"
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 'git config --global user.email "git@example.com"' if `git config user.email`.empty?
11
- sh 'git config --global user.name "GitExample"' if `git config user.name`.empty?
10
+ sh 'ruby bin/test'
12
11
 
13
- require File.dirname(__FILE__) + '/tests/all_tests.rb'
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
- if options[:log]
94
- @logger = options[:log]
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
@@ -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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Git
4
+ # This error is raised when a git command fails
5
+ #
6
+ class GitExecuteError < StandardError; end
7
+ 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
@@ -370,7 +368,7 @@ module Git
370
368
  # HEAD b8c63206f8d10f57892060375a86ae911fad356e
371
369
  # detached
372
370
  #
373
- command_lines('worktree',['list', '--porcelain']).each do |w|
371
+ command_lines('worktree', 'list', '--porcelain').each do |w|
374
372
  s = w.split("\s")
375
373
  directory = s[1] if s[0] == 'worktree'
376
374
  arr << [directory, s[1]] if s[0] == 'HEAD'
@@ -379,16 +377,16 @@ module Git
379
377
  end
380
378
 
381
379
  def worktree_add(dir, commitish = nil)
382
- return command('worktree', ['add', dir, commitish]) if !commitish.nil?
383
- command('worktree', ['add', dir])
380
+ return command('worktree', 'add', dir, commitish) if !commitish.nil?
381
+ command('worktree', 'add', dir)
384
382
  end
385
383
 
386
384
  def worktree_remove(dir)
387
- command('worktree', ['remove', dir])
385
+ command('worktree', 'remove', dir)
388
386
  end
389
387
 
390
388
  def worktree_prune
391
- command('worktree', ['prune'])
389
+ command('worktree', 'prune')
392
390
  end
393
391
 
394
392
  def list_files(ref_dir)
@@ -403,7 +401,7 @@ module Git
403
401
  end
404
402
 
405
403
  def branch_contains(commit, branch_name="")
406
- command("branch", [branch_name, "--contains", commit])
404
+ command("branch", branch_name, "--contains", commit)
407
405
  end
408
406
 
409
407
  # returns hash
@@ -415,13 +413,15 @@ module Git
415
413
  grep_opts = ['-n']
416
414
  grep_opts << '-i' if opts[:ignore_case]
417
415
  grep_opts << '-v' if opts[:invert_match]
416
+ grep_opts << '-E' if opts[:extended_regexp]
418
417
  grep_opts << '-e'
419
418
  grep_opts << string
420
419
  grep_opts << opts[:object] if opts[:object].is_a?(String)
421
- grep_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
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)
422
422
 
423
423
  hsh = {}
424
- command_lines('grep', grep_opts).each do |line|
424
+ command_lines('grep', *grep_opts).each do |line|
425
425
  if m = /(.*?)\:(\d+)\:(.*)/.match(line)
426
426
  hsh[m[1]] ||= []
427
427
  hsh[m[1]] << [m[2].to_i, m[3]]
@@ -436,7 +436,7 @@ module Git
436
436
  diff_opts << obj2 if obj2.is_a?(String)
437
437
  diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
438
438
 
439
- command('diff', diff_opts)
439
+ command('diff', *diff_opts)
440
440
  end
441
441
 
442
442
  def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
@@ -447,7 +447,7 @@ module Git
447
447
 
448
448
  hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}
449
449
 
450
- command_lines('diff', diff_opts).each do |file|
450
+ command_lines('diff', *diff_opts).each do |file|
451
451
  (insertions, deletions, filename) = file.split("\t")
452
452
  hsh[:total][:insertions] += insertions.to_i
453
453
  hsh[:total][:deletions] += deletions.to_i
@@ -466,7 +466,7 @@ module Git
466
466
 
467
467
  opts_arr << '--' << opts[:path] if opts[:path]
468
468
 
469
- command_lines('diff', opts_arr).inject({}) do |memo, line|
469
+ command_lines('diff', *opts_arr).inject({}) do |memo, line|
470
470
  status, path = line.split("\t")
471
471
  memo[path] = status
472
472
  memo
@@ -499,11 +499,11 @@ module Git
499
499
 
500
500
  def ls_remote(location=nil, opts={})
501
501
  arr_opts = []
502
- arr_opts << ['--refs'] if opts[:refs]
502
+ arr_opts << '--refs' if opts[:refs]
503
503
  arr_opts << (location || '.')
504
504
 
505
505
  Hash.new{ |h,k| h[k] = {} }.tap do |hsh|
506
- command_lines('ls-remote', arr_opts).each do |line|
506
+ command_lines('ls-remote', *arr_opts).each do |line|
507
507
  (sha, info) = line.split("\t")
508
508
  (ref, type, name) = info.split('/', 3)
509
509
  type ||= 'head'
@@ -584,7 +584,7 @@ module Git
584
584
 
585
585
  arr_opts << (path ? "#{objectish}:#{path}" : objectish)
586
586
 
587
- command('show', arr_opts.compact, chomp: false)
587
+ command('show', *arr_opts.compact, chomp: false)
588
588
  end
589
589
 
590
590
  ## WRITE COMMANDS ##
@@ -625,7 +625,7 @@ module Git
625
625
 
626
626
  arr_opts.flatten!
627
627
 
628
- command('add', arr_opts)
628
+ command('add', *arr_opts)
629
629
  end
630
630
 
631
631
  def remove(path = '.', opts = {})
@@ -639,7 +639,7 @@ module Git
639
639
  arr_opts << path
640
640
  end
641
641
 
642
- command('rm', arr_opts)
642
+ command('rm', *arr_opts)
643
643
  end
644
644
 
645
645
  # Takes the commit message with the options and executes the commit command
@@ -681,14 +681,14 @@ module Git
681
681
  arr_opts << '--no-gpg-sign'
682
682
  end
683
683
 
684
- command('commit', arr_opts)
684
+ command('commit', *arr_opts)
685
685
  end
686
686
 
687
687
  def reset(commit, opts = {})
688
688
  arr_opts = []
689
689
  arr_opts << '--hard' if opts[:hard]
690
690
  arr_opts << commit if commit
691
- command('reset', arr_opts)
691
+ command('reset', *arr_opts)
692
692
  end
693
693
 
694
694
  def clean(opts = {})
@@ -698,7 +698,7 @@ module Git
698
698
  arr_opts << '-d' if opts[:d]
699
699
  arr_opts << '-x' if opts[:x]
700
700
 
701
- command('clean', arr_opts)
701
+ command('clean', *arr_opts)
702
702
  end
703
703
 
704
704
  def revert(commitish, opts = {})
@@ -709,19 +709,19 @@ module Git
709
709
  arr_opts << '--no-edit' if opts[:no_edit]
710
710
  arr_opts << commitish
711
711
 
712
- command('revert', arr_opts)
712
+ command('revert', *arr_opts)
713
713
  end
714
714
 
715
715
  def apply(patch_file)
716
716
  arr_opts = []
717
717
  arr_opts << '--' << patch_file if patch_file
718
- command('apply', arr_opts)
718
+ command('apply', *arr_opts)
719
719
  end
720
720
 
721
721
  def apply_mail(patch_file)
722
722
  arr_opts = []
723
723
  arr_opts << '--' << patch_file if patch_file
724
- command('am', arr_opts)
724
+ command('am', *arr_opts)
725
725
  end
726
726
 
727
727
  def stashes_all
@@ -739,24 +739,24 @@ module Git
739
739
  end
740
740
 
741
741
  def stash_save(message)
742
- output = command('stash save', message)
742
+ output = command('stash', 'save', message)
743
743
  output =~ /HEAD is now at/
744
744
  end
745
745
 
746
746
  def stash_apply(id = nil)
747
747
  if id
748
- command('stash apply', id)
748
+ command('stash', 'apply', id)
749
749
  else
750
- command('stash apply')
750
+ command('stash', 'apply')
751
751
  end
752
752
  end
753
753
 
754
754
  def stash_clear
755
- command('stash clear')
755
+ command('stash', 'clear')
756
756
  end
757
757
 
758
758
  def stash_list
759
- command('stash list')
759
+ command('stash', 'list')
760
760
  end
761
761
 
762
762
  def branch_new(branch)
@@ -783,14 +783,14 @@ module Git
783
783
  arr_opts << branch
784
784
  arr_opts << opts[:start_point] if opts[:start_point] && arr_opts.include?('-b')
785
785
 
786
- command('checkout', arr_opts)
786
+ command('checkout', *arr_opts)
787
787
  end
788
788
 
789
789
  def checkout_file(version, file)
790
790
  arr_opts = []
791
791
  arr_opts << version
792
792
  arr_opts << file
793
- command('checkout', arr_opts)
793
+ command('checkout', *arr_opts)
794
794
  end
795
795
 
796
796
  def merge(branch, message = nil, opts = {})
@@ -798,8 +798,8 @@ module Git
798
798
  arr_opts << '--no-commit' if opts[:no_commit]
799
799
  arr_opts << '--no-ff' if opts[:no_ff]
800
800
  arr_opts << '-m' << message if message
801
- arr_opts += [branch]
802
- command('merge', arr_opts)
801
+ arr_opts += Array(branch)
802
+ command('merge', *arr_opts)
803
803
  end
804
804
 
805
805
  def merge_base(*args)
@@ -814,7 +814,7 @@ module Git
814
814
 
815
815
  arg_opts += args
816
816
 
817
- command('merge-base', arg_opts).lines.map(&:strip)
817
+ command('merge-base', *arg_opts).lines.map(&:strip)
818
818
  end
819
819
 
820
820
  def unmerged
@@ -848,7 +848,7 @@ module Git
848
848
  arr_opts << name
849
849
  arr_opts << url
850
850
 
851
- command('remote', arr_opts)
851
+ command('remote', *arr_opts)
852
852
  end
853
853
 
854
854
  def remote_set_url(name, url)
@@ -856,7 +856,7 @@ module Git
856
856
  arr_opts << name
857
857
  arr_opts << url
858
858
 
859
- command('remote', arr_opts)
859
+ command('remote', *arr_opts)
860
860
  end
861
861
 
862
862
  def remote_remove(name)
@@ -893,7 +893,7 @@ module Git
893
893
  arr_opts << '-m' << (opts[:m] || opts[:message])
894
894
  end
895
895
 
896
- command('tag', arr_opts)
896
+ command('tag', *arr_opts)
897
897
  end
898
898
 
899
899
  def fetch(remote, opts)
@@ -909,7 +909,7 @@ module Git
909
909
  arr_opts << remote if remote
910
910
  arr_opts << opts[:ref] if opts[:ref]
911
911
 
912
- command('fetch', arr_opts)
912
+ command('fetch', *arr_opts)
913
913
  end
914
914
 
915
915
  def push(remote, branch = 'master', opts = {})
@@ -923,10 +923,10 @@ module Git
923
923
  arr_opts << remote
924
924
 
925
925
  if opts[:mirror]
926
- command('push', arr_opts)
926
+ command('push', *arr_opts)
927
927
  else
928
- command('push', arr_opts + [branch])
929
- command('push', ['--tags'] + arr_opts) if opts[:tags]
928
+ command('push', *arr_opts, branch)
929
+ command('push', '--tags', *arr_opts) if opts[:tags]
930
930
  end
931
931
  end
932
932
 
@@ -954,7 +954,7 @@ module Git
954
954
  arr_opts = []
955
955
  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
956
956
  arr_opts += [treeish]
957
- command('read-tree', arr_opts)
957
+ command('read-tree', *arr_opts)
958
958
  end
959
959
 
960
960
  def write_tree
@@ -971,7 +971,7 @@ module Git
971
971
  arr_opts << tree
972
972
  arr_opts << '-p' << opts[:parent] if opts[:parent]
973
973
  arr_opts += [opts[:parents]].map { |p| ['-p', p] }.flatten if opts[:parents]
974
- command('commit-tree', arr_opts, redirect: "< #{escape t.path}")
974
+ command('commit-tree', *arr_opts, redirect: "< #{escape t.path}")
975
975
  end
976
976
 
977
977
  def update_ref(branch, commit)
@@ -985,7 +985,7 @@ module Git
985
985
  arr_opts << "--all" if opts[:all]
986
986
  arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
987
987
 
988
- command('checkout-index', arr_opts)
988
+ command('checkout-index', *arr_opts)
989
989
  end
990
990
 
991
991
  # creates an archive file
@@ -1017,7 +1017,7 @@ module Git
1017
1017
  arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
1018
1018
  arr_opts << sha
1019
1019
  arr_opts << '--' << opts[:path] if opts[:path]
1020
- command('archive', arr_opts, redirect: " > #{escape file}")
1020
+ command('archive', *arr_opts, redirect: " > #{escape file}")
1021
1021
  if opts[:add_gzip]
1022
1022
  file_content = File.read(file)
1023
1023
  Zlib::GzipWriter.open(file) do |gz|
@@ -1106,52 +1106,46 @@ module Git
1106
1106
  restore_git_system_env_variables()
1107
1107
  end
1108
1108
 
1109
- def command(cmd, *opts, &block)
1109
+ def command(*cmd, redirect: '', chomp: true, &block)
1110
1110
  Git::Lib.warn_if_old_command(self)
1111
1111
 
1112
- command_opts = { chomp: true, redirect: '' }
1113
- if opts.last.is_a?(Hash)
1114
- command_opts.merge!(opts.pop)
1115
- end
1116
- command_opts.keys.each do |k|
1117
- raise ArgumentError.new("Unsupported option: #{k}") unless [:chomp, :redirect].include?(k)
1118
- end
1112
+ raise 'cmd can not include a nested array' if cmd.any? { |o| o.is_a? Array }
1119
1113
 
1120
1114
  global_opts = []
1121
1115
  global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
1122
1116
  global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
1123
- global_opts << %w[-c core.quotePath=true]
1124
- global_opts << %w[-c color.ui=false]
1117
+ global_opts << '-c' << 'core.quotePath=true'
1118
+ global_opts << '-c' << 'color.ui=false'
1125
1119
 
1126
- opts = [opts].flatten.map {|s| escape(s) }.join(' ')
1120
+ escaped_cmd = cmd.map { |part| escape(part) }.join(' ')
1127
1121
 
1128
- global_opts = global_opts.flatten.map {|s| escape(s) }.join(' ')
1122
+ global_opts = global_opts.map { |s| escape(s) }.join(' ')
1129
1123
 
1130
- git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{cmd} #{opts} #{command_opts[:redirect]} 2>&1"
1124
+ git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{escaped_cmd} #{redirect} 2>&1"
1131
1125
 
1132
1126
  output = nil
1133
1127
 
1134
1128
  command_thread = nil;
1135
1129
 
1136
- exitstatus = nil
1130
+ status = nil
1137
1131
 
1138
1132
  with_custom_env_variables do
1139
1133
  command_thread = Thread.new do
1140
1134
  output = run_command(git_cmd, &block)
1141
- exitstatus = $?.exitstatus
1135
+ status = $?
1142
1136
  end
1143
1137
  command_thread.join
1144
1138
  end
1145
1139
 
1146
- if @logger
1147
- @logger.info(git_cmd)
1148
- @logger.debug(output)
1149
- end
1140
+ @logger.info(git_cmd)
1141
+ @logger.debug(output)
1150
1142
 
1151
- raise Git::GitExecuteError, "#{git_cmd}:#{output}" if
1152
- exitstatus > 1 || (exitstatus == 1 && output != '')
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
1153
1147
 
1154
- output.chomp! if output && command_opts[:chomp] && !block_given?
1148
+ output.chomp! if output && chomp && !block_given?
1155
1149
 
1156
1150
  output
1157
1151
  end
@@ -1164,7 +1158,7 @@ module Git
1164
1158
  def diff_as_hash(diff_command, opts=[])
1165
1159
  # update index before diffing to avoid spurious diffs
1166
1160
  command('status')
1167
- command_lines(diff_command, opts).inject({}) do |memo, line|
1161
+ command_lines(diff_command, *opts).inject({}) do |memo, line|
1168
1162
  info, file = line.split("\t")
1169
1163
  mode_src, mode_dest, sha_src, sha_dest, type = info.split
1170
1164
 
@@ -1208,7 +1202,10 @@ module Git
1208
1202
  arr_opts = []
1209
1203
 
1210
1204
  arr_opts << opts[:object] if opts[:object].is_a? String
1211
- arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter]
1205
+ if opts[:path_limiter]
1206
+ arr_opts << '--'
1207
+ arr_opts += Array(opts[:path_limiter])
1208
+ end
1212
1209
  arr_opts
1213
1210
  end
1214
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
@@ -1,5 +1,5 @@
1
1
  module Git
2
2
  # The current gem version
3
3
  # @return [String] the current gem version.
4
- VERSION='1.13.2'
4
+ VERSION='1.14.0'
5
5
  end
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.13.2
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-02-02 00:00:00.000000000 Z
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