-
Notifications
You must be signed in to change notification settings - Fork 680
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add GitFetcher and rework Fetchers+SourceReaders
This adds a new git fetcher. In doing so, it also refactors how the fetchers work a bit to better support fetchers that need to resolve user-provided sources to fully specified sources appropriate for a lockfile. Signed-off-by: Steven Danna <[email protected]>
- Loading branch information
1 parent
3777f06
commit 85cbe71
Showing
31 changed files
with
1,088 additions
and
619 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
# encoding: utf-8 | ||
require 'tmpdir' | ||
require 'fileutils' | ||
require 'mixlib/shellout' | ||
require 'inspec/log' | ||
|
||
module Fetchers | ||
# | ||
# The git fetcher uses the git binary to fetch remote git sources. | ||
# Git-based sources should be specified with the `git:` key in the | ||
# source hash. Additionally, we accept `:branch`, `:ref`, and `:tag` | ||
# keys to allow users to pin to a particular revision. | ||
# | ||
# Parts of this class are derived from: | ||
# | ||
# https://github.com/chef/omnibus/blob/master/lib/omnibus/fetchers/git_fetcher.rb | ||
# | ||
# which is Copyright 2012-2014 Chef Software, Inc. and offered under | ||
# the same Apache 2 software license as inspec. | ||
# | ||
# Many thanks to the omnibus authors! | ||
# | ||
# Note that we haven't replicated all of omnibus' features here. If | ||
# you got to this file during debugging, you may want to look at the | ||
# omnibus source for hints. | ||
# | ||
class Git < Inspec.fetcher(1) | ||
name 'git' | ||
priority 200 | ||
|
||
def self.resolve(target, opts = {}) | ||
if target.respond_to?(:has_key?) &&target.key?(:git) | ||
new(target[:git], opts.merge(target)) | ||
end | ||
end | ||
|
||
def initialize(remote_url, opts = {}) | ||
@branch = opts[:branch] | ||
@tag = opts[:tag] | ||
@ref = opts[:ref] | ||
@remote_url = remote_url | ||
@repo_directory = nil | ||
end | ||
|
||
def fetch(dir) | ||
@repo_directory = dir | ||
if cloned? | ||
checkout | ||
else | ||
Dir.mktmpdir do |tmpdir| | ||
checkout(tmpdir) | ||
Inspec::Log.debug("Checkout of #{resolved_ref} successful. Moving checkout to #{dir}") | ||
FileUtils.cp_r(tmpdir, @repo_directory) | ||
end | ||
end | ||
@repo_directory | ||
end | ||
|
||
def archive_path | ||
@repo_directory | ||
end | ||
|
||
def resolved_source | ||
{ git: @remote_url, ref: resolved_ref } | ||
end | ||
|
||
private | ||
|
||
def resolved_ref | ||
@resolved_ref ||= if @ref | ||
@ref | ||
elsif @branch | ||
resolve_ref(@branch) | ||
elsif @tag | ||
resolve_ref(@tag) | ||
else | ||
resolve_ref('master') | ||
end | ||
end | ||
|
||
def resolve_ref(ref_name) | ||
cmd = shellout("git ls-remote \"#{@remote_url}\" \"#{ref_name}*\"") | ||
ref = parse_ls_remote(cmd.stdout, ref_name) | ||
if !ref | ||
fail "Unable to resolve #{ref_name} to a specific git commit for #{@remote_url}" | ||
end | ||
ref | ||
end | ||
|
||
# | ||
# The following comment is a minor modification of the comment in | ||
# the omnibus source for a similar function: | ||
# | ||
# Dereference annotated tags. | ||
# | ||
# The +remote_list+ parameter is assumed to 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 ^{}. | ||
# | ||
# @param [String] output | ||
# output from `git ls-remote origin` command | ||
# @param [String] ref_name | ||
# the target git ref_name | ||
# | ||
# @return [String] | ||
# | ||
def parse_ls_remote(output, ref_name) | ||
pairs = output.lines.map { |l| l.chomp.split("\t") } | ||
tagged_commit = pairs.find { |m| m[1].end_with?("#{ref_name}^{}") } | ||
if tagged_commit | ||
tagged_commit.first | ||
else | ||
found = pairs.find { |m| m[1].end_with?(ref_name.to_s) } | ||
if found | ||
found.first | ||
end | ||
end | ||
end | ||
|
||
def cloned? | ||
File.directory?(File.join(@repo_directory, '.git')) | ||
end | ||
|
||
def clone(dir = @repo_directory) | ||
git_cmd("clone #{@remote_url} ./", dir) unless cloned? | ||
@repo_directory | ||
end | ||
|
||
def checkout(dir = @repo_directory) | ||
clone(dir) | ||
git_cmd("checkout #{resolved_ref}", dir) | ||
@repo_directory | ||
end | ||
|
||
def git_cmd(cmd, dir = @repo_directory) | ||
cmd = shellout("git #{cmd}", cwd: dir) | ||
cmd.error! | ||
cmd.status | ||
rescue Errno::ENOENT | ||
raise 'To use git sources, you must have git installed.' | ||
end | ||
|
||
def shellout(cmd, opts = {}) | ||
Inspec::Log.debug("Running external command: #{cmd} (#{opts})") | ||
cmd = Mixlib::ShellOut.new(cmd, opts) | ||
cmd.run_command | ||
Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}") | ||
Inspec::Log.debug('External command: STDOUT BEGIN') | ||
Inspec::Log.debug(cmd.stdout) | ||
Inspec::Log.debug('External command: STDOUT END') | ||
Inspec::Log.debug('External command: STDERR BEGIN') | ||
Inspec::Log.debug(cmd.stderr) | ||
Inspec::Log.debug('External command: STDERR END') | ||
cmd | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.