module FalkorLib::Git

Management of Git operations

Public Instance Methods

add(path, msg = "", options = {}) click to toggle source
Add a file/whatever to Git and commit it

Supported options:

  • :force [boolean]: force the add

# File lib/falkorlib/git/base.rb, line 242
def add(path, msg = "", options = {})
  exit_status = 0
  dir  = File.realpath(File.dirname(path))
  root = rootdir(path)
  relative_path_to_root = Pathname.new( File.realpath(path) ).relative_path_from Pathname.new(root)
  real_msg = ((msg.empty?) ? "add '#{relative_path_to_root}'" : msg)
  opts = '-f' if options[:force]
  Dir.chdir( dir ) do
    exit_status = run %(
              git add #{opts} #{path}
              git commit -s -m "#{real_msg}" #{path}
            )
  end
  exit_status.to_i
end
branch?(path = Dir.pwd) click to toggle source

Get the current git branch

# File lib/falkorlib/git/base.rb, line 193
def branch?(path = Dir.pwd)
  list_branch(path)[0]
end
command?(cmd) click to toggle source

Check the availability of a given git command

# File lib/falkorlib/git/base.rb, line 59
def command?(cmd)
  cg = MiniGit::Capturing.new
  cmd_list = cg.help :a => true
  # typical run:
  # usage: git [--version] [--help] [-C <path>] [-c name=value]
  #            [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
  #            [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
  #            [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
  #            <command> [<args>]
  #
  # available git commands in '/usr/local/Cellar/git/1.8.5.2/libexec/git-core'
  #
  #   add   [...]   \
  #   [...]          | The part we are interested in, delimited by '\n\n' sequence
  #   [...]         /
  #
  # 'git help -a' and 'git help -g' lists available subcommands and some
  # concept guides. See 'git help <command>' or 'git help <concept>'
  # to read about a specific subcommand or concept
  l = cmd_list.split("\n\n")
  l.shift # useless first part
  #ap l
  subl = l.each_index.select { |i| l[i] =~ /^\s\s+/ } # find sublines that starts with at least two whitespaces
  #ap subl
  return false if subl.empty?
  subl.any? { |i| l[i].split.include?(cmd) }
end
commits?(path) click to toggle source

Check if the repositories already holds some commits

# File lib/falkorlib/git/base.rb, line 49
def commits?(path)
  res = false
  Dir.chdir(path) do
    _stdout, _stderr, exit_status = Open3.capture3( "git rev-parse HEAD" )
    res = (exit_status.to_i.zero?)
  end
  res
end
config(key, dir = Dir.pwd, options = {}) click to toggle source
config ######

Retrieve the Git configuration You can propose a pattern as key Supported options:

* :list [boolean] list all configurations
* :hash [boolean] return a Hash
# File lib/falkorlib/git/base.rb, line 152
def config(key, dir = Dir.pwd, options = {})
  #info "Retrieve the Git configuration"
  res = nil
  if (options[:list] || (key.is_a? Regexp) || (key =~ /\*/))
    cg  = MiniGit::Capturing.new(dir)
    res = (cg.config :list => true).split("\n")
    res.select! { |e| e.match(/^#{key}/) } unless key == '*'
    #res = res.map { |e| e.split('=') }.to_h if options[:hash]
    res = Hash[ res.map { |e| e.split('=') } ] if options[:hash]
  else
    g = MiniGit.new(dir)
    res = g[key]
    res = { key => g[key] } if options[:hash]
  end
  #ap res
  res
end
config_warn(type = :subtrees) click to toggle source

Raise a warning message if subtree/submodule section is not present

# File lib/falkorlib/git/base.rb, line 474
def config_warn(type = :subtrees)
  warn "You shall setup 'Falkorlib.config.git[#{type.to_sym}]' to configure #{type} as follows:"
  warn "     FalkorLib.config.git do |c|"
  warn "       c[#{type.to_sym}] = {"
  warn "          '<subdir>' => {"
  warn "             :url    => '<giturl>',"
  warn "             :branch => 'develop'   # if different from master"
  warn "          },"
  warn "        }"
  warn "     end"
  if type == :submodules
    warn "This will configure the Git submodule into FalkorLib.config.git.submodulesdir"
    warn "i.e. '#{FalkorLib.config.git[:submodulesdir]}'" if FalkorLib.config.git[:submodulesdir]
  end
end
create_branch(branch, path = Dir.pwd) click to toggle source

Create a new branch

# File lib/falkorlib/git/base.rb, line 131
def create_branch(branch, path = Dir.pwd)
  #ap method(__method__).parameters.map { |arg| arg[1] }
  g = MiniGit.new(path)
  error "not yet any commit performed -- You shall do one" unless commits?(path)
  g.branch branch.to_s
end
create_remote(name, url, path = Dir.pwd, opts = {}) click to toggle source

Create a new remote <name> targeting url <url> You can pass additional options expected by git remote add in <opts>, for instance as follows:

create_remote('origin', url, dir, { :fetch => true })
# File lib/falkorlib/git/base.rb, line 318
def create_remote(name, url, path = Dir.pwd, opts = {})
  g = MiniGit.new(path)
  g.remote :add, opts, name, url.to_s
end
delete_branch(branch, path = Dir.pwd, opts = { :force => false }) click to toggle source

Delete a branch.

# File lib/falkorlib/git/base.rb, line 139
def delete_branch(branch, path = Dir.pwd, opts = { :force => false })
  g = MiniGit.new(path)
  error "'#{branch}' is not a valid existing branch" unless list_branch(path).include?( branch )
  g.branch ((opts[:force]) ? :D : :d) => branch.to_s
end
dirty?(path = Dir.pwd) click to toggle source
Check if a git directory is in dirty mode

git diff –shortstat 2> /dev/null | tail -n1

# File lib/falkorlib/git/base.rb, line 260
def dirty?(path = Dir.pwd)
  g = MiniGit.new(path)
  a = g.capturing.diff :shortstat => true
  #ap a
  !a.empty?
end
fetch(path = Dir.pwd) click to toggle source

Fetch the latest changes

# File lib/falkorlib/git/base.rb, line 172
def fetch(path = Dir.pwd)
  Dir.chdir( path ) do
    execute "git fetch --all -v"
  end
end
gitdir(path = Dir.pwd) click to toggle source

Return the git root directory for the path (current directory by default)

# File lib/falkorlib/git/base.rb, line 125
def gitdir(path = Dir.pwd)
  g = MiniGit.new
  g.find_git_dir(path)[0]
end
grab(branch, path = Dir.pwd, remote = 'origin') click to toggle source

Grab a remote branch

# File lib/falkorlib/git/base.rb, line 198
def grab(branch, path = Dir.pwd, remote = 'origin')
  exit_status = 1
  error "no branch provided" if branch.nil?
  #remotes  = FalkorLib::Git.remotes(path)
  branches = FalkorLib::Git.list_branch(path)
  if branches.include? "remotes/#{remote}/#{branch}"
    info "Grab the branch '#{remote}/#{branch}'"
    exit_status = execute_in_dir(FalkorLib::Git.rootdir( path ), "git branch --track #{branch} #{remote}/#{branch}")
  else
    warning "the remote branch '#{remote}/#{branch}' cannot be found"
  end
  exit_status
end
init(path = Dir.pwd, _options = {}) click to toggle source

Initialize a git repository

# File lib/falkorlib/git/base.rb, line 90
def init(path = Dir.pwd, _options = {})
  # FIXME: for travis test: ensure the global git configurations
  # 'user.email' and 'user.name' are set
  [ 'user.name', 'user.email' ].each do |userconf|
    next unless MiniGit[userconf].nil?
    warn "The Git global configuration '#{userconf}' is not set so"
    warn "you should *seriously* consider setting them by running\n\t git config --global #{userconf} 'your_#{userconf.sub(/\./, '_')}'"
    default_val = ENV['USER']
    default_val += '@domain.org' if userconf =~ /email/
    warn "Now putting a default value '#{default_val}' you could change later on"
    run %(
                   git config --global #{userconf} "#{default_val}"
              )
    #MiniGit[userconf] = default_val
  end
  exit_status = 1
  Dir.mkdir( path ) unless Dir.exist?( path )
  Dir.chdir( path ) do
    execute "git init" unless FalkorLib.config.debug
    exit_status = $?.to_i
  end
  # #puts "#init #{path}"
  # Dir.chdir( "#{path}" ) do
  #     %x[ pwd && git init ] unless FalkorLib.config.debug
  # end
  exit_status
end
init?(path = Dir.pwd) click to toggle source

Check if a git directory has been initialized

# File lib/falkorlib/git/base.rb, line 39
def init?(path = Dir.pwd)
  begin
    MiniGit.new(path)
  rescue Exception
    return false
  end
  true
end
last_tag_commit(path = Dir.pwd) click to toggle source

Get the last tag commit, or nil if no tag can be found

# File lib/falkorlib/git/base.rb, line 281
def last_tag_commit(path = Dir.pwd)
  res = ""
  g = MiniGit.new(path)
  unless (g.capturing.tag :list => true).empty?
    # git rev-list --tags --max-count=1
    res = (g.capturing.rev_list :tags => true, :max_count => 1).chomp
  end
  res
end
list_branch(path = Dir.pwd) click to toggle source

Get an array of the local branches present (first element is always the current branch)

# File lib/falkorlib/git/base.rb, line 180
def list_branch(path = Dir.pwd)
  cg = MiniGit::Capturing.new(path)
  res = cg.branch :a => true
  res = res.split("\n")
  # Eventually reorder to make the first element of the array the current branch
  i = res.find_index { |e| e =~ /^\*\s/ }
  res[0], res[i] = res[i], res[0] unless (i.nil? || i.zero?)
  res.each { |e| e.sub!(/^\*?\s+/, '') }
  res
end
list_files(path = Dir.pwd) click to toggle source

List the files currently under version

# File lib/falkorlib/git/base.rb, line 234
def list_files(path = Dir.pwd)
  g = MiniGit.new(path)
  g.capturing.ls_files.split
end
list_tag(path = Dir.pwd) click to toggle source

Get a hash table of tags under the format { <tag> => <commit> }

# File lib/falkorlib/git/base.rb, line 269
def list_tag(path = Dir.pwd)
  res = {}
  cg  = MiniGit::Capturing.new(path)
  unless (cg.tag :list => true).empty?
    # git show-ref --tags
    a = (cg.show_ref :tags => true).split("\n")
    res = Hash[ a.collect { |item| item.split(' refs/tags/') } ].invert
  end
  res
end
publish(branch, path = Dir.pwd, remote = 'origin') click to toggle source

Publish a branch on the remote

# File lib/falkorlib/git/base.rb, line 213
def publish(branch, path = Dir.pwd, remote = 'origin')
  exit_status = 1
  error "no branch provided" if branch.nil?
  #remotes  = FalkorLib::Git.remotes(path)
  branches = FalkorLib::Git.list_branch(path)
  Dir.chdir(FalkorLib::Git.rootdir( path ) ) do
    if branches.include? "remotes/#{remote}/#{branch}"
      warning "the  remote branch '#{remote}/#{branch}' already exists"
    else
      info "Publish the branch '#{branch}' on the remote '#{remote}'"
      exit_status = run %(
                      git push #{remote} #{branch}:refs/heads/#{branch}
                      git fetch #{remote}
                      git branch -u #{remote}/#{branch} #{branch}
            )
    end
  end
  exit_status
end
remotes(path = Dir.pwd) click to toggle source

List of Git remotes

# File lib/falkorlib/git/base.rb, line 302
def remotes(path = Dir.pwd)
  g = MiniGit.new(path)
  g.capturing.remote.split
end
remotes?(path = Dir.pwd) click to toggle source

Check existence of remotes

# File lib/falkorlib/git/base.rb, line 308
def remotes?(path = Dir.pwd)
  !remotes(path).empty?
end
rootdir(path = Dir.pwd) click to toggle source

Return the Git working tree from the proposed path (current directory by default)

# File lib/falkorlib/git/base.rb, line 119
def rootdir(path = Dir.pwd)
  g = MiniGit.new
  g.find_git_dir(path)[1]
end
submodule_init(path = Dir.pwd, submodules = FalkorLib.config.git[:submodules], _options = {}) click to toggle source

Initialize git submodule from the configuration

# File lib/falkorlib/git/base.rb, line 334
def submodule_init(path = Dir.pwd, submodules = FalkorLib.config.git[:submodules], _options = {})
  exit_status  = 1
  git_root_dir = rootdir(path)
  if File.exist?("#{git_root_dir}/.gitmodules")
    unless submodules.empty?
      # TODO: Check if it contains all submodules of the configuration
    end
  end
  #ap FalkorLib.config.git
  Dir.chdir(git_root_dir) do
    exit_status = FalkorLib::Git.submodule_update( git_root_dir )
    submodules.each do |subdir, conf|
      next if conf[:url].nil?
      url = conf[:url]
      dir = "#{FalkorLib.config.git[:submodulesdir]}/#{subdir}"
      branch = (conf[:branch].nil?) ? 'master' : conf[:branch]
      if File.directory?( dir )
        puts "  ... the git submodule '#{subdir}' is already setup."
      else
        info "adding Git submodule '#{dir}' from '#{url}'"
        exit_status = run %(
                       git submodule add -b #{branch} #{url} #{dir}
                       git commit -s -m "Add Git submodule '#{dir}' from '#{url}'" .gitmodules #{dir}
                    )
      end
    end
  end
  exit_status
end
submodule_update(path = Dir.pwd) click to toggle source

Update the Git submodules to the local registered version

# File lib/falkorlib/git/base.rb, line 365
def submodule_update(path = Dir.pwd)
  execute_in_dir(rootdir(path),
                 %(
               git submodule init
               git submodule update
        ))
end
submodule_upgrade(path = Dir.pwd) click to toggle source

Upgrade the Git submodules to the latest HEAD version from the remote

# File lib/falkorlib/git/base.rb, line 374
def submodule_upgrade(path = Dir.pwd)
  execute_in_dir(rootdir(path),
                 %{
               git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
         })
end
subtree_diff(path = Dir.pwd) click to toggle source

Show difference between local subtree(s) and their remotes“

# File lib/falkorlib/git/base.rb, line 423
def subtree_diff(path = Dir.pwd)
  raise ArgumentError, "Git 'subtree' command is not available" unless FalkorLib::Git.command? "subtree"
  if FalkorLib.config.git[:subtrees].empty?
    FalkorLib::Git.config_warn(:subtrees)
    return 1
  end
  exit_status = 0
  git_root_dir = rootdir(path)
  Dir.chdir(git_root_dir) do
    FalkorLib.config.git[:subtrees].each do |dir, conf|
      next if conf[:url].nil?
      #url    = conf[:url]
      remote = dir.gsub(/\//, '-')
      branch = (conf[:branch].nil?) ? 'master' : conf[:branch]
      remotes = FalkorLib::Git.remotes
      raise IOError, "The git remote '#{remote}' is not configured" unless remotes.include?( remote )
      raise IOError, "The git subtree directory '#{dir}' does not exists" unless File.directory?( File.join(git_root_dir, dir) )
      info "Git diff on subtree '#{dir}' with remote '#{remote}/#{branch}'"
      exit_status = execute "git diff #{remote}/#{branch} #{FalkorLib::Git.branch?( git_root_dir )}:#{dir}"
    end
  end
  exit_status
end
subtree_init(path = Dir.pwd) click to toggle source

Initialize git subtrees from the configuration

# File lib/falkorlib/git/base.rb, line 383
def subtree_init(path = Dir.pwd)
  raise ArgumentError, "Git 'subtree' command is not available" unless FalkorLib::Git.command? "subtree"
  if FalkorLib.config.git[:subtrees].empty?
    FalkorLib::Git.config_warn(:subtrees)
    return 1
  end
  exit_status = 0
  git_root_dir = rootdir(path)
  Dir.chdir(git_root_dir) do
    FalkorLib.config.git[:subtrees].each do |dir, conf|
      next if conf[:url].nil?
      url    = conf[:url]
      remote = dir.gsub(/\//, '-')
      branch = (conf[:branch].nil?) ? 'master' : conf[:branch]
      remotes = FalkorLib::Git.remotes
      unless remotes.include?( remote )
        info "Initialize Git remote '#{remote}' from URL '#{url}'"
        exit_status = execute "git remote add --no-tags -f #{remote} #{url}"
      end
      unless File.directory?( File.join(git_root_dir, dir) )
        info "initialize Git subtree '#{dir}'"
        exit_status = execute "git subtree add --prefix #{dir} --squash #{remote}/#{branch}"
      end
    end
  end
  exit_status
end
subtree_init?(path = Dir.pwd) click to toggle source

Check if the subtrees have been initialized. Actually based on a naive check of sub-directory existence

# File lib/falkorlib/git/base.rb, line 413
def subtree_init?(path = Dir.pwd)
  res = true
  FalkorLib.config.git[:subtrees].keys.each do |dir|
    res &&= File.directory?(File.join(path, dir))
  end
  res
end
subtree_pull(path = Dir.pwd)
Alias for: subtree_up
subtree_up(path = Dir.pwd) click to toggle source

Pull the latest changes, assuming the git repository is not dirty

# File lib/falkorlib/git/base.rb, line 448
def subtree_up(path = Dir.pwd)
  error "Unable to pull subtree(s): Dirty Git repository" if FalkorLib::Git.dirty?( path )
  exit_status = 0
  git_root_dir = rootdir(path)
  Dir.chdir(git_root_dir) do
    FalkorLib.config.git[:subtrees].each do |dir, conf|
      next if conf[:url].nil?
      #url    = conf[:url]
      remote = dir.gsub(/\//, '-')
      branch = (conf[:branch].nil?) ? 'master' : conf[:branch]
      remotes = FalkorLib::Git.remotes
      info "Pulling changes into subtree '#{dir}' using remote '#{remote}/#{branch}'"
      raise IOError, "The git remote '#{remote}' is not configured" unless remotes.include?( remote )
      info "\t\\__ fetching remote '#{remotes.join(',')}'"
      FalkorLib::Git.fetch( git_root_dir )
      raise IOError, "The git subtree directory '#{dir}' does not exists" unless File.directory?( File.join(git_root_dir, dir) )
      info "\t\\__ pulling changes"
      exit_status = execute "git subtree pull --prefix #{dir} --squash #{remote} #{branch}"
      #exit_status = puts "git subtree pull --prefix #{dir} --squash #{remote} #{branch}"
    end
  end
  exit_status
end
Also aliased as: subtree_pull
tag(name, path = Dir.pwd, opts = {}) click to toggle source
Create a new tag

You can add extra options to the git tag command through the opts hash. Ex:

FalkorLib::Git.tag('name', dir,  { :delete => true } )
# File lib/falkorlib/git/base.rb, line 296
def tag(name, path = Dir.pwd, opts = {})
  g = MiniGit.new(path)
  g.tag opts, name
end