class Git::Lib

Constants

ENV_VARIABLE_NAMES

Systen ENV variables involved in the git commands.

@return [<String>] the names of the EVN variables involved in the git commands

Attributes

git_dir[R]

The path to the Git repository directory. The default is ‘“#{git_work_dir}/.git”`.

@return [Pathname] the Git repository directory.

@see [Git repository](git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefrepositoryarepository)

git_index_file[R]

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

@return [Pathname] the Git index file

@see [Git index file](git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefindexaindex)

git_work_dir[R]

The path to the Git working copy. The default is ‘“./.git”’.

@return [Pathname] the path to the Git working copy.

@see [Git working tree](git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefworkingtreeaworkingtree)

Public Class Methods

new(base = nil, logger = nil) click to toggle source

Create a new Git::Lib object

@param [Git::Base, Hash] base An object that passes in values for

@git_work_dir, @git_dir, and @git_index_file

@param [Logger] logger

@option base [Pathname] :working_directory @option base [Pathname] :repository @option base [Pathname] :index

# File lib/git/lib.rb, line 50
def initialize(base = nil, logger = nil)
  @git_dir = nil
  @git_index_file = nil
  @git_work_dir = nil
  @path = 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
  @logger = logger
end

Public Instance Methods

add(paths='.',options={}) click to toggle source

updates the repository index using the working directory content

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

options:

:all => true
:force => true

@param [String,Array] paths files paths to be added to the repository @param [Hash] options

# File lib/git/lib.rb, line 611
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) click to toggle source
# File lib/git/lib.rb, line 704
def apply(patch_file)
  arr_opts = []
  arr_opts << '--' << patch_file if patch_file
  command('apply', arr_opts)
end
apply_mail(patch_file) click to toggle source
# File lib/git/lib.rb, line 710
def apply_mail(patch_file)
  arr_opts = []
  arr_opts << '--' << patch_file if patch_file
  command('am', arr_opts)
end
archive(sha, file = nil, opts = {}) click to toggle source

creates an archive file

options

:format  (zip, tar)
:prefix
:remote
:path
# File lib/git/lib.rb, line 976
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]
  command('archive', arr_opts, redirect: " > #{escape file}")
  if opts[:add_gzip]
    file_content = File.read(file)
    Zlib::GzipWriter.open(file) do |gz|
      gz.write(file_content)
    end
  end
  return file
end
branch_contains(commit, branch_name="") click to toggle source
# File lib/git/lib.rb, line 402
def branch_contains(commit, branch_name="")
  command("branch",  [branch_name, "--contains", commit])
end
branch_current() click to toggle source
# File lib/git/lib.rb, line 398
def branch_current
  branches_all.select { |b| b[1] }.first[0] rescue nil
end
branch_delete(branch) click to toggle source
# File lib/git/lib.rb, line 755
def branch_delete(branch)
  command('branch', '-D', branch)
end
branch_new(branch) click to toggle source
# File lib/git/lib.rb, line 751
def branch_new(branch)
  command('branch', branch)
end
branches_all() click to toggle source
# File lib/git/lib.rb, line 349
def branches_all
  arr = []
  command_lines('branch', '-a').each do |b|
    current = (b[0, 2] == '* ')
    arr << [b.gsub('* ', '').strip, current]
  end
  arr
end
change_head_branch(branch_name) click to toggle source
# File lib/git/lib.rb, line 345
def change_head_branch(branch_name)
  command('symbolic-ref', 'HEAD', "refs/heads/#{branch_name}")
end
checkout(branch, opts = {}) click to toggle source
# File lib/git/lib.rb, line 759
def checkout(branch, opts = {})
  arr_opts = []
  arr_opts << '-b' if opts[:new_branch] || opts[:b]
  arr_opts << '--force' if opts[:force] || opts[:f]
  arr_opts << branch

  command('checkout', arr_opts)
