Class: Inspec::Fetcher::Git

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

Overview

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 Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(remote_url, opts = {}) ⇒ Git

Returns a new instance of Git.



38
39
40
41
42
43
44
45
# File 'lib/inspec/fetcher/git.rb', line 38

def initialize(remote_url, opts = {})
  @branch = opts[:branch]
  @tag = opts[:tag]
  @ref = opts[:ref]
  @remote_url = expand_local_path(remote_url)
  @repo_directory = nil
  @relative_path = opts[:relative_path] if opts[:relative_path] && !opts[:relative_path].empty?
end

Class Method Details

.resolve(target, opts = {}) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/inspec/fetcher/git.rb', line 30

def self.resolve(target, opts = {})
  if target.is_a?(String)
    new(target, opts) if target.start_with?("git@") || target.end_with?(".git")
  elsif target.respond_to?(:has_key?) && target.key?(:git)
    new(target[:git], opts.merge(target))
  end
end

Instance Method Details

#archive_pathObject



105
106
107
# File 'lib/inspec/fetcher/git.rb', line 105

def archive_path
  @repo_directory
end

#cache_keyObject



99
100
101
102
103
# File 'lib/inspec/fetcher/git.rb', line 99

def cache_key
  return resolved_ref unless @relative_path

  OpenSSL::Digest.hexdigest("SHA256", resolved_ref + @relative_path)
end

#expand_local_path(url_or_file_path) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/inspec/fetcher/git.rb', line 47

def expand_local_path(url_or_file_path)
  # This paths to local on-disk repos, not relative paths within repos.
  # This is especially needed with testing.

  # We could try to do something clever with URI
  # processing, but then again, if you passed a relative path
  # to an on-disk repo, you probably expect it to exist.
  return url_or_file_path unless File.exist?(url_or_file_path)

  # It's important to expand this path, because it may be specified
  # locally in the metadata files, and when we clone, we will be
  # in a temp dir.
  File.expand_path(url_or_file_path)
end

#fetch(destination_path) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/inspec/fetcher/git.rb', line 62

def fetch(destination_path)
  @repo_directory = destination_path # Might be the cache, or vendoring, or something else
  FileUtils.mkdir_p(destination_path) unless Dir.exist?(destination_path)

  if cloned?
    checkout
  else
    Dir.mktmpdir do |working_dir|
      checkout(working_dir)
      if @relative_path
        perform_relative_path_fetch(destination_path, working_dir)
      else
        Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
                          "Moving checkout to #{destination_path}")
        FileUtils.cp_r(working_dir + "/.", destination_path)
      end
    end
  end
  @repo_directory
end

#perform_relative_path_fetch(destination_path, working_dir) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/inspec/fetcher/git.rb', line 83

def perform_relative_path_fetch(destination_path, working_dir)
  Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
                    "Moving #{@relative_path} to #{destination_path}")
  unless File.exist?("#{working_dir}/#{@relative_path}")
    # Cleanup the destination path - otherwise we'll have an empty dir
    # in the cache, which is enough to confuse the cache reader
    # This is a courtesy, assuming we're writing to the cache; if we're
    # vendoring to something more complex, don't bother.
    FileUtils.rmdir(destination_path) if Dir.empty?(destination_path)

    raise Inspec::FetcherFailure, "Cannot find relative path '#{@relative_path}' " \
                                  "within profile in git repo specified by '#{@remote_url}'"
  end
  FileUtils.cp_r("#{working_dir}/#{@relative_path}", destination_path)
end

#resolved_sourceObject



109
110
111
112
113
# File 'lib/inspec/fetcher/git.rb', line 109

def resolved_source
  source = { git: @remote_url, ref: resolved_ref }
  source[:relative_path] = @relative_path if @relative_path
  source
end

#update_from_opts(opts) ⇒ Object



115
116
117
# File 'lib/inspec/fetcher/git.rb', line 115

def update_from_opts(opts)
  %i{branch tag ref}.map { |opt_name| update_ivar_from_opt(opt_name, opts) }.any?
end