git 1.13.2 → 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 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