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