end
checkout_file(version, file) click to toggle source
# File lib/git/lib.rb, line 768
def checkout_file(version, file)
  arr_opts = []
  arr_opts << version
  arr_opts << file
  command('checkout', arr_opts)
end
checkout_index(opts = {}) click to toggle source
# File lib/git/lib.rb, line 959
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 = {}) click to toggle source
# File lib/git/lib.rb, line 683
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, name, opts = {}) click to toggle source

tries to clone the given repo

accepts options:

:bare::      no working directory
:branch::    name of branch to track (rather than 'master')
:depth::     the number of commits back to pull
:origin::    name of remote (same as remote)
:path::      directory where the repo will be cloned
:remote::    name of remote (rather than 'origin')
:recursive:: after the clone is created, initialize all submodules within, using their default settings.

TODO - make this work with SSH password or auth_key

@return [Hash] the options to pass to {Git::Base.new}

# File lib/git/lib.rb, line 98
def clone(repository, name, opts = {})
  @path = opts[:path] || '.'
  clone_dir = opts[:path] ? File.join(@path, name) : name

  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 << '--config' << opts[:config] if opts[:config]
  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
  arr_opts << clone_dir

  command('clone', arr_opts)

  return_base_opts_from_clone(clone_dir, opts)
end
commit(message, opts = {}) click to toggle source

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

@param [String] message the commit message to be used @param [Hash] opts the commit options to be used

# File lib/git/lib.rb, line 654
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]
    arr_opts <<
      if opts[:gpg_sign] == true
        '--gpg-sign'
      else
        "--gpg-sign=#{opts[:gpg_sign]}"
      end
  end

  command('commit', arr_opts)
end
commit_data(sha) click to toggle source

returns useful array of raw commit object data

# File lib/git/lib.rb, line 221
def commit_data(sha)
  sha = sha.to_s
  cdata = command_lines('cat-file', 'commit', sha)
  process_commit_data(cdata, sha, 0)
end
commit_tree(tree, opts = {}) click to toggle source
# File lib/git/lib.rb, line 942
def commit_tree(tree, opts = {})
  opts[:message] ||= "commit tree #{tree}"
  t = Tempfile.new('commit-message')
  t.write(opts[:message])
  t.close

  arr_opts = []
  arr_opts << tree
  arr_opts << '-p' << opts[:parent] if opts[:parent]
  arr_opts += [opts[:parents]].map { |p| ['-p', p] }.flatten if opts[:parents]
  command('commit-tree', arr_opts, redirect: "< #{escape t.path}")
end
config_get(name) click to toggle source
# File lib/git/lib.rb, line 527
def config_get(name)
  do_get = Proc.new do |path|
    command('config', '--get', name)
  end

  if @git_dir
    Dir.chdir(@git_dir, &do_get)
  else
    do_get.call
  end
end
config_list() click to toggle source
# File lib/git/lib.rb, line 543
def config_list
  build_list = Proc.new do |path|
    parse_config_list command_lines('config', '--list')
  end

  if @git_dir
    Dir.chdir(@git_dir, &build_list)
  else
    build_list.call
  end
end
config_remote(name) click to toggle source
# File lib/git/lib.rb, line 517
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 = {}) click to toggle source

WRITE COMMANDS ##

# File lib/git/lib.rb, line 587
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() { |file, your, their| ... } click to toggle source
# File lib/git/lib.rb, line 807
def conflicts # :yields: file, your, their
  self.unmerged.each do |f|
    your_tempfile = Tempfile.new("YOUR-#{File.basename(f)}")
    your = your_tempfile.path
    your_tempfile.close # free up file for git command process
    command('show', ":2:#{f}", redirect: "> #{escape your}")

    their_tempfile = Tempfile.new("THEIR-#{File.basename(f)}")
    their = their_tempfile.path
    their_tempfile.close # free up file for git command process
    command('show', ":3:#{f}", redirect: "> #{escape their}")
    yield(f, your, their)
  end
