Class: R10K::Tarball

Inherits:
Object
  • Object
show all
Includes:
Settings::Mixin, Util::Cacheable, Util::Downloader
Defined in:
lib/r10k/tarball.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util::Downloader

#checksum_algorithm

Methods included from Util::Cacheable

default_cachedir, #sanitized_dirname

Methods included from Settings::Mixin

included

Constructor Details

#initialize(name, source, checksum: nil) ⇒ Tarball

Returns a new instance of Tarball.

Parameters:

  • name (String)

    The name of the tarball content

  • source (String)

    The source for the tarball content

  • checksum (String) (defaults to: nil)

    The sha256 digest of the tarball content



38
39
40
41
42
43
44
45
46
# File 'lib/r10k/tarball.rb', line 38

def initialize(name, source, checksum: nil)
  @name = name
  @source = source
  @checksum = checksum

  # At this time, the only checksum type supported is sha256. In the future,
  # we may decide to support other algorithms if a use case arises. TBD.
  checksum_algorithm = :SHA256
end

Instance Attribute Details

#checksumString

Returns The tarball’s expected sha256 digest.

Returns:

  • (String)

    The tarball’s expected sha256 digest



33
34
35
# File 'lib/r10k/tarball.rb', line 33

def checksum
  @checksum
end

#nameString

Returns The tarball’s name.

Returns:

  • (String)

    The tarball’s name



25
26
27
# File 'lib/r10k/tarball.rb', line 25

def name
  @name
end

#sourceString

Returns The tarball’s source.

Returns:

  • (String)

    The tarball’s source



29
30
31
# File 'lib/r10k/tarball.rb', line 29

def source
  @source
end

Instance Method Details

#cache_basenameString

Returns The basename of the tarball cache file.

Returns:

  • (String)

    The basename of the tarball cache file.



64
65
66
67
68
69
70
# File 'lib/r10k/tarball.rb', line 64

def cache_basename
  if checksum.nil?
    sanitized_dirname(source) + '.tar.gz'
  else
    checksum + '.tar.gz'
  end
end

#cache_checksumObject

Raises:



166
167
168
169
# File 'lib/r10k/tarball.rb', line 166

def cache_checksum
  raise R10K::Error, _("Cache not present at %{path}") % {path: cache_path} unless File.exist?(cache_path)
  file_digest(cache_path)
end

#cache_dirnameString

Returns Directory. Where the cache_basename file will be created.

Returns:

  • (String)

    Directory. Where the cache_basename file will be created.



49
50
51
# File 'lib/r10k/tarball.rb', line 49

def cache_dirname
  File.join(settings[:cache_root], 'tarball')
end

#cache_pathString

The final cache_path should match one of the templates:

- {cachedir}/{checksum}.tar.gz
- {cachedir}/{source}.tar.gz

Returns:

  • (String)

    File. The full file path the tarball will be cached to.



59
60
61
# File 'lib/r10k/tarball.rb', line 59

def cache_path
  File.join(cache_dirname, cache_basename)
end

#cache_valid?Boolean

Checks the cached tarball’s digest against the expected checksum. Returns false if no cached file is present. If the tarball has no expected checksum, any cached file is assumed to be valid.

Returns:

  • (Boolean)


150
151
152
153
154
# File 'lib/r10k/tarball.rb', line 150

def cache_valid?
  return false unless File.exist?(cache_path)
  return true if checksum.nil?
  checksum == file_digest(cache_path)
end

#getObject

Download the tarball from @source to @cache_path



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/r10k/tarball.rb', line 112

def get
  Tempfile.open(cache_basename) do |tempfile|
    tempfile.binmode
    src_uri = URI.parse(source)

    temp_digest = case src_uri.scheme
                  when 'file', nil
                    copy(src_uri.path, tempfile)
                  when %r{^[a-z]$} # Windows drive letter
                    copy(src_uri.to_s, tempfile)
                  when %r{^https?$}
                    download(src_uri, tempfile)
                  else
                    raise "Unexpected source scheme #{src_uri.scheme}"
                  end

    # Verify the download
    unless (checksum == temp_digest) || checksum.nil?
      raise 'Downloaded file does not match checksum'
    end

    # Move the download to cache_path
    FileUtils::mkdir_p(cache_dirname)
    begin
      FileUtils.mv(tempfile.path, cache_path)
    rescue Errno::EACCES
      # It may be the case that permissions don't permit moving the file
      # into place, but do permit overwriting an existing in-place file.
      FileUtils.cp(tempfile.path, cache_path)
    end
  end
end

#insync?(target_dir, ignore_untracked_files: false) ⇒ Boolean

Parameters:

  • target_dir (String)

    The directory to check if is in sync with the tarball content

  • ignore_untracked_files (Boolean) (defaults to: false)

    If true, consider the target dir to be in sync as long as all tracked content matches.

Returns:

  • (Boolean)


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/r10k/tarball.rb', line 91

def insync?(target_dir, ignore_untracked_files: false)
  target_tree_entries = Find.find(target_dir).map(&:to_s) - [target_dir]
  each_tarball_entry do |entry|
    found = target_tree_entries.delete(File.join(target_dir, entry.full_name.chomp('/')))
    return false if found.nil?
    next if entry.directory?
    return false unless file_digest(found) == reader_digest(entry)
  end

  if ignore_untracked_files
    # We wouldn't have gotten this far if there were discrepancies in
    # tracked content
    true
  else
    # If there are still files in target_tree_entries, then there is
    # untracked content present in the target tree. If not, we're in sync.
    target_tree_entries.empty?
  end
end

#pathsArray

List all of the files contained in the tarball and their paths. This is useful for implementing R10K::Purgable

Returns:

  • (Array)

    A normalized list of file paths contained in the archive



160
161
162
163
164
# File 'lib/r10k/tarball.rb', line 160

def paths
  names = Array.new
  each_tarball_entry { |entry| names << Pathname.new(entry).cleanpath.to_s }
  names - ['.']
end

#unpack(target_dir) ⇒ Object

Extract the cached tarball to the target directory.

Parameters:

  • target_dir (String)

    Where to unpack the tarball



75
76
77
78
79
80
81
82
83
# File 'lib/r10k/tarball.rb', line 75

def unpack(target_dir)
  file = File.open(cache_path, 'rb')
  reader = Zlib::GzipReader.new(file)
  begin
    Minitar.unpack(reader, target_dir)
  ensure
    reader.close
  end
end