mirror of
https://github.com/anchore/syft.git
synced 2026-10-14 07:07:18 +02:00
Compare commits
131
Commits
+8
-8
@@ -2,7 +2,7 @@ tools:
|
||||
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
||||
- name: binny
|
||||
version:
|
||||
want: v0.8.0
|
||||
want: v0.9.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/binny
|
||||
@@ -18,7 +18,7 @@ tools:
|
||||
# used to sign mac binaries at release
|
||||
- name: quill
|
||||
version:
|
||||
want: v0.5.0
|
||||
want: v0.5.1
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/quill
|
||||
@@ -26,7 +26,7 @@ tools:
|
||||
# used for linting
|
||||
- name: golangci-lint
|
||||
version:
|
||||
want: v1.63.4
|
||||
want: v1.64.8
|
||||
method: github-release
|
||||
with:
|
||||
repo: golangci/golangci-lint
|
||||
@@ -34,7 +34,7 @@ tools:
|
||||
# used for showing the changelog at release
|
||||
- name: glow
|
||||
version:
|
||||
want: v2.0.0
|
||||
want: v2.1.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: charmbracelet/glow
|
||||
@@ -42,7 +42,7 @@ tools:
|
||||
# used for signing the checksums file at release
|
||||
- name: cosign
|
||||
version:
|
||||
want: v2.4.1
|
||||
want: v2.4.3
|
||||
method: github-release
|
||||
with:
|
||||
repo: sigstore/cosign
|
||||
@@ -58,7 +58,7 @@ tools:
|
||||
# used to release all artifacts
|
||||
- name: goreleaser
|
||||
version:
|
||||
want: v2.5.1
|
||||
want: v2.8.1
|
||||
method: github-release
|
||||
with:
|
||||
repo: goreleaser/goreleaser
|
||||
@@ -103,7 +103,7 @@ tools:
|
||||
# used for running all local and CI tasks
|
||||
- name: task
|
||||
version:
|
||||
want: v3.40.1
|
||||
want: v3.42.1
|
||||
method: github-release
|
||||
with:
|
||||
repo: go-task/task
|
||||
@@ -111,7 +111,7 @@ tools:
|
||||
# used for triggering a release
|
||||
- name: gh
|
||||
version:
|
||||
want: v2.65.0
|
||||
want: v2.69.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: cli/cli
|
||||
|
||||
@@ -5,7 +5,7 @@ inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
required: true
|
||||
default: "1.23.x"
|
||||
default: ">= 1.24"
|
||||
go-dependencies:
|
||||
description: "Download go dependencies"
|
||||
required: true
|
||||
@@ -29,7 +29,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# note: go mod and build is automatically cached on default with v4+
|
||||
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
- uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
if: inputs.go-version != ''
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
@@ -37,7 +37,7 @@ runs:
|
||||
- name: Restore tool cache
|
||||
if: inputs.tools == 'true'
|
||||
id: tool-cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tool
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
||||
@@ -60,7 +60,7 @@ runs:
|
||||
|
||||
- name: Restore ORAS cache from github actions
|
||||
if: inputs.download-test-fixture-cache == 'true'
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tmp/oras-cache
|
||||
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
||||
|
||||
@@ -19,7 +19,7 @@ updates:
|
||||
- "dependencies"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/boostrap"
|
||||
directory: "/.github/actions/bootstrap"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
@@ -86,8 +86,10 @@ def main(file_path: str | None):
|
||||
show("The following paths are missing or have no content, but have corresponding .fingerprint files:")
|
||||
for path in sorted(missing_content):
|
||||
show(f"- {path}")
|
||||
show("Please ensure these paths exist and have content if they are directories.")
|
||||
exit(1)
|
||||
# when adding new cache directories there is a time where it is not possible to have this directory without
|
||||
# running the tests first... but this step is a prerequisite for running the tests. We should not block on this.
|
||||
# show("Please ensure these paths exist and have content if they are directories.")
|
||||
# exit(1)
|
||||
|
||||
sha256_hash = calculate_sha256(fingerprint_contents)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
|
||||
Benchmark-Test:
|
||||
name: "Benchmark tests"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
# note: we want benchmarks to run on pull_request events in order to publish results to a sticky comment, and
|
||||
# we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
|
||||
# the job by event.
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore base benchmark result
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
path: test/results/benchmark-main.txt
|
||||
# use base sha for PR or new commit hash for main push in benchmark result key
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
|
||||
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: benchmark-test-results
|
||||
path: test/results/**/*
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
@@ -39,13 +39,13 @@ jobs:
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a #v5.2.0
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b #v5.4.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c #v3.28.1
|
||||
uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c #v3.28.1
|
||||
uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c #v3.28.1
|
||||
uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13
|
||||
|
||||
@@ -18,7 +18,7 @@ on:
|
||||
jobs:
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
jobs:
|
||||
quality-gate:
|
||||
environment: release
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
|
||||
release:
|
||||
needs: [quality-gate]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
@@ -113,13 +113,13 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
with:
|
||||
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
|
||||
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -148,13 +148,13 @@ jobs:
|
||||
# for updating brew formula in anchore/homebrew-syft
|
||||
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
|
||||
|
||||
- uses: anchore/sbom-action@df80a981bc6edbc4e220a492d3cbe9f5547a6e75 #v0.17.9
|
||||
- uses: anchore/sbom-action@f325610c9f50a54015d37c8d16cb3b0e2c8f4de0 #v0.18.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
file: go.mod
|
||||
artifact-name: sbom.spdx.json
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
|
||||
@@ -15,6 +15,7 @@ jobs:
|
||||
name: "Publish test fixture image cache"
|
||||
# we use this runner to get enough storage space for docker images and fixture cache
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f #v7.0.6
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f #v7.0.6
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f #v7.0.6
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
Update CPE dictionary index based on the latest available CPE dictionary
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: workflow,eventName,job
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
Static-Analysis:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
Unit-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Unit tests"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
Integration-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
|
||||
Build-Snapshot-Artifacts:
|
||||
name: "Build snapshot artifacts"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
# we need to preserve the snapshot data itself as well as the task data that confirms if the
|
||||
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
|
||||
@@ -89,11 +89,11 @@ jobs:
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
|
||||
Acceptance-Linux:
|
||||
Upload-Snapshot-Artifacts:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Acceptance tests (Linux)"
|
||||
name: "Upload snapshot artifacts"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -104,7 +104,62 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
.task
|
||||
fail-on-cache-miss: true
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
# workaround for https://github.com/actions/cache/issues/1265
|
||||
- name: (cache-miss) Snapshot build missing
|
||||
if: steps.snapshot-cache.outputs.cache-hit != 'true'
|
||||
run: echo "unable to download snapshots from previous job" && false
|
||||
|
||||
- run: npm install @actions/artifact@2.2.2
|
||||
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { readdirSync } = require('fs')
|
||||
const { DefaultArtifactClient } = require('@actions/artifact')
|
||||
const artifact = new DefaultArtifactClient()
|
||||
const ls = d => readdirSync(d, { withFileTypes: true })
|
||||
const baseDir = "./snapshot"
|
||||
const dirs = ls(baseDir).filter(f => f.isDirectory()).map(f => f.name)
|
||||
const uploads = []
|
||||
for (const dir of dirs) {
|
||||
// uploadArtifact returns Promise<{id, size}>
|
||||
uploads.push(artifact.uploadArtifact(
|
||||
// name of the archive:
|
||||
`${dir}`,
|
||||
// array of all files to include:
|
||||
ls(`${baseDir}/${dir}`).map(f => `${baseDir}/${dir}/${f.name}`),
|
||||
// base directory to trim from entries:
|
||||
`${baseDir}/${dir}`,
|
||||
{ retentionDays: 30 }
|
||||
))
|
||||
}
|
||||
// wait for all uploads to finish
|
||||
Promise.all(uploads)
|
||||
|
||||
Acceptance-Linux:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Acceptance tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -139,7 +194,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@v3.7.0
|
||||
uses: sigstore/cosign-installer@v3.8.1
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -152,7 +207,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -176,7 +231,7 @@ jobs:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "CLI tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
@@ -187,7 +242,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -207,13 +262,14 @@ jobs:
|
||||
Cleanup-Cache:
|
||||
name: "Cleanup snapshot cache"
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: write
|
||||
needs:
|
||||
- Acceptance-Linux
|
||||
- Acceptance-Mac
|
||||
- Cli-Linux
|
||||
- Upload-Snapshot-Artifacts
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ linters-settings:
|
||||
gosec:
|
||||
excludes:
|
||||
- G115
|
||||
|
||||
run:
|
||||
timeout: 10m
|
||||
tests: false
|
||||
|
||||
+5
-1
@@ -8,4 +8,8 @@ A cataloger contributed by Oracle Corporation that extracts packages given withi
|
||||
|
||||
## Swift Package Manager
|
||||
|
||||
A cataloger contributed by Axis Communications that catalogs packages resolved by Swift Package Manager.
|
||||
A cataloger contributed by Axis Communications that catalogs packages resolved by Swift Package Manager.
|
||||
|
||||
## Bitnami Packages
|
||||
|
||||
A cataloger contributed by Bitnami developer that catalogs packages described in Bitnami SBOMs.
|
||||
|
||||
@@ -123,6 +123,7 @@ Note that flags using the @<version> can be used for earlier versions of each sp
|
||||
### Supported Ecosystems
|
||||
|
||||
- Alpine (apk)
|
||||
- Bitnami packages
|
||||
- C (conan)
|
||||
- C++ (conan)
|
||||
- Dart (pubs)
|
||||
@@ -146,6 +147,7 @@ Note that flags using the @<version> can be used for earlier versions of each sp
|
||||
- Rust (cargo.lock)
|
||||
- Swift (cocoapods, swift-package-manager)
|
||||
- Wordpress plugins
|
||||
- Terraform providers (.terraform.lock.hcl)
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
+1
-1
@@ -581,7 +581,7 @@ tasks:
|
||||
- "{{ .NEXT_VERSION }}"
|
||||
cmds:
|
||||
- "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
|
||||
- "{{ .TOOL_DIR }}/glow {{ .CHANGELOG }}"
|
||||
- "{{ .TOOL_DIR }}/glow -w 0 {{ .CHANGELOG }}"
|
||||
|
||||
|
||||
## Release targets #################################
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_in_progress/task_line - 1]
|
||||
⠋ Creating a thing running a thing
|
||||
⠋ Creating a thing running a thing
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_in_progress/log - 1]
|
||||
@@ -11,7 +11,7 @@
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_complete/task_line - 1]
|
||||
✔ Created a thing running a thing
|
||||
✔ Created a thing running a thing
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_complete/log - 1]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleFetchImage/fetch_image_in_progress - 1]
|
||||
⠋ Loading image ━━━━━━━━━━━━━━━━━━━━ [current] the-image
|
||||
⠋ Loading image ━━━━━━━━━━━━━━━━━━━━ [current] the-image
|
||||
---
|
||||
|
||||
[TestHandler_handleFetchImage/fetch_image_complete - 1]
|
||||
✔ Loaded image the-image
|
||||
✔ Loaded image the-image
|
||||
---
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleFileIndexingStarted/cataloging_in_progress - 1]
|
||||
⠋ Indexing file system ━━━━━━━━━━━━━━━━━━━━ [current] /some/path
|
||||
⠋ Indexing file system ━━━━━━━━━━━━━━━━━━━━ [current] /some/path
|
||||
---
|
||||
|
||||
[TestHandler_handleFileIndexingStarted/cataloging_complete - 1]
|
||||
✔ Indexed file system /some/path
|
||||
✔ Indexed file system /some/path
|
||||
---
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleReadImage/read_image_in_progress - 1]
|
||||
⠋ Parsing image ━━━━━━━━━━━━━━━━━━━━ id
|
||||
⠋ Parsing image ━━━━━━━━━━━━━━━━━━━━ id
|
||||
---
|
||||
|
||||
[TestHandler_handleReadImage/read_image_complete - 1]
|
||||
✔ Parsed image id
|
||||
✔ Parsed image id
|
||||
---
|
||||
|
||||
@@ -61,7 +61,7 @@ type backgroundLineReader struct {
|
||||
func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
|
||||
reader, prog, taskInfo, err := syftEventParsers.ParseAttestationStartedEvent(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func (cts catalogerTaskModel) View() string {
|
||||
func (m *Handler) handleCatalogerTaskStarted(e partybus.Event) ([]tea.Model, tea.Cmd) {
|
||||
mon, info, err := syftEventParsers.ParseCatalogerTaskStarted(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleFetchImage(e partybus.Event) []tea.Model {
|
||||
imgName, prog, err := stereoEventParsers.ParseFetchImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleFileIndexingStarted(e partybus.Event) []tea.Model {
|
||||
path, prog, err := syftEventParsers.ParseFileIndexingStarted(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ type containerdPullStatusFormatter struct {
|
||||
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
|
||||
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ type dockerPullStatusFormatter struct {
|
||||
func (m *Handler) handlePullDockerImage(e partybus.Event) []tea.Model {
|
||||
_, pullStatus, err := stereoscopeParsers.ParsePullDockerImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleReadImage(e partybus.Event) []tea.Model {
|
||||
imgMetadata, prog, err := stereoEventParsers.ParseReadImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/stereoscope"
|
||||
ui2 "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
@@ -28,7 +28,7 @@ func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig
|
||||
|
||||
return clio.NewUICollection(
|
||||
ui.New(out, cfg.Log.Quiet,
|
||||
ui2.New(ui2.DefaultHandlerConfig()),
|
||||
handler.New(handler.DefaultHandlerConfig()),
|
||||
),
|
||||
noUI,
|
||||
), nil
|
||||
|
||||
@@ -3,6 +3,7 @@ package commands
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -14,7 +15,15 @@ import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
var (
|
||||
activelyAddedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("10")) // hi green
|
||||
deselectedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // dark grey
|
||||
activelyRemovedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("9")) // high red
|
||||
defaultStyle = lipgloss.NewStyle().Underline(true)
|
||||
deselectedDefaultStyle = lipgloss.NewStyle().Inherit(deselectedStyle).Underline(true)
|
||||
)
|
||||
|
||||
type catalogerListOptions struct {
|
||||
@@ -44,8 +53,9 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
||||
opts := defaultCatalogerListOptions()
|
||||
|
||||
return app.SetupCommand(&cobra.Command{
|
||||
Use: "list [OPTIONS]",
|
||||
Short: "List available catalogers",
|
||||
Use: "list [OPTIONS]",
|
||||
Short: "List available catalogers",
|
||||
PreRunE: disableUI(app, os.Stdout),
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
return runCatalogerList(opts)
|
||||
},
|
||||
@@ -53,13 +63,19 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
||||
}
|
||||
|
||||
func runCatalogerList(opts *catalogerListOptions) error {
|
||||
factories := task.DefaultPackageTaskFactories()
|
||||
allTasks, err := factories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
pkgTaskFactories := task.DefaultPackageTaskFactories()
|
||||
fileTaskFactories := task.DefaultFileTaskFactories()
|
||||
allPkgTasks, err := pkgTaskFactories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create cataloger tasks: %w", err)
|
||||
return fmt.Errorf("unable to create pkg cataloger tasks: %w", err)
|
||||
}
|
||||
|
||||
report, err := catalogerListReport(opts, allTasks)
|
||||
allFileTasks, err := fileTaskFactories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create file cataloger tasks: %w", err)
|
||||
}
|
||||
|
||||
report, err := catalogerListReport(opts, [][]task.Task{allPkgTasks, allFileTasks})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to generate cataloger list report: %w", err)
|
||||
}
|
||||
@@ -69,9 +85,10 @@ func runCatalogerList(opts *catalogerListOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (string, error) {
|
||||
selectedTasks, selectionEvidence, err := task.Select(allTasks,
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
func catalogerListReport(opts *catalogerListOptions, allTaskGroups [][]task.Task) (string, error) {
|
||||
selectedTaskGroups, selectionEvidence, err := task.SelectInGroups(
|
||||
allTaskGroups,
|
||||
cataloging.NewSelectionRequest().
|
||||
WithDefaults(opts.DefaultCatalogers...).
|
||||
WithExpression(opts.SelectCatalogers...),
|
||||
)
|
||||
@@ -82,12 +99,12 @@ func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (stri
|
||||
|
||||
switch opts.Output {
|
||||
case "json":
|
||||
report, err = renderCatalogerListJSON(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
report, err = renderCatalogerListJSON(flattenTaskGroups(selectedTaskGroups), selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
case "table", "":
|
||||
if opts.ShowHidden {
|
||||
report = renderCatalogerListTable(allTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
report = renderCatalogerListTables(allTaskGroups, selectionEvidence)
|
||||
} else {
|
||||
report = renderCatalogerListTable(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
report = renderCatalogerListTables(selectedTaskGroups, selectionEvidence)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +115,14 @@ func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (stri
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func flattenTaskGroups(taskGroups [][]task.Task) []task.Task {
|
||||
var allTasks []task.Task
|
||||
for _, tasks := range taskGroups {
|
||||
allTasks = append(allTasks, tasks...)
|
||||
}
|
||||
return allTasks
|
||||
}
|
||||
|
||||
func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) (string, error) {
|
||||
type node struct {
|
||||
Name string `json:"name"`
|
||||
@@ -109,7 +134,12 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
||||
nodesByName := make(map[string]node)
|
||||
|
||||
for name := range tagsByName {
|
||||
tagsSelected := selection.TokensByTask[name].SelectedOn.List()
|
||||
tokensByTask, ok := selection.TokensByTask[name]
|
||||
|
||||
var tagsSelected []string
|
||||
if ok {
|
||||
tagsSelected = tokensByTask.SelectedOn.List()
|
||||
}
|
||||
|
||||
if len(tagsSelected) == 1 && tagsSelected[0] == "all" {
|
||||
tagsSelected = tagsByName[name]
|
||||
@@ -153,10 +183,56 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) string {
|
||||
func renderCatalogerListTables(taskGroups [][]task.Task, selection task.Selection) string {
|
||||
pkgCatalogerTable := renderCatalogerListTable(taskGroups[0], selection, "Package Cataloger")
|
||||
fileCatalogerTable := renderCatalogerListTable(taskGroups[1], selection, "File Cataloger")
|
||||
|
||||
report := fileCatalogerTable + "\n" + pkgCatalogerTable + "\n"
|
||||
|
||||
hasAdditions := len(selection.Request.AddNames) > 0
|
||||
hasDefaults := len(selection.Request.DefaultNamesOrTags) > 0
|
||||
hasRemovals := len(selection.Request.RemoveNamesOrTags) > 0
|
||||
hasSubSelections := len(selection.Request.SubSelectTags) > 0
|
||||
expressions := len(selection.Request.SubSelectTags) + len(selection.Request.AddNames) + len(selection.Request.RemoveNamesOrTags)
|
||||
|
||||
var header string
|
||||
|
||||
header += fmt.Sprintf("Default selections: %d\n", len(selection.Request.DefaultNamesOrTags))
|
||||
if hasDefaults {
|
||||
for _, expr := range selection.Request.DefaultNamesOrTags {
|
||||
header += fmt.Sprintf(" • '%s'\n", expr)
|
||||
}
|
||||
}
|
||||
|
||||
header += fmt.Sprintf("Selection expressions: %d\n", expressions)
|
||||
|
||||
if hasSubSelections {
|
||||
for _, n := range selection.Request.SubSelectTags {
|
||||
header += fmt.Sprintf(" • '%s' (intersect)\n", n)
|
||||
}
|
||||
}
|
||||
if hasRemovals {
|
||||
for _, n := range selection.Request.RemoveNamesOrTags {
|
||||
header += fmt.Sprintf(" • '-%s' (remove)\n", n)
|
||||
}
|
||||
}
|
||||
if hasAdditions {
|
||||
for _, n := range selection.Request.AddNames {
|
||||
header += fmt.Sprintf(" • '+%s' (add)\n", n)
|
||||
}
|
||||
}
|
||||
|
||||
return header + report
|
||||
}
|
||||
|
||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, kindTitle string) string {
|
||||
if len(tasks) == 0 {
|
||||
return activelyRemovedStyle.Render(fmt.Sprintf("No %ss selected", strings.ToLower(kindTitle)))
|
||||
}
|
||||
|
||||
t := table.NewWriter()
|
||||
t.SetStyle(table.StyleLight)
|
||||
t.AppendHeader(table.Row{"Cataloger", "Tags"})
|
||||
t.AppendHeader(table.Row{kindTitle, "Tags"})
|
||||
|
||||
names, tagsByName := extractTaskInfo(tasks)
|
||||
|
||||
@@ -172,27 +248,12 @@ func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defau
|
||||
|
||||
report := t.Render()
|
||||
|
||||
if len(selections) > 0 {
|
||||
header := "Selected by expressions:\n"
|
||||
for _, expr := range selections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
if len(defaultSelections) > 0 {
|
||||
header := "Default selections:\n"
|
||||
for _, expr := range defaultSelections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||
isIncluded := selection.Result.Has(name)
|
||||
defaults := strset.New(selection.Request.DefaultNamesOrTags...)
|
||||
var selections *task.TokenSelection
|
||||
if s, exists := selection.TokensByTask[name]; exists {
|
||||
selections = &s
|
||||
@@ -200,35 +261,32 @@ func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||
|
||||
var formattedTags []string
|
||||
for _, tag := range tags {
|
||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded))
|
||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded, defaults))
|
||||
}
|
||||
|
||||
var tagStr string
|
||||
if isIncluded {
|
||||
tagStr = strings.Join(formattedTags, ", ")
|
||||
} else {
|
||||
tagStr = strings.Join(formattedTags, grey.Render(", "))
|
||||
tagStr = strings.Join(formattedTags, deselectedStyle.Render(", "))
|
||||
}
|
||||
|
||||
// TODO: selection should keep warnings (non-selections) in struct
|
||||
|
||||
return table.Row{
|
||||
formatToken(name, selections, isIncluded),
|
||||
formatToken(name, selections, isIncluded, defaults),
|
||||
tagStr,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
green = lipgloss.NewStyle().Foreground(lipgloss.Color("10")) // hi green
|
||||
grey = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // dark grey
|
||||
red = lipgloss.NewStyle().Foreground(lipgloss.Color("9")) // high red
|
||||
)
|
||||
|
||||
func formatToken(token string, selection *task.TokenSelection, included bool) string {
|
||||
func formatToken(token string, selection *task.TokenSelection, included bool, defaults *strset.Set) string {
|
||||
if included && selection != nil {
|
||||
// format all tokens in selection in green
|
||||
if selection.SelectedOn.Has(token) {
|
||||
return green.Render(token)
|
||||
if defaults.Has(token) {
|
||||
return defaultStyle.Render(token)
|
||||
}
|
||||
return activelyAddedStyle.Render(token)
|
||||
}
|
||||
|
||||
return token
|
||||
@@ -236,10 +294,12 @@ func formatToken(token string, selection *task.TokenSelection, included bool) st
|
||||
|
||||
// format all tokens in selection in red, all others in grey
|
||||
if selection != nil && selection.DeselectedOn.Has(token) {
|
||||
return red.Render(token)
|
||||
return activelyRemovedStyle.Render(token)
|
||||
}
|
||||
|
||||
return grey.Render(token)
|
||||
if defaults.Has(token) {
|
||||
return deselectedDefaultStyle.Render(token)
|
||||
}
|
||||
return deselectedStyle.Render(token)
|
||||
}
|
||||
|
||||
func extractTaskInfo(tasks []task.Task) ([]string, map[string][]string) {
|
||||
|
||||
@@ -40,23 +40,35 @@ func (d dummyTask) Execute(_ context.Context, _ file.Resolver, _ sbomsync.Builde
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func testTasks() []task.Task {
|
||||
return []task.Task{
|
||||
dummyTask{
|
||||
name: "task1",
|
||||
selectors: []string{"image", "a", "b", "1"},
|
||||
func testTasks() [][]task.Task {
|
||||
return [][]task.Task{
|
||||
{
|
||||
dummyTask{
|
||||
name: "task1",
|
||||
selectors: []string{"image", "a", "b", "1"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task2",
|
||||
selectors: []string{"image", "b", "c", "2"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task3",
|
||||
selectors: []string{"directory", "c", "d", "3"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task4",
|
||||
selectors: []string{"directory", "d", "e", "4"},
|
||||
},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task2",
|
||||
selectors: []string{"image", "b", "c", "2"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task3",
|
||||
selectors: []string{"directory", "c", "d", "3"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task4",
|
||||
selectors: []string{"directory", "d", "e", "4"},
|
||||
{
|
||||
dummyTask{
|
||||
name: "file-task1",
|
||||
selectors: []string{"file", "ft", "ft-1-b"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "file-task2",
|
||||
selectors: []string{"file", "ft", "ft-2-b"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -76,16 +88,23 @@ func Test_catalogerListReport(t *testing.T) {
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "all"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
│ task4 │ 4, d, directory, e │
|
||||
└───────────┴────────────────────┘
|
||||
Default selections: 1
|
||||
• 'all'
|
||||
Selection expressions: 0
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
│ file-task2 │ file, ft, ft-2-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
│ task4 │ 4, d, directory, e │
|
||||
└───────────────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -96,7 +115,7 @@ Default selections:
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["all"],"selection":[],"catalogers":[{"name":"task1","tags":["1","a","b","image"]},{"name":"task2","tags":["2","b","c","image"]},{"name":"task3","tags":["3","c","d","directory"]},{"name":"task4","tags":["4","d","directory","e"]}]}
|
||||
{"default":["all"],"selection":[],"catalogers":[{"name":"file-task1","tags":["file","ft","ft-1-b"]},{"name":"file-task2","tags":["file","ft","ft-2-b"]},{"name":"task1","tags":["1","a","b","image"]},{"name":"task2","tags":["2","b","c","image"]},{"name":"task3","tags":["3","c","d","directory"]},{"name":"task4","tags":["4","d","directory","e"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -105,19 +124,27 @@ Default selections:
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image",
|
||||
"image", // note: for backwards compatibility file will automatically be added
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "image"
|
||||
┌───────────┬────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
└───────────┴────────────────┘
|
||||
Default selections: 2
|
||||
• 'image'
|
||||
• 'file'
|
||||
Selection expressions: 0
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
│ file-task2 │ file, ft, ft-2-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
└───────────────────┴────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -131,7 +158,7 @@ Default selections:
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":[],"catalogers":[{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||
{"default":["image"],"selection":[],"catalogers":[{"name":"file-task1","tags":["file"]},{"name":"file-task2","tags":["file"]},{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -147,23 +174,32 @@ Default selections:
|
||||
"+task3",
|
||||
"-c",
|
||||
"b",
|
||||
"-file",
|
||||
"+file-task1",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "image"
|
||||
Selected by expressions:
|
||||
- "-directory"
|
||||
- "+task3"
|
||||
- "-c"
|
||||
- "b"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────┴────────────────────┘
|
||||
Default selections: 1
|
||||
• 'image'
|
||||
Selection expressions: 6
|
||||
• 'b' (intersect)
|
||||
• '-directory' (remove)
|
||||
• '-c' (remove)
|
||||
• '-file' (remove)
|
||||
• '+task3' (add)
|
||||
• '+file-task1' (add)
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -183,7 +219,7 @@ Selected by expressions:
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":["-directory","+task3","-c","b"],"catalogers":[{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
||||
{"default":["image"],"selection":["-directory","+task3","-c","b"],"catalogers":[{"name":"file-task1","tags":["file"]},{"name":"file-task2","tags":["file"]},{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
)
|
||||
|
||||
func disableUI(app clio.Application, out io.Writer) func(*cobra.Command, []string) error {
|
||||
return func(_ *cobra.Command, _ []string) error {
|
||||
type Stater interface {
|
||||
State() *clio.State
|
||||
}
|
||||
|
||||
state := app.(Stater).State()
|
||||
state.UI = clio.NewUICollection(ui.None(out, state.Config.Log.Quiet))
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
)
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
)
|
||||
@@ -57,35 +57,13 @@ func Test_defaultDir(t *testing.T) {
|
||||
env[k] = os.Getenv(k)
|
||||
}
|
||||
|
||||
unsetEnv := func(t *testing.T) {
|
||||
for k := range env {
|
||||
t.Setenv(k, "")
|
||||
}
|
||||
}
|
||||
|
||||
resetEnv := func() {
|
||||
for k, v := range env {
|
||||
if v == "" {
|
||||
_ = os.Unsetenv(k)
|
||||
} else {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
}
|
||||
|
||||
t.Cleanup(resetEnv)
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer resetEnv()
|
||||
restoreCache(t)
|
||||
|
||||
unsetEnv(t)
|
||||
for k, v := range test.env {
|
||||
t.Setenv(k, v)
|
||||
patchEnv(t, k, v)
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
|
||||
got := defaultDir()
|
||||
@@ -311,3 +289,35 @@ func Test_durationToString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// restoreCache ensures cache settings are restored after test
|
||||
func restoreCache(t testing.TB) {
|
||||
t.Helper()
|
||||
origEnabled := homedir.CacheEnabled()
|
||||
|
||||
t.Cleanup(func() {
|
||||
homedir.SetCacheEnable(origEnabled)
|
||||
homedir.Reset()
|
||||
})
|
||||
}
|
||||
|
||||
// patchEnv modifies an environment variable for the duration of the test
|
||||
func patchEnv(t testing.TB, key, value string) {
|
||||
t.Helper()
|
||||
original := os.Getenv(key)
|
||||
|
||||
if value != "" {
|
||||
os.Setenv(key, value)
|
||||
} else {
|
||||
os.Unsetenv(key)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
if original != "" {
|
||||
os.Setenv(key, original)
|
||||
} else {
|
||||
os.Unsetenv(key)
|
||||
}
|
||||
xdg.Reload()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||
@@ -33,6 +34,7 @@ type Catalog struct {
|
||||
DefaultCatalogers []string `yaml:"default-catalogers" json:"default-catalogers" mapstructure:"default-catalogers"`
|
||||
SelectCatalogers []string `yaml:"select-catalogers" json:"select-catalogers" mapstructure:"select-catalogers"`
|
||||
Package packageConfig `yaml:"package" json:"package" mapstructure:"package"`
|
||||
License licenseConfig `yaml:"license" json:"license" mapstructure:"license"`
|
||||
File fileConfig `yaml:"file" json:"file" mapstructure:"file"`
|
||||
Scope string `yaml:"scope" json:"scope" mapstructure:"scope"`
|
||||
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
|
||||
@@ -41,6 +43,7 @@ type Catalog struct {
|
||||
Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"`
|
||||
|
||||
// ecosystem-specific cataloger configuration
|
||||
Dotnet dotnetConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
|
||||
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
|
||||
JavaScript javaScriptConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
|
||||
@@ -65,18 +68,21 @@ var _ interface {
|
||||
} = (*Catalog)(nil)
|
||||
|
||||
func DefaultCatalog() Catalog {
|
||||
cfg := syft.DefaultCreateSBOMConfig()
|
||||
return Catalog{
|
||||
Compliance: defaultComplianceConfig(),
|
||||
Scope: source.SquashedScope.String(),
|
||||
Package: defaultPackageConfig(),
|
||||
License: defaultLicenseConfig(),
|
||||
LinuxKernel: defaultLinuxKernelConfig(),
|
||||
Dotnet: defaultDotnetConfig(),
|
||||
Golang: defaultGolangConfig(),
|
||||
Java: defaultJavaConfig(),
|
||||
File: defaultFileConfig(),
|
||||
Relationships: defaultRelationshipsConfig(),
|
||||
Unknowns: defaultUnknowns(),
|
||||
Source: defaultSourceConfig(),
|
||||
Parallelism: 1,
|
||||
Parallelism: cfg.Parallelism,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,9 +95,10 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig {
|
||||
WithUnknownsConfig(cfg.ToUnknownsConfig()).
|
||||
WithSearchConfig(cfg.ToSearchConfig()).
|
||||
WithPackagesConfig(cfg.ToPackagesConfig()).
|
||||
WithLicenseConfig(cfg.ToLicenseConfig()).
|
||||
WithFilesConfig(cfg.ToFilesConfig()).
|
||||
WithCatalogerSelection(
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
cataloging.NewSelectionRequest().
|
||||
WithDefaults(cfg.DefaultCatalogers...).
|
||||
WithExpression(cfg.SelectCatalogers...),
|
||||
)
|
||||
@@ -146,6 +153,13 @@ func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToLicenseConfig() cataloging.LicenseConfig {
|
||||
return cataloging.LicenseConfig{
|
||||
IncludeUnkownLicenseContent: cfg.License.IncludeUnknownLicenseContent,
|
||||
Coverage: cfg.License.LicenseCoverage,
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
archiveSearch := cataloging.ArchiveSearchConfig{
|
||||
IncludeIndexedArchives: cfg.Package.SearchIndexedArchives,
|
||||
@@ -153,9 +167,15 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
}
|
||||
return pkgcataloging.Config{
|
||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
||||
Dotnet: dotnet.DefaultCatalogerConfig().
|
||||
WithDepPackagesMustHaveDLL(cfg.Dotnet.DepPackagesMustHaveDLL).
|
||||
WithDepPackagesMustClaimDLL(cfg.Dotnet.DepPackagesMustClaimDLL).
|
||||
WithRelaxDLLClaimsWhenBundlingDetected(cfg.Dotnet.RelaxDLLClaimsWhenBundlingDetected),
|
||||
Golang: golang.DefaultCatalogerConfig().
|
||||
WithSearchLocalModCacheLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalModCacheLicenses)).
|
||||
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
|
||||
WithSearchLocalVendorLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalVendorLicenses)).
|
||||
WithLocalVendorDir(cfg.Golang.LocalVendorDir).
|
||||
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchRemoteLicenses)).
|
||||
WithProxy(cfg.Golang.Proxy).
|
||||
WithNoProxy(cfg.Golang.NoProxy).
|
||||
@@ -205,6 +225,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringArrayVarP(&cfg.Catalogers, "catalogers", "",
|
||||
"enable one or more package catalogers")
|
||||
|
||||
flags.IntVarP(&cfg.Parallelism, "parallelism", "",
|
||||
"number of cataloger workers to run in parallel")
|
||||
|
||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||
if err := pfp.PFlagSet().MarkDeprecated("catalogers", "use: override-default-catalogers and select-catalogers"); err != nil {
|
||||
panic(err)
|
||||
@@ -233,7 +256,8 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
}
|
||||
|
||||
func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&cfg.Parallelism, "number of cataloger workers to run in parallel")
|
||||
descriptions.Add(&cfg.Parallelism, `number of cataloger workers to run in parallel
|
||||
by default, when set to 0: this will be based on runtime.NumCPU * 4, if set to less than 0 it will be unbounded`)
|
||||
|
||||
descriptions.Add(&cfg.Enrich, fmt.Sprintf(`Enable data enrichment operations, which can utilize services such as Maven Central and NPM.
|
||||
By default all enrichment is disabled, use: all to enable everything.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
)
|
||||
|
||||
type dotnetConfig struct {
|
||||
DepPackagesMustHaveDLL bool `mapstructure:"dep-packages-must-have-dll" json:"dep-packages-must-have-dll" yaml:"dep-packages-must-have-dll"`
|
||||
|
||||
DepPackagesMustClaimDLL bool `mapstructure:"dep-packages-must-claim-dll" json:"dep-packages-must-claim-dll" yaml:"dep-packages-must-claim-dll"`
|
||||
|
||||
RelaxDLLClaimsWhenBundlingDetected bool `mapstructure:"relax-dll-claims-when-bundling-detected" json:"relax-dll-claims-when-bundling-detected" yaml:"relax-dll-claims-when-bundling-detected"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*dotnetConfig)(nil)
|
||||
|
||||
func (o *dotnetConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.DepPackagesMustHaveDLL, `only keep dep.json packages which an executable on disk can be found for`)
|
||||
descriptions.Add(&o.DepPackagesMustClaimDLL, `only keep dep.json packages which have a runtime/resource DLL claimed in the deps.json targets section (but not necessarily found on disk)`)
|
||||
descriptions.Add(&o.RelaxDLLClaimsWhenBundlingDetected, `show all packages from the deps.json if bundling tooling is present as a dependency (e.g. ILRepack)`)
|
||||
}
|
||||
|
||||
func defaultDotnetConfig() dotnetConfig {
|
||||
def := dotnet.DefaultCatalogerConfig()
|
||||
return dotnetConfig{
|
||||
DepPackagesMustHaveDLL: def.DepPackagesMustHaveDLL,
|
||||
DepPackagesMustClaimDLL: def.DepPackagesMustClaimDLL,
|
||||
RelaxDLLClaimsWhenBundlingDetected: def.RelaxDLLClaimsWhenBundlingDetected,
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
type golangConfig struct {
|
||||
SearchLocalModCacheLicenses *bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
|
||||
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
|
||||
SearchLocalVendorLicenses *bool `json:"search-local-vendor-licenses" yaml:"search-local-vendor-licenses" mapstructure:"search-local-vendor-licenses"`
|
||||
LocalVendorDir string `json:"local-vendor-dir" yaml:"local-vendor-dir" mapstructure:"local-vendor-dir"`
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
|
||||
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
||||
@@ -24,6 +26,9 @@ func (o *golangConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchLocalModCacheLicenses, `search for go package licences in the GOPATH of the system running Syft, note that this is outside the
|
||||
container filesystem and potentially outside the root of a local directory scan`)
|
||||
descriptions.Add(&o.LocalModCacheDir, `specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod`)
|
||||
descriptions.Add(&o.SearchLocalVendorLicenses, `search for go package licences in the vendor folder on the system running Syft, note that this is outside the
|
||||
container filesystem and potentially outside the root of a local directory scan`)
|
||||
descriptions.Add(&o.LocalVendorDir, `specify an explicit go vendor directory, if unset this defaults to ./vendor`)
|
||||
descriptions.Add(&o.SearchRemoteLicenses, `search for go package licences by retrieving the package from a network proxy`)
|
||||
descriptions.Add(&o.Proxy, `remote proxy to use when retrieving go packages from the network,
|
||||
if unset this defaults to $GOPROXY followed by https://proxy.golang.org`)
|
||||
@@ -49,6 +54,8 @@ func defaultGolangConfig() golangConfig {
|
||||
return golangConfig{
|
||||
SearchLocalModCacheLicenses: nil, // this defaults to false, which is the API default
|
||||
LocalModCacheDir: def.LocalModCacheDir,
|
||||
SearchLocalVendorLicenses: nil, // this defaults to false, which is the API default
|
||||
LocalVendorDir: def.LocalVendorDir,
|
||||
SearchRemoteLicenses: nil, // this defaults to false, which is the API default
|
||||
Proxy: strings.Join(def.Proxies, ","),
|
||||
NoProxy: strings.Join(def.NoProxy, ","),
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
)
|
||||
|
||||
type licenseConfig struct {
|
||||
IncludeUnknownLicenseContent bool `yaml:"include-unknown-license-content" json:"include-unknown-license-content" mapstructure:"include-unknown-license-content"`
|
||||
LicenseCoverage float64 `yaml:"license-coverage" json:"license-coverage" mapstructure:"license-coverage"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*licenseConfig)(nil)
|
||||
|
||||
func (o *licenseConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.IncludeUnknownLicenseContent, `include the content of a license in the SBOM when syft
|
||||
cannot determine a valid SPDX ID for the given license`)
|
||||
descriptions.Add(&o.LicenseCoverage, `adjust the percent as a fraction of the total text, in normalized words, that
|
||||
matches any valid license for the given inputs, expressed as a percentage across all of the licenses matched.`)
|
||||
}
|
||||
|
||||
func defaultLicenseConfig() licenseConfig {
|
||||
return licenseConfig{
|
||||
IncludeUnknownLicenseContent: false,
|
||||
LicenseCoverage: 75,
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,9 @@ package options
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/fangs"
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ var _ interface {
|
||||
} = (*packageConfig)(nil)
|
||||
|
||||
func (o *packageConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
note: enabling this may result in a performance impact since all discovered compressed tars will be decompressed
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.ExcludeBinaryOverlapByOwnership, `allows users to exclude synthetic binary packages from the sbom
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/format"
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
@@ -228,6 +228,8 @@ func Test_newSBOMMultiWriter(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_newSBOMWriterDescription(t *testing.T) {
|
||||
h, err := homedir.Dir()
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
@@ -236,7 +238,7 @@ func Test_newSBOMWriterDescription(t *testing.T) {
|
||||
{
|
||||
name: "expand home dir",
|
||||
path: "~/place.txt",
|
||||
expected: filepath.Join(homedir.Get(), "place.txt"),
|
||||
expected: filepath.Join(h, "place.txt"),
|
||||
},
|
||||
{
|
||||
name: "passthrough other paths",
|
||||
|
||||
@@ -78,11 +78,27 @@ var imageOnlyTestCases = []testCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find dot net executable",
|
||||
name: "find .NET packages (deps.json + .dlls)",
|
||||
pkgType: pkg.DotnetPkg,
|
||||
pkgLanguage: pkg.Dotnet,
|
||||
pkgInfo: map[string]string{
|
||||
// executable
|
||||
"DocuSign.eSign": "6.8.0.0",
|
||||
// deps.json
|
||||
"AWSSDK.Core": "3.7.10.6",
|
||||
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Options": "6.0.0",
|
||||
"Microsoft.Extensions.Primitives": "6.0.0",
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"Serilog": "2.10.0",
|
||||
"Serilog.Sinks.Console": "4.0.1",
|
||||
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
|
||||
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -241,10 +257,11 @@ var dirOnlyTestCases = []testCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find dotnet packages",
|
||||
name: "find dotnet packages (.deps.json)",
|
||||
pkgType: pkg.DotnetPkg,
|
||||
pkgLanguage: pkg.Dotnet,
|
||||
pkgInfo: map[string]string{
|
||||
// all from deps.json
|
||||
"AWSSDK.Core": "3.7.10.6",
|
||||
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
@@ -255,10 +272,10 @@ var dirOnlyTestCases = []testCase{
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"Serilog": "2.10.0",
|
||||
"Serilog.Sinks.Console": "4.0.1",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
|
||||
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -418,6 +435,14 @@ var dirOnlyTestCases = []testCase{
|
||||
"ocaml-base-compiler": "4.14.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find terraform packages",
|
||||
pkgType: pkg.TerraformPkg,
|
||||
pkgLanguage: pkg.Go,
|
||||
pkgInfo: map[string]string{
|
||||
"registry.terraform.io/hashicorp/aws": "5.72.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var commonTestCases = []testCase{
|
||||
|
||||
@@ -74,6 +74,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.ConanPkg))
|
||||
definedPkgs.Remove(string(pkg.HackagePkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.BitnamiPkg))
|
||||
definedPkgs.Remove(string(pkg.GraalVMNativeImagePkg))
|
||||
definedPkgs.Remove(string(pkg.HexPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
@@ -82,6 +84,7 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.OpamPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
||||
definedPkgs.Remove(string(pkg.TerraformPkg))
|
||||
|
||||
var cases []testCase
|
||||
cases = append(cases, commonTestCases...)
|
||||
@@ -218,6 +221,8 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
definedLanguages.Remove(pkg.R.String())
|
||||
observedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.BitnamiPkg))
|
||||
definedPkgs.Remove(string(pkg.GraalVMNativeImagePkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
definedPkgs.Remove(string(pkg.Rpkg))
|
||||
|
||||
@@ -52,8 +52,16 @@ func TestAllPackageCatalogersReachableInTasks(t *testing.T) {
|
||||
|
||||
assert.Equal(t, len(taskTagsByName), constructorCount, "mismatch in number of cataloger constructors and task names")
|
||||
|
||||
exceptions := strset.New(
|
||||
// not reachable since they are deprecated
|
||||
"dotnet-portable-executable-cataloger",
|
||||
"dotnet-deps-cataloger",
|
||||
// not reachable by design
|
||||
"sbom-cataloger",
|
||||
)
|
||||
|
||||
for taskName, tags := range taskTagsByName {
|
||||
if taskName == "sbom-cataloger" {
|
||||
if exceptions.Has(taskName) {
|
||||
continue // this is a special case
|
||||
}
|
||||
if !strset.New(tags...).HasAny(pkgcataloging.ImageTag, pkgcataloging.DirectoryTag) {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
|
||||
docker create --name generate-rpmdb-fixture centos:latest sh -c 'tail -f /dev/null'
|
||||
docker create --name generate-rpmdb-fixture rockylinux:9 sh -c 'tail -f /dev/null'
|
||||
|
||||
function cleanup {
|
||||
docker kill generate-rpmdb-fixture
|
||||
|
||||
Generated
+25
@@ -0,0 +1,25 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "5.72.1"
|
||||
constraints = ">= 5.72.0"
|
||||
hashes = [
|
||||
"h1:jhd5O5o0CfZCNEwwN0EiDAzb7ApuFrtxJqa6HXW4EKE=",
|
||||
"zh:0dea6843836e926d33469b48b948744079023816d16a2ff7666bcfb6aa3522d4",
|
||||
"zh:195fa9513f75800a0d62797ebec75ee73e9b8c28d713fe9b63d3b1d1eec129b3",
|
||||
"zh:1ed92f3961715bf0e024bcde3c12dfbdc50b00c1f8a43cc00802cfc45a256208",
|
||||
"zh:2ac687e3a52606466cae4a6813e81d923042488df88d2424e28d3f8530f091bb",
|
||||
"zh:32e7ca75f9314557daada3c44628fe1f3bf964a4f833bfb4b2295d833fe64b6f",
|
||||
"zh:374ee0e6b4327cc6ef666908ce5d6450a3a56e90cd2b785e83c2bcfc100021d2",
|
||||
"zh:5500fd6fdac44f96411fcf9c6d01691159ec35455ed127eb4c3a498e1cc92a64",
|
||||
"zh:723a2dc4b064c12e7ee62ad4fbfd72fa5e025206ea47b735994ef53f3c373152",
|
||||
"zh:89d97b87605f1d734f27e642567cbecf785b521af8ea81dac55c77ccde876221",
|
||||
"zh:951ee1e5731e8d65d521d71b95927e55055b3c4656eef6d46fa580a63328befc",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:9b2b362470b64ec227b2da64762ab8bc4111c6b80365fd9d82fc5e1e33f44038",
|
||||
"zh:aa6e57d0cb974ff0da5dee5d43ad2745cbbc4a2b507d4c799839b9fa96daf688",
|
||||
"zh:ba0d14c4a6b7aa844a830d47c0bf995b632e37f0795394b5b60c638b62b7fc03",
|
||||
"zh:c9764065a9c5d324db0b02bd201b9e3a2118e49c4960884acdeea377173302e9",
|
||||
]
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
@@ -20,7 +21,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Sco
|
||||
Name: "syft-tester",
|
||||
Version: "v0.99.0",
|
||||
}).WithCatalogerSelection(
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
cataloging.NewSelectionRequest().
|
||||
WithExpression(catalogerSelection...),
|
||||
)
|
||||
cfg.Search.Scope = scope
|
||||
@@ -55,7 +56,7 @@ func catalogDirectory(t *testing.T, dir string, catalogerSelection ...string) (s
|
||||
Name: "syft-tester",
|
||||
Version: "v0.99.0",
|
||||
}).WithCatalogerSelection(
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
cataloging.NewSelectionRequest().
|
||||
WithExpression(catalogerSelection...),
|
||||
)
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
case partybus.Event:
|
||||
log.WithFields("component", "ui").Tracef("event: %q", msg.Type)
|
||||
log.WithFields("component", "ui", "event", msg.Type).Trace("event")
|
||||
|
||||
switch msg.Type {
|
||||
case event.CLIReport, event.CLINotification, event.CLIAppUpdateAvailable:
|
||||
|
||||
@@ -74,7 +74,7 @@ func getSBOM(src source.Source) sbom.SBOM {
|
||||
// only use OS related catalogers that would have been used with the kind of
|
||||
// source type (container image or directory), but also add a specific python cataloger
|
||||
WithCatalogerSelection(
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
cataloging.NewSelectionRequest().
|
||||
WithSubSelections("os").
|
||||
WithAdditions("python-package-cataloger"),
|
||||
).
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
@@ -55,7 +56,7 @@ func getSBOM(src source.Source, defaultTags ...string) sbom.SBOM {
|
||||
WithCatalogerSelection(
|
||||
// here you can sub-select, add, remove catalogers from the default selection...
|
||||
// or replace the default selection entirely!
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
cataloging.NewSelectionRequest().
|
||||
WithDefaults(defaultTags...),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,74 +1,80 @@
|
||||
module github.com/anchore/syft
|
||||
|
||||
go 1.23.2
|
||||
go 1.24.1
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/OneOfOne/xxhash v1.2.8
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acobaugh/osrelease v0.1.0
|
||||
github.com/adrg/xdg v0.5.3
|
||||
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
|
||||
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837
|
||||
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10
|
||||
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716
|
||||
github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
|
||||
github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d
|
||||
github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f
|
||||
github.com/anchore/stereoscope v0.0.12
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115
|
||||
github.com/anchore/stereoscope v0.1.2
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
// we are hinting brotli to latest due to warning when installing archiver v3:
|
||||
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.0
|
||||
github.com/aquasecurity/go-pep440-version v0.0.1
|
||||
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.2.4
|
||||
github.com/charmbracelet/lipgloss v1.0.0
|
||||
github.com/charmbracelet/bubbletea v1.3.4
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
github.com/dave/jennifer v1.7.1
|
||||
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/docker v27.5.0+incompatible
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/elliotchance/phpserialize v1.4.0
|
||||
github.com/facebookincubator/nvdtools v0.1.5
|
||||
github.com/github/go-spdx/v2 v2.3.2
|
||||
github.com/gkampitakis/go-snaps v0.5.8
|
||||
github.com/gkampitakis/go-snaps v0.5.11
|
||||
github.com/go-git/go-billy/v5 v5.6.2
|
||||
github.com/go-git/go-git/v5 v5.13.1
|
||||
github.com/go-git/go-git/v5 v5.14.0
|
||||
github.com/go-test/deep v1.1.1
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1
|
||||
github.com/gohugoio/hashstructure v0.5.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-containerregistry v0.20.3
|
||||
github.com/google/licensecheck v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/hcl/v2 v2.23.0
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.5
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
|
||||
github.com/knqyf263/go-rpmdb v0.1.1
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/magiconair/properties v1.8.9
|
||||
github.com/mholt/archives v0.1.0
|
||||
github.com/moby/sys/mountinfo v0.7.2
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22
|
||||
github.com/saferwall/pe v1.5.6
|
||||
github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/sanity-io/litter v1.5.6
|
||||
github.com/sanity-io/litter v1.5.8
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb
|
||||
github.com/spdx/tools-golang v0.5.5
|
||||
github.com/spf13/afero v1.12.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/afero v1.14.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/vbatts/go-mtree v0.5.4
|
||||
github.com/vifraa/gopom v1.0.0
|
||||
@@ -77,21 +83,11 @@ require (
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
go.uber.org/goleak v1.3.0
|
||||
golang.org/x/mod v0.22.0
|
||||
golang.org/x/net v0.34.0
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
|
||||
golang.org/x/mod v0.24.0
|
||||
golang.org/x/net v0.38.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.34.5
|
||||
)
|
||||
|
||||
require google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/OneOfOne/xxhash v1.2.8
|
||||
github.com/adrg/xdg v0.5.3
|
||||
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51
|
||||
github.com/magiconair/properties v1.8.9
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
modernc.org/sqlite v1.37.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -103,43 +99,52 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.7 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.3 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/STARRY-S/zip v0.2.1 // indirect
|
||||
github.com/agext/levenshtein v1.2.1 // indirect; indirectt
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.1 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||
github.com/bodgit/sevenzip v1.6.0 // indirect
|
||||
github.com/bodgit/windows v1.0.1 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.4.5 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.8 // indirect
|
||||
github.com/cloudflare/circl v1.6.0 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/containerd v1.7.24 // indirect
|
||||
github.com/containerd/containerd/api v1.7.19 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/containerd v1.7.27 // indirect
|
||||
github.com/containerd/containerd/api v1.8.0 // indirect
|
||||
github.com/containerd/continuity v0.4.4 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.5 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v27.5.0+incompatible // indirect
|
||||
github.com/docker/cli v28.0.4+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v28.0.4+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/felixge/fgprof v0.9.3 // indirect
|
||||
github.com/felixge/fgprof v0.9.5 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gkampitakis/ciinfo v0.3.1 // indirect
|
||||
github.com/gkampitakis/go-diff v1.3.2 // indirect
|
||||
@@ -149,17 +154,17 @@ require (
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/goccy/go-yaml v1.15.13 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
@@ -172,6 +177,8 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
@@ -181,36 +188,36 @@ require (
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sorairolake/lzip-go v0.3.5 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spf13/viper v1.20.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.20.2 // indirect
|
||||
github.com/sylabs/squashfs v1.0.4 // indirect
|
||||
github.com/sylabs/sif/v2 v2.21.1 // indirect
|
||||
github.com/sylabs/squashfs v1.0.6 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
@@ -223,6 +230,7 @@ require (
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/zclconf/go-cty v1.13.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||
@@ -231,22 +239,26 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/term v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/term v0.30.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
||||
google.golang.org/grpc v1.67.3 // indirect
|
||||
google.golang.org/protobuf v1.36.3 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.36.4 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
modernc.org/libc v1.55.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/libc v1.62.1 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.9.1 // indirect
|
||||
)
|
||||
|
||||
require github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6
|
||||
|
||||
retract (
|
||||
v0.53.2
|
||||
v0.53.1 // Published accidentally with incorrect license in depdencies
|
||||
|
||||
@@ -56,8 +56,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg=
|
||||
@@ -80,14 +80,18 @@ github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
||||
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
||||
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
|
||||
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
|
||||
github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
|
||||
github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
|
||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -96,36 +100,44 @@ github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51 h1:yhk+P8lF3
|
||||
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51/go.mod h1:nwuGSd7aZp0rtYt79YggCGafz1RYsclE7pi3fhLwvuw=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
|
||||
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837 h1:bIG3WsfosZsJ5LMC7PB9J/ekFM3a0j0ZEDvN3ID6GTI=
|
||||
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837/go.mod h1:tRQVKkjYeejrh9AdM0s1esbwtMU7rdHAHSQWkv4qskE=
|
||||
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10 h1:w+HibE+e/heP6ysADh7sWxg5LhYdVqrpB1A4Hmgjyx8=
|
||||
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10/go.mod h1:s0L1//Sxn6Rq0Dcxx+dmT/RRmD9HhsaJjJkPUJHLJLM=
|
||||
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716 h1:2sIdYJlQESEnyk3Y0WD2vXWW5eD2iMz9Ev8fj1Z8LNA=
|
||||
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716/go.mod h1:Utb9i4kwiCWvqAIxZaJeMIXFO9uOgQXlvH2BfbfO/zI=
|
||||
github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2 h1:GC2QaO0YsmjpsZ4rtVKv9DnproIxqqn+qkskpc+i8MA=
|
||||
github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2/go.mod h1:XUbUECwVKuD3qYRUj+QZIOHjyyXua2gFmVjKA40iHXA=
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q=
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8=
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw=
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg=
|
||||
github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d h1:gT69osH9AsdpOfqxbRwtxcNnSZ1zg4aKy2BevO3ZBdc=
|
||||
github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d/go.mod h1:PhSnuFYknwPZkOWKB1jXBNToChBA+l0FjwOxtViIc50=
|
||||
github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722 h1:2SqmFgE7h+Ql4VyBzhjLkRF/3gDrcpUBj8LjvvO6OOM=
|
||||
github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722/go.mod h1:oFuE8YuTCM+spgMXhePGzk3asS94yO9biUfDzVTFqNw=
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU=
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
|
||||
github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6 h1:Ha+LSCVuXYSYGi7wIkJK6G8g6jI3LH7y6LbyEVyp4Io=
|
||||
github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6/go.mod h1:+9oM3XUy8iea/vWj9FhZ9bQGUBN8JpPxxJm5Wbcx9XM=
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8=
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f h1:dAQPIrQ3a5PBqZeZ+B9NGZsGmodk4NO9OjDIsQmQyQM=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
|
||||
github.com/anchore/stereoscope v0.0.12 h1:ovUWeyeZGml6pTGiu/uha/rCbToANFPu+cnhLbeperY=
|
||||
github.com/anchore/stereoscope v0.0.12/go.mod h1:cmb/MGya7ccOd6fZZEREuhdSH2kFALBMrkY/66Sfv1o=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 h1:ZyRCmiEjnoGJZ1+Ah0ZZ/mKKqNhGcUZBl0s7PTTDzvY=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
|
||||
github.com/anchore/stereoscope v0.1.2 h1:0+Jcf7hoImYKfrH2XzN6vvbmbpm68A/woabC43gZ4eU=
|
||||
github.com/anchore/stereoscope v0.1.2/go.mod h1:kU4LkiocOimxuSnlmJgilHCfDMCR5t/UroKIpzI8jNw=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 h1:vmXNl+HDfqqXgr0uY1UgK1GAhps8nbAAtqHNBcgyf+4=
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46/go.mod h1:olhPNdiiAAMiSujemd1O/sc6GcyePr23f/6uGKtthNg=
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 h1:rcEG5HI490FF0a7zuvxOxen52ddygCfNVjP0XOCMl+M=
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
|
||||
github.com/aquasecurity/go-pep440-version v0.0.1 h1:8VKKQtH2aV61+0hovZS3T//rUF+6GDn18paFTVS0h0M=
|
||||
github.com/aquasecurity/go-pep440-version v0.0.1/go.mod h1:3naPe+Bp6wi3n4l5iBFCZgS0JG8vY6FT0H4NGhFJ+i4=
|
||||
github.com/aquasecurity/go-version v0.0.1 h1:4cNl516agK0TCn5F7mmYN+xVs1E3S45LkgZk3cbaW2E=
|
||||
github.com/aquasecurity/go-version v0.0.1/go.mod h1:s1UU6/v2hctXcOa3OLwfj5d9yoXHa3ahf+ipSwEvGT0=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
@@ -143,37 +155,60 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.0 h1:DSXtrypQddoug1459viM9X9D3dp1Z7993fw36I2kNcQ=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef h1:TSFnfbbu2oAOuWbeDDTtwXWE6z+PmpgbSsMBeV7l0ww=
|
||||
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef/go.mod h1:9iglf1GG4oNRJ39bZ5AZrjgAFD2RwQbXw6Qf7Cs47wo=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
|
||||
github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
|
||||
github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A=
|
||||
github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc=
|
||||
github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
|
||||
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
|
||||
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
|
||||
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
|
||||
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
|
||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
|
||||
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
|
||||
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
|
||||
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
||||
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@@ -186,12 +221,12 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA=
|
||||
github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
|
||||
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
|
||||
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
|
||||
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
|
||||
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
|
||||
github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
|
||||
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
|
||||
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
|
||||
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
|
||||
github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
@@ -202,18 +237,17 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
|
||||
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
|
||||
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
|
||||
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
|
||||
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
|
||||
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -226,12 +260,12 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM=
|
||||
github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A=
|
||||
github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U=
|
||||
github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
|
||||
github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
@@ -240,15 +274,13 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ=
|
||||
github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/elliotchance/phpserialize v1.4.0 h1:cAp/9+KSnEbUC8oYCE32n2n84BeW8HOY3HMDI8hG2OY=
|
||||
github.com/elliotchance/phpserialize v1.4.0/go.mod h1:gt7XX9+ETUcLXbtTKEuyrqW3lcLUAeS/AnGZ2e49TZs=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@@ -274,15 +306,16 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
|
||||
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@@ -292,8 +325,8 @@ github.com/gkampitakis/ciinfo v0.3.1 h1:lzjbemlGI4Q+XimPg64ss89x8Mf3xihJqy/0Mgag
|
||||
github.com/gkampitakis/ciinfo v0.3.1/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
|
||||
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
|
||||
github.com/gkampitakis/go-snaps v0.5.8 h1:BB4ihcyXgJEVO/Pj/P+4bs7pFzsLcEjsfU2+mFdJh1c=
|
||||
github.com/gkampitakis/go-snaps v0.5.8/go.mod h1:PcKmy8q5Se7p48ywpogN5Td13reipz1Iivah4wrTIvY=
|
||||
github.com/gkampitakis/go-snaps v0.5.11 h1:LFG0ggUKR+KEiiaOvFCmLgJ5NO2zf93AxxddkBn3LdQ=
|
||||
github.com/gkampitakis/go-snaps v0.5.11/go.mod h1:PcKmy8q5Se7p48ywpogN5Td13reipz1Iivah4wrTIvY=
|
||||
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
|
||||
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
@@ -304,8 +337,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
|
||||
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
|
||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -324,18 +357,26 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-yaml v1.15.13 h1:Xd87Yddmr2rC1SLLTm2MNDcTjeO/GYo0JGiww6gSTDg=
|
||||
github.com/goccy/go-yaml v1.15.13/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg=
|
||||
github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
@@ -380,8 +421,9 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
|
||||
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -406,8 +448,9 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -449,8 +492,11 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
|
||||
github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
|
||||
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||
@@ -468,6 +514,7 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
@@ -475,10 +522,11 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77
|
||||
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3NgSqAo=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@@ -493,8 +541,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
@@ -513,6 +561,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
@@ -522,6 +571,7 @@ github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc8
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
|
||||
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@@ -548,8 +598,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5 h1:tQRHcLQwnwrPq2j2Qra/NnyjyESBGwdeBeVdAE9kXYg=
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5/go.mod h1:vYT9HE7WCvL64iVeZylKmCsWKfE+JZ8105iuh2Trk8g=
|
||||
github.com/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q=
|
||||
github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
@@ -559,13 +609,11 @@ github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HK
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
@@ -595,25 +643,28 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 h1:MYzLheyVx1tJVDqfu3YnN4jtnyALNzLvwl+f58TcvQY=
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
|
||||
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM=
|
||||
@@ -621,12 +672,12 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
|
||||
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -653,8 +704,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
@@ -665,24 +716,22 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c h1:8gOLsYwaY2JwlTMT4brS5/9XJdrdIbmk2obvQ748CC0=
|
||||
github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c/go.mod h1:kwM/7r/rVluTE8qJbHAffduuqmSv4knVQT2IajGvSiA=
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/saferwall/pe v1.5.6 h1:DrRLnoQFxHWJ5lJUmrH7X2L0xeUu6SUS95Dc61eW2Yc=
|
||||
github.com/saferwall/pe v1.5.6/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/sanity-io/litter v1.5.6 h1:hCFycYzhRnW4niFbbmR7QKdmds69PbVa/sNmEN5euSU=
|
||||
github.com/sanity-io/litter v1.5.6/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg=
|
||||
github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ=
|
||||
@@ -690,44 +739,45 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
|
||||
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc=
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg=
|
||||
github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb h1:bLo8hvc8XFm9J47r690TUKBzcjSWdJDxmjXJZ+/f92U=
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
|
||||
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
|
||||
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
|
||||
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -752,10 +802,10 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/sylabs/sif/v2 v2.20.2 h1:HGEPzauCHhIosw5o6xmT3jczuKEuaFzSfdjAsH33vYw=
|
||||
github.com/sylabs/sif/v2 v2.20.2/go.mod h1:WyYryGRaR4Wp21SAymm5pK0p45qzZCSRiZMFvUZiuhc=
|
||||
github.com/sylabs/squashfs v1.0.4 h1:uFSw7WXv7zjutPvU+JzY0nY494Vw8s4FAf4+7DhoMdI=
|
||||
github.com/sylabs/squashfs v1.0.4/go.mod h1:PDgf8YmCntvN4d9Y8hBUBDCZL6qZOzOQwRGxnIdbERk=
|
||||
github.com/sylabs/sif/v2 v2.21.1 h1:GZ0b5//AFAqJEChd8wHV/uSKx/l1iuGYwjR8nx+4wPI=
|
||||
github.com/sylabs/sif/v2 v2.21.1/go.mod h1:YoqEGQnb5x/ItV653bawXHZJOXQaEWpGwHsSD3YePJI=
|
||||
github.com/sylabs/squashfs v1.0.6 h1:PvJcDzxr+vIm2kH56mEMbaOzvGu79gK7P7IX+R7BDZI=
|
||||
github.com/sylabs/squashfs v1.0.6/go.mod h1:DlDeUawVXLWAsSRa085Eo0ZenGzAB32JdAUFaB0LZfE=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.6/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
@@ -774,7 +824,6 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vbatts/go-mtree v0.5.4 h1:OMAb8jaCyiFA7zXj0Zc/oARcxBDBoeu2LizjB8BVJl0=
|
||||
github.com/vbatts/go-mtree v0.5.4/go.mod h1:5GqJbVhm9BBiCc4K5uc/c42FPgXulHaQs4sFUEfIWMo=
|
||||
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs=
|
||||
@@ -806,6 +855,10 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
|
||||
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 h1:V+UsotZpAVvfj3X/LMoEytoLzSiP6Lg0F7wdVyu9gGg=
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis=
|
||||
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
@@ -848,6 +901,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
|
||||
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -860,8 +915,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -872,8 +927,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -901,8 +956,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -946,8 +1001,9 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -977,8 +1033,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1047,18 +1103,20 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1069,13 +1127,13 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -1131,14 +1189,14 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@@ -1243,8 +1301,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f h1:M65LEviCfuZTfrfzwwEoxVtgvfkFkBUbFnRbxCXuXhU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f/go.mod h1:Yo94eF2nj7igQt+TiJ49KxjIH8ndLYPZMIRSiRcEbg0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@@ -1290,8 +1348,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -1300,8 +1358,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -1324,28 +1380,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
|
||||
modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
|
||||
modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic=
|
||||
modernc.org/cc/v4 v4.25.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.25.1 h1:TFSzPrAGmDsdnhT9X2UrcPMI3N/mJ9/X9ykKXwLhDsU=
|
||||
modernc.org/ccgo/v4 v4.25.1/go.mod h1:njjuAYiPflywOOrm3B7kCB444ONP5pAVr8PIEoE0uDw=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
||||
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g=
|
||||
modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/libc v1.62.1 h1:s0+fv5E3FymN8eJVmnk0llBe6rOxCu/DEU+XygRbS8s=
|
||||
modernc.org/libc v1.62.1/go.mod h1:iXhATfJQLjG3NWy56a6WVU73lWOcdYVxsvwCgoPljuo=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g=
|
||||
modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
|
||||
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
|
||||
Vendored
+2
-2
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/gohugoio/hashstructure"
|
||||
)
|
||||
|
||||
// hashType returns a stable hash based on the structure of the type
|
||||
@@ -12,7 +12,7 @@ func hashType[T any]() string {
|
||||
// get the base type and hash an empty instance
|
||||
var t T
|
||||
empty := emptyValue(reflect.TypeOf(t)).Interface()
|
||||
hash, err := hashstructure.Hash(empty, hashstructure.FormatV2, &hashstructure.HashOptions{
|
||||
hash, err := hashstructure.Hash(empty, &hashstructure.HashOptions{
|
||||
ZeroNil: false,
|
||||
IgnoreZeroValue: false,
|
||||
SlicesAsSets: false,
|
||||
|
||||
Vendored
+2
-2
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/gohugoio/hashstructure"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -99,7 +99,7 @@ func Test_hashType(t *testing.T) {
|
||||
|
||||
func Test_hashIgnores(t *testing.T) {
|
||||
hash := func(v any) string {
|
||||
v, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{})
|
||||
v, err := hashstructure.Hash(v, &hashstructure.HashOptions{})
|
||||
require.NoError(t, err)
|
||||
return fmt.Sprintf("%x", v)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func DefaultCommonOptions() []cmp.Option {
|
||||
return CommonOptions(nil, nil)
|
||||
func DefaultOptions() []cmp.Option {
|
||||
return BuildOptions(nil, nil)
|
||||
}
|
||||
|
||||
func CommonOptions(licenseCmp LicenseComparer, locationCmp LocationComparer) []cmp.Option {
|
||||
func DefaultIgnoreLocationLayerOptions() []cmp.Option {
|
||||
return BuildOptions(LicenseComparerWithoutLocationLayer, LocationComparerWithoutLayer)
|
||||
}
|
||||
|
||||
func BuildOptions(licenseCmp LicenseComparer, locationCmp LocationComparer) []cmp.Option {
|
||||
if licenseCmp == nil {
|
||||
licenseCmp = DefaultLicenseComparer
|
||||
}
|
||||
@@ -25,47 +29,9 @@ func CommonOptions(licenseCmp LicenseComparer, locationCmp LocationComparer) []c
|
||||
cmpopts.IgnoreFields(pkg.Package{}, "id"), // note: ID is not deterministic for test purposes
|
||||
cmpopts.SortSlices(pkg.Less),
|
||||
cmpopts.SortSlices(DefaultRelationshipComparer),
|
||||
cmp.Comparer(
|
||||
func(x, y file.LocationSet) bool {
|
||||
xs := x.ToSlice()
|
||||
ys := y.ToSlice()
|
||||
|
||||
if len(xs) != len(ys) {
|
||||
return false
|
||||
}
|
||||
for i, xe := range xs {
|
||||
ye := ys[i]
|
||||
if !locationCmp(xe, ye) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
),
|
||||
cmp.Comparer(
|
||||
func(x, y pkg.LicenseSet) bool {
|
||||
xs := x.ToSlice()
|
||||
ys := y.ToSlice()
|
||||
|
||||
if len(xs) != len(ys) {
|
||||
return false
|
||||
}
|
||||
for i, xe := range xs {
|
||||
ye := ys[i]
|
||||
if !licenseCmp(xe, ye) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
),
|
||||
cmp.Comparer(
|
||||
locationCmp,
|
||||
),
|
||||
cmp.Comparer(
|
||||
licenseCmp,
|
||||
),
|
||||
cmp.Comparer(buildSetComparer[file.Location, file.LocationSet](locationCmp)),
|
||||
cmp.Comparer(buildSetComparer[pkg.License, pkg.LicenseSet](licenseCmp)),
|
||||
cmp.Comparer(locationCmp),
|
||||
cmp.Comparer(licenseCmp),
|
||||
}
|
||||
}
|
||||
|
||||
+13
-16
@@ -10,20 +10,17 @@ import (
|
||||
type LicenseComparer func(x, y pkg.License) bool
|
||||
|
||||
func DefaultLicenseComparer(x, y pkg.License) bool {
|
||||
return cmp.Equal(x, y, cmp.Comparer(DefaultLocationComparer), cmp.Comparer(
|
||||
func(x, y file.LocationSet) bool {
|
||||
xs := x.ToSlice()
|
||||
ys := y.ToSlice()
|
||||
if len(xs) != len(ys) {
|
||||
return false
|
||||
}
|
||||
for i, xe := range xs {
|
||||
ye := ys[i]
|
||||
if !DefaultLocationComparer(xe, ye) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
))
|
||||
return cmp.Equal(
|
||||
x, y,
|
||||
cmp.Comparer(DefaultLocationComparer),
|
||||
cmp.Comparer(buildSetComparer[file.Location, file.LocationSet](DefaultLocationComparer)),
|
||||
)
|
||||
}
|
||||
|
||||
func LicenseComparerWithoutLocationLayer(x, y pkg.License) bool {
|
||||
return cmp.Equal(
|
||||
x, y,
|
||||
cmp.Comparer(LocationComparerWithoutLayer),
|
||||
cmp.Comparer(buildSetComparer[file.Location, file.LocationSet](LocationComparerWithoutLayer)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,3 +11,7 @@ type LocationComparer func(x, y file.Location) bool
|
||||
func DefaultLocationComparer(x, y file.Location) bool {
|
||||
return cmp.Equal(x.Coordinates, y.Coordinates) && cmp.Equal(x.AccessPath, y.AccessPath)
|
||||
}
|
||||
|
||||
func LocationComparerWithoutLayer(x, y file.Location) bool {
|
||||
return cmp.Equal(x.Coordinates.RealPath, y.Coordinates.RealPath) && cmp.Equal(x.AccessPath, y.AccessPath)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package cmptest
|
||||
|
||||
type slicer[T any] interface {
|
||||
ToSlice() []T
|
||||
}
|
||||
|
||||
func buildSetComparer[T any, S slicer[T]](l func(x, y T) bool) func(x, y S) bool {
|
||||
return func(x, y S) bool {
|
||||
xs := x.ToSlice()
|
||||
ys := y.ToSlice()
|
||||
|
||||
if len(xs) != len(ys) {
|
||||
return false
|
||||
}
|
||||
for i, xe := range xs {
|
||||
ye := ys[i]
|
||||
if !l(xe, ye) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,5 @@ package internal
|
||||
const (
|
||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||
JSONSchemaVersion = "16.0.19"
|
||||
JSONSchemaVersion = "16.0.24"
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
@@ -12,7 +13,11 @@ import (
|
||||
// CloseAndLogError closes the given io.Closer and reports any errors found as a warning in the log
|
||||
func CloseAndLogError(closer io.Closer, location string) {
|
||||
if err := closer.Close(); err != nil {
|
||||
log.Warnf("unable to close file for location=%q: %+v", location, err)
|
||||
// suppress "file already closed" log messages
|
||||
if errors.Is(err, fs.ErrClosed) {
|
||||
return
|
||||
}
|
||||
log.Debugf("unable to close file for location=%q: %+v", location, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package evidence
|
||||
|
||||
// this package exists so that the file package can reference package evidence in tests without creating a circular dependency.
|
||||
|
||||
const (
|
||||
AnnotationKey = "evidence"
|
||||
PrimaryAnnotation = "primary"
|
||||
SupportingAnnotation = "supporting"
|
||||
)
|
||||
@@ -1,12 +1,15 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/go-sync"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
@@ -21,7 +24,7 @@ func supportedHashAlgorithms() []crypto.Hash {
|
||||
}
|
||||
}
|
||||
|
||||
func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
||||
func NewDigestsFromFile(ctx context.Context, closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
||||
hashes = NormalizeHashes(hashes)
|
||||
// create a set of hasher objects tied together with a single writer to feed content into
|
||||
hashers := make([]hash.Hash, len(hashes))
|
||||
@@ -31,7 +34,7 @@ func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Dige
|
||||
writers[idx] = hashers[idx]
|
||||
}
|
||||
|
||||
size, err := io.Copy(io.MultiWriter(writers...), closer)
|
||||
size, err := io.Copy(sync.ParallelWriter(ctx, cataloging.ExecutorCPU, writers...), closer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -81,7 +82,7 @@ func TestNewDigestsFromFile(t *testing.T) {
|
||||
fh, err := os.Open(tt.fixture)
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := NewDigestsFromFile(fh, tt.hashes)
|
||||
got, err := NewDigestsFromFile(context.TODO(), fh, tt.hashes)
|
||||
tt.wantErr(t, err)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -10,9 +10,9 @@ func SetContextLicenseScanner(ctx context.Context, s Scanner) context.Context {
|
||||
return context.WithValue(ctx, licenseScannerKey{}, s)
|
||||
}
|
||||
|
||||
func ContextLicenseScanner(ctx context.Context) Scanner {
|
||||
func ContextLicenseScanner(ctx context.Context) (Scanner, error) {
|
||||
if s, ok := ctx.Value(licenseScannerKey{}).(Scanner); ok {
|
||||
return s
|
||||
return s, nil
|
||||
}
|
||||
return NewDefaultScanner()
|
||||
}
|
||||
|
||||
@@ -2,67 +2,84 @@ package licenses
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/google/licensecheck"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
const coverageThreshold = 75 // determined by experimentation
|
||||
const (
|
||||
DefaultCoverageThreshold = 75 // determined by experimentation
|
||||
DefaultIncludeLicenseContent = false
|
||||
)
|
||||
|
||||
type Scanner interface {
|
||||
IdentifyLicenseIDs(context.Context, io.Reader) ([]string, error)
|
||||
IdentifyLicenseIDs(context.Context, io.Reader) ([]string, []byte, error)
|
||||
FileSearch(context.Context, file.LocationReadCloser) ([]file.License, error)
|
||||
PkgSearch(context.Context, file.LocationReadCloser) ([]pkg.License, error)
|
||||
}
|
||||
|
||||
var _ Scanner = (*scanner)(nil)
|
||||
|
||||
type scanner struct {
|
||||
coverageThreshold float64 // between 0 and 100
|
||||
scanner func([]byte) licensecheck.Coverage
|
||||
coverageThreshold float64 // between 0 and 100
|
||||
includeLicenseContent bool
|
||||
scanner func([]byte) licensecheck.Coverage
|
||||
}
|
||||
|
||||
type ScannerConfig struct {
|
||||
CoverageThreshold float64
|
||||
IncludeLicenseContent bool
|
||||
Scanner func([]byte) licensecheck.Coverage
|
||||
}
|
||||
|
||||
type Option func(*scanner)
|
||||
|
||||
func WithCoverage(coverage float64) Option {
|
||||
return func(s *scanner) {
|
||||
s.coverageThreshold = coverage
|
||||
}
|
||||
}
|
||||
|
||||
func WithIncludeLicenseContent(includeLicenseContent bool) Option {
|
||||
return func(s *scanner) {
|
||||
s.includeLicenseContent = includeLicenseContent
|
||||
}
|
||||
}
|
||||
|
||||
// NewDefaultScanner returns a scanner that uses a new instance of the default licensecheck package scanner.
|
||||
func NewDefaultScanner() Scanner {
|
||||
func NewDefaultScanner(o ...Option) (Scanner, error) {
|
||||
s, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses())
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Trace("unable to create default license scanner")
|
||||
s = nil
|
||||
return nil, fmt.Errorf("unable to create default license scanner: %w", err)
|
||||
}
|
||||
newScanner := &scanner{
|
||||
coverageThreshold: DefaultCoverageThreshold,
|
||||
includeLicenseContent: DefaultIncludeLicenseContent,
|
||||
scanner: s.Scan,
|
||||
}
|
||||
|
||||
for _, opt := range o {
|
||||
opt(newScanner)
|
||||
}
|
||||
return newScanner, nil
|
||||
}
|
||||
|
||||
// NewScanner generates a license Scanner with the given ScannerConfig
|
||||
// if config is nil NewDefaultScanner is used
|
||||
func NewScanner(c *ScannerConfig) (Scanner, error) {
|
||||
if c == nil {
|
||||
return NewDefaultScanner()
|
||||
}
|
||||
|
||||
return &scanner{
|
||||
coverageThreshold: coverageThreshold,
|
||||
scanner: s.Scan,
|
||||
}
|
||||
}
|
||||
|
||||
// TestingOnlyScanner returns a scanner that uses the built-in license scanner from the licensecheck package.
|
||||
// THIS IS ONLY MEANT FOR TEST CODE, NOT PRODUCTION CODE.
|
||||
func TestingOnlyScanner() Scanner {
|
||||
return &scanner{
|
||||
coverageThreshold: coverageThreshold,
|
||||
scanner: licensecheck.Scan,
|
||||
}
|
||||
}
|
||||
|
||||
func (s scanner) IdentifyLicenseIDs(_ context.Context, reader io.Reader) ([]string, error) {
|
||||
if s.scanner == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cov := s.scanner(content)
|
||||
if cov.Percent < s.coverageThreshold {
|
||||
// unknown or no licenses here?
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var ids []string
|
||||
for _, m := range cov.Match {
|
||||
ids = append(ids, m.ID)
|
||||
}
|
||||
return ids, nil
|
||||
coverageThreshold: c.CoverageThreshold,
|
||||
includeLicenseContent: c.IncludeLicenseContent,
|
||||
scanner: c.Scanner,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package licenses
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/licensecheck"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIdentifyLicenseIDs(t *testing.T) {
|
||||
type expectation struct {
|
||||
yieldError bool
|
||||
ids []string
|
||||
content []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
expected expectation
|
||||
}{
|
||||
{
|
||||
name: "apache license 2.0",
|
||||
in: `test-fixtures/apache-license-2.0`,
|
||||
expected: expectation{
|
||||
yieldError: false,
|
||||
ids: []string{"Apache-2.0"},
|
||||
content: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom license includes content for IdentifyLicenseIDs",
|
||||
in: "test-fixtures/nvidia-software-and-cuda-supplement",
|
||||
expected: expectation{
|
||||
yieldError: false,
|
||||
ids: []string{},
|
||||
content: mustOpen("test-fixtures/nvidia-software-and-cuda-supplement"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
content, err := os.ReadFile(test.in)
|
||||
require.NoError(t, err)
|
||||
ids, content, err := testScanner(false).IdentifyLicenseIDs(context.TODO(), bytes.NewReader(content))
|
||||
if test.expected.yieldError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, ids, len(test.expected.ids))
|
||||
require.Len(t, content, len(test.expected.content))
|
||||
|
||||
if len(test.expected.ids) > 0 {
|
||||
require.Equal(t, ids, test.expected.ids)
|
||||
}
|
||||
|
||||
if len(test.expected.content) > 0 {
|
||||
require.Equal(t, content, test.expected.content)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testScanner(includeLicenseContent bool) Scanner {
|
||||
return &scanner{
|
||||
coverageThreshold: DefaultCoverageThreshold,
|
||||
includeLicenseContent: includeLicenseContent,
|
||||
scanner: licensecheck.Scan,
|
||||
}
|
||||
}
|
||||
|
||||
func mustOpen(fixture string) []byte {
|
||||
content, err := os.ReadFile(fixture)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
+101
-6
@@ -2,24 +2,119 @@ package licenses
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/license"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
// Search scans the contents of a license file to attempt to determine the type of license it is
|
||||
func Search(ctx context.Context, scanner Scanner, reader file.LocationReadCloser) (licenses []pkg.License, err error) {
|
||||
const (
|
||||
unknownLicenseType = "UNKNOWN"
|
||||
UnknownLicensePrefix = unknownLicenseType + "_"
|
||||
)
|
||||
|
||||
func getCustomLicenseContentHash(contents []byte) string {
|
||||
hash := sha256.Sum256(contents)
|
||||
return fmt.Sprintf("%x", hash[:])
|
||||
}
|
||||
|
||||
func (s *scanner) IdentifyLicenseIDs(_ context.Context, reader io.Reader) ([]string, []byte, error) {
|
||||
if s.scanner == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cov := s.scanner(content)
|
||||
if cov.Percent < s.coverageThreshold {
|
||||
// unknown or no licenses here
|
||||
// => check return content to Search to process
|
||||
return nil, content, nil
|
||||
}
|
||||
|
||||
var ids []string
|
||||
for _, m := range cov.Match {
|
||||
ids = append(ids, m.ID)
|
||||
}
|
||||
return ids, nil, nil
|
||||
}
|
||||
|
||||
// PkgSearch scans the contents of a license file to attempt to determine the type of license it is
|
||||
func (s *scanner) PkgSearch(ctx context.Context, reader file.LocationReadCloser) (licenses []pkg.License, err error) {
|
||||
licenses = make([]pkg.License, 0)
|
||||
|
||||
ids, err := scanner.IdentifyLicenseIDs(ctx, reader)
|
||||
ids, content, err := s.IdentifyLicenseIDs(ctx, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
lic := pkg.NewLicenseFromLocations(id, reader.Location)
|
||||
lic.Type = license.Concluded
|
||||
// IdentifyLicenseIDs can only return a list of ID or content
|
||||
// These return values are mutually exclusive.
|
||||
// If the scanner threshold for matching scores < 75% then we return the license full content
|
||||
if len(ids) > 0 {
|
||||
for _, id := range ids {
|
||||
lic := pkg.NewLicenseFromLocations(id, reader.Location)
|
||||
lic.Type = license.Concluded
|
||||
|
||||
licenses = append(licenses, lic)
|
||||
}
|
||||
} else if len(content) > 0 {
|
||||
// harmonize line endings to unix compatible first:
|
||||
// 1. \r\n => \n (Windows => UNIX)
|
||||
// 2. \r => \n (Macintosh => UNIX)
|
||||
content = []byte(strings.ReplaceAll(strings.ReplaceAll(string(content), "\r\n", "\n"), "\r", "\n"))
|
||||
|
||||
lic := pkg.NewLicenseFromLocations(unknownLicenseType, reader.Location)
|
||||
lic.SPDXExpression = UnknownLicensePrefix + getCustomLicenseContentHash(content)
|
||||
if s.includeLicenseContent {
|
||||
lic.Contents = string(content)
|
||||
}
|
||||
lic.Type = license.Declared
|
||||
|
||||
licenses = append(licenses, lic)
|
||||
}
|
||||
|
||||
return licenses, nil
|
||||
}
|
||||
|
||||
// FileSearch scans the contents of a license file to attempt to determine the type of license it is
|
||||
func (s *scanner) FileSearch(ctx context.Context, reader file.LocationReadCloser) (licenses []file.License, err error) {
|
||||
licenses = make([]file.License, 0)
|
||||
|
||||
ids, content, err := s.IdentifyLicenseIDs(ctx, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// IdentifyLicenseIDs can only return a list of ID or content
|
||||
// These return values are mutually exclusive.
|
||||
// If the scanner threshold for matching scores < 75% then we return the license full content
|
||||
if len(ids) > 0 {
|
||||
for _, id := range ids {
|
||||
lic := file.NewLicense(id)
|
||||
lic.Type = license.Concluded
|
||||
|
||||
licenses = append(licenses, lic)
|
||||
}
|
||||
} else if len(content) > 0 {
|
||||
// harmonize line endings to unix compatible first:
|
||||
// 1. \r\n => \n (Windows => UNIX)
|
||||
// 2. \r => \n (Macintosh => UNIX)
|
||||
content = []byte(strings.ReplaceAll(strings.ReplaceAll(string(content), "\r\n", "\n"), "\r", "\n"))
|
||||
|
||||
lic := file.NewLicense(unknownLicenseType)
|
||||
lic.SPDXExpression = UnknownLicensePrefix + getCustomLicenseContentHash(content)
|
||||
if s.includeLicenseContent {
|
||||
lic.Contents = string(content)
|
||||
}
|
||||
lic.Type = license.Declared
|
||||
|
||||
licenses = append(licenses, lic)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
package licenses
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
type bytesReadCloser struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
func (brc *bytesReadCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newBytesReadCloser(data []byte) *bytesReadCloser {
|
||||
return &bytesReadCloser{
|
||||
Buffer: *bytes.NewBuffer(data),
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchFileLicenses(t *testing.T) {
|
||||
type expectation struct {
|
||||
yieldError bool
|
||||
licenses []file.License
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
includeUnkownLicenseContent bool
|
||||
expected expectation
|
||||
}{
|
||||
{
|
||||
name: "apache license 2.0",
|
||||
in: "test-fixtures/apache-license-2.0",
|
||||
expected: expectation{
|
||||
yieldError: false,
|
||||
licenses: []file.License{
|
||||
{
|
||||
Value: "Apache-2.0",
|
||||
SPDXExpression: "Apache-2.0",
|
||||
Type: "concluded",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
content, err := os.ReadFile(test.in)
|
||||
require.NoError(t, err)
|
||||
s := testScanner(false)
|
||||
result, err := s.FileSearch(ctx, file.NewLocationReadCloser(file.NewLocation("LICENSE"), io.NopCloser(bytes.NewReader(content))))
|
||||
if test.expected.yieldError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, result, len(test.expected.licenses))
|
||||
|
||||
if len(test.expected.licenses) > 0 {
|
||||
require.Equal(t, test.expected.licenses, result)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchPkgLicenses(t *testing.T) {
|
||||
type expectation struct {
|
||||
wantErr require.ErrorAssertionFunc
|
||||
licenses []pkg.License
|
||||
}
|
||||
|
||||
testLocation := file.NewLocation("LICENSE")
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
includeUnkownLicenseContent bool
|
||||
expected expectation
|
||||
}{
|
||||
{
|
||||
name: "apache license 2.0",
|
||||
in: "test-fixtures/apache-license-2.0",
|
||||
expected: expectation{
|
||||
licenses: []pkg.License{
|
||||
{
|
||||
Value: "Apache-2.0",
|
||||
SPDXExpression: "Apache-2.0",
|
||||
Type: "concluded",
|
||||
URLs: nil,
|
||||
Locations: file.NewLocationSet(testLocation),
|
||||
Contents: "",
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom license no content by default",
|
||||
in: "test-fixtures/nvidia-software-and-cuda-supplement",
|
||||
expected: expectation{
|
||||
licenses: []pkg.License{
|
||||
{
|
||||
Value: "UNKNOWN",
|
||||
SPDXExpression: "UNKNOWN_eebcea3ab1d1a28e671de90119ffcfb35fe86951e4af1b17af52b7a82fcf7d0a",
|
||||
Type: "declared",
|
||||
URLs: nil,
|
||||
Locations: file.NewLocationSet(testLocation),
|
||||
Contents: "",
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom license with content when scanner has content config",
|
||||
in: "test-fixtures/nvidia-software-and-cuda-supplement",
|
||||
includeUnkownLicenseContent: true,
|
||||
expected: expectation{
|
||||
licenses: []pkg.License{
|
||||
{
|
||||
Value: "UNKNOWN",
|
||||
SPDXExpression: "UNKNOWN_eebcea3ab1d1a28e671de90119ffcfb35fe86951e4af1b17af52b7a82fcf7d0a",
|
||||
Type: "declared",
|
||||
URLs: nil,
|
||||
Locations: file.NewLocationSet(testLocation),
|
||||
Contents: string(mustOpen("test-fixtures/nvidia-software-and-cuda-supplement")),
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
content, err := os.ReadFile(test.in)
|
||||
require.NoError(t, err)
|
||||
s := testScanner(test.includeUnkownLicenseContent)
|
||||
result, err := s.PkgSearch(ctx, file.NewLocationReadCloser(file.NewLocation("LICENSE"), io.NopCloser(bytes.NewReader(content))))
|
||||
if test.expected.wantErr != nil {
|
||||
test.expected.wantErr(t, err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, result, len(test.expected.licenses))
|
||||
|
||||
if len(test.expected.licenses) > 0 {
|
||||
require.Equal(t, test.expected.licenses, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
1. Definitions.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
END OF TERMS AND CONDITIONS
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,5 @@
|
||||
End User License Agreement
|
||||
--------------------------
|
||||
|
||||
NVIDIA Software License Agreement and CUDA Supplement to
|
||||
Software License Agreement. Last updated: October 8, 2021
|
||||
@@ -58,11 +58,10 @@ func generateRelationships(resolver file.Resolver, accessor sbomsync.Accessor, i
|
||||
|
||||
// PackagesToRemove returns a list of binary packages (resolved by the ELF cataloger) that should be removed from the SBOM
|
||||
// These packages are removed because they are already represented by a higher order packages in the SBOM.
|
||||
func PackagesToRemove(resolver file.Resolver, accessor sbomsync.Accessor) []artifact.ID {
|
||||
func PackagesToRemove(accessor sbomsync.Accessor) []artifact.ID {
|
||||
pkgsToDelete := make([]artifact.ID, 0)
|
||||
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
|
||||
// OTHER package type > ELF package type > Binary package type
|
||||
pkgsToDelete = append(pkgsToDelete, getBinaryPackagesToDelete(resolver, s)...)
|
||||
// ELF package type > Binary package type
|
||||
pkgsToDelete = append(pkgsToDelete, compareElfBinaryPackages(s)...)
|
||||
})
|
||||
return pkgsToDelete
|
||||
@@ -114,33 +113,6 @@ func isElfPackage(p pkg.Package) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
func getBinaryPackagesToDelete(resolver file.Resolver, s *sbom.SBOM) []artifact.ID {
|
||||
pkgsToDelete := make([]artifact.ID, 0)
|
||||
for p := range s.Artifacts.Packages.Enumerate() {
|
||||
if p.Type == pkg.BinaryPkg {
|
||||
continue
|
||||
}
|
||||
fileOwner, ok := p.Metadata.(pkg.FileOwner)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ownedFiles := fileOwner.OwnedFiles()
|
||||
locations, err := resolver.FilesByPath(ownedFiles...)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Trace("unable to find path for owned file")
|
||||
continue
|
||||
}
|
||||
for _, loc := range locations {
|
||||
for _, pathPkg := range s.Artifacts.Packages.PackagesByPath(loc.RealPath) {
|
||||
if pathPkg.Type == pkg.BinaryPkg {
|
||||
pkgsToDelete = append(pkgsToDelete, pathPkg.ID())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pkgsToDelete
|
||||
}
|
||||
|
||||
func populateRelationships(exec file.Executable, parentPkg pkg.Package, resolver file.Resolver, addRelationship func(artifact.Relationship), index *sharedLibraryIndex) {
|
||||
for _, libReference := range exec.ImportedLibraries {
|
||||
// for each library reference, check s.Artifacts.Packages.Sorted(pkg.BinaryPkg) for a binary package that represents that library
|
||||
|
||||
@@ -21,7 +21,7 @@ func TestPackagesToRemove(t *testing.T) {
|
||||
Name: "glibc",
|
||||
Version: "2.28-236.el8_9.12",
|
||||
Locations: file.NewLocationSet(
|
||||
file.NewLocation(glibcCoordinate.RealPath),
|
||||
file.NewLocation("path/to/rpmdb"),
|
||||
),
|
||||
Type: pkg.RpmPkg,
|
||||
Metadata: pkg.RpmDBEntry{
|
||||
@@ -88,50 +88,45 @@ func TestPackagesToRemove(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
resolver file.Resolver
|
||||
accessor sbomsync.Accessor
|
||||
want []artifact.ID
|
||||
}{
|
||||
{
|
||||
name: "remove packages that are overlapping rpm --> binary",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{glibCPackage, glibCBinaryELFPackage}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{glibCBinaryELFPackage.ID()},
|
||||
// this is surprising, right? the calling function reasons about if any generic binary package (regardless of it being an ELF package or not)
|
||||
// should be deleted or kept based on the user configuration to do so.
|
||||
want: []artifact.ID{},
|
||||
},
|
||||
{
|
||||
name: "keep packages that are overlapping rpm --> binary when the binary self identifies as an RPM",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{glibCPackage, glibCBinaryELFPackageAsRPM}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{},
|
||||
},
|
||||
{
|
||||
name: "remove no packages when there is a single binary package (or self identifying RPM)",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{glibCBinaryELFPackage, glibCBinaryELFPackageAsRPM}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{},
|
||||
},
|
||||
{
|
||||
name: "remove packages when there is a single binary package and a classifier package",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{glibCBinaryELFPackage, glibCBinaryClassifierPackage}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{glibCBinaryClassifierPackage.ID()},
|
||||
},
|
||||
{
|
||||
name: "ensure we're considering ELF packages, not just binary packages (supporting evidence)",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{glibCBinaryClassifierPackage}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{},
|
||||
},
|
||||
{
|
||||
name: "ensure we're considering ELF packages, not just binary packages (primary evidence)",
|
||||
resolver: file.NewMockResolverForPaths(glibcCoordinate.RealPath),
|
||||
accessor: newAccessor([]pkg.Package{libCBinaryClassifierPackage}, map[file.Coordinates]file.Executable{}, nil),
|
||||
want: []artifact.ID{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
pkgsToDelete := PackagesToRemove(tt.resolver, tt.accessor)
|
||||
pkgsToDelete := PackagesToRemove(tt.accessor)
|
||||
if diff := cmp.Diff(tt.want, pkgsToDelete); diff != "" {
|
||||
t.Errorf("unexpected packages to delete (-want, +got): %s", diff)
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func TestOwnershipByFilesRelationship(t *testing.T) {
|
||||
assert.Len(t, relationships, len(expectedRelations))
|
||||
for idx, expectedRelationship := range expectedRelations {
|
||||
actualRelationship := relationships[idx]
|
||||
if d := cmp.Diff(expectedRelationship, actualRelationship, cmptest.DefaultCommonOptions()...); d != "" {
|
||||
if d := cmp.Diff(expectedRelationship, actualRelationship, cmptest.DefaultOptions()...); d != "" {
|
||||
t.Errorf("unexpected relationship (-want, +got): %s", d)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ var (
|
||||
binaryCatalogerTypes = []pkg.Type{
|
||||
pkg.BinaryPkg,
|
||||
}
|
||||
bitnamiCatalogerTypes = []pkg.Type{
|
||||
pkg.BitnamiPkg,
|
||||
}
|
||||
binaryMetadataTypes = []string{
|
||||
reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(),
|
||||
reflect.TypeOf(pkg.BinarySignature{}).Name(),
|
||||
@@ -65,6 +68,10 @@ func excludeByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collection) a
|
||||
return idToRemove
|
||||
}
|
||||
|
||||
if idToRemove := identifyOverlappingBitnamiRelationship(parent, child); idToRemove != "" {
|
||||
return idToRemove
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -124,3 +131,24 @@ func identifyOverlappingOSRelationship(parent *pkg.Package, child *pkg.Package)
|
||||
|
||||
return child.ID()
|
||||
}
|
||||
|
||||
// identifyOverlappingBitnamiRelationship indicates the package ID to remove if this is a Bitnami pkg -> bin pkg relationship.
|
||||
func identifyOverlappingBitnamiRelationship(parent *pkg.Package, child *pkg.Package) artifact.ID {
|
||||
if !slices.Contains(bitnamiCatalogerTypes, parent.Type) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if slices.Contains(binaryCatalogerTypes, child.Type) {
|
||||
return child.ID()
|
||||
}
|
||||
|
||||
if child.Metadata == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if !slices.Contains(binaryMetadataTypes, reflect.TypeOf(child.Metadata).Name()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return child.ID()
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ func TestExcludeByFileOwnershipOverlap(t *testing.T) {
|
||||
packageA := pkg.Package{Name: "package-a", Type: pkg.ApkPkg}
|
||||
packageB := pkg.Package{Name: "package-b", Type: pkg.BinaryPkg, Metadata: pkg.JavaVMInstallation{}}
|
||||
packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}}
|
||||
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC} {
|
||||
packageD := pkg.Package{Name: "package-d", Type: pkg.BitnamiPkg}
|
||||
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} {
|
||||
p := p
|
||||
p.SetID()
|
||||
}
|
||||
@@ -46,6 +47,17 @@ func TestExcludeByFileOwnershipOverlap(t *testing.T) {
|
||||
packages: pkg.NewCollection(packageC, packageB),
|
||||
shouldExclude: true,
|
||||
},
|
||||
{
|
||||
// prove that Bitnami -> bin exclusions are wired
|
||||
name: "exclusions from bitnami -> binary",
|
||||
relationship: artifact.Relationship{
|
||||
Type: artifact.OwnershipByFileOverlapRelationship,
|
||||
From: packageD, // Bitnami
|
||||
To: packageC, // ELF binary
|
||||
},
|
||||
packages: pkg.NewCollection(packageD, packageC),
|
||||
shouldExclude: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -117,6 +129,63 @@ func TestIdentifyOverlappingOSRelationship(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifyOverlappingBitnamiRelationship(t *testing.T) {
|
||||
packageA := pkg.Package{Name: "package-a", Type: pkg.BitnamiPkg} // Bitnami package
|
||||
packageB := pkg.Package{Name: "package-b", Type: pkg.BinaryPkg}
|
||||
packageC := pkg.Package{Name: "package-c", Type: pkg.BinaryPkg, Metadata: pkg.BinarySignature{}}
|
||||
packageD := pkg.Package{Name: "package-d", Type: pkg.PythonPkg} // Language package
|
||||
packageE := pkg.Package{Name: "package-e", Type: pkg.BinaryPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{}}
|
||||
|
||||
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE} {
|
||||
p.SetID()
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
parent *pkg.Package
|
||||
child *pkg.Package
|
||||
expectedID artifact.ID
|
||||
}{
|
||||
{
|
||||
name: "Bitnami -> binary without metadata",
|
||||
parent: &packageA,
|
||||
child: &packageB,
|
||||
expectedID: packageB.ID(), // Bitnami package to binary package, should return child ID
|
||||
},
|
||||
{
|
||||
name: "Bitnami -> binary with binary metadata",
|
||||
parent: &packageA,
|
||||
child: &packageC,
|
||||
expectedID: packageC.ID(), // Bitnami package to binary package with binary metadata, should return child ID
|
||||
},
|
||||
{
|
||||
name: "Bitnami -> non-binary package",
|
||||
parent: &packageA,
|
||||
child: &packageD,
|
||||
expectedID: "", // Bitnami package to non-binary package, no exclusion
|
||||
},
|
||||
{
|
||||
name: "Bitnami -> binary with ELF metadata",
|
||||
parent: &packageA,
|
||||
child: &packageE,
|
||||
expectedID: packageE.ID(), // Bitnami package to binary package with ELF metadata, should return child ID
|
||||
},
|
||||
{
|
||||
name: "non-Bitnami parent",
|
||||
parent: &packageD, // non-Bitnami package
|
||||
child: &packageC,
|
||||
expectedID: "", // non-Bitnami parent, no exclusion
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resultID := identifyOverlappingBitnamiRelationship(tt.parent, tt.child)
|
||||
assert.Equal(t, tt.expectedID, resultID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifyOverlappingJVMRelationship(t *testing.T) {
|
||||
|
||||
packageA := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at 2024-08-20 11:33:49.349625 -0400 EDT m=+0.383911876
|
||||
// This file was generated by robots at 2024-11-29 09:22:05.594787 +0100 CET m=+2.414400043
|
||||
// using data from https://spdx.org/licenses/licenses.json
|
||||
package spdxlicense
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
)
|
||||
|
||||
type CatalogingFactoryConfig struct {
|
||||
ComplianceConfig cataloging.ComplianceConfig
|
||||
SearchConfig cataloging.SearchConfig
|
||||
RelationshipsConfig cataloging.RelationshipsConfig
|
||||
DataGenerationConfig cataloging.DataGenerationConfig
|
||||
LicenseConfig cataloging.LicenseConfig
|
||||
PackagesConfig pkgcataloging.Config
|
||||
FilesConfig filecataloging.Config
|
||||
}
|
||||
|
||||
func DefaultCatalogingFactoryConfig() CatalogingFactoryConfig {
|
||||
return CatalogingFactoryConfig{
|
||||
ComplianceConfig: cataloging.DefaultComplianceConfig(),
|
||||
SearchConfig: cataloging.DefaultSearchConfig(),
|
||||
RelationshipsConfig: cataloging.DefaultRelationshipsConfig(),
|
||||
DataGenerationConfig: cataloging.DefaultDataGenerationConfig(),
|
||||
LicenseConfig: cataloging.DefaultLicenseConfig(),
|
||||
PackagesConfig: pkgcataloging.DefaultConfig(),
|
||||
FilesConfig: filecataloging.DefaultConfig(),
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,8 @@ import (
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/internal/unknown"
|
||||
@@ -18,64 +15,17 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type Executor struct {
|
||||
numWorkers int
|
||||
tasks chan Task
|
||||
}
|
||||
|
||||
func NewTaskExecutor(tasks []Task, numWorkers int) *Executor {
|
||||
p := &Executor{
|
||||
numWorkers: numWorkers,
|
||||
tasks: make(chan Task, len(tasks)),
|
||||
func RunTask(ctx context.Context, tsk Task, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error {
|
||||
err := runTaskSafely(ctx, tsk, resolver, s)
|
||||
unknowns, remainingErrors := unknown.ExtractCoordinateErrors(err)
|
||||
if len(unknowns) > 0 {
|
||||
appendUnknowns(s, tsk.Name(), unknowns)
|
||||
}
|
||||
|
||||
for i := range tasks {
|
||||
p.tasks <- tasks[i]
|
||||
if remainingErrors != nil {
|
||||
prog.SetError(remainingErrors)
|
||||
}
|
||||
close(p.tasks)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error {
|
||||
var lock sync.Mutex
|
||||
withLock := func(fn func()) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
fn()
|
||||
}
|
||||
var errs error
|
||||
wg := &sync.WaitGroup{}
|
||||
for i := 0; i < p.numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for {
|
||||
tsk, ok := <-p.tasks
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := runTaskSafely(ctx, tsk, resolver, s)
|
||||
unknowns, remainingErrors := unknown.ExtractCoordinateErrors(err)
|
||||
if len(unknowns) > 0 {
|
||||
appendUnknowns(s, tsk.Name(), unknowns)
|
||||
}
|
||||
if remainingErrors != nil {
|
||||
withLock(func() {
|
||||
errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", remainingErrors))
|
||||
prog.SetError(remainingErrors)
|
||||
})
|
||||
}
|
||||
prog.Increment()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return errs
|
||||
prog.Increment()
|
||||
return remainingErrors
|
||||
}
|
||||
|
||||
func appendUnknowns(builder sbomsync.Builder, taskName string, unknowns []unknown.CoordinateError) {
|
||||
|
||||
@@ -16,9 +16,8 @@ func Test_TaskExecutor_PanicHandling(t *testing.T) {
|
||||
tsk := NewTask("panicking-cataloger", func(_ context.Context, _ file.Resolver, _ sbomsync.Builder) error {
|
||||
panic("something bad happened")
|
||||
})
|
||||
ex := NewTaskExecutor([]Task{tsk}, 1)
|
||||
|
||||
err := ex.Execute(context.Background(), nil, nil, &monitor.CatalogerTaskProgress{
|
||||
err := RunTask(context.Background(), tsk, nil, nil, &monitor.CatalogerTaskProgress{
|
||||
Manual: progress.NewManual(-1),
|
||||
})
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
var expressionNodePattern = regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9-+]*)+$`)
|
||||
@@ -142,7 +142,7 @@ func (ec expressionContext) newExpression(exp string, operation Operation, token
|
||||
}
|
||||
}
|
||||
|
||||
func newExpressionsFromSelectionRequest(nc *expressionContext, selectionRequest pkgcataloging.SelectionRequest) Expressions {
|
||||
func newExpressionsFromSelectionRequest(nc *expressionContext, selectionRequest cataloging.SelectionRequest) Expressions {
|
||||
var all Expressions
|
||||
|
||||
for _, exp := range selectionRequest.DefaultNamesOrTags {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
func Test_newExpressionsFromSelectionRequest(t *testing.T) {
|
||||
@@ -135,7 +135,7 @@ func Test_newExpressionsFromSelectionRequest(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
req := pkgcataloging.NewSelectionRequest().WithDefaults(tt.basis...).WithExpression(tt.expressions...)
|
||||
req := cataloging.NewSelectionRequest().WithDefaults(tt.basis...).WithExpression(tt.expressions...)
|
||||
|
||||
result := newExpressionsFromSelectionRequest(nc, req)
|
||||
if tt.expectedErrors != nil {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
)
|
||||
|
||||
type factory func(cfg CatalogingFactoryConfig) Task
|
||||
|
||||
type Factories []factory
|
||||
|
||||
func (f Factories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) {
|
||||
var allTasks []Task
|
||||
taskNames := strset.New()
|
||||
duplicateTaskNames := strset.New()
|
||||
var err error
|
||||
for _, fact := range f {
|
||||
tsk := fact(cfg)
|
||||
if tsk == nil {
|
||||
continue
|
||||
}
|
||||
tskName := tsk.Name()
|
||||
if taskNames.Has(tskName) {
|
||||
duplicateTaskNames.Add(tskName)
|
||||
}
|
||||
|
||||
allTasks = append(allTasks, tsk)
|
||||
taskNames.Add(tskName)
|
||||
}
|
||||
if duplicateTaskNames.Size() > 0 {
|
||||
names := duplicateTaskNames.List()
|
||||
sort.Strings(names)
|
||||
err = fmt.Errorf("duplicate cataloger task names: %v", strings.Join(names, ", "))
|
||||
}
|
||||
|
||||
return allTasks, err
|
||||
}
|
||||
+58
-27
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
||||
@@ -15,14 +16,27 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash) Task {
|
||||
if selection == file.NoFilesSelection || len(hashers) == 0 {
|
||||
return nil
|
||||
func DefaultFileTaskFactories() Factories {
|
||||
return Factories{
|
||||
newFileDigestCatalogerTaskFactory("digest"),
|
||||
newFileMetadataCatalogerTaskFactory("file-metadata"),
|
||||
newFileContentCatalogerTaskFactory("content"),
|
||||
newExecutableCatalogerTaskFactory("binary-metadata"),
|
||||
}
|
||||
}
|
||||
|
||||
digestsCataloger := filedigest.NewCataloger(hashers)
|
||||
func newFileDigestCatalogerTaskFactory(tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return newFileDigestCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Hashers, tags...)
|
||||
}
|
||||
}
|
||||
|
||||
func newFileDigestCatalogerTask(selection file.Selection, hashers []crypto.Hash, tags ...string) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
if selection == file.NoFilesSelection || len(hashers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
coordinates, ok := coordinatesForSelection(selection, builder.(sbomsync.Accessor))
|
||||
@@ -30,7 +44,7 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...)
|
||||
result, err := filedigest.NewCataloger(hashers).Catalog(ctx, resolver, coordinates...)
|
||||
|
||||
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
|
||||
sbom.Artifacts.FileDigests = result
|
||||
@@ -39,17 +53,21 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash
|
||||
return err
|
||||
}
|
||||
|
||||
return NewTask("file-digest-cataloger", fn)
|
||||
return NewTask("file-digest-cataloger", fn, commonFileTags(tags)...)
|
||||
}
|
||||
|
||||
func NewFileMetadataCatalogerTask(selection file.Selection) Task {
|
||||
if selection == file.NoFilesSelection {
|
||||
return nil
|
||||
func newFileMetadataCatalogerTaskFactory(tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return newFileMetadataCatalogerTask(cfg.FilesConfig.Selection, tags...)
|
||||
}
|
||||
}
|
||||
|
||||
metadataCataloger := filemetadata.NewCataloger()
|
||||
|
||||
func newFileMetadataCatalogerTask(selection file.Selection, tags ...string) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
if selection == file.NoFilesSelection {
|
||||
return nil
|
||||
}
|
||||
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
coordinates, ok := coordinatesForSelection(selection, builder.(sbomsync.Accessor))
|
||||
@@ -57,7 +75,7 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...)
|
||||
result, err := filemetadata.NewCataloger().Catalog(ctx, resolver, coordinates...)
|
||||
|
||||
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
|
||||
sbom.Artifacts.FileMetadata = result
|
||||
@@ -66,20 +84,24 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task {
|
||||
return err
|
||||
}
|
||||
|
||||
return NewTask("file-metadata-cataloger", fn)
|
||||
return NewTask("file-metadata-cataloger", fn, commonFileTags(tags)...)
|
||||
}
|
||||
|
||||
func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
|
||||
if len(cfg.Globs) == 0 {
|
||||
return nil
|
||||
func newFileContentCatalogerTaskFactory(tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return newFileContentCatalogerTask(cfg.FilesConfig.Content, tags...)
|
||||
}
|
||||
}
|
||||
|
||||
cat := filecontent.NewCataloger(cfg)
|
||||
|
||||
func newFileContentCatalogerTask(cfg filecontent.Config, tags ...string) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
if len(cfg.Globs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
result, err := cat.Catalog(ctx, resolver)
|
||||
result, err := filecontent.NewCataloger(cfg).Catalog(ctx, resolver)
|
||||
|
||||
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
|
||||
sbom.Artifacts.FileContents = result
|
||||
@@ -88,20 +110,24 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
|
||||
return err
|
||||
}
|
||||
|
||||
return NewTask("file-content-cataloger", fn)
|
||||
return NewTask("file-content-cataloger", fn, commonFileTags(tags)...)
|
||||
}
|
||||
|
||||
func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config) Task {
|
||||
if selection == file.NoFilesSelection {
|
||||
return nil
|
||||
func newExecutableCatalogerTaskFactory(tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return newExecutableCatalogerTask(cfg.FilesConfig.Selection, cfg.FilesConfig.Executable, tags...)
|
||||
}
|
||||
}
|
||||
|
||||
cat := executable.NewCataloger(cfg)
|
||||
func newExecutableCatalogerTask(selection file.Selection, cfg executable.Config, tags ...string) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
if selection == file.NoFilesSelection {
|
||||
return nil
|
||||
}
|
||||
|
||||
fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
result, err := cat.Catalog(resolver)
|
||||
result, err := executable.NewCataloger(cfg).CatalogCtx(ctx, resolver)
|
||||
|
||||
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
|
||||
sbom.Artifacts.Executables = result
|
||||
@@ -110,7 +136,7 @@ func NewExecutableCatalogerTask(selection file.Selection, cfg executable.Config)
|
||||
return err
|
||||
}
|
||||
|
||||
return NewTask("file-executable-cataloger", fn)
|
||||
return NewTask("file-executable-cataloger", fn, commonFileTags(tags)...)
|
||||
}
|
||||
|
||||
// TODO: this should be replaced with a fix that allows passing a coordinate or location iterator to the cataloger
|
||||
@@ -154,3 +180,8 @@ func coordinatesForSelection(selection file.Selection, accessor sbomsync.Accesso
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func commonFileTags(tags []string) []string {
|
||||
tags = append(tags, filecataloging.FileTag)
|
||||
return tags
|
||||
}
|
||||
|
||||
@@ -3,12 +3,9 @@ package task
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/relationship"
|
||||
@@ -23,67 +20,18 @@ import (
|
||||
cpeutils "github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
|
||||
)
|
||||
|
||||
type packageTaskFactory func(cfg CatalogingFactoryConfig) Task
|
||||
|
||||
type PackageTaskFactories []packageTaskFactory
|
||||
|
||||
type CatalogingFactoryConfig struct {
|
||||
ComplianceConfig cataloging.ComplianceConfig
|
||||
SearchConfig cataloging.SearchConfig
|
||||
RelationshipsConfig cataloging.RelationshipsConfig
|
||||
DataGenerationConfig cataloging.DataGenerationConfig
|
||||
PackagesConfig pkgcataloging.Config
|
||||
}
|
||||
|
||||
func DefaultCatalogingFactoryConfig() CatalogingFactoryConfig {
|
||||
return CatalogingFactoryConfig{
|
||||
ComplianceConfig: cataloging.DefaultComplianceConfig(),
|
||||
SearchConfig: cataloging.DefaultSearchConfig(),
|
||||
RelationshipsConfig: cataloging.DefaultRelationshipsConfig(),
|
||||
DataGenerationConfig: cataloging.DefaultDataGenerationConfig(),
|
||||
PackagesConfig: pkgcataloging.DefaultConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
func newPackageTaskFactory(catalogerFactory func(CatalogingFactoryConfig) pkg.Cataloger, tags ...string) packageTaskFactory {
|
||||
func newPackageTaskFactory(catalogerFactory func(CatalogingFactoryConfig) pkg.Cataloger, tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return NewPackageTask(cfg, catalogerFactory(cfg), tags...)
|
||||
}
|
||||
}
|
||||
|
||||
func newSimplePackageTaskFactory(catalogerFactory func() pkg.Cataloger, tags ...string) packageTaskFactory {
|
||||
func newSimplePackageTaskFactory(catalogerFactory func() pkg.Cataloger, tags ...string) factory {
|
||||
return func(cfg CatalogingFactoryConfig) Task {
|
||||
return NewPackageTask(cfg, catalogerFactory(), tags...)
|
||||
}
|
||||
}
|
||||
|
||||
func (f PackageTaskFactories) Tasks(cfg CatalogingFactoryConfig) ([]Task, error) {
|
||||
var allTasks []Task
|
||||
taskNames := strset.New()
|
||||
duplicateTaskNames := strset.New()
|
||||
var err error
|
||||
for _, factory := range f {
|
||||
tsk := factory(cfg)
|
||||
if tsk == nil {
|
||||
continue
|
||||
}
|
||||
tskName := tsk.Name()
|
||||
if taskNames.Has(tskName) {
|
||||
duplicateTaskNames.Add(tskName)
|
||||
}
|
||||
|
||||
allTasks = append(allTasks, tsk)
|
||||
taskNames.Add(tskName)
|
||||
}
|
||||
if duplicateTaskNames.Size() > 0 {
|
||||
names := duplicateTaskNames.List()
|
||||
sort.Strings(names)
|
||||
err = fmt.Errorf("duplicate cataloger task names: %v", strings.Join(names, ", "))
|
||||
}
|
||||
|
||||
return allTasks, err
|
||||
}
|
||||
|
||||
// NewPackageTask creates a Task function for a generic pkg.Cataloger, honoring the common configuration options.
|
||||
func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, sbom sbomsync.Builder) error {
|
||||
@@ -153,7 +101,7 @@ func finalizePkgCatalogerResults(cfg CatalogingFactoryConfig, resolver file.Path
|
||||
// create file-to-package relationships for files owned by the package
|
||||
owningRelationships, err := packageFileOwnershipRelationships(p, resolver)
|
||||
if err != nil {
|
||||
log.Warnf("unable to create any package-file relationships for package name=%q type=%q: %v", p.Name, p.Type, err)
|
||||
log.Debugf("unable to create any package-file relationships for package name=%q type=%q: %v", p.Name, p.Type, err)
|
||||
} else {
|
||||
relationships = append(relationships, owningRelationships...)
|
||||
}
|
||||
@@ -226,7 +174,7 @@ func applyComplianceRules(p *pkg.Package, cfg cataloging.ComplianceConfig) (bool
|
||||
return true
|
||||
|
||||
case cataloging.ComplianceActionKeep:
|
||||
log.WithFields("pkg", p.String(), "location", loc).Tracef("package with missing %s, taking no action", fieldName)
|
||||
log.WithFields("pkg", p.String(), "location", loc, "field", fieldName).Trace("package with missing field, taking no action")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/alpine"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/arch"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||
bitnamiSbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/bitnami"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/cpp"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dart"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
||||
@@ -31,6 +32,7 @@ import (
|
||||
sbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/sbom"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/swift"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/swipl"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/terraform"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/wordpress"
|
||||
)
|
||||
|
||||
@@ -50,8 +52,8 @@ const (
|
||||
)
|
||||
|
||||
//nolint:funlen
|
||||
func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
return []packageTaskFactory{
|
||||
func DefaultPackageTaskFactories() Factories {
|
||||
return []factory{
|
||||
// OS package installed catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(arch.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "alpm", "archlinux"),
|
||||
newSimplePackageTaskFactory(alpine.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "apk", "alpine"),
|
||||
@@ -61,6 +63,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
|
||||
// OS package declared catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(redhat.NewArchiveCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.OSTag, "linux", "rpm", "redhat"),
|
||||
newSimplePackageTaskFactory(debian.NewArchiveCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.OSTag, "linux", "deb", "debian"),
|
||||
|
||||
// language-specific package installed catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(cpp.NewConanInfoCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "cpp", "conan"),
|
||||
@@ -73,7 +76,6 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
// language-specific package declared catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(cpp.NewConanCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "cpp", "conan"),
|
||||
newSimplePackageTaskFactory(dart.NewPubspecLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dart"),
|
||||
newSimplePackageTaskFactory(dotnet.NewDotnetDepsCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dotnet", "c#"),
|
||||
newSimplePackageTaskFactory(elixir.NewMixLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "elixir"),
|
||||
newSimplePackageTaskFactory(erlang.NewRebarLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang"),
|
||||
newSimplePackageTaskFactory(erlang.NewOTPCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang", "otp"),
|
||||
@@ -114,8 +116,13 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
newSimplePackageTaskFactory(ocaml.NewOpamPackageManagerCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "ocaml", "opam"),
|
||||
|
||||
// language-specific package for both image and directory scans (but not necessarily declared) ////////////////////////////////////////
|
||||
newPackageTaskFactory(
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
return dotnet.NewDotnetDepsBinaryCataloger(cfg.PackagesConfig.Dotnet)
|
||||
},
|
||||
pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dotnet", "c#",
|
||||
),
|
||||
newSimplePackageTaskFactory(dotnet.NewDotnetPackagesLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.ImageTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dotnet", "c#"),
|
||||
newSimplePackageTaskFactory(dotnet.NewDotnetPortableExecutableCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "dotnet", "c#", "binary"),
|
||||
newSimplePackageTaskFactory(python.NewInstalledPackageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "python"),
|
||||
newPackageTaskFactory(
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
@@ -151,6 +158,13 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "linux", "kernel",
|
||||
),
|
||||
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, "sbom"), // note: not evidence of installed packages
|
||||
newSimplePackageTaskFactory(bitnamiSbomCataloger.NewCataloger, "bitnami", pkgcataloging.InstalledTag, pkgcataloging.ImageTag),
|
||||
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
|
||||
newSimplePackageTaskFactory(terraform.NewLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "terraform"),
|
||||
|
||||
// deprecated catalogers ////////////////////////////////////////
|
||||
// these are catalogers that should not be selectable other than specific inclusion via name or "deprecated" tag (to remain backwards compatible)
|
||||
newSimplePackageTaskFactory(dotnet.NewDotnetDepsCataloger, pkgcataloging.DeprecatedTag), // TODO: remove in syft v2.0
|
||||
newSimplePackageTaskFactory(dotnet.NewDotnetPortableExecutableCataloger, pkgcataloging.DeprecatedTag), // TODO: remove in syft v2.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func finalizeRelationships(resolver file.Resolver, builder sbomsync.Builder, cfg
|
||||
|
||||
// remove ELF packages and Binary packages that are already
|
||||
// represented by a source package (e.g. a package that is evident by some package manager)
|
||||
builder.DeletePackages(binary.PackagesToRemove(resolver, accessor)...)
|
||||
builder.DeletePackages(binary.PackagesToRemove(accessor)...)
|
||||
|
||||
// add relationships showing packages that are evident by a file which is owned by another package (package-to-package)
|
||||
if cfg.PackageFileOwnershipOverlap {
|
||||
|
||||
+152
-3
@@ -3,17 +3,19 @@ package task
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
||||
)
|
||||
|
||||
// Selection represents the users request for a subset of tasks to run and the resulting set of task names that were
|
||||
// selected. Additionally, all tokens that were matched on to reach the returned conclusion are also provided.
|
||||
type Selection struct {
|
||||
Request pkgcataloging.SelectionRequest
|
||||
Request cataloging.SelectionRequest
|
||||
Result *strset.Set
|
||||
TokensByTask map[string]TokenSelection
|
||||
}
|
||||
@@ -52,7 +54,18 @@ func newSelection() Selection {
|
||||
// Select parses the given expressions as two sets: expressions that represent a "set" operation, and expressions that
|
||||
// represent all other operations. The parsed expressions are then evaluated against the given tasks to return
|
||||
// a subset (or the same) set of tasks.
|
||||
func Select(allTasks []Task, selectionRequest pkgcataloging.SelectionRequest) ([]Task, Selection, error) {
|
||||
func Select(allTasks []Task, selectionRequest cataloging.SelectionRequest) ([]Task, Selection, error) {
|
||||
ensureDefaultSelectionHasFiles(&selectionRequest, allTasks)
|
||||
|
||||
return _select(allTasks, selectionRequest)
|
||||
}
|
||||
|
||||
func _select(allTasks []Task, selectionRequest cataloging.SelectionRequest) ([]Task, Selection, error) {
|
||||
if selectionRequest.IsEmpty() {
|
||||
selection := newSelection()
|
||||
selection.Request = selectionRequest
|
||||
return nil, selection, nil
|
||||
}
|
||||
nodes := newExpressionsFromSelectionRequest(newExpressionContext(allTasks), selectionRequest)
|
||||
|
||||
finalTasks, selection := selectByExpressions(allTasks, nodes)
|
||||
@@ -62,6 +75,142 @@ func Select(allTasks []Task, selectionRequest pkgcataloging.SelectionRequest) ([
|
||||
return finalTasks, selection, nodes.Validate()
|
||||
}
|
||||
|
||||
// ensureDefaultSelectionHasFiles ensures that the default selection request has the "file" tag, as this is a required
|
||||
// for backwards compatibility (when catalogers were only for packages and not for separate groups of tasks).
|
||||
func ensureDefaultSelectionHasFiles(selectionRequest *cataloging.SelectionRequest, allTasks ...[]Task) {
|
||||
for _, ts := range allTasks {
|
||||
_, leftOver := tagsOrNamesThatTaskGroupRespondsTo(ts, strset.New(filecataloging.FileTag))
|
||||
if leftOver.Has(filecataloging.FileTag) {
|
||||
// the given set of tasks do not respond to file, so don't include it in the default selection
|
||||
continue
|
||||
}
|
||||
|
||||
defaultNamesOrTags := strset.New(selectionRequest.DefaultNamesOrTags...)
|
||||
removals := strset.New(selectionRequest.RemoveNamesOrTags...)
|
||||
missingFileIshTag := !defaultNamesOrTags.Has(filecataloging.FileTag) && !defaultNamesOrTags.Has("all") && !defaultNamesOrTags.Has("default")
|
||||
if missingFileIshTag && !removals.Has(filecataloging.FileTag) {
|
||||
log.Warnf("adding '%s' tag to the default cataloger selection, to override add '-%s' to the cataloger selection request", filecataloging.FileTag, filecataloging.FileTag)
|
||||
selectionRequest.DefaultNamesOrTags = append(selectionRequest.DefaultNamesOrTags, filecataloging.FileTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SelectInGroups is a convenience function that allows for selecting tasks from multiple groups of tasks. The original
|
||||
// request is split into sub-requests, where only tokens that are relevant to the given group of tasks are considered.
|
||||
// If tokens are passed that are not relevant to any group of tasks, an error is returned.
|
||||
func SelectInGroups(taskGroups [][]Task, selectionRequest cataloging.SelectionRequest) ([][]Task, Selection, error) {
|
||||
ensureDefaultSelectionHasFiles(&selectionRequest, taskGroups...)
|
||||
|
||||
reqs, errs := splitCatalogerSelectionRequest(selectionRequest, taskGroups)
|
||||
if errs != nil {
|
||||
return nil, Selection{
|
||||
Request: selectionRequest,
|
||||
}, errs
|
||||
}
|
||||
|
||||
var finalTasks [][]Task
|
||||
var selections []Selection
|
||||
for idx, req := range reqs {
|
||||
tskGroup := taskGroups[idx]
|
||||
subFinalTasks, subSelection, err := _select(tskGroup, req)
|
||||
if err != nil {
|
||||
return nil, Selection{
|
||||
Request: selectionRequest,
|
||||
}, err
|
||||
}
|
||||
finalTasks = append(finalTasks, subFinalTasks)
|
||||
selections = append(selections, subSelection)
|
||||
}
|
||||
|
||||
return finalTasks, mergeSelections(selections, selectionRequest), nil
|
||||
}
|
||||
|
||||
func mergeSelections(selections []Selection, ogRequest cataloging.SelectionRequest) Selection {
|
||||
finalSelection := newSelection()
|
||||
for _, s := range selections {
|
||||
finalSelection.Result.Add(s.Result.List()...)
|
||||
for name, tokenSelection := range s.TokensByTask {
|
||||
if existing, exists := finalSelection.TokensByTask[name]; exists {
|
||||
existing.merge(tokenSelection)
|
||||
finalSelection.TokensByTask[name] = existing
|
||||
} else {
|
||||
finalSelection.TokensByTask[name] = tokenSelection
|
||||
}
|
||||
}
|
||||
}
|
||||
finalSelection.Request = ogRequest
|
||||
return finalSelection
|
||||
}
|
||||
|
||||
func splitCatalogerSelectionRequest(req cataloging.SelectionRequest, selectablePkgTaskGroups [][]Task) ([]cataloging.SelectionRequest, error) {
|
||||
requestTagsOrNames := allRequestReferences(req)
|
||||
leftoverTags := strset.New()
|
||||
usedTagsAndNames := strset.New()
|
||||
var usedTagGroups []*strset.Set
|
||||
for _, taskGroup := range selectablePkgTaskGroups {
|
||||
selectedTagOrNames, remainingTagsOrNames := tagsOrNamesThatTaskGroupRespondsTo(taskGroup, requestTagsOrNames)
|
||||
leftoverTags = strset.Union(leftoverTags, remainingTagsOrNames)
|
||||
usedTagGroups = append(usedTagGroups, selectedTagOrNames)
|
||||
usedTagsAndNames.Add(selectedTagOrNames.List()...)
|
||||
}
|
||||
|
||||
leftoverTags = strset.Difference(leftoverTags, usedTagsAndNames)
|
||||
leftoverTags.Remove("all")
|
||||
|
||||
if leftoverTags.Size() > 0 {
|
||||
l := leftoverTags.List()
|
||||
sort.Strings(l)
|
||||
return nil, fmt.Errorf("no cataloger tasks respond to the following selections: %v", strings.Join(l, ", "))
|
||||
}
|
||||
|
||||
var newSelections []cataloging.SelectionRequest
|
||||
for _, tags := range usedTagGroups {
|
||||
newSelections = append(newSelections, newSelectionWithTags(req, tags))
|
||||
}
|
||||
|
||||
return newSelections, nil
|
||||
}
|
||||
|
||||
func newSelectionWithTags(req cataloging.SelectionRequest, tags *strset.Set) cataloging.SelectionRequest {
|
||||
return cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: filterTags(req.DefaultNamesOrTags, tags),
|
||||
SubSelectTags: filterTags(req.SubSelectTags, tags),
|
||||
AddNames: filterTags(req.AddNames, tags),
|
||||
RemoveNamesOrTags: filterTags(req.RemoveNamesOrTags, tags),
|
||||
}
|
||||
}
|
||||
|
||||
func filterTags(reqTags []string, filterTags *strset.Set) []string {
|
||||
var filtered []string
|
||||
for _, tag := range reqTags {
|
||||
if filterTags.Has(tag) {
|
||||
filtered = append(filtered, tag)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
func tagsOrNamesThatTaskGroupRespondsTo(tasks []Task, requestTagsOrNames *strset.Set) (*strset.Set, *strset.Set) {
|
||||
positiveRefs := strset.New()
|
||||
for _, t := range tasks {
|
||||
if sel, ok := t.(Selector); ok {
|
||||
positiveRefs.Add("all") // everything responds to "all"
|
||||
positiveRefs.Add(strset.Intersection(requestTagsOrNames, strset.New(sel.Selectors()...)).List()...)
|
||||
}
|
||||
positiveRefs.Add(t.Name())
|
||||
}
|
||||
return positiveRefs, strset.Difference(requestTagsOrNames, positiveRefs)
|
||||
}
|
||||
|
||||
func allRequestReferences(s cataloging.SelectionRequest) *strset.Set {
|
||||
st := strset.New()
|
||||
st.Add(s.DefaultNamesOrTags...)
|
||||
st.Add(s.SubSelectTags...)
|
||||
st.Add(s.AddNames...)
|
||||
st.Add(s.RemoveNamesOrTags...)
|
||||
return st
|
||||
}
|
||||
|
||||
// selectByExpressions the set of tasks to run based on the given expression(s).
|
||||
func selectByExpressions(ts tasks, nodes Expressions) (tasks, Selection) {
|
||||
if len(nodes) == 0 {
|
||||
|
||||
+459
-41
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
@@ -21,45 +21,54 @@ func dummyTask(name string, tags ...string) Task {
|
||||
}
|
||||
|
||||
// note: this test fixture does not need to be kept up to date here, but makes a great test subject
|
||||
func createDummyTasks() tasks {
|
||||
func createDummyPackageTasks() tasks {
|
||||
return []Task{
|
||||
// OS package installed catalogers
|
||||
dummyTask("alpm-db-cataloger", "directory", "installed", "image", "os", "alpm", "archlinux"),
|
||||
dummyTask("apk-db-cataloger", "directory", "installed", "image", "os", "apk", "alpine"),
|
||||
dummyTask("dpkg-db-cataloger", "directory", "installed", "image", "os", "dpkg", "debian"),
|
||||
dummyTask("portage-cataloger", "directory", "installed", "image", "os", "portage", "gentoo"),
|
||||
dummyTask("rpm-db-cataloger", "directory", "installed", "image", "os", "rpm", "redhat"),
|
||||
dummyTask("alpm-db-cataloger", "package", "directory", "installed", "image", "os", "alpm", "archlinux"),
|
||||
dummyTask("apk-db-cataloger", "package", "directory", "installed", "image", "os", "apk", "alpine"),
|
||||
dummyTask("dpkg-db-cataloger", "package", "directory", "installed", "image", "os", "dpkg", "debian"),
|
||||
dummyTask("portage-cataloger", "package", "directory", "installed", "image", "os", "portage", "gentoo"),
|
||||
dummyTask("rpm-db-cataloger", "package", "directory", "installed", "image", "os", "rpm", "redhat"),
|
||||
|
||||
// OS package declared catalogers
|
||||
dummyTask("rpm-archive-cataloger", "declared", "directory", "os", "rpm", "redhat"),
|
||||
dummyTask("rpm-archive-cataloger", "package", "declared", "directory", "os", "rpm", "redhat"),
|
||||
|
||||
// language-specific package installed catalogers
|
||||
dummyTask("conan-info-cataloger", "installed", "image", "language", "cpp", "conan"),
|
||||
dummyTask("javascript-package-cataloger", "installed", "image", "language", "javascript", "node"),
|
||||
dummyTask("php-composer-installed-cataloger", "installed", "image", "language", "php", "composer"),
|
||||
dummyTask("ruby-installed-gemspec-cataloger", "installed", "image", "language", "ruby", "gem", "gemspec"),
|
||||
dummyTask("rust-cargo-lock-cataloger", "installed", "image", "language", "rust", "binary"),
|
||||
dummyTask("conan-info-cataloger", "package", "installed", "image", "language", "cpp", "conan"),
|
||||
dummyTask("javascript-package-cataloger", "package", "installed", "image", "language", "javascript", "node"),
|
||||
dummyTask("php-composer-installed-cataloger", "package", "installed", "image", "language", "php", "composer"),
|
||||
dummyTask("ruby-installed-gemspec-cataloger", "package", "installed", "image", "language", "ruby", "gem", "gemspec"),
|
||||
dummyTask("rust-cargo-lock-cataloger", "package", "installed", "image", "language", "rust", "binary"),
|
||||
|
||||
// language-specific package declared catalogers
|
||||
dummyTask("conan-cataloger", "declared", "directory", "language", "cpp", "conan"),
|
||||
dummyTask("dart-pubspec-lock-cataloger", "declared", "directory", "language", "dart"),
|
||||
dummyTask("dotnet-deps-cataloger", "declared", "directory", "language", "dotnet", "c#"),
|
||||
dummyTask("elixir-mix-lock-cataloger", "declared", "directory", "language", "elixir"),
|
||||
dummyTask("erlang-rebar-lock-cataloger", "declared", "directory", "language", "erlang"),
|
||||
dummyTask("javascript-lock-cataloger", "declared", "directory", "language", "javascript", "node", "npm"),
|
||||
dummyTask("conan-cataloger", "package", "declared", "directory", "language", "cpp", "conan"),
|
||||
dummyTask("dart-pubspec-lock-cataloger", "package", "declared", "directory", "language", "dart"),
|
||||
dummyTask("dotnet-deps-cataloger", "package", "declared", "directory", "language", "dotnet", "c#"),
|
||||
dummyTask("elixir-mix-lock-cataloger", "package", "declared", "directory", "language", "elixir"),
|
||||
dummyTask("erlang-rebar-lock-cataloger", "package", "declared", "directory", "language", "erlang"),
|
||||
dummyTask("javascript-lock-cataloger", "package", "declared", "directory", "language", "javascript", "node", "npm"),
|
||||
|
||||
// language-specific package for both image and directory scans (but not necessarily declared)
|
||||
dummyTask("dotnet-portable-executable-cataloger", "directory", "installed", "image", "language", "dotnet", "c#"),
|
||||
dummyTask("python-installed-package-cataloger", "directory", "installed", "image", "language", "python"),
|
||||
dummyTask("go-module-binary-cataloger", "directory", "installed", "image", "language", "go", "golang", "gomod", "binary"),
|
||||
dummyTask("java-archive-cataloger", "directory", "installed", "image", "language", "java", "maven"),
|
||||
dummyTask("graalvm-native-image-cataloger", "directory", "installed", "image", "language", "java"),
|
||||
dummyTask("dotnet-portable-executable-cataloger", "package", "directory", "installed", "image", "language", "dotnet", "c#"),
|
||||
dummyTask("python-installed-package-cataloger", "package", "directory", "installed", "image", "language", "python"),
|
||||
dummyTask("go-module-binary-cataloger", "package", "directory", "installed", "image", "language", "go", "golang", "gomod", "binary"),
|
||||
dummyTask("java-archive-cataloger", "package", "directory", "installed", "image", "language", "java", "maven"),
|
||||
dummyTask("graalvm-native-image-cataloger", "package", "directory", "installed", "image", "language", "java"),
|
||||
|
||||
// other package catalogers
|
||||
dummyTask("binary-cataloger", "declared", "directory", "image", "binary"),
|
||||
dummyTask("github-actions-usage-cataloger", "declared", "directory", "github", "github-actions"),
|
||||
dummyTask("github-action-workflow-usage-cataloger", "declared", "directory", "github", "github-actions"),
|
||||
dummyTask("sbom-cataloger", "declared", "directory", "image", "sbom"),
|
||||
dummyTask("binary-cataloger", "package", "declared", "directory", "image", "binary"),
|
||||
dummyTask("github-actions-usage-cataloger", "package", "declared", "directory", "github", "github-actions"),
|
||||
dummyTask("github-action-workflow-usage-cataloger", "package", "declared", "directory", "github", "github-actions"),
|
||||
dummyTask("sbom-cataloger", "package", "declared", "directory", "image", "sbom"),
|
||||
}
|
||||
}
|
||||
|
||||
func createDummyFileTasks() tasks {
|
||||
return []Task{
|
||||
dummyTask("file-content-cataloger", "file", "content"),
|
||||
dummyTask("file-metadata-cataloger", "file", "metadata"),
|
||||
dummyTask("file-digest-cataloger", "file", "digest"),
|
||||
dummyTask("file-executable-cataloger", "file", "binary-metadata"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +81,7 @@ func TestSelect(t *testing.T) {
|
||||
expressions []string
|
||||
wantNames []string
|
||||
wantTokens map[string]TokenSelection
|
||||
wantRequest pkgcataloging.SelectionRequest
|
||||
wantRequest cataloging.SelectionRequest
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
@@ -82,11 +91,11 @@ func TestSelect(t *testing.T) {
|
||||
expressions: []string{},
|
||||
wantNames: []string{},
|
||||
wantTokens: map[string]TokenSelection{},
|
||||
wantRequest: pkgcataloging.SelectionRequest{},
|
||||
wantRequest: cataloging.SelectionRequest{},
|
||||
},
|
||||
{
|
||||
name: "use default tasks",
|
||||
allTasks: createDummyTasks(),
|
||||
allTasks: createDummyPackageTasks(),
|
||||
basis: []string{
|
||||
"image",
|
||||
},
|
||||
@@ -129,13 +138,13 @@ func TestSelect(t *testing.T) {
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
},
|
||||
wantRequest: pkgcataloging.SelectionRequest{
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "select, add, and remove tasks",
|
||||
allTasks: createDummyTasks(),
|
||||
allTasks: createDummyPackageTasks(),
|
||||
basis: []string{
|
||||
"image",
|
||||
},
|
||||
@@ -175,7 +184,7 @@ func TestSelect(t *testing.T) {
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
},
|
||||
wantRequest: pkgcataloging.SelectionRequest{
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image"},
|
||||
SubSelectTags: []string{"os"},
|
||||
RemoveNamesOrTags: []string{"dpkg"},
|
||||
@@ -184,7 +193,7 @@ func TestSelect(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "allow for partial selections",
|
||||
allTasks: createDummyTasks(),
|
||||
allTasks: createDummyPackageTasks(),
|
||||
basis: []string{
|
||||
"image",
|
||||
},
|
||||
@@ -228,7 +237,7 @@ func TestSelect(t *testing.T) {
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
},
|
||||
wantRequest: pkgcataloging.SelectionRequest{
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image"},
|
||||
SubSelectTags: []string{"os", "rust-cargo-lock-cataloger"},
|
||||
RemoveNamesOrTags: []string{"dpkg"},
|
||||
@@ -238,7 +247,7 @@ func TestSelect(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "select all tasks",
|
||||
allTasks: createDummyTasks(),
|
||||
allTasks: createDummyPackageTasks(),
|
||||
basis: []string{
|
||||
"all",
|
||||
},
|
||||
@@ -299,13 +308,13 @@ func TestSelect(t *testing.T) {
|
||||
"github-action-workflow-usage-cataloger": newTokenSelection([]string{"all"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"all"}, nil),
|
||||
},
|
||||
wantRequest: pkgcataloging.SelectionRequest{
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"all"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set default with multiple tags",
|
||||
allTasks: createDummyTasks(),
|
||||
allTasks: createDummyPackageTasks(),
|
||||
basis: []string{
|
||||
"gemspec",
|
||||
"python",
|
||||
@@ -319,10 +328,31 @@ func TestSelect(t *testing.T) {
|
||||
"ruby-installed-gemspec-cataloger": newTokenSelection([]string{"gemspec"}, nil),
|
||||
"python-installed-package-cataloger": newTokenSelection([]string{"python"}, nil),
|
||||
},
|
||||
wantRequest: pkgcataloging.SelectionRequest{
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"gemspec", "python"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "automatically add file to default tags",
|
||||
allTasks: createDummyFileTasks(),
|
||||
basis: []string{},
|
||||
expressions: []string{},
|
||||
wantNames: []string{
|
||||
"file-content-cataloger",
|
||||
"file-metadata-cataloger",
|
||||
"file-digest-cataloger",
|
||||
"file-executable-cataloger",
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
"file-content-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"file"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -330,7 +360,7 @@ func TestSelect(t *testing.T) {
|
||||
tt.wantErr = assert.NoError
|
||||
}
|
||||
|
||||
req := pkgcataloging.NewSelectionRequest().WithDefaults(tt.basis...).WithExpression(tt.expressions...)
|
||||
req := cataloging.NewSelectionRequest().WithDefaults(tt.basis...).WithExpression(tt.expressions...)
|
||||
|
||||
got, gotEvidence, err := Select(tt.allTasks, req)
|
||||
tt.wantErr(t, err)
|
||||
@@ -367,3 +397,391 @@ func TestSelect(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectInGroups(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
taskGroups [][]Task
|
||||
selectionReq cataloging.SelectionRequest
|
||||
wantGroups [][]string
|
||||
wantTokens map[string]TokenSelection
|
||||
wantRequest cataloging.SelectionRequest
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "select only within the file tasks (leave package tasks alone)",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().
|
||||
WithDefaults("image"). // note: file missing
|
||||
WithSubSelections("content", "digest"),
|
||||
wantGroups: [][]string{
|
||||
{
|
||||
// this is the original, untouched package task list
|
||||
"alpm-db-cataloger",
|
||||
"apk-db-cataloger",
|
||||
"dpkg-db-cataloger",
|
||||
"portage-cataloger",
|
||||
"rpm-db-cataloger",
|
||||
"conan-info-cataloger",
|
||||
"javascript-package-cataloger",
|
||||
"php-composer-installed-cataloger",
|
||||
"ruby-installed-gemspec-cataloger",
|
||||
"rust-cargo-lock-cataloger",
|
||||
"dotnet-portable-executable-cataloger",
|
||||
"python-installed-package-cataloger",
|
||||
"go-module-binary-cataloger",
|
||||
"java-archive-cataloger",
|
||||
"graalvm-native-image-cataloger",
|
||||
"binary-cataloger",
|
||||
"sbom-cataloger",
|
||||
},
|
||||
{
|
||||
// this has been filtered based on the request
|
||||
"file-content-cataloger",
|
||||
"file-digest-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// packages
|
||||
"alpm-db-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"apk-db-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"conan-info-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"dotnet-portable-executable-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"dpkg-db-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"go-module-binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"graalvm-native-image-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"java-archive-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"javascript-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"php-composer-installed-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"portage-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"python-installed-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"rpm-db-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"ruby-installed-gemspec-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"rust-cargo-lock-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
// files
|
||||
"file-content-cataloger": newTokenSelection([]string{"content", "file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"digest", "file"}, nil),
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image", "file"}, // note: file automatically added
|
||||
SubSelectTags: []string{"content", "digest"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "select package tasks (leave file tasks alone)",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().WithDefaults("image").WithSubSelections("os"),
|
||||
wantGroups: [][]string{
|
||||
{
|
||||
// filtered based on the request
|
||||
"alpm-db-cataloger",
|
||||
"apk-db-cataloger",
|
||||
"dpkg-db-cataloger",
|
||||
"portage-cataloger",
|
||||
"rpm-db-cataloger",
|
||||
},
|
||||
{
|
||||
// this is the original, untouched file task list
|
||||
"file-content-cataloger",
|
||||
"file-metadata-cataloger",
|
||||
"file-digest-cataloger",
|
||||
"file-executable-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// packages - os
|
||||
"alpm-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"apk-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"rpm-archive-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"rpm-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"portage-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"dpkg-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
// packages - remaining
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"conan-info-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"dotnet-portable-executable-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"go-module-binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"graalvm-native-image-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"java-archive-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"javascript-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"php-composer-installed-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"python-installed-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"ruby-installed-gemspec-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"rust-cargo-lock-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
// files
|
||||
"file-content-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image", "file"},
|
||||
SubSelectTags: []string{"os"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "select only file tasks (default)",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().WithDefaults("file"),
|
||||
wantGroups: [][]string{
|
||||
// filtered based on the request
|
||||
nil,
|
||||
{
|
||||
// this is the original, untouched file task list
|
||||
"file-content-cataloger",
|
||||
"file-metadata-cataloger",
|
||||
"file-digest-cataloger",
|
||||
"file-executable-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// files
|
||||
"file-content-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"file"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "select only file tasks (via removal of package)",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().WithDefaults("file", "image").WithRemovals("package"),
|
||||
wantGroups: [][]string{
|
||||
// filtered based on the request
|
||||
nil,
|
||||
{
|
||||
// this is the original, untouched file task list
|
||||
"file-content-cataloger",
|
||||
"file-metadata-cataloger",
|
||||
"file-digest-cataloger",
|
||||
"file-executable-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// packages
|
||||
"alpm-db-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"apk-db-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"conan-info-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"dotnet-portable-executable-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"dpkg-db-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"go-module-binary-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"graalvm-native-image-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"java-archive-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"javascript-package-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"php-composer-installed-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"portage-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"python-installed-package-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"rpm-db-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"ruby-installed-gemspec-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"rust-cargo-lock-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, []string{"package"}),
|
||||
"rpm-archive-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"conan-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"dart-pubspec-lock-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"dotnet-deps-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"elixir-mix-lock-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"erlang-rebar-lock-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"javascript-lock-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"github-actions-usage-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
"github-action-workflow-usage-cataloger": newTokenSelection(nil, []string{"package"}),
|
||||
// files
|
||||
"file-content-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"file", "image"},
|
||||
RemoveNamesOrTags: []string{"package"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "select file and package tasks",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().
|
||||
WithDefaults("image").
|
||||
WithSubSelections("os", "content", "digest"),
|
||||
wantGroups: [][]string{
|
||||
{
|
||||
// filtered based on the request
|
||||
"alpm-db-cataloger",
|
||||
"apk-db-cataloger",
|
||||
"dpkg-db-cataloger",
|
||||
"portage-cataloger",
|
||||
"rpm-db-cataloger",
|
||||
},
|
||||
{
|
||||
// filtered based on the request
|
||||
"file-content-cataloger",
|
||||
"file-digest-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// packages - os
|
||||
"alpm-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"apk-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"rpm-archive-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"rpm-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"portage-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
"dpkg-db-cataloger": newTokenSelection([]string{"os", "image"}, nil),
|
||||
// packages - remaining
|
||||
"binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"conan-info-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"dotnet-portable-executable-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"go-module-binary-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"graalvm-native-image-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"java-archive-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"javascript-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"php-composer-installed-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"python-installed-package-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"ruby-installed-gemspec-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"rust-cargo-lock-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
"sbom-cataloger": newTokenSelection([]string{"image"}, nil),
|
||||
// files
|
||||
"file-content-cataloger": newTokenSelection([]string{"file", "content"}, nil), // note extra tags
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file", "digest"}, nil), // note extra tags
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"image", "file"},
|
||||
SubSelectTags: []string{"os", "content", "digest"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "complex selection with multiple operators across groups",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().
|
||||
WithDefaults("os"). // note: no file tag present
|
||||
WithExpression("+github-actions-usage-cataloger", "-dpkg", "-digest", "content", "+file-metadata-cataloger", "-declared"),
|
||||
wantGroups: [][]string{
|
||||
{
|
||||
"alpm-db-cataloger",
|
||||
"apk-db-cataloger",
|
||||
"portage-cataloger",
|
||||
"rpm-db-cataloger",
|
||||
"github-actions-usage-cataloger",
|
||||
},
|
||||
{
|
||||
"file-content-cataloger",
|
||||
"file-metadata-cataloger",
|
||||
},
|
||||
},
|
||||
wantTokens: map[string]TokenSelection{
|
||||
// selected package tasks
|
||||
"alpm-db-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"apk-db-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"dpkg-db-cataloger": newTokenSelection([]string{"os"}, []string{"dpkg"}),
|
||||
"portage-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"rpm-archive-cataloger": newTokenSelection([]string{"os"}, []string{"declared"}),
|
||||
"rpm-db-cataloger": newTokenSelection([]string{"os"}, nil),
|
||||
"github-actions-usage-cataloger": newTokenSelection([]string{"github-actions-usage-cataloger"}, []string{"declared"}),
|
||||
|
||||
// selected file tasks
|
||||
"file-content-cataloger": newTokenSelection([]string{"content", "file"}, nil),
|
||||
"file-metadata-cataloger": newTokenSelection([]string{"file-metadata-cataloger", "file"}, nil),
|
||||
|
||||
// removed package tasks
|
||||
"binary-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"conan-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"dart-pubspec-lock-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"dotnet-deps-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"elixir-mix-lock-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"erlang-rebar-lock-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"github-action-workflow-usage-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"javascript-lock-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
"sbom-cataloger": newTokenSelection(nil, []string{"declared"}),
|
||||
|
||||
// removed file tasks
|
||||
"file-executable-cataloger": newTokenSelection([]string{"file"}, nil),
|
||||
"file-digest-cataloger": newTokenSelection([]string{"file"}, []string{"digest"}),
|
||||
},
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"os", "file"}, // note: file added automatically
|
||||
SubSelectTags: []string{"content"},
|
||||
RemoveNamesOrTags: []string{"dpkg", "digest", "declared"},
|
||||
AddNames: []string{"github-actions-usage-cataloger", "file-metadata-cataloger"},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid tag",
|
||||
taskGroups: [][]Task{
|
||||
createDummyPackageTasks(),
|
||||
createDummyFileTasks(),
|
||||
},
|
||||
selectionReq: cataloging.NewSelectionRequest().WithDefaults("invalid"),
|
||||
wantGroups: nil,
|
||||
wantTokens: nil,
|
||||
wantRequest: cataloging.SelectionRequest{
|
||||
DefaultNamesOrTags: []string{"invalid", "file"},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr == nil {
|
||||
tt.wantErr = assert.NoError
|
||||
}
|
||||
|
||||
gotGroups, gotSelection, err := SelectInGroups(tt.taskGroups, tt.selectionReq)
|
||||
tt.wantErr(t, err)
|
||||
if err != nil {
|
||||
// dev note: this is useful for debugging when needed...
|
||||
//for _, e := range gotEvidence.Request.Expressions {
|
||||
// t.Logf("expression (errors %q): %#v", e.Errors, e)
|
||||
//}
|
||||
|
||||
// note: we DON'T bail early in validations... this is because we should always return the full set of
|
||||
// of selected tasks and surrounding evidence.
|
||||
}
|
||||
|
||||
var gotGroupNames [][]string
|
||||
for _, group := range gotGroups {
|
||||
var names []string
|
||||
for _, task := range group {
|
||||
names = append(names, task.Name())
|
||||
}
|
||||
gotGroupNames = append(gotGroupNames, names)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.wantGroups, gotGroupNames)
|
||||
assert.Equal(t, tt.wantTokens, gotSelection.TokensByTask)
|
||||
assert.Equal(t, tt.wantRequest, gotSelection.Request)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func ProcessPathErrors(err error) error {
|
||||
}
|
||||
}
|
||||
unknowns, remainingErrors := ExtractCoordinateErrors(err)
|
||||
log.Warn(remainingErrors)
|
||||
log.Debug(remainingErrors)
|
||||
|
||||
var out []error
|
||||
for _, u := range unknowns {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "anchore.io/schema/syft/json/16.0.19/document",
|
||||
"$id": "anchore.io/schema/syft/json/16.0.24/document",
|
||||
"$ref": "#/$defs/Document",
|
||||
"$defs": {
|
||||
"AlpmDbEntry": {
|
||||
@@ -218,6 +218,44 @@
|
||||
"matches"
|
||||
]
|
||||
},
|
||||
"BitnamiSbomEntry": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"arch": {
|
||||
"type": "string"
|
||||
},
|
||||
"distro": {
|
||||
"type": "string"
|
||||
},
|
||||
"revision": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"arch",
|
||||
"distro",
|
||||
"revision",
|
||||
"version",
|
||||
"path",
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"CConanFileEntry": {
|
||||
"properties": {
|
||||
"ref": {
|
||||
@@ -481,6 +519,14 @@
|
||||
},
|
||||
"hashPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"executables": {
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
"$ref": "#/$defs/DotnetPortableExecutableEntry"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -548,6 +594,66 @@
|
||||
"productVersion"
|
||||
]
|
||||
},
|
||||
"DpkgArchiveEntry": {
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"sourceVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"architecture": {
|
||||
"type": "string"
|
||||
},
|
||||
"maintainer": {
|
||||
"type": "string"
|
||||
},
|
||||
"installedSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"provides": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"depends": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"preDepends": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/DpkgFileRecord"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"package",
|
||||
"source",
|
||||
"version",
|
||||
"sourceVersion",
|
||||
"architecture",
|
||||
"maintainer",
|
||||
"installedSize",
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"DpkgDbEntry": {
|
||||
"properties": {
|
||||
"package": {
|
||||
@@ -1288,6 +1394,9 @@
|
||||
"$ref": "#/$defs/Location"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"contents": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -1650,6 +1759,9 @@
|
||||
{
|
||||
"$ref": "#/$defs/BinarySignature"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/BitnamiSbomEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/CConanFileEntry"
|
||||
},
|
||||
@@ -1677,6 +1789,9 @@
|
||||
{
|
||||
"$ref": "#/$defs/DotnetPortableExecutableEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/DpkgArchiveEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/DpkgDbEntry"
|
||||
},
|
||||
@@ -1782,6 +1897,9 @@
|
||||
{
|
||||
"$ref": "#/$defs/SwiplpackPackage"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/TerraformLockProviderEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/WordpressPluginEntry"
|
||||
}
|
||||
@@ -2720,6 +2838,32 @@
|
||||
"dependencies"
|
||||
]
|
||||
},
|
||||
"TerraformLockProviderEntry": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"constraints": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"hashes": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url",
|
||||
"constraints",
|
||||
"version",
|
||||
"hashes"
|
||||
]
|
||||
},
|
||||
"WordpressPluginEntry": {
|
||||
"properties": {
|
||||
"pluginInstallDirectory": {
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ package artifact
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/gohugoio/hashstructure"
|
||||
)
|
||||
|
||||
// ID represents a unique value for each package added to a package catalog.
|
||||
@@ -14,7 +14,7 @@ type Identifiable interface {
|
||||
}
|
||||
|
||||
func IDByHash(obj interface{}) (ID, error) {
|
||||
f, err := hashstructure.Hash(obj, hashstructure.FormatV2, &hashstructure.HashOptions{
|
||||
f, err := hashstructure.Hash(obj, &hashstructure.HashOptions{
|
||||
ZeroNil: true,
|
||||
SlicesAsSets: true,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package cataloging
|
||||
|
||||
// ExecutorCPU is the name to use when executing parallel functions which are CPU-intensive, such as
|
||||
// hashing full files
|
||||
const ExecutorCPU = "cpu"
|
||||
|
||||
// ExecutorFile is the name to use when executing parallel file reading functions, such as cataloging
|
||||
const ExecutorFile = "file"
|
||||
@@ -0,0 +1,6 @@
|
||||
package filecataloging
|
||||
|
||||
const (
|
||||
// FileTag should be used to identify catalogers that primarily discover information about files (as opposed to packages).
|
||||
FileTag = "file"
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package cataloging
|
||||
|
||||
import "github.com/anchore/syft/internal/licenses"
|
||||
|
||||
type LicenseConfig struct {
|
||||
IncludeUnkownLicenseContent bool `json:"include-unknown-license-content" yaml:"include-unknown-license-content" mapstructure:"include-unknown-license-content"`
|
||||
Coverage float64 `json:"coverage" yaml:"coverage" mapstructure:"coverage"`
|
||||
}
|
||||
|
||||
func DefaultLicenseConfig() LicenseConfig {
|
||||
return LicenseConfig{
|
||||
IncludeUnkownLicenseContent: licenses.DefaultIncludeLicenseContent,
|
||||
Coverage: licenses.DefaultCoverageThreshold,
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user