Class: Git::Lib

Inherits:
Object
  • Object
show all
Defined in:
lib/git/lib.rb

Constant Summary collapse

CAT_FILE_HEADER_LINE =
/\A(?<key>\w+) (?<value>.*)\z/
BRANCH_LINE_REGEXP =
/
  ^
    # Prefix indicates if this branch is checked out. The prefix is one of:
    (?:
      (?<current>\*[[:blank:]]) |  # Current branch (checked out in the current worktree)
      (?<worktree>\+[[:blank:]]) | # Branch checked out in a different worktree
      [[:blank:]]{2}               # Branch not checked out
    )

    # The branch's full refname
    (?:
      (?<not_a_branch>\(not[[:blank:]]a[[:blank:]]branch\)) |
      (?:\(HEAD[[:blank:]]detached[[:blank:]]at[[:blank:]](?<detached_ref>[^\)]+)\)) |
      (?<refname>[^[[:blank:]]]+)
    )

    # Optional symref
    # If this ref is a symbolic reference, this is the ref referenced
    (?:
      [[:blank:]]->[[:blank:]](?<symref>.*)
    )?
  $
/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base, logger) ⇒ Lib #initialize(base, logger) ⇒ Lib

Create a new Git::Lib object

Overloads:

  • #initialize(base, logger) ⇒ Lib

    Parameters:

    • base (Hash)

      the hash containing paths to the Git working copy, the Git repository directory, and the Git index file.

    • logger (Logger)

    Options Hash (base):

    • :working_directory (Pathname)
    • :repository (Pathname)
    • :index (Pathname)
  • #initialize(base, logger) ⇒ Lib

    Parameters:

    • base (#dir, #repo, #index)

      an object with methods to get the Git worktree (#dir), the Git repository directory (#repo), and the Git index file (#index).

    • logger (Logger)


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/git/lib.rb', line 59

def initialize(base = nil, logger = nil)
  @git_dir = nil
  @git_index_file = nil
  @git_work_dir = nil
  @path = nil
  @logger = logger || Logger.new(nil)

  if base.is_a?(Git::Base)
    @git_dir = base.repo.path
    @git_index_file = base.index.path if base.index
    @git_work_dir = base.dir.path if base.dir
  elsif base.is_a?(Hash)
    @git_dir = base[:repository]
    @git_index_file = base[:index]
    @git_work_dir = base[:working_directory]
  end
end

Instance Attribute Details

#git_dirPathname (readonly)

The path to the Git repository directory. The default is "#{git_work_dir}/.git".

Returns:

  • (Pathname)

    the Git repository directory.

See Also:

  • repository](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefrepositoryarepository)


28
29
30
# File 'lib/git/lib.rb', line 28

def git_dir
  @git_dir
end

#git_index_filePathname (readonly)

The Git index file used to stage changes (using git add) before they are committed.

Returns:

  • (Pathname)

    the Git index file

See Also:

  • index file](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefindexaindex)


37
38
39
# File 'lib/git/lib.rb', line 37

def git_index_file
  @git_index_file
end

#git_work_dirPathname (readonly)

The path to the Git working copy. The default is '"./.git"'.

Returns:

  • (Pathname)

    the path to the Git working copy.

See Also:

  • working tree](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefworkingtreeaworkingtree)


19
20
21
# File 'lib/git/lib.rb', line 19

def git_work_dir
  @git_work_dir
end

Class Method Details

.warn_if_old_command(lib)



1353
1354
1355
1356
1357
1358
1359
1360
# File 'lib/git/lib.rb', line 1353

def self.warn_if_old_command(lib)
  return true if @version_checked
  @version_checked = true
  unless lib.meets_required_version?
    $stderr.puts "[WARNING] The git gem requires git #{lib.required_command_version.join('.')} or later, but only found #{lib.current_command_version.join('.')}. You should probably upgrade."
  end
  true
end

Instance Method Details

#add(paths = '.', options = {})

Update the index from the current worktree to prepare the for the next commit

Examples:

lib.add('path/to/file')
lib.add(['path/to/file1','path/to/file2'])
lib.add(:all => true)

Parameters:

  • paths (String, Array<String>) (defaults to: '.')

    files to be added to the repository (relative to the worktree root)

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :all (Boolean)

    Add, modify, and remove index entries to match the worktree

  • :force (Boolean)

    Allow adding otherwise ignored files



859
860
861
862
863
864
865
866
867
868
869
870
871
872
# File 'lib/git/lib.rb', line 859

def add(paths='.',options={})
  arr_opts = []

  arr_opts << '--all' if options[:all]
  arr_opts << '--force' if options[:force]

  arr_opts << '--'

  arr_opts << paths

  arr_opts.flatten!

  command('add', *arr_opts)
end

#apply(patch_file)



967
968
969
970
971
# File 'lib/git/lib.rb', line 967

def apply(patch_file)
  arr_opts = []
  arr_opts << '--' << patch_file if patch_file
  command('apply', *arr_opts)
end

#apply_mail(patch_file)



973
974
975
976
977
# File 'lib/git/lib.rb', line 973

def apply_mail(patch_file)
  arr_opts = []
  arr_opts << '--' << patch_file if patch_file
  command('am', *arr_opts)
end

#archive(sha, file = nil, opts = {})

creates an archive file

options :format (zip, tar) :prefix :remote :path



1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
# File 'lib/git/lib.rb', line 1285

def archive(sha, file = nil, opts = {})
  opts[:format] ||= 'zip'

  if opts[:format] == 'tgz'
    opts[:format] = 'tar'
    opts[:add_gzip] = true
  end

  if !file
    tempfile = Tempfile.new('archive')
    file = tempfile.path
    # delete it now, before we write to it, so that Ruby doesn't delete it
    # when it finalizes the Tempfile.
    tempfile.close!
  end

  arr_opts = []
  arr_opts << "--format=#{opts[:format]}" if opts[:format]
  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
  arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
  arr_opts << sha
  arr_opts << '--' << opts[:path] if opts[:path]

  f = File.open(file, 'wb')
  command('archive', *arr_opts, out: f)
  f.close

  if opts[:add_gzip]
    file_content = File.read(file)
    Zlib::GzipWriter.open(file) do |gz|
      gz.write(file_content)
    end
  end
  return file
