diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock.go b/syft/pkg/cataloger/rust/parse_cargo_lock.go index d800eec7a..79c6d07c1 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock.go @@ -3,14 +3,17 @@ package rust import ( "context" "fmt" + "strings" "github.com/pelletier/go-toml" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" + "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" ) var _ generic.Parser = parseCargoLock @@ -33,7 +36,6 @@ func parseCargoLock(_ context.Context, _ file.Resolver, _ *generic.Environment, } var pkgs []pkg.Package - pkgIndex := make(map[string]int) for _, p := range m.Packages { if p.Dependencies == nil { @@ -47,36 +49,42 @@ func parseCargoLock(_ context.Context, _ file.Resolver, _ *generic.Environment, pkgs, newPkg, ) - newIx := len(pkgs) - 1 - // Cargo.lock dependencies are strings that are the name of a package, if that - // is unambiguous, or a string like "name version" if the name alone is not - // ambiguous. Set both keys in the map, since we don't know which key is - // going to be used until we're trying to resolve dependencies. If the - // first key is overwritten, that means the package name was an ambiguous dependency - // and "name version" will be used as the key anyway. - keys := []string{ - newPkg.Name, - fmt.Sprintf("%s %s", newPkg.Name, newPkg.Version), - } - for _, k := range keys { - pkgIndex[k] = newIx - } - } - var relationships []artifact.Relationship - for _, p := range pkgs { - meta := p.Metadata.(pkg.RustCargoLockEntry) - for _, d := range meta.Dependencies { - i, ok := pkgIndex[d] - if !ok { - continue - } - relationships = append(relationships, artifact.Relationship{ - From: p, - To: pkgs[i], - Type: artifact.DependencyOfRelationship, - }) - } } - return pkgs, relationships, unknown.IfEmptyf(pkgs, "unable to determine packages") + return pkgs, dependency.Resolve(dependencySpecification, pkgs), unknown.IfEmptyf(pkgs, "unable to determine packages") +} + +func dependencySpecification(p pkg.Package) dependency.Specification { + rustMeta, ok := p.Metadata.(pkg.RustCargoLockEntry) + if !ok { + log.Tracef("cataloger failed to extract rust Cargo.lock metadata for package %+v", p.Name) + return dependency.Specification{} + } + + // Cargo.lock dependencies are strings that are the name of a package, if that + // is unambiguous, or a string like "name version" if the name alone is not + // ambiguous, or strings like "name version (source)" if "name version" is ambiguous. + // Provide all the strings, since we don't know which string will be used. + // In other words, each package "provides" 3 entries, one for each name format, + // and each package "requires" whatever it actually requires based on the Cargo.lock. + provides := []string{ + p.Name, + fmt.Sprintf("%s %s", p.Name, p.Version), + } + + if rustMeta.Source != "" { + src := rustMeta.Source + if strings.HasPrefix(src, "git") && strings.Contains(src, "#") { + src = strings.Split(src, "#")[0] + } + + provides = append(provides, fmt.Sprintf("%s %s (%s)", p.Name, p.Version, src)) + } + + return dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: rustMeta.Dependencies, + }, + } } diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go index 2d7d2b4b6..15313f55a 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go @@ -3,6 +3,8 @@ package rust import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -279,43 +281,43 @@ func TestParseCargoLock(t *testing.T) { expectedRelationships := []artifact.Relationship{ { - From: ansiTerm, + To: ansiTerm, + From: winapi, + Type: artifact.DependencyOfRelationship, + }, + { + To: errno, + From: windowsSys52, + Type: artifact.DependencyOfRelationship, + }, + { + To: nom, + From: memchr, + Type: artifact.DependencyOfRelationship, + }, + { + To: nom, + From: versionCheck, + Type: artifact.DependencyOfRelationship, + }, + { + To: schannel, + From: windowsSys59, + Type: artifact.DependencyOfRelationship, + }, + { + To: unicodeBidi, + From: matches, + Type: artifact.DependencyOfRelationship, + }, + { To: winapi, + From: winAPIi686PCWindowsGNU, Type: artifact.DependencyOfRelationship, }, { - From: errno, - To: windowsSys52, - Type: artifact.DependencyOfRelationship, - }, - { - From: nom, - To: memchr, - Type: artifact.DependencyOfRelationship, - }, - { - From: nom, - To: versionCheck, - Type: artifact.DependencyOfRelationship, - }, - { - From: schannel, - To: windowsSys59, - Type: artifact.DependencyOfRelationship, - }, - { - From: unicodeBidi, - To: matches, - Type: artifact.DependencyOfRelationship, - }, - { - From: winapi, - To: winAPIi686PCWindowsGNU, - Type: artifact.DependencyOfRelationship, - }, - { - From: winapi, - To: winAPIx8664PCWindowsGNU, + To: winapi, + From: winAPIx8664PCWindowsGNU, Type: artifact.DependencyOfRelationship, }, } @@ -323,6 +325,513 @@ func TestParseCargoLock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships) } +func TestCargoLockWithGitDependencies(t *testing.T) { + fixture := "test-fixtures/Cargo.lock-with-git-deps" + locations := file.NewLocationSet(file.NewLocation(fixture)) + + ahoCorasick := pkg.Package{ + Name: "aho-corasick", + Version: "1.1.3", + PURL: "pkg:cargo/aho-corasick@1.1.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "aho-corasick", + Version: "1.1.3", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916", + Dependencies: []string{ + "memchr", + }, + }, + } + + helloWorld := pkg.Package{ + Name: "hello_world", + Version: "0.1.0", + PURL: "pkg:cargo/hello_world@0.1.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "hello_world", + Version: "0.1.0", + Dependencies: []string{ + "nom-regex", + "regex 1.11.1 (git+https://github.com/rust-lang/regex.git)", + }, + }, + } + + memchr := pkg.Package{ + Name: "memchr", + Version: "2.7.4", + PURL: "pkg:cargo/memchr@2.7.4", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "memchr", + Version: "2.7.4", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3", + Dependencies: []string{}, + }, + } + + minimalLexical := pkg.Package{ + Name: "minimal-lexical", + Version: "0.2.1", + PURL: "pkg:cargo/minimal-lexical@0.2.1", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "minimal-lexical", + Version: "0.2.1", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a", + Dependencies: []string{}, + }, + } + + nom := pkg.Package{ + Name: "nom", + Version: "7.1.3", + PURL: "pkg:cargo/nom@7.1.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "nom", + Version: "7.1.3", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a", + Dependencies: []string{ + "memchr", + "minimal-lexical", + }, + }, + } + + nomRegex := pkg.Package{ + Name: "nom-regex", + Version: "0.2.0", + PURL: "pkg:cargo/nom-regex@0.2.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "nom-regex", + Version: "0.2.0", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "72e5c7731c4c1370b61604ed52a2475e861aac9e08dec9f23903d4ddfdc91c18", + Dependencies: []string{ + "nom", + "regex 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + }, + }, + } + + regexCrates := pkg.Package{ + Name: "regex", + Version: "1.11.1", + PURL: "pkg:cargo/regex@1.11.1", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex", + Version: "1.11.1", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-automata 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + }, + }, + } + + regexGit := pkg.Package{ + Name: "regex", + Version: "1.11.1", + PURL: "pkg:cargo/regex@1.11.1", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex", + Version: "1.11.1", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-automata 0.4.9 (git+https://github.com/rust-lang/regex.git)", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + } + + regexAutomataCrates := pkg.Package{ + Name: "regex-automata", + Version: "0.4.9", + PURL: "pkg:cargo/regex-automata@0.4.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-automata", + Version: "0.4.9", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + }, + }, + } + + regexAutomataGit := pkg.Package{ + Name: "regex-automata", + Version: "0.4.9", + PURL: "pkg:cargo/regex-automata@0.4.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-automata", + Version: "0.4.9", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + } + + regexSyntaxCrates := pkg.Package{ + Name: "regex-syntax", + Version: "0.8.5", + PURL: "pkg:cargo/regex-syntax@0.8.5", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-syntax", + Version: "0.8.5", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c", + Dependencies: []string{}, + }, + } + + regexSyntaxGit := pkg.Package{ + Name: "regex-syntax", + Version: "0.8.5", + PURL: "pkg:cargo/regex-syntax@0.8.5", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-syntax", + Version: "0.8.5", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{}, + }, + } + + expectedPkgs := []pkg.Package{ + ahoCorasick, helloWorld, memchr, minimalLexical, nom, nomRegex, regexCrates, regexGit, + regexAutomataCrates, regexAutomataGit, regexSyntaxCrates, regexSyntaxGit, + } + expectedRelationships := []artifact.Relationship{ + { + From: memchr, + To: ahoCorasick, + Type: artifact.DependencyOfRelationship, + }, + { + From: nomRegex, + To: helloWorld, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexGit, + To: helloWorld, + Type: artifact.DependencyOfRelationship, + }, + { + From: memchr, + To: nom, + Type: artifact.DependencyOfRelationship, + }, + { + From: minimalLexical, + To: nom, + Type: artifact.DependencyOfRelationship, + }, + { + From: nom, + To: nomRegex, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexCrates, + To: nomRegex, + Type: artifact.DependencyOfRelationship, + }, + { + From: ahoCorasick, + To: regexCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: memchr, + To: regexCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexAutomataCrates, + To: regexCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexSyntaxCrates, + To: regexCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexSyntaxCrates, + To: regexAutomataCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: ahoCorasick, + To: regexGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: memchr, + To: regexGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexAutomataGit, + To: regexGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexSyntaxGit, + To: regexAutomataGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: regexSyntaxGit, + To: regexGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: ahoCorasick, + To: regexAutomataCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: memchr, + To: regexAutomataCrates, + Type: artifact.DependencyOfRelationship, + }, + { + From: ahoCorasick, + To: regexAutomataGit, + Type: artifact.DependencyOfRelationship, + }, + { + From: memchr, + To: regexAutomataGit, + Type: artifact.DependencyOfRelationship, + }, + } + // what I know so far - it's not sorting, it's not + + pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships) +} + +func TestCargoLockDependencySpecification(t *testing.T) { + tests := []struct { + name string + p pkg.Package + provides []string + requires []string + }{ + { + name: "requires git source", + p: pkg.Package{ + Name: "hello_world", + Version: "0.1.0", + PURL: "pkg:cargo/hello_world@0.1.0", + Locations: file.NewLocationSet(), + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "hello_world", + Version: "0.1.0", + Dependencies: []string{ + "nom-regex", + "regex 1.11.1 (git+https://github.com/rust-lang/regex.git)", + }, + }, + }, + provides: []string{ + "hello_world", + "hello_world 0.1.0", + }, + requires: []string{ + "nom-regex", + "regex 1.11.1 (git+https://github.com/rust-lang/regex.git)", + }, + }, + { + name: "provides git source", + p: pkg.Package{ + Name: "regex-automata", + Version: "0.4.9", + PURL: "pkg:cargo/regex-automata@0.4.9", + Locations: file.NewLocationSet(), + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-automata", + Version: "0.4.9", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + }, + provides: []string{ + "regex-automata", + "regex-automata 0.4.9", + "regex-automata 0.4.9 (git+https://github.com/rust-lang/regex.git)", + }, + requires: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + { + name: "regex-automata git", + p: pkg.Package{ + Name: "regex-automata", + Version: "0.4.9", + PURL: "pkg:cargo/regex-automata@0.4.9", + Locations: file.NewLocationSet(), + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-automata", + Version: "0.4.9", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + }, + provides: []string{ + "regex-automata", + "regex-automata 0.4.9", + "regex-automata 0.4.9 (git+https://github.com/rust-lang/regex.git)", + }, + requires: []string{ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + }, + { + name: "regex-syntax git", + p: pkg.Package{ + Name: "regex-syntax", + Version: "0.8.5", + PURL: "pkg:cargo/regex-syntax@0.8.5", + Locations: file.NewLocationSet(), + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-syntax", + Version: "0.8.5", + Source: "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa", + Dependencies: []string{}, + }, + }, + provides: []string{ + "regex-syntax", + "regex-syntax 0.8.5", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", + }, + requires: []string{}, + }, + { + name: "regex-syntax crates", + p: pkg.Package{ + Name: "regex-syntax", + Version: "0.8.5", + PURL: "pkg:cargo/regex-syntax@0.8.5", + Locations: file.NewLocationSet(), + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Metadata: pkg.RustCargoLockEntry{ + Name: "regex-syntax", + Version: "0.8.5", + Source: "registry+https://github.com/rust-lang/crates.io-index", + Checksum: "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c", + Dependencies: []string{}, + }, + }, + provides: []string{ + "regex-syntax", + "regex-syntax 0.8.5", + "regex-syntax 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + }, + requires: []string{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + spec := dependencySpecification(test.p) + assert.Equal(t, test.provides, spec.Provides) + assert.Equal(t, test.requires, spec.Requires) + }) + } +} + func Test_corruptCargoLock(t *testing.T) { pkgtest.NewCatalogTester(). FromFile(t, "test-fixtures/glob-paths/src/Cargo.lock"). diff --git a/syft/pkg/cataloger/rust/test-fixtures/Cargo.lock-with-git-deps b/syft/pkg/cataloger/rust/test-fixtures/Cargo.lock-with-git-deps new file mode 100644 index 000000000..d9b7c7121 --- /dev/null +++ b/syft/pkg/cataloger/rust/test-fixtures/Cargo.lock-with-git-deps @@ -0,0 +1,107 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "hello_world" +version = "0.1.0" +dependencies = [ + "nom-regex", + "regex 1.11.1 (git+https://github.com/rust-lang/regex.git)", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom-regex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e5c7731c4c1370b61604ed52a2475e861aac9e08dec9f23903d4ddfdc91c18" +dependencies = [ + "nom", + "regex 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9 (git+https://github.com/rust-lang/regex.git)", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5 (git+https://github.com/rust-lang/regex.git)", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "git+https://github.com/rust-lang/regex.git#1a069b9232c607b34c4937122361aa075ef573fa"