end
current_command_version() click to toggle source

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

# File lib/git/lib.rb, line 1009
def current_command_version
  output = command('version')
  version = output[/\d+\.\d+(\.\d+)+/]
  version.split('.').collect {|i| i.to_i}
end
describe(committish=nil, opts={}) click to toggle source

Returns most recent tag that is reachable from a commit

accepts options:

:all
:tags
:contains
:debug
:exact_match
:dirty
:abbrev
:candidates
:long
:always
:math

@param [String|NilClass] committish target commit sha or object name
@param [{Symbol=>Object}] opts the given options
@return [String] the tag name
# File lib/git/lib.rb, line 151
def describe(committish=nil, opts={})
  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 << committish if committish

  return command('describe', arr_opts)
end
diff_files() click to toggle source

compares the index and the working directory

# File lib/git/lib.rb, line 474
def diff_files
  diff_as_hash('diff-files')
end
diff_full(obj1 = 'HEAD', obj2 = nil, opts = {}) click to toggle source
# File lib/git/lib.rb, line 430
def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
  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) click to toggle source

compares the index and the repository

# File lib/git/lib.rb, line 479
def diff_index(treeish)
  diff_as_hash('diff-index', treeish)
end
diff_name_status(reference1 = nil, reference2 = nil, opts = {}) click to toggle source
# File lib/git/lib.rb, line 459
def diff_name_status(reference1 = nil, reference2 = nil, opts = {})
  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 = {}) click to toggle source
# File lib/git/lib.rb, line 439
def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
  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
fetch(remote, opts) click to toggle source
# File lib/git/lib.rb, line 878
def fetch(remote, opts)
  arr_opts = []
  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 << '--unshallow' if opts[:unshallow]
  arr_opts << '--depth' << opts[:depth] if opts[:depth]
  arr_opts << '--'
  arr_opts << remote
  arr_opts << opts[:ref] if opts[:ref]

  command('fetch', arr_opts)
end
full_log_commits(opts={}) click to toggle source
# File lib/git/lib.rb, line 184
def full_log_commits(opts={})
  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) click to toggle source
# File lib/git/lib.rb, line 337
def full_tree(sha)
  command_lines('ls-tree', '-r', sha)
end
gc() click to toggle source
# File lib/git/lib.rb, line 926
def gc
  command('gc', '--prune', '--aggressive', '--auto')
end
global_config_get(name) click to toggle source
# File lib/git/lib.rb, line 539
def global_config_get(name)
  command('config', '--global', '--get', name)
end
global_config_list() click to toggle source
# File lib/git/lib.rb, line 555
def global_config_list
  parse_config_list command_lines('config', '--global', '--list')
end
global_config_set(name, value) click to toggle source
# File lib/git/lib.rb, line 595
def global_config_set(name, value)
  command('config', '--global', name, value)
end
grep(string, opts = {}) click to toggle source

returns hash

tree-ish

[[line_no, match], [line_no, match2]]

tree-ish

[[line_no, match], [line_no, match2]]

# File lib/git/lib.rb, line 409
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'
  grep_opts << string
  grep_opts << opts[:object] if opts[:object].is_a?(String)
  grep_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String

  hsh = {}
  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
  hsh
end
ignored_files() click to toggle source
# File lib/git/lib.rb, line 512
def ignored_files
  command_lines('ls-files', '--others', '-i', '--exclude-standard')
end
init(opts={}) click to toggle source

creates or reinitializes the repository

options:

:bare
:working_directory
:initial_branch
# File lib/git/lib.rb, line 75
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) click to toggle source
# File lib/git/lib.rb, line 391
def list_files(ref_dir)
  dir = File.join(@git_dir, 'refs', ref_dir)
  files = []
  Dir.chdir(dir) { files = Dir.glob('**/*').select { |f| File.file?(f) } } rescue nil
  files