end

#assert_args_are_not_options(arg_name, *args)

This method returns an undefined value.

Validate that the given arguments cannot be mistaken for a command-line option

Parameters:

  • arg_name (String)

    the name of the arguments to mention in the error message

  • args (Array<String, nil>)

    the arguments to validate

Raises:

  • (ArgumentError)

    if any of the parameters are a string starting with a hyphen



640
641
642
643
644
645
# File 'lib/git/lib.rb', line 640

def assert_args_are_not_options(arg_name, *args)
  invalid_args = args.select { |arg| arg&.start_with?('-') }
  if invalid_args.any?
    raise ArgumentError, "Invalid #{arg_name}: '#{invalid_args.join("', '")}'"
  end
end

#branch_contains(commit, branch_name = "")



598
599
600
# File 'lib/git/lib.rb', line 598

def branch_contains(commit, branch_name="")
  command("branch",  branch_name, "--contains", commit)
end

#branch_current



594
595
596
# File 'lib/git/lib.rb', line 594

def branch_current
  branches_all.select { |b| b[1] }.first[0] rescue nil
end

#branch_delete(branch)



1018
1019
1020
# File 'lib/git/lib.rb', line 1018

def branch_delete(branch)
  command('branch', '-D', branch)
end

#branch_new(branch)



1014
1015
1016
# File 'lib/git/lib.rb', line 1014

def branch_new(branch)
  command('branch', branch)
end

#branches_all



537
538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/git/lib.rb', line 537

def branches_all
  command_lines('branch', '-a').map do |line|
    match_data = line.match(BRANCH_LINE_REGEXP)
    raise Git::UnexpectedResultError, 'Unexpected branch line format' unless match_data
    next nil if match_data[:not_a_branch] || match_data[:detached_ref]
    [
      match_data[:refname],
      !match_data[:current].nil?,
      !match_data[:worktree].nil?,
      match_data[:symref]
    ]
  end.compact
end

#change_head_branch(branch_name)



509
510
511
# File 'lib/git/lib.rb', line 509

def change_head_branch(branch_name)
  command('symbolic-ref', 'HEAD', "refs/heads/#{branch_name}")
end

#checkout(branch = nil, opts = {})

Runs checkout command to checkout or create branch

accepts options: :new_branch :force :start_point

Parameters:

  • branch (String) (defaults to: nil)
  • opts (Hash) (defaults to: {})


1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
# File 'lib/git/lib.rb', line 1031

def checkout(branch = nil, opts = {})
  if branch.is_a?(Hash) && opts == {}
    opts = branch
    branch = nil
  end

  arr_opts = []
  arr_opts << '-b' if opts[:new_branch] || opts[:b]
  arr_opts << '--force' if opts[:force] || opts[:f]
  arr_opts << branch if branch
  arr_opts << opts[:start_point] if opts[:start_point] && arr_opts.include?('-b')

  command('checkout', *arr_opts)
end

#checkout_file(version, file)



1046
1047
1048
1049
1050
1051
# File 'lib/git/lib.rb', line 1046

def checkout_file(version, file)
  arr_opts = []
  arr_opts << version
  arr_opts << file
  command('checkout', *arr_opts)
end

#checkout_index(opts = {})



1268
1269
1270
1271
1272
1273
1274
1275
1276
# File 'lib/git/lib.rb', line 1268

def checkout_index(opts = {})
  arr_opts = []
  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
  arr_opts << "--force" if opts[:force]
  arr_opts << "--all" if opts[:all]
  arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String

  command('checkout-index', *arr_opts)
end

#clean(opts = {})



946
947
948
949
950
951
952
953
954
# File 'lib/git/lib.rb', line 946

def clean(opts = {})
  arr_opts = []
  arr_opts << '--force' if opts[:force]
  arr_opts << '-ff' if opts[:ff]
  arr_opts << '-d' if opts[:d]
  arr_opts << '-x' if opts[:x]

  command('clean', *arr_opts)
end

#clone(repository_url, directory, opts = {}) ⇒ Hash

TODO:

make this work with SSH password or auth_key

Clones a repository into a newly created directory

Parameters:

  • repository_url (String)

    the URL of the repository to clone

  • directory (String, nil)

    the directory to clone into

    If nil, the repository is cloned into a directory with the same name as the repository.

  • opts (Hash) (defaults to: {})

    the options for this command

Options Hash (opts):

  • :bare (Boolean) — default: false

    if true, clone as a bare repository

  • :branch (String)

    the branch to checkout

  • :config (String, Array)

    one or more configuration options to set

  • :depth (Integer)

    the number of commits back to pull

  • :filter (String)

    specify partial clone

  • :mirror (String)

    set up a mirror of the source repository

  • :origin (String)

    the name of the remote

  • :path (String)

    an optional prefix for the directory parameter

  • :remote (String)

    the name of the remote

  • :recursive (Boolean)

    after the clone is created, initialize all submodules within, using their default settings

  • :timeout (Numeric, nil)

    the number of seconds to wait for the command to complete

    See #command for more information about :timeout

Returns:

  • (Hash)

    the options to pass to Base.new



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/git/lib.rb', line 120

def clone(repository_url, directory, opts = {})
  @path = opts[:path] || '.'
  clone_dir = opts[:path] ? File.join(@path, directory) : directory

  arr_opts = []
  arr_opts << '--bare' if opts[:bare]
  arr_opts << '--branch' << opts[:branch] if opts[:branch]
  arr_opts << '--depth' << opts[:depth].to_i if opts[:depth] && opts[:depth].to_i > 0
  arr_opts << '--filter' << opts[:filter] if opts[:filter]
  Array(opts[:config]).each { |c| arr_opts << '--config' << c }
  arr_opts << '--origin' << opts[:remote] || opts[:origin] if opts[:remote] || opts[:origin]
  arr_opts << '--recursive' if opts[:recursive]
  arr_opts << '--mirror' if opts[:mirror]

  arr_opts << '--'

  arr_opts << repository_url
  arr_opts << clone_dir

  command('clone', *arr_opts, timeout: opts[:timeout])

  return_base_opts_from_clone(clone_dir, opts)
