github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/utils/pip/dependencies/dependencies.go (about) 1 package dependencies 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "github.com/jfrog/jfrog-client-go/artifactory" 7 "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" 8 serviceutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 9 "github.com/jfrog/jfrog-client-go/utils/errorutils" 10 "github.com/jfrog/jfrog-client-go/utils/log" 11 "strings" 12 ) 13 14 // Populate project's dependencies with checksums and file names. 15 // If the dependency was downloaded in this pip-install execution, checksum will be fetched from Artifactory. 16 // Otherwise, check if exists in cache. 17 // Return dependency-names of all dependencies which its information could not be obtained. 18 func AddDepsInfoAndReturnMissingDeps(dependenciesMap map[string]*buildinfo.Dependency, dependenciesCache *DependenciesCache, dependencyToFileMap map[string]string, servicesManager *artifactory.ArtifactoryServicesManager, repository string) ([]string, error) { 19 var missingDeps []string 20 // Iterate dependencies map to update info. 21 for depName := range dependenciesMap { 22 // Get dependency info. 23 depFileName, depChecksum, err := getDependencyInfo(depName, repository, dependenciesCache, dependencyToFileMap, servicesManager) 24 if err != nil { 25 return nil, err 26 } 27 28 // Check if info not found. 29 if depFileName == "" || depChecksum == nil { 30 // Dependency either wasn't downloaded in this run nor stored in cache. 31 missingDeps = append(missingDeps, depName) 32 33 // dependenciesMapT should contain only dependencies with checksums. 34 delete(dependenciesMap, depName) 35 36 continue 37 } 38 fileType := "" 39 // Update dependency info. 40 dependenciesMap[depName].Id = depFileName 41 if i := strings.LastIndex(depFileName, "."); i != -1 { 42 fileType = depFileName[i+1:] 43 } 44 dependenciesMap[depName].Type = fileType 45 dependenciesMap[depName].Checksum = depChecksum 46 } 47 48 return missingDeps, nil 49 } 50 51 // Get dependency information. 52 // If dependency was downloaded in this pip-install execution, fetch info from Artifactory. 53 // Otherwise, fetch info from cache. 54 func getDependencyInfo(depName, repository string, dependenciesCache *DependenciesCache, dependencyToFileMap map[string]string, servicesManager *artifactory.ArtifactoryServicesManager) (string, *buildinfo.Checksum, error) { 55 // Check if this dependency was updated during this pip-install execution, and we have its file-name. 56 // If updated - fetch checksum from Artifactory, regardless of what was previously stored in cache. 57 depFileName, ok := dependencyToFileMap[depName] 58 if ok && depFileName != "" { 59 checksum, err := getDependencyChecksumFromArtifactory(servicesManager, repository, depFileName) 60 return depFileName, checksum, err 61 } 62 63 // Check cache for dependency checksum. 64 if dependenciesCache != nil { 65 dep := dependenciesCache.GetDependency(depName) 66 if dep != nil { 67 // Checksum found in cache, return info 68 return dep.Id, dep.Checksum, nil 69 } 70 } 71 72 return "", nil, nil 73 } 74 75 // Fetch checksum for file from Artifactory. 76 // If the file isn't found, or md5 or sha1 are missing, return nil. 77 func getDependencyChecksumFromArtifactory(servicesManager *artifactory.ArtifactoryServicesManager, repository, dependencyFile string) (*buildinfo.Checksum, error) { 78 log.Debug(fmt.Sprintf("Fetching checksums for: %s", dependencyFile)) 79 result, err := servicesManager.Aql(serviceutils.CreateAqlQueryForPypi(repository, dependencyFile)) 80 if err != nil { 81 return nil, err 82 } 83 84 parsedResult := new(aqlResult) 85 err = json.Unmarshal(result, parsedResult) 86 if err = errorutils.CheckError(err); err != nil { 87 return nil, err 88 } 89 if len(parsedResult.Results) == 0 { 90 log.Debug(fmt.Sprintf("File: %s could not be found in repository: %s", dependencyFile, repository)) 91 return nil, nil 92 } 93 94 // Verify checksum exist. 95 sha1 := parsedResult.Results[0].Actual_sha1 96 md5 := parsedResult.Results[0].Actual_md5 97 if sha1 == "" || md5 == "" { 98 // Missing checksum. 99 log.Debug(fmt.Sprintf("Missing checksums for file: %s, sha1: '%s', md5: '%s'", dependencyFile, sha1, md5)) 100 return nil, nil 101 } 102 103 // Update checksum. 104 checksum := &buildinfo.Checksum{Sha1: sha1, Md5: md5} 105 log.Debug(fmt.Sprintf("Found checksums for file: %s, sha1: '%s', md5: '%s'", dependencyFile, sha1, md5)) 106 107 return checksum, nil 108 } 109 110 type aqlResult struct { 111 Results []*results `json:"results,omitempty"` 112 } 113 114 type results struct { 115 Actual_md5 string `json:"actual_md5,omitempty"` 116 Actual_sha1 string `json:"actual_sha1,omitempty"` 117 }