Class: Omnibus::GitCache

Inherits:
Object
  • Object
show all
Includes:
Logging, Util
Defined in:
lib/omnibus/git_cache.rb

Constant Summary collapse

SERIAL_NUMBER =

The serial number represents compatibility of a cache entry with the current version of the omnibus code base. Any time a change is made to omnibus that makes the code incompatible with any cache entries created before the code change, the serial number should be incremented.

For example, if a code change generates content in the `install_dir` before cache snapshots are taken, any snapshots created before upgrade will not have the generated content, so these snapshots would be incompatible with the current omnibus codebase. Incrementing the serial number ensures these old shapshots will not be used in subsequent builds.

3
REQUIRED_GIT_FILES =
%w{
HEAD
description
hooks
info
objects
refs}.freeze

Constants included from Util

Util::SHELLOUT_OPTIONS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

included

Methods included from Util

#compiler_safe_path, #copy_file, #create_directory, #create_file, #create_link, included, #path_key, #remove_directory, #remove_file, #retry_block, #shellout, #shellout!, #windows_safe_path

Constructor Details

#initialize(software) ⇒ GitCache

Returns a new instance of GitCache.

Parameters:

  • software (Software)

    the software this git cache is for


54
55
56
# File 'lib/omnibus/git_cache.rb', line 54

def initialize(software)
  @software = software
end

Instance Attribute Details

#softwareSoftware (readonly)

Returns:


48
49
50
# File 'lib/omnibus/git_cache.rb', line 48

def software
  @software
end

Instance Method Details

#cache_pathString

The path to the full install_dir cache for the project.

Returns:

  • (String)

63
64
65
# File 'lib/omnibus/git_cache.rb', line 63

def cache_path
  @cache_path ||= File.join(Config.git_cache_dir, install_dir)
end

#create_cache_pathtrue, false

Creates the full path if it does not exist already.

Returns:

  • (true, false)

    true if the path was created, false otherwise


73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/omnibus/git_cache.rb', line 73

def create_cache_path
  if File.directory?(cache_path)
    false
  else
    create_directory(File.dirname(cache_path))
    git_cmd("init -q")
    # On windows, git is very picky about single vs double quotes
    git_cmd("config --local user.name \"Omnibus Git Cache\"")
    git_cmd("config --local user.email \"[email protected]\"")
    true
  end
end

#incrementalObject

Create an incremental install path cache for the software step


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/omnibus/git_cache.rb', line 124

def incremental
  log.internal(log_key) { "Performing incremental cache" }

  create_cache_path
  remove_git_dirs

  git_cmd("add -A -f")

  begin
    git_cmd(%Q{commit -q -m "Backup of #{tag}"})
  rescue CommandFailed => e
    raise unless e.message.include?("nothing to commit")
  end

  git_cmd(%Q{tag -f "#{tag}"})
end

#remove_git_dirstrue

Git caching will attempt to version embedded git directories, partially versioning them. This causes failures on subsequent runs. This method will find git directories and remove them to prevent those errors.

Returns:

  • (true)

172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/omnibus/git_cache.rb', line 172

def remove_git_dirs
  log.internal(log_key) { "Removing git directories" }

  Dir.glob("#{install_dir}/**/{,.*}/config").reject do |path|
    REQUIRED_GIT_FILES.any? do |required_file|
      !File.exist?(File.join(File.dirname(path), required_file))
    end
  end.each do |path|
    log.internal(log_key) { "Removing git dir `#{path}'" }
    FileUtils.rm_rf(File.dirname(path))
  end

  true
end

#restoreObject


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/omnibus/git_cache.rb', line 141

def restore
  log.internal(log_key) { "Performing cache restoration" }

  create_cache_path

  if has_tag(tag)
    log.internal(log_key) { "Detected tag `#{tag}' can be restored, marking it for restoration" }
    git_cmd(%Q{tag -f restore_here "#{tag}"})
    true
  elsif has_tag("restore_here")
    log.internal(log_key) { "Could not find tag `#{tag}', restoring previous tag" }
    restore_from_cache
    false
  else
    log.internal(log_key) { "Could not find marker tag `restore_here', nothing to restore" }
    false
  end
end

#restore_from_cacheObject


160
161
162
163
164
# File 'lib/omnibus/git_cache.rb', line 160

def restore_from_cache
  git_cmd("checkout -f restore_here")
ensure
  git_cmd("tag -d restore_here")
end

#tagString

Computes the tag for this cache entry.

Returns:

  • (String)

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/omnibus/git_cache.rb', line 91

def tag
  return @tag if @tag

  log.internal(log_key) { "Calculating tag" }

  # Accumulate an array of all the software projects that come before
  # the name and version we are tagging. So if you have
  #
  # build_order = [ 1, 2, 3, 4, 5 ]
  #
  # And we are tagging 3, you would get dep_list = [ 1, 2 ]
  dep_list = software.project.library.build_order.take_while do |dep|
    if dep.name == software.name && dep.version == software.version
      false
    else
      true
    end
  end

  log.internal(log_key) { "dep_list: #{dep_list.map(&:name).inspect}" }

  # This is the list of all the unqiue shasums of all the software build
  # dependencies, including the on currently being acted upon.
  shasums = [dep_list.map(&:shasum), software.shasum].flatten
  suffix  = Digest::SHA256.hexdigest(shasums.join("|"))
  @tag    = "#{software.name}-#{suffix}-#{SERIAL_NUMBER}"

  log.internal(log_key) { "tag: #{@tag}" }

  @tag
end