end

#commit(message, opts = {})

Takes the commit message with the options and executes the commit command

accepts options: :amend :all :allow_empty :author :date :no_verify :allow_empty_message :gpg_sign (accepts true or a gpg key ID as a String) :no_gpg_sign (conflicts with :gpg_sign)

Parameters:

  • message (String)

    the commit message to be used

  • opts (Hash) (defaults to: {})

    the commit options to be used



912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
# File 'lib/git/lib.rb', line 912

def commit(message, opts = {})
  arr_opts = []
  arr_opts << "--message=#{message}" if message
  arr_opts << '--amend' << '--no-edit' if opts[:amend]
  arr_opts << '--all' if opts[:add_all] || opts[:all]
  arr_opts << '--allow-empty' if opts[:allow_empty]
  arr_opts << "--author=#{opts[:author]}" if opts[:author]
  arr_opts << "--date=#{opts[:date]}" if opts[:date].is_a? String
  arr_opts << '--no-verify' if opts[:no_verify]
  arr_opts << '--allow-empty-message' if opts[:allow_empty_message]

  if opts[:gpg_sign] && opts[:no_gpg_sign]
    raise ArgumentError, 'cannot specify :gpg_sign and :no_gpg_sign'
  elsif opts[:gpg_sign]
    arr_opts <<
      if opts[:gpg_sign] == true
        '--gpg-sign'
      else
        "--gpg-sign=#{opts[:gpg_sign]}"
      end
  elsif opts[:no_gpg_sign]
    arr_opts << '--no-gpg-sign'
  end

  command('commit', *arr_opts)
end

#commit_data(sha)

returns useful array of raw commit object data



365
366
367
368
369
# File 'lib/git/lib.rb', line 365

def commit_data(sha)
  sha = sha.to_s
  cdata = command_lines('cat-file', 'commit', sha)
  process_commit_data(cdata, sha)
end

#commit_tree(tree, opts = {})



1254
1255
1256
1257
1258
1259
1260
1261
1262
# File 'lib/git/lib.rb', line 1254

def commit_tree(tree, opts = {})
  opts[:message] ||= "commit tree #{tree}"
  arr_opts = []
  arr_opts << tree
  arr_opts << '-p' << opts[:parent] if opts[:parent]
  Array(opts[:parents]).each { |p| arr_opts << '-p' << p } if opts[:parents]
  arr_opts << '-m' << opts[:message]
  command('commit-tree', *arr_opts)
end

#compare_version_to(*other_version) ⇒ Integer

Returns current_command_version <=> other_version

Examples:

lib.current_command_version #=> [2, 42, 0]

lib.compare_version_to(2, 41, 0) #=> 1
lib.compare_version_to(2, 42, 0) #=> 0
lib.compare_version_to(2, 43, 0) #=> -1

Parameters:

  • other_version (Array<Object>)

    the other version to compare to

Returns:

  • (Integer)

    -1 if this version is less than other_version, 0 if equal, or 1 if greater than



1341
1342
1343
# File 'lib/git/lib.rb', line 1341

def compare_version_to(*other_version)
  current_command_version <=> other_version
end

#config_get(name)



789
790
791
# File 'lib/git/lib.rb', line 789

def config_get(name)
  command('config', '--get', name, chdir: @git_dir)
end

#config_list



797
798
799
# File 'lib/git/lib.rb', line 797

def config_list
  parse_config_list command_lines('config', '--list', chdir: @git_dir)
end

#config_remote(name)



779
780
781
782
783
784
785
786
787
# File 'lib/git/lib.rb', line 779

def config_remote(name)
  hsh = {}
  config_list.each do |key, value|
    if /remote.#{name}/.match(key)
      hsh[key.gsub("remote.#{name}.", '')] = value
    end
  end
  hsh
end

#config_set(name, value, options = {})

WRITE COMMANDS ##



833
834
835
836
837
838
839
# File 'lib/git/lib.rb', line 833

def config_set(name, value, options = {})
  if options[:file].to_s.empty?
    command('config', name, value)
  else
    command('config', '--file', options[:file], name, value)
  end
end

#conflicts

:yields: file, your, their



1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
# File 'lib/git/lib.rb', line 1085

def conflicts # :yields: file, your, their
  self.unmerged.each do |f|
    Tempfile.create("YOUR-#{File.basename(f)}") do |your|
      command('show', ":2:#{f}", out: your)
      your.close

      Tempfile.create("THEIR-#{File.basename(f)}") do |their|
        command('show', ":3:#{f}", out: their)
        their.close

        yield(f, your.path, their.path)
      end
    end
  end
end

#current_command_version

returns the current version of git, as an Array of Fixnums.



1322
1323
1324
1325
1326
1327
# File 'lib/git/lib.rb', line 1322

def current_command_version
  output = command('version')
  version = output[/\d+(\.\d+)+/]
  version_parts = version.split('.').collect { |i| i.to_i }
  version_parts.fill(0, version_parts.length...3)
end

#describe(commit_ish = nil, opts = {}) ⇒ String

Finds most recent tag that is reachable from a commit

Parameters:

  • commit_ish (String, nil) (defaults to: nil)

    target commit sha or object name

  • opts (Hash) (defaults to: {})

    the given options

Options Hash (opts):

  • :all (Boolean)
  • :tags (Boolean)
  • :contains (Boolean)
  • :debug (Boolean)
  • :long (Boolean)
  • :always (Boolean)
  • :exact_match (Boolean)
  • :dirty (true, String)
  • :abbrev (String)
  • :candidates (String)
  • :match (String)

Returns:

  • (String)

    the tag name

Raises:

  • (ArgumentError)

    if the commit_ish is a string starting with a hyphen

See Also:



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/git/lib.rb', line 196

