Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 15:49:16 -05:00
pkg-proxy/internal/mirror/swift.go
simon chrzanowski 1979fb098e
Accept Swift source repository PURLs in the denylist and retention rules (#641)
* Accept Swift source repository PURLs in the denylist and retention rules

Closes #613. pkg:swift/github.com/apple/swift-nio, as SBOM tools and GHSA
write Swift packages, is resolved to its registry identity through the
upstream's /identifiers:

- Denylist entries are resolved at startup, and the proxy refuses to start
  when one can't be, since a skipped entry would let the version through.
- Retention keys are accepted at validation and kept pending. The
  retention loop resolves them before each sweep, and Swift isn't swept
  while any is pending, so a rule that keeps a package is never skipped.

The mirror's source URL helper moves to the handler as SwiftSourceURL.

* Resolve Swift source denylist entries in proxy mirror too

serve resolved source-form Swift denylist entries through the upstream,
but proxy mirror built its denylist directly, so such an entry never
matched a mirror download. Both now use server.ConfigureDenylist, and
neither runs when an entry can't be resolved.

* Apply Swift source policies to every listed identity

A Swift registry may list several identities for one source repository,
but a denylist entry or retention rule naming the repository only
covered the first. Denying pkg:swift/github.com/acme/widget@1.0.0 let
acme.widget through when the registry listed other.widget first, and a
never-evict rule cleared the cached apple.swift-nio archive when
other.swift-nio came first.

Both now cover every identity the registry lists. A retention rule that
conflicts with another rule for any of them stays pending, with none
applied. Mirroring a source PURL still downloads the first identity.
2026-10-31 11:34:05 +00:00

57 lines
1.9 KiB
Go

package mirror
import (
"context"
"fmt"
"strings"
"github.com/git-pkgs/proxy/internal/handler"
)
// mirrorSwift mirrors the source archive of a Swift registry release, with
// its release metadata, from the registry the proxy serves Swift packages
// from.
func (m *Mirror) mirrorSwift(ctx context.Context, pv PackageVersion, tracker *progressTracker) {
upstream, err := m.registryURL("swift", pv.Name)
if err != nil {
m.recordFailure(tracker, pv, err)
return
}
h := handler.NewSwiftHandler(m.proxy, "", upstream)
var scope, name string
if source := handler.SwiftSourceURL(pv.Name); source != "" {
scope, name, err = h.ResolveIdentity(ctx, source)
} else {
scope, name, err = swiftScopeAndName(pv.Name)
}
if err != nil {
m.recordFailure(tracker, pv, err)
return
}
result, err := h.MirrorRelease(ctx, scope, name, pv.Version)
if err != nil {
m.recordFailure(tracker, pv, err)
return
}
m.recordResult(tracker, pv, result)
}
// registryURL returns the registry base URL Versions lists purlType packages
// from, which is the configured upstream, or empty for the default one.
func (m *Mirror) registryURL(purlType, name string) (string, error) {
if r, ok := m.Versions.(RegistryVersions); ok && r.URL != nil {
return r.URL(purlType, name)
}
return "", nil
}
// swiftScopeAndName splits the name of a pkg:swift PURL whose namespace is
// a registry scope, as in pkg:swift/apple/swift-nio for the identity
// apple.swift-nio.
func swiftScopeAndName(name string) (scope, pkg string, _ error) {
scope, pkg, ok := strings.Cut(name, "/")
if !ok || scope == "" || pkg == "" || strings.ContainsAny(scope, ".:") || strings.Contains(pkg, "/") {
return "", "", fmt.Errorf("pkg:swift/%s needs a registry scope or a source repository as the namespace, such as pkg:swift/apple/swift-nio or pkg:swift/github.com/apple/swift-nio", name)
}
return scope, pkg, nil
}