end
log_commits(opts={}) click to toggle source
# File lib/git/lib.rb, line 174
def log_commits(opts={})
  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) click to toggle source
# File lib/git/lib.rb, line 483
def ls_files(location=nil)
  location ||= '.'
  hsh = {}
  command_lines('ls-files', '--stage', location).each do |line|
    (info, file) = line.split("\t")
    (mode, sha, stage) = info.split
    file = eval(file) if file =~ /^\".*\"$/ # This takes care of quoted strings returned from git
    hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
  end
  hsh
end
ls_remote(location=nil, opts={}) click to toggle source
# File lib/git/lib.rb, line 495
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) click to toggle source
# File lib/git/lib.rb, line 321
def ls_tree(sha)
  data = {'blob' => {}, 'tree' => {}}

  command_lines('ls-tree', sha).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?() click to toggle source
# File lib/git/lib.rb, line 1019
def meets_required_version?
  (self.current_command_version <=>  self.required_command_version) >= 0
end
merge(branch, message = nil, opts = {}) click to toggle source
# File lib/git/lib.rb, line 775
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 += [branch]
  command('merge', arr_opts)
end
merge_base(*args) click to toggle source
# File lib/git/lib.rb, line 784
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) click to toggle source
# File lib/git/lib.rb, line 333
def mv(file1, file2)
  command_lines('mv', '--', file1, file2)
end
namerev(string) click to toggle source
# File lib/git/lib.rb, line 208
def namerev(string)
  command('name-rev', string).split[1]
end
object_contents(sha, &block) click to toggle source
# File lib/git/lib.rb, line 317
def object_contents(sha, &block)
  command('cat-file', '-p', sha, &block)
end
object_size(sha) click to toggle source
# File lib/git/lib.rb, line 216
def object_size(sha)
  command('cat-file', '-s', sha).to_i
end
object_type(sha) click to toggle source
# File lib/git/lib.rb, line 212
def object_type(sha)
  command('cat-file', '-t', sha)
end
parse_config(file) click to toggle source
# File lib/git/lib.rb, line 568
def parse_config(file)
  parse_config_list command_lines('config', '--list', '--file', file)
end
parse_config_list(lines) click to toggle source
# File lib/git/lib.rb, line 559
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 = nil, indent = 4) click to toggle source
# File lib/git/lib.rb, line 227
def process_commit_data(data, sha = nil, indent = 4)
  hsh = {
    'sha'     => sha,
    'message' => '',
    'parent'  => []
  }

  loop do
    key, *value = data.shift.split

    break if key.nil?

    if key == 'parent'
      hsh['parent'] << value.join(' ')
    else
      hsh[key] = value.join(' ')
    end
  end

  hsh['message'] = data.collect {|line| line[indent..-1]}.join("\n") + "\n"

  return hsh
end
process_commit_log_data(data) click to toggle source
# File lib/git/lib.rb, line 276
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, indent=4) click to toggle source
# File lib/git/lib.rb, line 257
def process_tag_data(data, name, indent=4)
  hsh = {
    'name'    => name,
    'message' => ''
  }

  loop do
    key, *value = data.shift.split

    break if key.nil?

    hsh[key] = value.join(' ')
  end

  hsh['message'] = data.collect {|line| line[indent..-1]}.join("\n") + "\n"

  return hsh
end
pull(remote='origin', branch='master') click to toggle source
# File lib/git/lib.rb, line 911
def pull(remote='origin', branch='master')
  command('pull', remote, branch)
end
push(remote, branch = 'master', opts = {}) click to toggle source
# File lib/git/lib.rb, line 893
def push(remote, branch = 'master', opts = {})
  # Small hack to keep backwards compatibility with the 'push(remote, branch, tags)' method signature.
  opts = {:tags => opts} if [true, false].include?(opts)

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

  if opts[:mirror]
      command('push', arr_opts)
  else
      command('push', arr_opts + [branch])
      command('push', ['--tags'] + arr_opts) if opts[:tags]
  end