def describe(commit_ish = nil, opts = {})
  assert_args_are_not_options('commit-ish object', commit_ish)

  arr_opts = []

  arr_opts << '--all' if opts[:all]
  arr_opts << '--tags' if opts[:tags]
  arr_opts << '--contains' if opts[:contains]
  arr_opts << '--debug' if opts[:debug]
  arr_opts << '--long' if opts[:long]
  arr_opts << '--always' if opts[:always]
  arr_opts << '--exact-match' if opts[:exact_match] || opts[:"exact-match"]

  arr_opts << '--dirty' if opts[:dirty] == true
  arr_opts << "--dirty=#{opts[:dirty]}" if opts[:dirty].is_a?(String)

  arr_opts << "--abbrev=#{opts[:abbrev]}" if opts[:abbrev]
  arr_opts << "--candidates=#{opts[:candidates]}" if opts[:candidates]
  arr_opts << "--match=#{opts[:match]}" if opts[:match]

  arr_opts << commit_ish if commit_ish

  return command('describe', *arr_opts)
end

#diff_files

compares the index and the working directory



697
698
699
# File 'lib/git/lib.rb', line 697

def diff_files
  diff_as_hash('diff-files')
end

#diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})



647
648
649
650
651
652
653
654
655
656
# File 'lib/git/lib.rb', line 647

def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
  assert_args_are_not_options('commit or commit range', obj1, obj2)

  diff_opts = ['-p']
  diff_opts << obj1
  diff_opts << obj2 if obj2.is_a?(String)
  diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String

  command('diff', *diff_opts)
end

#diff_index(treeish)

compares the index and the repository



702
703
704
# File 'lib/git/lib.rb', line 702

def diff_index(treeish)
  diff_as_hash('diff-index', treeish)
end

#diff_name_status(reference1 = nil, reference2 = nil, opts = {})



680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
# File 'lib/git/lib.rb', line 680

def diff_name_status(reference1 = nil, reference2 = nil, opts = {})
  assert_args_are_not_options('commit or commit range', reference1, reference2)

  opts_arr = ['--name-status']
  opts_arr << reference1 if reference1
  opts_arr << reference2 if reference2

  opts_arr << '--' << opts[:path] if opts[:path]

  command_lines('diff', *opts_arr).inject({}) do |memo, line|
    status, path = line.split("\t")
    memo[path] = status
    memo
  end
end

#diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
# File 'lib/git/lib.rb', line 658

def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
  assert_args_are_not_options('commit or commit range', obj1, obj2)

  diff_opts = ['--numstat']
  diff_opts << obj1
  diff_opts << obj2 if obj2.is_a?(String)
  diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String

  hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}

  command_lines('diff', *diff_opts).each do |file|
    (insertions, deletions, filename) = file.split("\t")
    hsh[:total][:insertions] += insertions.to_i
    hsh[:total][:deletions] += deletions.to_i
    hsh[:total][:lines] = (hsh[:total][:deletions] + hsh[:total][:insertions])
    hsh[:total][:files] += 1
    hsh[:files][filename] = {:insertions => insertions.to_i, :deletions => deletions.to_i}
  end

  hsh
end

#each_cat_file_header(data)



392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/git/lib.rb', line 392

def each_cat_file_header(data)
  while (match = CAT_FILE_HEADER_LINE.match(data.shift))
    key = match[:key]
    value_lines = [match[:value]]

    while data.first.start_with?(' ')
      value_lines << data.shift.lstrip
    end

    yield key, value_lines.join("\n")
  end
end

#empty?Boolean

Returns true if the repository is empty (meaning it has no commits)

Returns:

  • (Boolean)


888
889
890
891
892
893
894
895
# File 'lib/git/lib.rb', line 888

def empty?
  command('rev-parse', '--verify', 'HEAD')
  false
rescue Git::FailedError => e
  raise unless e.result.status.exitstatus == 128 &&
    e.result.stderr == 'fatal: Needed a single revision'
  true
end

#fetch(remote, opts)



1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
# File 'lib/git/lib.rb', line 1157

def fetch(remote, opts)
  arr_opts = []
  arr_opts << '--all' if opts[:all]
  arr_opts << '--tags' if opts[:t] || opts[:tags]
  arr_opts << '--prune' if opts[:p] || opts[:prune]
  arr_opts << '--prune-tags' if opts[:P] || opts[:'prune-tags']
  arr_opts << '--force' if opts[:f] || opts[:force]
  arr_opts << '--update-head-ok' if opts[:u] || opts[:'update-head-ok']
  arr_opts << '--unshallow' if opts[:unshallow]
  arr_opts << '--depth' << opts[:depth] if opts[:depth]
  arr_opts << '--' if remote || opts[:ref]
  arr_opts << remote if remote
  arr_opts << opts[:ref] if opts[:ref]

  command('fetch', *arr_opts, merge: true)
end

#full_log_commits(opts = {}) ⇒ Array<Hash>

Return the commits that are within the given revision range

Parameters:

  • opts (Hash) (defaults to: {})

    the given options

Options Hash (opts):

  • :count (Integer)

    the maximum number of commits to return (maps to max-count)

  • :all (Boolean)
  • :cherry (Boolean)
  • :since (String)
  • :until (String)
  • :grep (String)
  • :author (String)
  • :between (Array<String>)

    an array of two commit-ish strings to specify a revision range

    Only :between or :object options can be used, not both.

  • :object (String)

    the revision range for the git log command

    Only :between or :object options can be used, not both.

  • :path_limiter (Array<String>, String)

    only include commits that impact files from the specified paths

  • :skip (Integer)

Returns:

  • (Array<Hash>)

    the log output parsed into an array of hashs for each commit

    Each hash contains the following keys:

    • 'sha' [String] the commit sha
    • 'author' [String] the author of the commit
    • 'message' [String] the commit message
    • 'parent' [Array] the commit shas of the parent commits
    • 'tree' [String] the tree sha
    • 'author' [String] the author of the commit and timestamp of when the changes were created
    • 'committer' [String] the committer of the commit and timestamp of when the commit was applied

Raises:

  • (ArgumentError)

    if the revision range (specified with :between or :object) is a string starting with a hyphen

See Also:



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/git/lib.rb', line 298

def full_log_commits(opts = {})
  assert_args_are_not_options('between', opts[:between]&.first)
  assert_args_are_not_options('object', opts[:object])

  arr_opts = log_common_options(opts)

  arr_opts << '--pretty=raw'
  arr_opts << "--skip=#{opts[:skip]}" if opts[:skip]

  arr_opts += log_path_options(opts)

  full_log = command_lines('log', *arr_opts)

  process_commit_log_data(full_log)
