Skip to content

Commit 9dc4ab0

Browse files
committed
docs(purl): clarify New contract and OCI exception
- spell out concrete (nil, nil) scenarios in New's godoc: empty pkg.Name, parseGolang for local paths, parseOCI without RepoDigests - expand the OCI case comment to explain the metadata.RepoDigests derivation and why the empty-name guard does not apply - add a Maven test case where parsing collapses Name to ""
1 parent 6b12271 commit 9dc4ab0

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

pkg/purl/purl.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ func FromString(s string) (*PackageURL, error) {
6565

6666
// New builds a PackageURL from the given package and metadata.
6767
//
68-
// It returns (nil, nil) — without error — when the input cannot produce a
69-
// well-formed PURL, in particular:
70-
// - the resolved package name is empty (e.g. local package.json without a
71-
// name field, or a parser that strips the name);
72-
// - the OCI metadata does not contain enough information to build a PURL.
68+
// It returns (nil, nil), without error, when the input cannot produce a
69+
// well-formed PURL. Concretely:
70+
// - the resolved package name is empty: either pkg.Name is empty
71+
// (e.g. a local package.json with no "name" field) or a parser
72+
// strips it (parseGolang returns "" for local paths "./..." or "../...");
73+
// - for OCI, parseOCI returns nil when metadata.RepoDigests is missing
74+
// or unparseable.
7375
//
7476
// nolint: gocyclo
7577
func New(t ftypes.TargetType, metadata types.Metadata, pkg ftypes.Package) (*PackageURL, error) {
@@ -123,9 +125,10 @@ func New(t ftypes.TargetType, metadata types.Metadata, pkg ftypes.Package) (*Pac
123125
case packageurl.TypeCocoapods:
124126
name, subpath = parseCocoapods(name)
125127
case packageurl.TypeOCI:
126-
// OCI PURLs are derived from metadata, not pkg.Name, and several callers
127-
// pass ftypes.Package{} here. The function returns from inside this case,
128-
// so the empty-name guard at the bottom does not apply to OCI.
128+
// OCI PURLs are built from metadata.RepoDigests and deliberately
129+
// ignore pkg.Name (callers like pkg/sbom/io/encode.go pass an empty
130+
// ftypes.Package{}). This case returns from the switch, so the
131+
// empty-name guard at the bottom does not apply to OCI.
129132
purl, err := parseOCI(metadata)
130133
if err != nil {
131134
return nil, err

pkg/purl/purl_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,18 @@ func TestNewPackageURL(t *testing.T) {
534534
},
535535
want: nil,
536536
},
537+
{
538+
// parseMaven turns ":" into "/", which parsePkgName then splits
539+
// into empty namespace and empty name; the bottom guard must
540+
// catch this even though pkg.Name was not empty on entry.
541+
name: "maven name parses to empty",
542+
typ: ftypes.Jar,
543+
pkg: ftypes.Package{
544+
Name: ":",
545+
Version: "1.0.0",
546+
},
547+
want: nil,
548+
},
537549
}
538550

539551
for _, tc := range testCases {

0 commit comments

Comments
 (0)