From af8a0c46c540ac5bd28ed6e7ff3ae09df1e86a0b Mon Sep 17 00:00:00 2001 From: Vladislav Rassokhin Date: Sun, 26 Nov 2017 00:02:54 +0300 Subject: [PATCH] Do not re-download iso multiple times from different urls In case of two or more iso_urls checks for downloaded files prior to downloading them. Speedups case when some iso already downloaded and another url prepended to iso_urls list. --- common/step_download.go | 45 ++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/common/step_download.go b/common/step_download.go index f63070a04..765a07d23 100644 --- a/common/step_download.go +++ b/common/step_download.go @@ -61,10 +61,12 @@ func (s *StepDownload) Run(state multistep.StateBag) multistep.StepAction { ui.Say(fmt.Sprintf("Downloading or copying %s", s.Description)) - var finalPath string - for _, url := range s.Url { - ui.Message(fmt.Sprintf("Downloading or copying: %s", url)) + // First try to use any already downloaded file + // If it fails, proceed to regualar download logic + var downloadConfigs = make([]*DownloadConfig, len(s.Url)) + var finalPath string + for i, url := range s.Url { targetPath := s.TargetPath if targetPath == "" { // Determine a cache key. This is normally just the URL but @@ -90,22 +92,37 @@ func (s *StepDownload) Run(state multistep.StateBag) multistep.StepAction { Checksum: checksum, UserAgent: "Packer", } + downloadConfigs[i] = config - path, err, retry := s.download(config, state) - if err != nil { - ui.Message(fmt.Sprintf("Error downloading: %s", err)) - } - - if !retry { - return multistep.ActionHalt - } - - if err == nil { - finalPath = path + if match, _ := NewDownloadClient(config).VerifyChecksum(config.TargetPath); match { + ui.Message(fmt.Sprintf("Found already downloaded, initial checksum matched, no download needed: %s", url)) + finalPath = config.TargetPath break } } + if finalPath == "" { + for i, url := range s.Url { + ui.Message(fmt.Sprintf("Downloading or copying: %s", url)) + + config := downloadConfigs[i] + + path, err, retry := s.download(config, state) + if err != nil { + ui.Message(fmt.Sprintf("Error downloading: %s", err)) + } + + if !retry { + return multistep.ActionHalt + } + + if err == nil { + finalPath = path + break + } + } + } + if finalPath == "" { err := fmt.Errorf("%s download failed.", s.Description) state.Put("error", err)