end

#full_tree(sha)



501
502
503
# File 'lib/git/lib.rb', line 501

def full_tree(sha)
  command_lines('ls-tree', '-r', sha)
end

#gc



1238
1239
1240
# File 'lib/git/lib.rb', line 1238

def gc
  command('gc', '--prune', '--aggressive', '--auto')
end

#global_config_get(name)



793
794
795
# File 'lib/git/lib.rb', line 793

def global_config_get(name)
  command('config', '--global', '--get', name)
end

#global_config_list



801
802
803
# File 'lib/git/lib.rb', line 801

def global_config_list
  parse_config_list command_lines('config', '--global', '--list')
end

#global_config_set(name, value)



841
842
843
# File 'lib/git/lib.rb', line 841

def global_config_set(name, value)
  command('config', '--global', name, value)
end

#grep(string, opts = {})

returns hash [tree-ish] = [[line_no, match], [line_no, match2]] [tree-ish] = [[line_no, match], [line_no, match2]]



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
# File 'lib/git/lib.rb', line 605

def grep(string, opts = {})
  opts[:object] ||= 'HEAD'

  grep_opts = ['-n']
  grep_opts << '-i' if opts[:ignore_case]
  grep_opts << '-v' if opts[:invert_match]
  grep_opts << '-E' if opts[:extended_regexp]
  grep_opts << '-e'
  grep_opts << string
  grep_opts << opts[:object] if opts[:object].is_a?(String)
  grep_opts.push('--', opts[:path_limiter]) if opts[:path_limiter].is_a?(String)
  grep_opts.push('--', *opts[:path_limiter]) if opts[:path_limiter].is_a?(Array)

  hsh = {}
  begin
    command_lines('grep', *grep_opts).each do |line|
      if m = /(.*?)\:(\d+)\:(.*)/.match(line)
        hsh[m[1]] ||= []
        hsh[m[1]] << [m[2].to_i, m[3]]
      end
    end
  rescue Git::FailedError => e
    raise unless e.result.status.exitstatus == 1 && e.result.stderr == ''
  end
  hsh
end

#ignored_files



771
772
773
# File 'lib/git/lib.rb', line 771

def ignored_files
  command_lines('ls-files', '--others', '-i', '--exclude-standard').map { |f| unescape_quoted_path(f) }
end

#init(opts = {})

creates or reinitializes the repository

options: :bare :working_directory :initial_branch



84
85
86
87
88
89
90
# File 'lib/git/lib.rb', line 84

def init(opts={})
  arr_opts = []
  arr_opts << '--bare' if opts[:bare]
  arr_opts << "--initial-branch=#{opts[:initial_branch]}" if opts[:initial_branch]

  command('init', *arr_opts)
end

#list_files(ref_dir)



584
585
586
587
588
589
590
591
592
# File 'lib/git/lib.rb', line 584

def list_files(ref_dir)
  dir = File.join(@git_dir, 'refs', ref_dir)
  files = []
  begin
    files = Dir.glob('**/*', base: dir).select { |f| File.file?(File.join(dir, f)) }
  rescue
  end
  files
end

#log_commits(opts = {}) ⇒ Array<String>

Return the commits that are within the given revision range

Parameters:

  • opts (Hash) (defaults to: {})

    the given options

Options Hash (opts):

  • :count (Integer)

    the maximum number of commits to return (maps to max-count)

  • :all (Boolean)
  • :cherry (Boolean)
  • :since (String)
  • :until (String)
  • :grep (String)
  • :author (String)
  • :between (Array<String>)

    an array of two commit-ish strings to specify a revision range

    Only :between or :object options can be used, not both.

  • :object (String)

    the revision range for the git log command

    Only :between or :object options can be used, not both.

  • :path_limiter (Array<String>, String)

    only include commits that impact files from the specified paths

Returns:

  • (Array<String>)

    the log output

Raises:

  • (ArgumentError)

    if the resulting revision range is a string starting with a hyphen

See Also:



248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/git/lib.rb', line 248

def log_commits(opts = {})
  assert_args_are_not_options('between', opts[:between]&.first)
  assert_args_are_not_options('object', opts[:object])

  arr_opts = log_common_options(opts)

  arr_opts << '--pretty=oneline'

  arr_opts += log_path_options(opts)

  command_lines('log', *arr_opts).map { |l| l.split.first }
end

#ls_files(location = nil) ⇒ Hash<String, Hash>

List all files that are in the index

Parameters:

  • location (String) (defaults to: nil)

    the location to list the files from

Returns:

  • (Hash<String, Hash>)

    a hash of files in the index

    • key: file [String] the file path
    • value: file_info [Hash] the file information containing the following keys:
      • :path [String] the file path
      • :mode_index [String] the file mode
      • :sha_index [String] the file sha
      • :stage [String] the file stage


718
719
720
721
722
723
724
725
726
727
728
729
# File 'lib/git/lib.rb', line 718

def ls_files(location=nil)
  location ||= '.'
  {}.tap do |files|
    command_lines('ls-files', '--stage', location).each do |line|
      (info, file) = line.split("\t")
      (mode, sha, stage) = info.split
      files[unescape_quoted_path(file)] = {
        :path => file, :mode_index => mode, :sha_index => sha, :stage => stage
      }
    end
  end
end

#ls_remote(location = nil, opts = {})



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
# File 'lib/git/lib.rb', line 754

def ls_remote(location=nil, opts={})
  arr_opts = []
  arr_opts << '--refs' if opts[:refs]
  arr_opts << (location || '.')

  Hash.new{ |h,k| h[k] = {} }.tap do |hsh|
    command_lines('ls-remote', *arr_opts).each do |line|
      (sha, info) = line.split("\t")
      (ref, type, name) = info.split('/', 3)
      type ||= 'head'
      type = 'branches' if type == 'heads'
      value = {:ref => ref, :sha => sha}
      hsh[type].update( name.nil? ? value : { name => value })
    end
  end
end

#ls_tree(sha, opts = {})



480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# File 'lib/git/lib.rb', line 480

