feat: add dependency information to conan lockfile parser (#2131)

Signed-off-by: Stefan Profanter <stefan.profanter@agile-robots.com>
This commit is contained in:
Stefan Profanter 2023-09-15 20:31:08 +02:00 committed by GitHub
parent 094b41b301
commit ec4d595920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 2366 additions and 49 deletions

View File

@ -3,5 +3,5 @@ package internal
const ( const (
// JSONSchemaVersion is the current schema version output by the JSON encoder // 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. // 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 = "10.0.2" JSONSchemaVersion = "11.0.0"
) )

File diff suppressed because it is too large Load Diff

View File

@ -36,12 +36,24 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
if err := json.NewDecoder(reader).Decode(&cl); err != nil { if err := json.NewDecoder(reader).Decode(&cl); err != nil {
return nil, nil, err return nil, nil, err
} }
for _, node := range cl.GraphLock.Nodes {
// requires is a list of package indices. We first need to fill it, and then we can resolve the package
// in a second iteration
var indexToPkgMap = map[string]pkg.Package{}
// we do not want to store the index list requires in the conan metadata, because it is not useful to have it in
// the SBOM. Instead, we will store it in a map and then use it to build the relationships
// maps pkg.ID to a list of indices
var parsedPkgRequires = map[artifact.ID][]string{}
for idx, node := range cl.GraphLock.Nodes {
metadata := pkg.ConanLockMetadata{ metadata := pkg.ConanLockMetadata{
Ref: node.Ref, Ref: node.Ref,
Options: parseOptions(node.Options), Options: parseOptions(node.Options),
Path: node.Path, Path: node.Path,
Context: node.Context, Context: node.Context,
PackageID: node.PackageID,
Prev: node.Prev,
} }
p := newConanlockPackage( p := newConanlockPackage(
@ -50,11 +62,28 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
) )
if p != nil { if p != nil {
pkgs = append(pkgs, *p) pk := *p
pkgs = append(pkgs, pk)
parsedPkgRequires[pk.ID()] = node.Requires
indexToPkgMap[idx] = pk
} }
} }
return pkgs, nil, nil var relationships []artifact.Relationship
for _, p := range pkgs {
requires := parsedPkgRequires[p.ID()]
for _, r := range requires {
// this is a pkg that package "p" depends on... make a relationship
relationships = append(relationships, artifact.Relationship{
From: indexToPkgMap[r],
To: p,
Type: artifact.DependencyOfRelationship,
})
}
}
return pkgs, relationships, nil
} }
func parseOptions(options string) map[string]string { func parseOptions(options string) map[string]string {

View File

@ -13,56 +13,296 @@ func TestParseConanlock(t *testing.T) {
fixture := "test-fixtures/conan.lock" fixture := "test-fixtures/conan.lock"
expected := []pkg.Package{ expected := []pkg.Package{
{ {
Name: "spdlog", Name: "mfast",
Version: "1.11.0", Version: "1.2.2",
PURL: "pkg:conan/spdlog@1.11.0", PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)), Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP, Language: pkg.CPP,
Type: pkg.ConanPkg, Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType, MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{ Metadata: pkg.ConanLockMetadata{
Ref: "spdlog/1.11.0", Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
Options: map[string]string{ Options: map[string]string{
"fPIC": "True", "fPIC": "True",
"header_only": "False", "shared": "False",
"no_exceptions": "False", "with_sqlite3": "False",
"shared": "False", "boost:addr2line_location": "/usr/bin/addr2line",
"wchar_filenames": "False", "boost:asio_no_deprecated": "False",
"wchar_support": "False", "boost:buildid": "None",
"fmt:fPIC": "True", "boost:bzip2": "True",
"fmt:header_only": "False", "boost:debug_level": "0",
"fmt:shared": "False", "boost:diagnostic_definitions": "False",
"fmt:with_fmt_alias": "False", "boost:error_code_header_only": "False",
"fmt:with_os_api": "True", "boost:extra_b2_flags": "None",
"boost:fPIC": "True",
"boost:filesystem_no_deprecated": "False",
"boost:header_only": "False",
"boost:i18n_backend": "deprecated",
"boost:i18n_backend_iconv": "libc",
"boost:i18n_backend_icu": "False",
"boost:layout": "system",
"boost:lzma": "False",
"boost:magic_autolink": "False",
"boost:multithreading": "True",
"boost:namespace": "boost",
"boost:namespace_alias": "False",
"boost:numa": "True",
"boost:pch": "True",
"boost:python_executable": "None",
"boost:python_version": "None",
"boost:segmented_stacks": "False",
"boost:shared": "False",
"boost:system_no_deprecated": "False",
"boost:system_use_utf8": "False",
"boost:visibility": "hidden",
"boost:with_stacktrace_backtrace": "True",
"boost:without_atomic": "False",
"boost:without_chrono": "False",
"boost:without_container": "False",
"boost:without_context": "False",
"boost:without_contract": "False",
"boost:without_coroutine": "False",
"boost:without_date_time": "False",
"boost:without_exception": "False",
"boost:without_fiber": "False",
"boost:without_filesystem": "False",
"boost:without_graph": "False",
"boost:without_graph_parallel": "True",
"boost:without_iostreams": "False",
"boost:without_json": "False",
"boost:without_locale": "False",
"boost:without_log": "False",
"boost:without_math": "False",
"boost:without_mpi": "True",
"boost:without_nowide": "False",
"boost:without_program_options": "False",
"boost:without_python": "True",
"boost:without_random": "False",
"boost:without_regex": "False",
"boost:without_serialization": "False",
"boost:without_stacktrace": "False",
"boost:without_system": "False",
"boost:without_test": "False",
"boost:without_thread": "False",
"boost:without_timer": "False",
"boost:without_type_erasure": "False",
"boost:without_wave": "False",
"boost:zlib": "True",
"boost:zstd": "False",
"bzip2:build_executable": "True",
"bzip2:fPIC": "True",
"bzip2:shared": "False",
"libbacktrace:fPIC": "True",
"libbacktrace:shared": "False",
"tinyxml2:fPIC": "True",
"tinyxml2:shared": "False",
"zlib:fPIC": "True",
"zlib:shared": "False",
}, },
Path: "conanfile.py", Context: "host",
Context: "host", PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac",
Prev: "0ca9799450422cc55a92ccc6ffd57fba",
}, },
}, },
{ {
Name: "fmt", Name: "boost",
Version: "9.1.0", Version: "1.75.0",
PURL: "pkg:conan/my_user/fmt@9.1.0?channel=my_channel", PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)), Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP, Language: pkg.CPP,
Type: pkg.ConanPkg, Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType, MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{ Metadata: pkg.ConanLockMetadata{
Ref: "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba", Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
Options: map[string]string{ Options: map[string]string{
"fPIC": "True", "addr2line_location": "/usr/bin/addr2line",
"header_only": "False", "asio_no_deprecated": "False",
"shared": "False", "buildid": "None",
"with_fmt_alias": "False", "bzip2": "True",
"with_os_api": "True", "debug_level": "0",
"diagnostic_definitions": "False",
"error_code_header_only": "False",
"extra_b2_flags": "None",
"fPIC": "True",
"filesystem_no_deprecated": "False",
"header_only": "False",
"i18n_backend": "deprecated",
"i18n_backend_iconv": "libc",
"i18n_backend_icu": "False",
"layout": "system",
"lzma": "False",
"magic_autolink": "False",
"multithreading": "True",
"namespace": "boost",
"namespace_alias": "False",
"numa": "True",
"pch": "True",
"python_executable": "None",
"python_version": "None",
"segmented_stacks": "False",
"shared": "False",
"system_no_deprecated": "False",
"system_use_utf8": "False",
"visibility": "hidden",
"with_stacktrace_backtrace": "True",
"without_atomic": "False",
"without_chrono": "False",
"without_container": "False",
"without_context": "False",
"without_contract": "False",
"without_coroutine": "False",
"without_date_time": "False",
"without_exception": "False",
"without_fiber": "False",
"without_filesystem": "False",
"without_graph": "False",
"without_graph_parallel": "True",
"without_iostreams": "False",
"without_json": "False",
"without_locale": "False",
"without_log": "False",
"without_math": "False",
"without_mpi": "True",
"without_nowide": "False",
"without_program_options": "False",
"without_python": "True",
"without_random": "False",
"without_regex": "False",
"without_serialization": "False",
"without_stacktrace": "False",
"without_system": "False",
"without_test": "False",
"without_thread": "False",
"without_timer": "False",
"without_type_erasure": "False",
"without_wave": "False",
"zlib": "True",
"zstd": "False",
"bzip2:build_executable": "True",
"bzip2:fPIC": "True",
"bzip2:shared": "False",
"libbacktrace:fPIC": "True",
"libbacktrace:shared": "False",
"zlib:fPIC": "True",
"zlib:shared": "False",
},
Context: "host",
PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
Prev: "b9d7912e6131dfa453c725593b36c808",
},
},
{
Name: "zlib",
Version: "1.2.12",
PURL: "pkg:conan/zlib@1.2.12",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
Prev: "7cd359d44f89ab08e33b5db75605002c",
},
},
{
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
Options: map[string]string{
"build_executable": "True",
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e",
Prev: "b746948bc999d6f17f52a1f76e729e80",
},
},
{
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
},
Context: "host",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
Prev: "98a976f017e894c27e9a158b807ec0c7",
},
},
{
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
MetadataType: pkg.ConanLockMetadataType,
Metadata: pkg.ConanLockMetadata{
Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
Options: map[string]string{
"fPIC": "True",
"shared": "False",
}, },
Context: "host", Context: "host",
// intentionally remove to test missing PackageID and Prev
// PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e",
// Prev: "548bb273d2980991baa519453d68e5cd",
}, },
}, },
} }
// TODO: relationships are not under test var expectedRelationships = []artifact.Relationship{
var expectedRelationships []artifact.Relationship {
From: expected[1], // boost
To: expected[0], // mfast
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[5], // tinyxml2
To: expected[0], // mfast
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[2], // zlib
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[3], // bzip2
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
{
From: expected[4], // libbacktrace
To: expected[1], // boost
Type: artifact.DependencyOfRelationship,
Data: nil,
},
}
pkgtest.TestFileParser(t, fixture, parseConanlock, expected, expectedRelationships) pkgtest.TestFileParser(t, fixture, parseConanlock, expected, expectedRelationships)
} }