end
read_tree(treeish, opts = {}) click to toggle source

reads a tree into the current index file

# File lib/git/lib.rb, line 931
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 = {}) click to toggle source
# File lib/git/lib.rb, line 822
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) click to toggle source
# File lib/git/lib.rb, line 841
def remote_remove(name)
  command('remote', 'rm', name)
end
remote_set_url(name, url) click to toggle source
# File lib/git/lib.rb, line 833
def remote_set_url(name, url)
  arr_opts = ['set-url']
  arr_opts << name
  arr_opts << url

  command('remote', arr_opts)
end
remotes() click to toggle source
# File lib/git/lib.rb, line 845
def remotes
  command_lines('remote')
end
remove(path = '.', opts = {}) click to toggle source
# File lib/git/lib.rb, line 626
def remove(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 << '--'
  if path.is_a?(Array)
    arr_opts += path
  else
    arr_opts << path
  end

  command('rm', arr_opts)
end
repack() click to toggle source
# File lib/git/lib.rb, line 922
def repack
  command('repack', '-a', '-d')
end
required_command_version() click to toggle source
# File lib/git/lib.rb, line 1015
def required_command_version
  [1, 6]
end
reset(commit, opts = {}) click to toggle source
# File lib/git/lib.rb, line 676
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) click to toggle source
# File lib/git/lib.rb, line 121
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
revert(commitish, opts = {}) click to toggle source
# File lib/git/lib.rb, line 693
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
revparse(string) click to toggle source
# File lib/git/lib.rb, line 197
def revparse(string)
  return string if string =~ /^[A-Fa-f0-9]{40}$/  # passing in a sha - just no-op it
  rev = ['head', 'remotes', 'tags'].map do |d|
    File.join(@git_dir, 'refs', d, string)
  end.find do |path|
    File.file?(path)
  end
  return File.read(rev).chomp if rev
  command('rev-parse', string)
end
show(objectish=nil, path=nil) click to toggle source

Shows objects

@param [String|NilClass] objectish the target object reference (nil == HEAD) @param [String|NilClass] path the path of the file to be shown @return [String] the object information

# File lib/git/lib.rb, line 577
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) click to toggle source
# File lib/git/lib.rb, line 735
def stash_apply(id = nil)
  if id
    command('stash apply', id)
  else
    command('stash apply')
  end
end
stash_clear() click to toggle source
# File lib/git/lib.rb, line 743
def stash_clear
  command('stash clear')
end
stash_list() click to toggle source
# File lib/git/lib.rb, line 747
def stash_list
  command('stash list')
end
stash_save(message) click to toggle source
# File lib/git/lib.rb, line 730
def stash_save(message)
  output = command('stash save', message)
  output =~ /HEAD is now at/
end
stashes_all() click to toggle source
# File lib/git/lib.rb, line 716
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) click to toggle source
# File lib/git/lib.rb, line 853
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  "Can not create an [:a|:annotate] tag without the precense of [:m|: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) click to toggle source
# File lib/git/lib.rb, line 251
def tag_data(name)
  sha = sha.to_s
  tdata = command_lines('cat-file', 'tag', name)
  process_tag_data(tdata, name, 0)
end
tag_sha(tag_name) click to toggle source
# File lib/git/lib.rb, line 915
def tag_sha(tag_name)
  head = File.join(@git_dir, 'refs', 'tags', tag_name)
  return File.read(head).chomp if File.exist?(head)

  command('show-ref',  '--tags', '-s', tag_name)
end
tags() click to toggle source
# File lib/git/lib.rb, line 849
def tags
  command_lines('tag')
end
tree_depth(sha) click to toggle source
# File lib/git/lib.rb, line 341
def tree_depth(sha)
  full_tree(sha).size
