| 167 | } |
| 168 | |
| 169 | func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) { |
| 170 | // Calculate cache key |
| 171 | cacheKey, err := a.calcCacheKey() |
| 172 | if err != nil { |
| 173 | return artifact.Reference{}, xerrors.Errorf("failed to calculate a cache key: %w", err) |
| 174 | } |
| 175 | |
| 176 | // Check if the cache exists only when it's a clean git repository |
| 177 | if a.isClean && a.repoMetadata.Commit != "" { |
| 178 | _, missingBlobs, err := a.cache.MissingBlobs(ctx, cacheKey, []string{cacheKey}) |
| 179 | if err != nil { |
| 180 | return artifact.Reference{}, xerrors.Errorf("unable to get missing blob: %w", err) |
| 181 | } |
| 182 | |
| 183 | if len(missingBlobs) == 0 { |
| 184 | // Cache hit |
| 185 | a.logger.DebugContext(ctx, "Cache hit", log.String("key", cacheKey)) |
| 186 | return artifact.Reference{ |
| 187 | Name: cmp.Or(a.artifactOption.Original, a.rootPath), |
| 188 | Type: a.artifactOption.Type, |
| 189 | ID: cacheKey, |
| 190 | BlobIDs: []string{cacheKey}, |
| 191 | RepoMetadata: a.repoMetadata, |
| 192 | }, nil |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | // `errgroup` cancels the context after Wait returns, so it can’t be use later. |
| 197 | // We need a separate context specifically for Analyze. |
| 198 | eg, egCtx := errgroup.WithContext(ctx) |
| 199 | result := analyzer.NewAnalysisResult() |
| 200 | limit := semaphore.New(a.artifactOption.Parallel) |
| 201 | opts := analyzer.AnalysisOptions{ |
| 202 | Offline: a.artifactOption.Offline, |
| 203 | FileChecksum: a.artifactOption.FileChecksum, |
| 204 | } |
| 205 | |
| 206 | // Prepare filesystem for post analysis |
| 207 | composite, err := a.analyzer.PostAnalyzerFS() |
| 208 | if err != nil { |
| 209 | return artifact.Reference{}, xerrors.Errorf("failed to prepare filesystem for post analysis: %w", err) |
| 210 | } |
| 211 | defer composite.Cleanup() |
| 212 | |
| 213 | // Use static paths instead of traversing the filesystem when all analyzers implement StaticPathAnalyzer |
| 214 | // so that we can analyze files faster |
| 215 | var walkErr error |
| 216 | if paths, canUseStaticPaths := a.analyzer.StaticPaths(a.artifactOption.DisabledAnalyzers); canUseStaticPaths { |
| 217 | // Analyze files in static paths |
| 218 | a.logger.Debug("Analyzing files in static paths") |
| 219 | if err = a.analyzeWithStaticPaths(egCtx, eg, limit, result, composite, opts, paths); err != nil { |
| 220 | walkErr = xerrors.Errorf("analyze with static paths: %w", err) |
| 221 | } |
| 222 | } else { |
| 223 | // Analyze files by traversing the root directory |
| 224 | if err = a.analyzeWithRootDir(egCtx, eg, limit, result, composite, opts); err != nil { |
| 225 | walkErr = xerrors.Errorf("analyze with traversal: %w", err) |
| 226 | } |