Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/git-pkgs/gcs v0.1.0
github.com/git-pkgs/integrity v0.2.0
github.com/git-pkgs/magic v0.5.0
github.com/git-pkgs/purl v0.1.23
github.com/git-pkgs/purl v0.1.24
github.com/git-pkgs/registries v0.11.0
github.com/git-pkgs/sbom v0.1.7
github.com/git-pkgs/spdx v0.3.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ github.com/git-pkgs/magic v0.5.0 h1:Pm+4fkHR+K6kg9pwJM4hnwWUuBlkYdLmF1yIAI8lU9Q=
github.com/git-pkgs/magic v0.5.0/go.mod h1:SXOqcsNmbmpZjJZHEEWnwxprbsFvpwWgTAZrgXp4Jm4=
github.com/git-pkgs/pom v0.1.8 h1:mXCuWw6XkrKKZb6IurRZyIznYLPhV5AYg5ZO38Uj/l8=
github.com/git-pkgs/pom v0.1.8/go.mod h1:sQBeYRzjCUn77fcABPn6I/a1aBHFxm55jTmkNxYtGtw=
github.com/git-pkgs/purl v0.1.23 h1:RG7F73S4ZnbAnB/posWf2WS4OhdG0xUbyX8UIkEUhPw=
github.com/git-pkgs/purl v0.1.23/go.mod h1:l8rCfvt5iXVrFIcoQ8+vCLOaHhrtEW2id0LENP+IzMw=
github.com/git-pkgs/purl v0.1.24 h1:JMEB1uNWI+baEpl6AeVx+Kfq1c+xkou+THxa5KJ3MrU=
github.com/git-pkgs/purl v0.1.24/go.mod h1:l8rCfvt5iXVrFIcoQ8+vCLOaHhrtEW2id0LENP+IzMw=
github.com/git-pkgs/registries v0.11.0 h1:kkB80NjO9UncyyxGfKmdPXWqUMNE/CkNw5Z/6gqW7Rs=
github.com/git-pkgs/registries v0.11.0/go.mod h1:bKxgdy/PwnzQXL2FnOktmSQHTKk6B85MA4VtvvYItPc=
github.com/git-pkgs/sbom v0.1.7 h1:4eboy/Yed/SC9ZcC/xT50iywHPzWbmCU7azDb5T1RbA=
Expand Down
74 changes: 18 additions & 56 deletions internal/denylist/denylist.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package denylist

import (
"fmt"
"regexp"
"strings"

"github.com/git-pkgs/purl"
Expand Down Expand Up @@ -116,65 +115,28 @@ func (id identity) channelKey() string {
return id.key + "?channel=" + id.channel
}

var pypiSeparators = regexp.MustCompile(`[-_.]+`)

// swiftRegistryIdentity returns the registry scope and name of a Swift
// package. A source coordinate such as pkg:swift/github.com/apple/swift-nio
// names no registry identity.
func swiftRegistryIdentity(pkg *purl.PURL) (scope, name string, ok bool) {
switch {
case pkg.Type == "swift" && pkg.Namespace != "" && !strings.ContainsAny(pkg.Namespace, "./"):
return pkg.Namespace, pkg.Name, true
case pkg.Type == "generic" && strings.EqualFold(pkg.Namespace, "swift-registry"):
scope, name, found := strings.Cut(pkg.Name, ".")
return scope, name, found && scope != "" && name != ""
// genericSwiftRegistry returns the scope and name of a Swift registry archive,
// which the proxy stores as pkg:generic/swift-registry/{scope}.{name}.
func genericSwiftRegistry(pkg *purl.PURL) (scope, name string, ok bool) {
if pkg.Type != "generic" || !strings.EqualFold(pkg.Namespace, "swift-registry") {
return "", "", false
}
return "", "", false
scope, name, found := strings.Cut(pkg.Name, ".")
return scope, name, found && scope != "" && name != ""
}

// identify compares PURLs in purl's comparison form. The generic
// swift-registry spelling is the proxy's own, so it is mapped here first.
func identify(pkg *purl.PURL) identity {
namespace, name, version := pkg.Namespace, pkg.Name, pkg.Version
if scope, name, ok := genericSwiftRegistry(pkg); ok {
pkg = purl.New("swift", scope, name, pkg.Version, nil)
}
c := pkg.ComparisonForm()
var channel string
switch pkg.Type {
case "pypi":
// PEP 503: case-insensitive, runs of -, _ and . are equivalent.
name = pypiSeparators.ReplaceAllString(strings.ToLower(name), "-")
case "nuget":
// NuGet ids and versions are case-insensitive.
name, version = strings.ToLower(name), strings.ToLower(version)
case "conda":
// The conda handler names packages "channel/name"; entries may give the
// channel as a qualifier or namespace. An entry without one matches
// every channel.
channel = pkg.Qualifier("channel")
if namespace != "" {
channel, namespace = namespace, ""
}
if i := strings.LastIndex(name, "/"); i >= 0 {
channel, name = name[:i], name[i+1:]
}
case "composer":
// Packagist keeps a tag's leading v ("v6.1.7"); Composer treats it
// as the same version.
if len(version) > 1 && (version[0] == 'v' || version[0] == 'V') && version[1] >= '0' && version[1] <= '9' {
version = version[1:]
}
case "oci":
// Handlers name the repository as one name, library%2Falpine;
// entries write it as a path, library/alpine.
if namespace != "" {
name, namespace = namespace+"/"+name, ""
}
case "swift", "generic":
// Swift registry archives are stored as
// pkg:generic/swift-registry/{scope}.{name}; entries may write
// pkg:swift/{scope}/{name}. Registry identities ignore case.
if scope, pkgName, ok := swiftRegistryIdentity(pkg); ok {
namespace, name = strings.ToLower(scope), strings.ToLower(pkgName)
key := purl.New("swift", namespace, name, "", nil).String()
return identity{key: key, version: version}
}
if c.Type == "conda" {
// An entry without a channel matches every channel.
channel = c.Qualifier("channel")
}
key := purl.New(pkg.Type, namespace, name, "", nil).String()
return identity{key: key, channel: channel, version: version}
key := purl.New(c.Type, c.Namespace, c.Name, "", nil).String()
return identity{key: key, channel: channel, version: c.Version}
}
6 changes: 4 additions & 2 deletions internal/handler/nuget.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const (

// Packages are stored under pkg:nuget/{id} with the id lowercased, since
// NuGet ids are case-insensitive. purl keeps nuget names as written, so
// package rules are lowercased the same way before the default mapping.
// package rules go through its comparison form, which lowercases them the
// same way, before the default mapping.
func init() {
retention.Default.Register(retention.Spec{Key: "nuget", CanonicalPackage: nugetRetentionKey})
}
Expand All @@ -29,7 +30,8 @@ func nugetRetentionKey(p *purl.PURL) (string, bool) {
if p == nil {
return "", false
}
return retention.DefaultCanonical("nuget")(purl.New(p.Type, p.Namespace, strings.ToLower(p.Name), "", nil))
c := p.ComparisonForm()
return retention.DefaultCanonical("nuget")(purl.New(c.Type, c.Namespace, c.Name, "", nil))
}

// NuGetHandler handles NuGet V3 API protocol requests.
Expand Down
Loading