end
unmerged() click to toggle source
# File lib/git/lib.rb, line 799
def unmerged
  unmerged = []
  command_lines('diff', "--cached").each do |line|
    unmerged << $1 if line =~ /^\* Unmerged path (.*)/
  end
  unmerged
end
update_ref(branch, commit) click to toggle source
# File lib/git/lib.rb, line 955
def update_ref(branch, commit)
  command('update-ref', branch, commit)
end
worktree_add(dir, commitish = nil) click to toggle source
# File lib/git/lib.rb, line 378
def worktree_add(dir, commitish = nil)
  return command('worktree', ['add', dir, commitish]) if !commitish.nil?
  command('worktree', ['add', dir])
end
worktree_prune() click to toggle source
# File lib/git/lib.rb, line 387
def worktree_prune
  command('worktree', ['prune'])
end
worktree_remove(dir) click to toggle source
# File lib/git/lib.rb, line 383
def worktree_remove(dir)
  command('worktree', ['remove', dir])
end
worktrees_all() click to toggle source
# File lib/git/lib.rb, line 358
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() click to toggle source
# File lib/git/lib.rb, line 938
def write_tree
  command('write-tree')
end

Private Instance Methods

command(cmd, *opts, &block) click to toggle source
# File lib/git/lib.rb, line 1078
def command(cmd, *opts, &block)
  command_opts = { chomp: true, redirect: '' }
  if opts.last.is_a?(Hash)
    command_opts.merge!(opts.pop)
  end
  command_opts.keys.each do |k|
    raise ArgumentError.new("Unsupported option: #{k}") unless [:chomp, :redirect].include?(k)
  end

  global_opts = []
  global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
  global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
  global_opts << %w[-c core.quotePath=true]
  global_opts << %w[-c color.ui=false]

  opts = [opts].flatten.map {|s| escape(s) }.join(' ')

  global_opts = global_opts.flatten.map {|s| escape(s) }.join(' ')

  git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{cmd} #{opts} #{command_opts[:redirect]} 2>&1"

  output = nil

  command_thread = nil;

  exitstatus = nil

  with_custom_env_variables do
    command_thread = Thread.new do
      output = run_command(git_cmd, &block)
      exitstatus = $?.exitstatus
    end
    command_thread.join
  end

  if @logger
    @logger.info(git_cmd)
    @logger.debug(output)
  end

  raise Git::GitExecuteError, "#{git_cmd}:#{output}" if
    exitstatus > 1 || (exitstatus == 1 && output != '')

  output.chomp! if output && command_opts[:chomp] && !block_given?

  output
end
command_lines(cmd, *opts) click to toggle source
# File lib/git/lib.rb, line 1031
def command_lines(cmd, *opts)
  cmd_op = command(cmd, *opts)
  if cmd_op.encoding.name != "UTF-8"
    op = cmd_op.encode("UTF-8", "binary", :invalid => :replace, :undef => :replace)
  else
    op = cmd_op
  end
  op.split("\n")
end
diff_as_hash(diff_command, opts=[]) click to toggle source

Takes the diff command line output (as Array) and parse it into a Hash

@param [String] diff_command the diff commadn to be used @param [Array] opts the diff options to be used @return [Hash] the diff as Hash

# File lib/git/lib.rb, line 1131
def diff_as_hash(diff_command, opts=[])
  # update index before diffing to avoid spurious diffs
  command('status')
  command_lines(diff_command, opts).inject({}) do |memo, line|
    info, file = line.split("\t")
    mode_src, mode_dest, sha_src, sha_dest, type = info.split

    memo[file] = {
      :mode_index => mode_dest,
      :mode_repo => mode_src.to_s[1, 7],
      :path => file,
      :sha_repo => sha_src,
      :sha_index => sha_dest,
      :type => type
    }

    memo
  end
end
escape(s) click to toggle source
# File lib/git/lib.rb, line 1188
def escape(s)
  windows_platform? ? escape_for_windows(s) : escape_for_sh(s)