View File

@ -0,0 +1,17 @@
# Conan test data
This folder contains the test data for the Conan package manager.
## conan.lock
The conan lock file is created in the following way.
We explicitly use a package which has dependencies, which in turn also have dependendencies.
This is necessary to verify that the dependency tree is properly parsed.
1. Use `conan lock create --reference "mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39"`
2. Manually modify the user and channel of mfast package, to be able to test that it is properly set in SBOM:
`sed -i 's|mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39|mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39|g' conan.lock`
3. Manually delete the package id and prev from tinyxml2 entry to test conan lock parsing if they are missing:
`sed -i 's|\"package_id\": \"6557f18ca99c0b6a233f43db00e30efaa525e27e\",||g' conan.lock`
`sed -i 's|\"prev\": \"548bb273d2980991baa519453d68e5cd\",||g' conan.lock`

View File

@ -1,20 +1,55 @@
{ {
"graph_lock": { "graph_lock": {
"nodes": { "nodes": {
"0": { "1": {
"ref": "spdlog/1.11.0", "ref": "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
"options": "fPIC=True\nheader_only=False\nno_exceptions=False\nshared=False\nwchar_filenames=False\nwchar_support=False\nfmt:fPIC=True\nfmt:header_only=False\nfmt:shared=False\nfmt:with_fmt_alias=False\nfmt:with_os_api=True", "options": "fPIC=True\nshared=False\nwith_sqlite3=False\nboost:addr2line_location=/usr/bin/addr2line\nboost:asio_no_deprecated=False\nboost:buildid=None\nboost:bzip2=True\nboost:debug_level=0\nboost:diagnostic_definitions=False\nboost:error_code_header_only=False\nboost:extra_b2_flags=None\nboost:fPIC=True\nboost:filesystem_no_deprecated=False\nboost:header_only=False\nboost:i18n_backend=deprecated\nboost:i18n_backend_iconv=libc\nboost:i18n_backend_icu=False\nboost:layout=system\nboost:lzma=False\nboost:magic_autolink=False\nboost:multithreading=True\nboost:namespace=boost\nboost:namespace_alias=False\nboost:numa=True\nboost:pch=True\nboost:python_executable=None\nboost:python_version=None\nboost:segmented_stacks=False\nboost:shared=False\nboost:system_no_deprecated=False\nboost:system_use_utf8=False\nboost:visibility=hidden\nboost:with_stacktrace_backtrace=True\nboost:without_atomic=False\nboost:without_chrono=False\nboost:without_container=False\nboost:without_context=False\nboost:without_contract=False\nboost:without_coroutine=False\nboost:without_date_time=False\nboost:without_exception=False\nboost:without_fiber=False\nboost:without_filesystem=False\nboost:without_graph=False\nboost:without_graph_parallel=True\nboost:without_iostreams=False\nboost:without_json=False\nboost:without_locale=False\nboost:without_log=False\nboost:without_math=False\nboost:without_mpi=True\nboost:without_nowide=False\nboost:without_program_options=False\nboost:without_python=True\nboost:without_random=False\nboost:without_regex=False\nboost:without_serialization=False\nboost:without_stacktrace=False\nboost:without_system=False\nboost:without_test=False\nboost:without_thread=False\nboost:without_timer=False\nboost:without_type_erasure=False\nboost:without_wave=False\nboost:zlib=True\nboost:zstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\ntinyxml2:fPIC=True\ntinyxml2:shared=False\nzlib:fPIC=True\nzlib:shared=False",
"package_id": "9d1f076b471417647c2022a78d5e2c1f834289ac",
"prev": "0ca9799450422cc55a92ccc6ffd57fba",
"requires": [ "requires": [
"1" "2",
"6"
], ],
"path": "conanfile.py",
"context": "host" "context": "host"
}, },
"1": { "2": {
"ref": "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba", "ref": "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
"options": "fPIC=True\nheader_only=False\nshared=False\nwith_fmt_alias=False\nwith_os_api=True", "options": "addr2line_location=/usr/bin/addr2line\nasio_no_deprecated=False\nbuildid=None\nbzip2=True\ndebug_level=0\ndiagnostic_definitions=False\nerror_code_header_only=False\nextra_b2_flags=None\nfPIC=True\nfilesystem_no_deprecated=False\nheader_only=False\ni18n_backend=deprecated\ni18n_backend_iconv=libc\ni18n_backend_icu=False\nlayout=system\nlzma=False\nmagic_autolink=False\nmultithreading=True\nnamespace=boost\nnamespace_alias=False\nnuma=True\npch=True\npython_executable=None\npython_version=None\nsegmented_stacks=False\nshared=False\nsystem_no_deprecated=False\nsystem_use_utf8=False\nvisibility=hidden\nwith_stacktrace_backtrace=True\nwithout_atomic=False\nwithout_chrono=False\nwithout_container=False\nwithout_context=False\nwithout_contract=False\nwithout_coroutine=False\nwithout_date_time=False\nwithout_exception=False\nwithout_fiber=False\nwithout_filesystem=False\nwithout_graph=False\nwithout_graph_parallel=True\nwithout_iostreams=False\nwithout_json=False\nwithout_locale=False\nwithout_log=False\nwithout_math=False\nwithout_mpi=True\nwithout_nowide=False\nwithout_program_options=False\nwithout_python=True\nwithout_random=False\nwithout_regex=False\nwithout_serialization=False\nwithout_stacktrace=False\nwithout_system=False\nwithout_test=False\nwithout_thread=False\nwithout_timer=False\nwithout_type_erasure=False\nwithout_wave=False\nzlib=True\nzstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\nzlib:fPIC=True\nzlib:shared=False",
"package_id": "2c09c8f84c016041549fcee94e4caae5d89424b6", "package_id": "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
"prev": "9f5ab13fc7c73e4a9f87e4e213f2cfa4", "prev": "b9d7912e6131dfa453c725593b36c808",
"requires": [
"3",
"4",
"5"
],
"context": "host"
},
"3": {
"ref": "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
"options": "fPIC=True\nshared=False",
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
"prev": "7cd359d44f89ab08e33b5db75605002c",
"context": "host"
},
"4": {
"ref": "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
"options": "build_executable=True\nfPIC=True\nshared=False",
"package_id": "c32092bf4d4bb47cf962af898e02823f499b017e",
"prev": "b746948bc999d6f17f52a1f76e729e80",
"context": "host"
},
"5": {
"ref": "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
"options": "fPIC=True\nshared=False",
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
"prev": "98a976f017e894c27e9a158b807ec0c7",
"context": "host"
},
"6": {
"ref": "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
"options": "fPIC=True\nshared=False",
"context": "host" "context": "host"
} }
}, },

View File

@ -1,7 +1,18 @@
github.com/CycloneDX/cyclonedx-go v0.6.0/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg=
github.com/CycloneDX/cyclonedx-go v0.7.0 h1:jNxp8hL7UpcvPDFXjY+Y1ibFtsW+e5zyF9QoSmhK/zg= github.com/CycloneDX/cyclonedx-go v0.7.0 h1:jNxp8hL7UpcvPDFXjY+Y1ibFtsW+e5zyF9QoSmhK/zg=
github.com/CycloneDX/cyclonedx-go v0.7.0/go.mod h1:W5Z9w8pTTL+t+yG3PCiFRGlr8PUlE0pGWzKSJbsyXkg= github.com/CycloneDX/cyclonedx-go v0.7.0/go.mod h1:W5Z9w8pTTL+t+yG3PCiFRGlr8PUlE0pGWzKSJbsyXkg=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= 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/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/bradleyjkemp/cupaloy/v2 v2.7.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= 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/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -11,9 +11,9 @@ type ConanLockMetadata struct {
Ref string `json:"ref"` Ref string `json:"ref"`
PackageID string `json:"package_id,omitempty"` PackageID string `json:"package_id,omitempty"`
Prev string `json:"prev,omitempty"` Prev string `json:"prev,omitempty"`
Requires string `json:"requires,omitempty"` Requires []string `json:"requires,omitempty"`
BuildRequires string `json:"build_requires,omitempty"` BuildRequires []string `json:"build_requires,omitempty"`
PythonRequires string `json:"py_requires,omitempty"` PythonRequires []string `json:"py_requires,omitempty"`
Options map[string]string `json:"options,omitempty"` Options map[string]string `json:"options,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Context string `json:"context,omitempty"` Context string `json:"context,omitempty"`