Skip to content

Commit b19533e

Browse files
committed
Add --cachedir
This caches downloaded files and git repos so when we are working on changes to packaging, we don't have to download them every time we run the build again.
1 parent 0e47400 commit b19533e

File tree

7 files changed

+53
-19
lines changed

7 files changed

+53
-19
lines changed

lib/vanagon/cli/build.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Build < Vanagon::CLI
2222
managed automatically based on `keepwork` option
2323
-k, --keepwork RULE Rule for preserving local `workdir`: [Default: never]
2424
always, on-success, on-failure, never
25+
--cachedir DIRECTORY Directory to cache source files and git repos
2526
-v, --verbose Only here for backwards compatibility. Does nothing.
2627
2728
Engines:
@@ -64,6 +65,7 @@ def options_translate(docopt_options)
6465
translations = {
6566
'--verbose' => :verbose,
6667
'--workdir' => :workdir,
68+
'--cachedir' => :cachedir,
6769
'--remote-workdir' => :'remote-workdir',
6870
'--configdir' => :configdir,
6971
'--engine' => :engine,

lib/vanagon/component.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def mirrors # rubocop:disable Lint/DuplicateMethods
261261
# if #fetch is successful.
262262
def fetch_mirrors(options)
263263
mirrors.to_a.shuffle.each do |mirror|
264-
VanagonLogger.info %(Attempting to fetch from mirror URL "#{mirror}")
264+
VanagonLogger.info %(Attempting to fetch from mirror URL "#{mirror}"#{' unless already cached' if options[:cachedir]})
265265
@source = Vanagon::Component::Source.source(mirror, **options)
266266
return true if source.fetch
267267
rescue Vanagon::InvalidSource
@@ -290,7 +290,7 @@ def fetch_mirrors(options)
290290
# @return [Boolean] return True if the source can be retrieved,
291291
# or False otherwise
292292
def fetch_url(options)
293-
VanagonLogger.info %(Attempting to fetch from canonical URL "#{url}")
293+
VanagonLogger.info %(Attempting to fetch from canonical URL "#{url}"#{' unless already cached' if options[:cachedir]})
294294
@source = Vanagon::Component::Source.source(url, **options)
295295
# Explicitly coerce the return value of #source.fetch,
296296
# because each subclass of Vanagon::Component::Source returns
@@ -313,8 +313,9 @@ def deprecated_rewrite_url
313313
# makefile template
314314
#
315315
# @param workdir [String] working directory to put the source into
316-
def get_source(workdir)
317-
opts = options.merge({ workdir: workdir, dirname: dirname })
316+
# @param cachedir [String] directory to cache downloaded sources
317+
def get_source(workdir, cachedir = nil)
318+
opts = options.merge({ workdir: workdir, cachedir: cachedir, dirname: dirname })
318319
if url || !mirrors.empty?
319320
if %w[y yes true 1].include? ENV.fetch('VANAGON_USE_MIRRORS', 'n').downcase
320321
fetch_mirrors(opts) || fetch_url(opts)
@@ -358,10 +359,11 @@ def get_dependency_hash
358359
# Fetches secondary sources for the component. These are just dumped into the workdir currently.
359360
#
360361
# @param workdir [String] working directory to put the source into
361-
def get_sources(workdir) # rubocop:disable Metrics/AbcSize
362+
# @param cachedir [String] directory to cache downloaded sources
363+
def get_sources(workdir, cachedir = nil)
362364
sources.each do |source|
363365
src = Vanagon::Component::Source.source(
364-
source.url, workdir: workdir, ref: source.ref, sum: source.sum
366+
source.url, workdir: workdir, cachedir: cachedir, ref: source.ref, sum: source.sum
365367
)
366368
src.fetch
367369
src.verify

lib/vanagon/component/source.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class << self
1717
# @param uri_instance [#to_s] URI of the source file (includes git@... style links)
1818
# @param options [Hash] hash of the options needed for the subtype
1919
# @param workdir [String] working directory to fetch the source into
20+
# @param cacheedir [String] directory to cache source files and git repos
2021
# @return [Vanagon::Component::Source] the correct subtype for the given source
2122
def source(uri_instance, **options)
2223
# Sometimes the uri comes in as a string, but sometimes it's already been
@@ -39,6 +40,7 @@ def source(uri_instance, **options)
3940
sum: options[:sum],
4041
ref: options[:ref],
4142
workdir: options[:workdir],
43+
cachedir: options[:cachedir],
4244
dirname: options[:dirname],
4345
clone_options: options[:clone_options]
4446
end
@@ -47,6 +49,7 @@ def source(uri_instance, **options)
4749
return Vanagon::Component::Source::Http.new uri,
4850
sum: options[:sum],
4951
workdir: options[:workdir],
52+
cachedir: options[:cachedir],
5053
# Default sum_type is md5 if unspecified:
5154
sum_type: options[:sum_type] || "md5"
5255
end

lib/vanagon/component/source/git.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Vanagon
1313
class Component
1414
class Source
1515
class Git
16-
attr_accessor :url, :log_url, :ref, :workdir, :clone_options
16+
attr_accessor :url, :log_url, :ref, :workdir, :cachedir, :clone_options
1717
attr_reader :version, :default_options, :repo
1818

1919
class << self
@@ -94,7 +94,8 @@ def default_options # rubocop:disable Lint/DuplicateMethods
9494
# @param url [String] url of git repo to use as source
9595
# @param ref [String] ref to checkout from git repo
9696
# @param workdir [String] working directory to clone into
97-
def initialize(url, workdir:, **options)
97+
# @param cachedir [String] directory to cache cloned repos
98+
def initialize(url, workdir:, cachedir: nil, **options)
9899
opts = default_options.merge(options.reject { |k, v| v.nil? })
99100

100101
# Ensure that #url returns a URI object
@@ -103,6 +104,7 @@ def initialize(url, workdir:, **options)
103104
@ref = opts[:ref]
104105
@dirname = opts[:dirname]
105106
@workdir = File.realpath(workdir)
107+
@cachedir = cachedir ? File.realpath(cachedir) : nil
106108
@clone_options = opts[:clone_options] ||= {}
107109

108110
# We can test for Repo existence without cloning
@@ -114,6 +116,11 @@ def initialize(url, workdir:, **options)
114116
# a side effect.
115117
def fetch
116118
begin
119+
if @cachedir && File.directory?("#{@cachedir}/#{dirname}")
120+
VanagonLogger.info "Using cached copy of Git repo '#{dirname}' in #{cachedir}"
121+
FileUtils.cp_r("#{@cachedir}/#{dirname}", workdir)
122+
@wascached = true
123+
end
117124
@clone ||= ::Git.open(File.join(workdir, dirname))
118125
@clone.fetch
119126
rescue ::Git::Error, ArgumentError
@@ -156,6 +163,11 @@ def clone
156163
else
157164
@clone ||= ::Git.clone(url, dirname, path: workdir, **clone_options)
158165
end
166+
if @cachedir && !@wascached
167+
FileUtils.cp_r(File.join(workdir, dirname), cachedir)
168+
@wascached = true
169+
end
170+
@clone
159171
end
160172

161173
# Attempt to connect to whatever URL is provided and
@@ -183,8 +195,10 @@ def refs
183195
# Clone a remote repo, make noise about it, and fail entirely
184196
# if we're unable to retrieve the remote repo
185197
def clone!
186-
VanagonLogger.info "Cloning Git repo '#{log_url}'"
187-
VanagonLogger.info "Successfully cloned '#{dirname}'" if clone
198+
unless @wascached
199+
VanagonLogger.info "Cloning Git repo '#{log_url}'"
200+
VanagonLogger.info "Successfully cloned '#{dirname}'" if clone
201+
end
188202
rescue ::Git::Error
189203
raise Vanagon::InvalidRepo, "Unable to clone from '#{log_url}'"
190204
end

lib/vanagon/component/source/http.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Http < Vanagon::Component::Source::Local
1212
include Vanagon::Utilities
1313

1414
# Accessors :url, :file, :extension, :workdir, :cleanup are inherited from Local
15-
attr_accessor :sum, :sum_type
15+
attr_accessor :sum, :sum_type, :cachedir
1616

1717
# Allowed checksum algorithms to use when validating files
1818
CHECKSUM_TYPES = %w[md5 sha1 sha256 sha512].freeze
@@ -48,8 +48,9 @@ def valid_url?(target_url)
4848
# sum from
4949
# @param workdir [String] working directory to download into
5050
# @param sum_type [String] type of sum we are verifying
51+
# @param cachedir [String] directory to cache downloaded sources
5152
# @raise [RuntimeError] an exception is raised is sum is nil
52-
def initialize(url, sum:, workdir:, sum_type:, **options)
53+
def initialize(url, sum:, workdir:, sum_type:, cachedir: nil, **options)
5354
unless sum
5455
fail "sum is required to validate the http source"
5556
end
@@ -63,6 +64,7 @@ def initialize(url, sum:, workdir:, sum_type:, **options)
6364
@url = url
6465
@sum = sum
6566
@workdir = workdir
67+
@cachedir = cachedir ? File.realpath(cachedir) : nil
6668
@sum_type = sum_type
6769

6870
if Vanagon::Component::Source::Http.valid_url?(@sum)
@@ -81,9 +83,14 @@ def initialize(url, sum:, workdir:, sum_type:, **options)
8183
end
8284

8385
# Download the source from the url specified. Sets the full path to the
84-
# file as @file and the @extension for the file as a side effect.
86+
# file as @file and the @extension for the file as a side effect. Use
87+
# the cached copy if it exists and is valid.
8588
def fetch
8689
@file = File.basename(URI.parse(@url).path)
90+
if @cachedir && File.exist?(File.join(@cachedir, @file))
91+
VanagonLogger.info "Using cached copy of #{@file} in #{@cachedir}"
92+
FileUtils.cp(File.join(@cachedir, @file), workdir)
93+
end
8794
if File.exist?(File.join(workdir, file))
8895
begin
8996
return if verify
@@ -138,9 +145,13 @@ def download(target_url, target_file = nil, headers = { "Accept-Encoding" => "id
138145
location = URI.parse(response.header['location'])
139146
download(uri + location, target_file)
140147
when Net::HTTPSuccess
141-
File.open(File.join(@workdir, target_file), 'w') do |io|
148+
dir = @cachedir || @workdir
149+
File.open(File.join(dir, target_file), 'w') do |io|
142150
response.read_body { |chunk| io.write(chunk) }
143151
end
152+
if @cachedir
153+
FileUtils.cp(File.join(@cachedir, target_file), File.join(@workdir, target_file))
154+
end
144155
else
145156
fail "Error: #{response.code.to_s}. Unable to get source from #{target_url}"
146157
end

lib/vanagon/driver.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Vanagon
1212
class Driver
1313
include Vanagon::Utilities
1414

15-
attr_accessor :platform, :project, :target, :workdir, :remote_workdir, :verbose, :preserve, :keepwork
15+
attr_accessor :platform, :project, :target, :workdir, :cachedir, :remote_workdir, :verbose, :preserve, :keepwork
1616

1717
def timeout
1818
@timeout ||= @project.timeout || ENV["VANAGON_TIMEOUT"] || 7200
@@ -27,6 +27,7 @@ def initialize(platform, project, options = {})
2727
@verbose = options[:verbose] || false
2828
@preserve = options[:preserve] || :'on-failure'
2929
@workdir = options[:workdir] || Dir.mktmpdir
30+
@cachedir = options[:cachedir]
3031
@keepwork = options[:keepwork] || :never
3132

3233
@@configdir = options[:configdir] || File.join(Dir.pwd, "configs")
@@ -144,7 +145,7 @@ def run
144145
Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
145146
install_build_dependencies
146147
end
147-
@project.fetch_sources(workdir, retry_count, timeout)
148+
@project.fetch_sources(workdir, retry_count, timeout, cachedir)
148149

149150
@project.make_makefile(workdir)
150151
@project.make_bill_of_materials(workdir)

lib/vanagon/project.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,18 @@ def vendor_email_only
227227
# Collects all sources and patches into the provided workdir
228228
#
229229
# @param workdir [String] directory to stage sources into
230+
# @param cachedir [String] directory to cache source files and git repos
230231
# @param retry_count [Integer] number of times to retry each fetch
231232
# @param timeout [Integer] How long to wait (in seconds) for each
232233
# fetch before aborting
233-
def fetch_sources(workdir, retry_count = 1, timeout = 7200)
234+
def fetch_sources(workdir, retry_count = 1, timeout = 7200, cachedir = nil)
234235
@components.each do |component|
235236
Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
236-
component.get_source(workdir)
237+
component.get_source(workdir, cachedir)
237238
end
238239
# Fetch secondary sources
239240
Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
240-
component.get_sources(workdir)
241+
component.get_sources(workdir, cachedir)
241242
end
242243
Vanagon::Utilities.retry_with_timeout(retry_count, timeout) do
243244
component.get_patches(workdir)

0 commit comments

Comments
 (0)