def ls_tree(sha, opts = {})
  data = { 'blob' => {}, 'tree' => {}, 'commit' => {} }

  ls_tree_opts = []
  ls_tree_opts << '-r' if opts[:recursive]
  # path must be last arg
  ls_tree_opts << opts[:path] if opts[:path]

  command_lines('ls-tree', sha, *ls_tree_opts).each do |line|
    (info, filenm) = line.split("\t")
    (mode, type, sha) = info.split
    data[type][filenm] = {:mode => mode, :sha => sha}
  end

  data
end

#meets_required_version?Boolean

Returns:

  • (Boolean)


1349
1350
1351
# File 'lib/git/lib.rb', line 1349

def meets_required_version?
  (self.current_command_version <=>  self.required_command_version) >= 0
end

#merge(branch, message = nil, opts = {})



1053
1054
1055
1056
1057
1058
1059
1060
# File 'lib/git/lib.rb', line 1053

def merge(branch, message = nil, opts = {})
  arr_opts = []
  arr_opts << '--no-commit' if opts[:no_commit]
  arr_opts << '--no-ff' if opts[:no_ff]
  arr_opts << '-m' << message if message
  arr_opts += Array(branch)
  command('merge', *arr_opts)
end

#merge_base(*args)



1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
# File 'lib/git/lib.rb', line 1062

def merge_base(*args)
  opts = args.last.is_a?(Hash) ? args.pop : {}

  arg_opts = []

  arg_opts << '--octopus' if opts[:octopus]
  arg_opts << '--independent' if opts[:independent]
  arg_opts << '--fork-point' if opts[:fork_point]
  arg_opts << '--all' if opts[:all]

  arg_opts += args

  command('merge-base', *arg_opts).lines.map(&:strip)
end

#mv(file1, file2)



497
498
499
# File 'lib/git/lib.rb', line 497

def mv(file1, file2)
  command_lines('mv', '--', file1, file2)
end

#name_rev(commit_ish) ⇒ String? Also known as: namerev

Find the first symbolic name for given commit_ish

Parameters:

  • commit_ish (String)

    the commit_ish to find the symbolic name of

Returns:

  • (String, nil)

    the first symbolic name or nil if the commit_ish isn't found

Raises:

  • (ArgumentError)

    if the commit_ish is a string starting with a hyphen



348
349
350
351
352
# File 'lib/git/lib.rb', line 348

def name_rev(commit_ish)
  assert_args_are_not_options('commit_ish', commit_ish)

  command('name-rev', commit_ish).split[1]
end

#object_contents(sha, &block)



464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/git/lib.rb', line 464

def object_contents(sha, &block)
  if block_given?
    Tempfile.create do |file|
      # If a block is given, write the output from the process to a temporary
      # file and then yield the file to the block
      #
      command('cat-file', "-p", sha, out: file, err: file)
      file.rewind
      yield file
    end
  else
    # If a block is not given, return stdout
    command('cat-file', '-p', sha)
  end
end

#object_size(sha)



360
361
362
# File 'lib/git/lib.rb', line 360

def object_size(sha)
  command('cat-file', '-s', sha).to_i
end

#object_type(sha)



356
357
358
# File 'lib/git/lib.rb', line 356

def object_type(sha)
  command('cat-file', '-t', sha)
end

#parse_config(file)



814
815
816
# File 'lib/git/lib.rb', line 814

def parse_config(file)
  parse_config_list command_lines('config', '--list', '--file', file)
end

#parse_config_list(lines)



805
806
807
808
809
810
811
812
# File 'lib/git/lib.rb', line 805

def parse_config_list(lines)
  hsh = {}
  lines.each do |line|
    (key, *values) = line.split('=')
    hsh[key] = values.join('=')
  end
  hsh
end

#process_commit_data(data, sha)



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/git/lib.rb', line 371

def process_commit_data(data, sha)
  hsh = {
    'sha'    => sha,
    'parent' => []
  }

  each_cat_file_header(data) do |key, value|
    if key == 'parent'
      hsh['parent'] << value
    else
      hsh[key] = value
    end
  end

  hsh['message'] = data.join("\n") + "\n"

  return hsh
end

#process_commit_log_data(data)



423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'lib/git/lib.rb', line 423

def process_commit_log_data(data)
  in_message = false

  hsh_array = []

  hsh = nil

  data.each do |line|
    line = line.chomp

    if line[0].nil?
      in_message = !in_message
      next
    end

    in_message = false if in_message && line[0..3] != "    "

    if in_message
      hsh['message'] << "#{line[4..-1]}\n"
      next
    end

    key, *value = line.split
    value = value.join(' ')

    case key
      when 'commit'
        hsh_array << hsh if hsh
        hsh = {'sha' => value, 'message' => '', 'parent' => []}
      when 'parent'
        hsh['parent'] << value
      else
        hsh[key] = value
    end
  end

  hsh_array << hsh if hsh

  return hsh_array
end

#process_tag_data(data, name)



411
412
413
414
415
416
417
418
419
420
421
# File 'lib/git/lib.rb', line 411

def process_tag_data(data, name)
  hsh = { 'name' => name }

  each_cat_file_header(data) do |key, value|
    hsh[key] = value
  end

  hsh['message'] = data.join("\n") + "\n"

  return hsh
end

#pull(remote = nil, branch = nil, opts = {})

Raises:

  • (ArgumentError)


1211
1212
1213
1214
1215
1216
1217
1218
1219
# File 'lib/git/lib.rb', line 1211

def pull(remote = nil, branch = nil, opts = {})
  raise ArgumentError, "You must specify a remote if a branch is specified" if remote.nil? && !branch.nil?

  arr_opts = []
  arr_opts << '--allow-unrelated-histories' if opts[:allow_unrelated_histories]
  arr_opts << remote if remote
  arr_opts << branch if branch
  command('pull', *arr_opts)
end

#push(remote = nil, branch = nil, opts = nil)

Raises:

  • (ArgumentError)


1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
# File 'lib/git/lib.rb', line 1174

