class Omnibus::GitFetcher

Fetcher implementation for projects in git.

Attributes

project_dir[R]
source[R]
version[R]

Public Class Methods

new(software) click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 29
def initialize(software)
  @name         = software.name
  @source       = software.source
  @version      = software.version
  @project_dir  = software.project_dir
end

Public Instance Methods

clean() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 48
def clean
  if existing_git_clone?
    log "cleaning existing build"
    clean_cmd = "git clean -fdx"
    shell = Mixlib::ShellOut.new(clean_cmd, :live_stream => STDOUT, :cwd => project_dir)
    shell.run_command
    shell.error!
  end
rescue Exception => e
  ErrorReporter.new(e, self).explain("Failed to clean git repository '#{@source[:git]}'")
  raise
end
description() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 36
    def description
      s=<<-E
repo URI:       #{@source[:git]}
local location: #{@project_dir}
E
    end
fetch() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 65
def fetch
  retries ||= 0
  if existing_git_clone?
    fetch_updates unless current_rev_matches_target_rev?
  else
    clone
    checkout
  end
rescue Exception => e
  if retries >= 3
    ErrorReporter.new(e, self).explain("Failed to fetch git repository '#{@source[:git]}'")
    raise
  else
    # Deal with github failing all the time :(
    time_to_sleep = 5 * (2 ** retries)
    retries += 1
    log "git clone/fetch failed for #{@source} #{retries} time(s), retrying in #{time_to_sleep}s"
    sleep(time_to_sleep)
    retry
  end
end
fetch_required?() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 61
def fetch_required?
  !existing_git_clone? || !current_rev_matches_target_rev?
end
version_guid() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 43
def version_guid
  "git:#{current_revision}".chomp
rescue
end

Private Instance Methods

checkout() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 97
def checkout
  sha_ref = target_revision

  checkout_cmd = "git checkout #{sha_ref}"
  shell = Mixlib::ShellOut.new(checkout_cmd, :live_stream => STDOUT, :cwd => project_dir)
  shell.run_command
  shell.error!
end
clone() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 89
def clone
  puts "cloning the source from git"
  clone_cmd = "git clone #{@source[:git]} #{project_dir}"
  shell = Mixlib::ShellOut.new(clone_cmd, :live_stream => STDOUT)
  shell.run_command
  shell.error!
end
current_rev_matches_target_rev?() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 118
def current_rev_matches_target_rev?
  current_revision && current_revision.strip.to_i(16) == target_revision.strip.to_i(16)
end
current_revision() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 122
def current_revision
  @current_rev ||= begin
                     rev_cmd = "git rev-parse HEAD"
                     shell = Mixlib::ShellOut.new(rev_cmd, :live_stream => STDOUT, :cwd => project_dir)
                     shell.run_command
                     shell.error!
                     output = shell.stdout

                     sha_hash?(output) ? output : nil
                   end
end
existing_git_clone?() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 114
def existing_git_clone?
  File.exist?("#{project_dir}/.git")
end
fetch_updates() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 106
def fetch_updates
  puts "fetching updates and resetting to revision #{target_revision}"
  fetch_cmd = "git fetch origin && git fetch origin --tags && git reset --hard #{target_revision}"
  shell = Mixlib::ShellOut.new(fetch_cmd, :live_stream => STDOUT, :cwd => project_dir)
  shell.run_command
  shell.error!
end
process_remote_list(stdout, ref) click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 179
def process_remote_list(stdout, ref)
  # Dereference annotated tags.
  #
  # Output will look like this:
  #
  # a2ed66c01f42514bcab77fd628149eccb4ecee28        refs/tags/rel-0.11.0
  # f915286abdbc1907878376cce9222ac0b08b12b8        refs/tags/rel-0.11.0^{}
  #
  # The SHA with ^{} is the commit pointed to by an annotated
  # tag. If ref isn't an annotated tag, there will not be a line
  # with trailing ^{}.
  #
  # We'll return the SHA corresponding to the ^{} which is the
  # commit pointed to by an annotated tag. If no such commit
  # exists (not an annotated tag) then we return the SHA of the
  # ref.  If nothing matches, return "".
  lines = stdout.split("\n")
  matches = lines.map { |line| line.split("\t") }
  # first try for ^{} indicating the commit pointed to by an
  # annotated tag
  tagged_commit = matches.find { |m| m[1].end_with?("#{ref}^{}") }
  if tagged_commit
    tagged_commit[0]
  else
    found = matches.find { |m| m[1].end_with?("#{ref}") }
    if found
      found[0]
    else
      nil
    end
  end
end
revision_from_remote_reference(ref) click to toggle source

Return the SHA corresponding to ref. If ref is an annotated tag, return the SHA that was tagged not the SHA of the tag itself.

# File lib/omnibus/fetchers/git_fetcher.rb, line 150
def revision_from_remote_reference(ref)
  retries ||= 0
  # execute `git ls-remote` the trailing '*' does globbing. This
  # allows us to return the SHA of the tagged commit for annotated
  # tags. We take care to only return exact matches in
  # process_remote_list.
  cmd = "git ls-remote origin #{ref}*"
  shell = Mixlib::ShellOut.new(cmd, :live_stream => STDOUT, :cwd => project_dir)
  shell.run_command
  shell.error!
  commit_ref = process_remote_list(shell.stdout, ref)
  if !commit_ref
    raise "Could not parse SHA reference"
  end
  commit_ref
rescue Exception => e
  if retries >= 3
    ErrorReporter.new(e, self).explain("Failed to fetch git repository '#{@source[:git]}'")
    raise
  else
    # Deal with github failing all the time :(
    time_to_sleep = 5 * (2 ** retries)
    retries += 1
    log "git ls-remote failed for #{@source} #{retries} time(s), retrying in #{time_to_sleep}s"
    sleep(time_to_sleep)
    retry
  end
end
sha_hash?(rev) click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 144
def sha_hash?(rev)
  rev =~ /^[0-9a-f]{40}$/
end
target_revision() click to toggle source
# File lib/omnibus/fetchers/git_fetcher.rb, line 134
def target_revision
  @target_rev ||= begin
                    if sha_hash?(version)
                      version
                    else
                      revision_from_remote_reference(version)
                    end
                  end
end