func (i *installer) install(scripts []string, userResults, sourceResults, defaultResults map[string]*downloadResult, dstDir string) []api.InstallResult { resultList := make([]api.InstallResult, len(scripts)) locationsResultsMap := map[string]map[string]*downloadResult{ api.UserScripts: userResults, api.SourceScripts: sourceResults, api.DefaultScripts: defaultResults, } // iterate over scripts for idx, script := range scripts { result := api.InstallResult{Script: script} // and possible locations for _, location := range locationsOrder { locationResults, ok := locationsResultsMap[location] if !ok || locationResults == nil { continue } downloadResult, ok := locationResults[script] if !ok { continue } result.URL = downloadResult.location // if location results are erroneous we store error in result object // and continue searching other locations if downloadResult.err != nil { // one exception is when error contains information about scripts being inside the image if e, ok := downloadResult.err.(errors.Error); ok && e.ErrorCode == errors.ScriptsInsideImageError { // in which case update result object and break further searching result.Error = nil result.Downloaded = false result.Installed = true break } else { result.Error = downloadResult.err continue } } // if there was no error src := filepath.Join(dstDir, location, script) dst := filepath.Join(dstDir, api.UploadScripts, script) // move script to upload directory if err := i.fs.Rename(src, dst); err != nil { result.Error = err continue } // set appropriate permissions if err := i.fs.Chmod(dst, 0755); err != nil { result.Error = err continue } // and finally update result object result.Error = nil result.Downloaded = true result.Installed = true break } resultList[idx] = result } return resultList }