def push(remote = nil, branch = nil, opts = nil)
  if opts.nil? && branch.instance_of?(Hash)
    opts = branch
    branch = nil
  end

  if opts.nil? && remote.instance_of?(Hash)
    opts = remote
    remote = nil
  end

  opts ||= {}

  # Small hack to keep backwards compatibility with the 'push(remote, branch, tags)' method signature.
  opts = {:tags => opts} if [true, false].include?(opts)

  raise ArgumentError, "You must specify a remote if a branch is specified" if remote.nil? && !branch.nil?

  arr_opts = []
  arr_opts << '--mirror'  if opts[:mirror]
  arr_opts << '--delete'  if opts[:delete]
  arr_opts << '--force'   if opts[:force] || opts[:f]
  arr_opts << '--all'     if opts[:all] && remote

  Array(opts[:push_option]).each { |o| arr_opts << '--push-option' << o } if opts[:push_option]
  arr_opts << remote if remote
  arr_opts_with_branch = arr_opts.dup
  arr_opts_with_branch << branch if branch

  if opts[:mirror]
      command('push', *arr_opts_with_branch)
  else
      command('push', *arr_opts_with_branch)
      command('push', '--tags', *arr_opts) if opts[:tags]
  end
end

#read_tree(treeish, opts = {})

reads a tree into the current index file



1243
1244
1245
1246
1247
1248
# File 'lib/git/lib.rb', line 1243

def read_tree(treeish, opts = {})
  arr_opts = []
  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
  arr_opts += [treeish]
  command('read-tree', *arr_opts)
end

#remote_add(name, url, opts = {})



1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
# File 'lib/git/lib.rb', line 1101

def remote_add(name, url, opts = {})
  arr_opts = ['add']
  arr_opts << '-f' if opts[:with_fetch] || opts[:fetch]
  arr_opts << '-t' << opts[:track] if opts[:track]
  arr_opts << '--'
  arr_opts << name
  arr_opts << url

  command('remote', *arr_opts)
end

#remote_remove(name)



1120
1121
1122
# File 'lib/git/lib.rb', line 1120

def remote_remove(name)
  command('remote', 'rm', name)
end

#remote_set_url(name, url)



1112
1113
1114
1115
1116
1117
1118
# File 'lib/git/lib.rb', line 1112

def remote_set_url(name, url)
  arr_opts = ['set-url']
  arr_opts << name
  arr_opts << url

  command('remote', *arr_opts)
end

#remotes



1124
1125
1126
# File 'lib/git/lib.rb', line 1124

def remotes
  command_lines('remote')
end

#repack



1234
1235
1236
# File 'lib/git/lib.rb', line 1234

def repack
  command('repack', '-a', '-d')
end

#repository_default_branch(repository) ⇒ String

Returns the name of the default branch of the given repository

Parameters:

  • repository (URI, Pathname, String)

    The (possibly remote) repository to clone from

Returns:

  • (String)

    the name of the default branch

Raises:



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/git/lib.rb', line 158

def repository_default_branch(repository)
  output = command('ls-remote', '--symref', '--', repository, 'HEAD')

  match_data = output.match(%r{^ref: refs/remotes/origin/(?<default_branch>[^\t]+)\trefs/remotes/origin/HEAD$})
  return match_data[:default_branch] if match_data

  match_data = output.match(%r{^ref: refs/heads/(?<default_branch>[^\t]+)\tHEAD$})
  return match_data[:default_branch] if match_data

  raise Git::UnexpectedResultError, 'Unable to determine the default branch'
end

#required_command_version



1345
1346
1347
# File 'lib/git/lib.rb', line 1345

def required_command_version
  [2, 28]
end

#reset(commit, opts = {})



939
940
941
942
943
944
# File 'lib/git/lib.rb', line 939

def reset(commit, opts = {})
  arr_opts = []
  arr_opts << '--hard' if opts[:hard]
  arr_opts << commit if commit
  command('reset', *arr_opts)
end

#return_base_opts_from_clone(clone_dir, opts)



144
145
146
147
148
149
150
# File 'lib/git/lib.rb', line 144

def return_base_opts_from_clone(clone_dir, opts)
  base_opts = {}
  base_opts[:repository] = clone_dir if (opts[:bare] || opts[:mirror])
  base_opts[:working_directory] = clone_dir unless (opts[:bare] || opts[:mirror])
  base_opts[:log] = opts[:log] if opts[:log]
  base_opts
end

#rev_parse(revision) ⇒ String Also known as: revparse

Verify and resolve a Git revision to its full SHA

Examples:

lib.rev_parse('HEAD') # => '9b9b31e704c0b85ffdd8d2af2ded85170a5af87d'
lib.rev_parse('9b9b31e') # => '9b9b31e704c0b85ffdd8d2af2ded85170a5af87d'

Parameters:

  • revision (String)

    the revision to resolve

Returns:

  • (String)

    the full commit hash

Raises:

  • (Git::FailedError)

    if the revision cannot be resolved

  • (ArgumentError)

    if the revision is a string starting with a hyphen

See Also:



331
332
333
334
335
# File 'lib/git/lib.rb', line 331

def rev_parse(revision)
  assert_args_are_not_options('rev', revision)

  command('rev-parse', revision)
end

#revert(commitish, opts = {})



956
957
958
959
960
961
962
963
964
965
# File 'lib/git/lib.rb', line 956

def revert(commitish, opts = {})
  # Forcing --no-edit as default since it's not an interactive session.
  opts = {:no_edit => true}.merge(opts)

  arr_opts = []
  arr_opts << '--no-edit' if opts[:no_edit]
  arr_opts << commitish

  command('revert', *arr_opts)
end

#rm(path = '.', opts = {})



874
875
876
877
878
879
880
881
882
# File 'lib/git/lib.rb', line 874

def rm(path = '.', opts = {})
  arr_opts = ['-f']  # overrides the up-to-date check by default
  arr_opts << '-r' if opts[:recursive]
  arr_opts << '--cached' if opts[:cached]
  arr_opts << '--'
  arr_opts += Array(path)

  command('rm', *arr_opts)
end

#show(objectish = nil, path = nil) ⇒ String

Shows objects

Parameters:

  • objectish (String|NilClass) (defaults to: nil)

    the target object reference (nil == HEAD)

  • path (String|NilClass) (defaults to: nil)

    the path of the file to be shown

Returns:

  • (String)

    the object information