end
escape_for_sh(s) click to toggle source
# File lib/git/lib.rb, line 1192
def escape_for_sh(s)
  "'#{s && s.to_s.gsub('\'','\'"\'"\'')}'"
end
escape_for_windows(s) click to toggle source
# File lib/git/lib.rb, line 1196
def escape_for_windows(s)
  # Escape existing double quotes in s and then wrap the result with double quotes
  escaped_string = s.to_s.gsub('"','\\"')
  %Q{"#{escaped_string}"}
end
log_common_options(opts) click to toggle source

Returns an array holding the common options for the log commands

@param [Hash] opts the given options @return [Array] the set of common options that the log command will use

# File lib/git/lib.rb, line 1155
def log_common_options(opts)
  arr_opts = []

  arr_opts << "-#{opts[:count]}" if opts[:count]
  arr_opts << "--no-color"
  arr_opts << "--cherry" if opts[:cherry]
  arr_opts << "--since=#{opts[:since]}" if opts[:since].is_a? String
  arr_opts << "--until=#{opts[:until]}" if opts[:until].is_a? String
  arr_opts << "--grep=#{opts[:grep]}" if opts[:grep].is_a? String
  arr_opts << "--author=#{opts[:author]}" if opts[:author].is_a? String
  arr_opts << "#{opts[:between][0].to_s}..#{opts[:between][1].to_s}" if (opts[:between] && opts[:between].size == 2)

  arr_opts
end
log_path_options(opts) click to toggle source

Retrurns an array holding path options for the log commands

@param [Hash] opts the given options @return [Array] the set of path options that the log command will use

# File lib/git/lib.rb, line 1174
def log_path_options(opts)
  arr_opts = []

  arr_opts << opts[:object] if opts[:object].is_a? String
  arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter]
  arr_opts
end
restore_git_system_env_variables() click to toggle source

Takes the previously stored git’s ENV variables and set them again on ENV.

# File lib/git/lib.rb, line 1050
def restore_git_system_env_variables
  ENV_VARIABLE_NAMES.each do |env_variable_name|
    ENV[env_variable_name] = @git_system_env_variables[env_variable_name]
  end
end
run_command(git_cmd, &block) click to toggle source
# File lib/git/lib.rb, line 1182
def run_command(git_cmd, &block)
  return IO.popen(git_cmd, &block) if block_given?

  `#{git_cmd}`.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join
end
set_custom_git_env_variables() click to toggle source

Sets git’s ENV variables to the custom values for the current instance.

# File lib/git/lib.rb, line 1057
def set_custom_git_env_variables
  ENV['GIT_DIR'] = @git_dir
  ENV['GIT_WORK_TREE'] = @git_work_dir
  ENV['GIT_INDEX_FILE'] = @git_index_file
  ENV['GIT_SSH'] = Git::Base.config.git_ssh
end
store_git_system_env_variables() click to toggle source

Takes the current git’s system ENV variables and store them.

# File lib/git/lib.rb, line 1042
def store_git_system_env_variables
  @git_system_env_variables = {}
  ENV_VARIABLE_NAMES.each do |env_variable_name|
    @git_system_env_variables[env_variable_name] = ENV[env_variable_name]
  end
end
windows_platform?() click to toggle source
# File lib/git/lib.rb, line 1202
def windows_platform?
  # Check if on Windows via RUBY_PLATFORM (CRuby) and RUBY_DESCRIPTION (JRuby)
  win_platform_regex = /mingw|mswin/
  RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex
end
with_custom_env_variables(&block) click to toggle source

Runs a block inside an environment with customized ENV variables. It restores the ENV after execution.

@param [Proc] block block to be executed within the customized environment

# File lib/git/lib.rb, line 1068
def with_custom_env_variables(&block)
  @@semaphore.synchronize do
    store_git_system_env_variables()
    set_custom_git_env_variables()
    return block.call()
  end
ensure
  restore_git_system_env_variables()
end