823
824
825
826
827
828
829
# File 'lib/git/lib.rb', line 823

def show(objectish=nil, path=nil)
  arr_opts = []

  arr_opts << (path ? "#{objectish}:#{path}" : objectish)

  command('show', *arr_opts.compact, chomp: false)
end

#stash_apply(id = nil)



998
999
1000
1001
1002
1003
1004
# File 'lib/git/lib.rb', line 998

def stash_apply(id = nil)
  if id
    command('stash', 'apply', id)
  else
    command('stash', 'apply')
  end
end

#stash_clear



1006
1007
1008
# File 'lib/git/lib.rb', line 1006

def stash_clear
  command('stash', 'clear')
end

#stash_list



1010
1011
1012
# File 'lib/git/lib.rb', line 1010

def stash_list
  command('stash', 'list')
end

#stash_save(message)



993
994
995
996
# File 'lib/git/lib.rb', line 993

def stash_save(message)
  output = command('stash', 'save', message)
  output =~ /HEAD is now at/
end

#stashes_all



979
980
981
982
983
984
985
986
987
988
989
990
991
# File 'lib/git/lib.rb', line 979

def stashes_all
  arr = []
  filename = File.join(@git_dir, 'logs/refs/stash')
  if File.exist?(filename)
    File.open(filename) do |f|
      f.each_with_index do |line, i|
        m = line.match(/:(.*)$/)
        arr << [i, m[1].strip]
      end
    end
  end
  arr
end

#tag(name, *opts)



1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
# File 'lib/git/lib.rb', line 1132

def tag(name, *opts)
  target = opts[0].instance_of?(String) ? opts[0] : nil

  opts = opts.last.instance_of?(Hash) ? opts.last : {}

  if (opts[:a] || opts[:annotate]) && !(opts[:m] || opts[:message])
    raise  ArgumentError, 'Cannot create an annotated tag without a message.'
  end

  arr_opts = []

  arr_opts << '-f' if opts[:force] || opts[:f]
  arr_opts << '-a' if opts[:a] || opts[:annotate]
  arr_opts << '-s' if opts[:s] || opts[:sign]
  arr_opts << '-d' if opts[:d] || opts[:delete]
  arr_opts << name
  arr_opts << target if target

  if opts[:m] || opts[:message]
    arr_opts << '-m' << (opts[:m] || opts[:message])
  end

  command('tag', *arr_opts)
end

#tag_data(name)



405
406
407
408
409
# File 'lib/git/lib.rb', line 405

def tag_data(name)
  sha = sha.to_s
  tdata = command_lines('cat-file', 'tag', name)
  process_tag_data(tdata, name)
end

#tag_sha(tag_name)



1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
# File 'lib/git/lib.rb', line 1221

def tag_sha(tag_name)
  head = File.join(@git_dir, 'refs', 'tags', tag_name)
  return File.read(head).chomp if File.exist?(head)

  begin
    command('show-ref',  '--tags', '-s', tag_name)
  rescue Git::FailedError => e
    raise unless e.result.status.exitstatus == 1 && e.result.stderr == ''

    ''
  end
end

#tags



1128
1129
1130
# File 'lib/git/lib.rb', line 1128

def tags
  command_lines('tag')
end

#tree_depth(sha)



505
506
507
# File 'lib/git/lib.rb', line 505

def tree_depth(sha)
  full_tree(sha).size
end

#unescape_quoted_path(path) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Unescape a path if it is quoted

Git commands that output paths (e.g. ls-files, diff), will escape unusual characters.

Examples:

lib.unescape_if_quoted('"quoted_file_\\342\\230\\240"') # => 'quoted_file_☠'
lib.unescape_if_quoted('unquoted_file')   # => 'unquoted_file'

Parameters:

  • path (String)

    the path to unescape if quoted

Returns:

  • (String)

    the unescaped path if quoted otherwise the original path



746
747
748
749
750
751
752
# File 'lib/git/lib.rb', line 746

def unescape_quoted_path(path)
  if path.start_with?('"') && path.end_with?('"')
    Git::EscapedPath.new(path[1..-2]).unescape
  else
    path
  end
end

#unmerged



1077
1078
1079
1080
1081
1082
1083
# File 'lib/git/lib.rb', line 1077

def unmerged
  unmerged = []
  command_lines('diff', "--cached").each do |line|
    unmerged << $1 if line =~ /^\* Unmerged path (.*)/
  end
  unmerged
end

#untracked_files



775
776
777
# File 'lib/git/lib.rb', line 775

def untracked_files
  command_lines('ls-files', '--others', '--exclude-standard', chdir: @git_work_dir)
end

#update_ref(ref, commit)



1264
1265
1266
# File 'lib/git/lib.rb', line 1264

def update_ref(ref, commit)
  command('update-ref', ref, commit)
end

#worktree_add(dir, commitish = nil)



571
572
573
574
# File 'lib/git/lib.rb', line 571

def worktree_add(dir, commitish = nil)
  return command('worktree', 'add', dir, commitish) if !commitish.nil?
  command('worktree', 'add', dir)
end

#worktree_prune



580
581
582
# File 'lib/git/lib.rb', line 580

def worktree_prune
  command('worktree', 'prune')
end

#worktree_remove(dir)



576
577
578
# File 'lib/git/lib.rb', line 576

def worktree_remove(dir)
  command('worktree', 'remove', dir)
end

#worktrees_all



551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/git/lib.rb', line 551

def worktrees_all
  arr = []
  directory = ''
  # Output example for `worktree list --porcelain`:
  # worktree /code/public/ruby-git
  # HEAD 4bef5abbba073c77b4d0ccc1ffcd0ed7d48be5d4
  # branch refs/heads/master
  #
  # worktree /tmp/worktree-1
  # HEAD b8c63206f8d10f57892060375a86ae911fad356e
  # detached
  #
  command_lines('worktree', 'list', '--porcelain').each do |w|
    s = w.split("\s")
    directory = s[1] if s[0] == 'worktree'
    arr << [directory, s[1]] if s[0] == 'HEAD'
  end
  arr
end

#write_tree



1250
1251
1252
# File 'lib/git/lib.rb', line 1250

def write_tree
  command('write-tree')
end