Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-10 08:09:17 -05:00
pkg-proxy/internal/server/hosted_archives_test.go
simon chrzanowski e7449d1540
Read the package manifest of pushed archives
Resolvers take a version's dependencies from the registry metadata, not from the archive, so listing a pushed version needs its manifest. A push now reads package.json from the top directory of an npm tarball, or composer.json from the root or the single top directory of a Composer zip, and keeps it in the new artifacts.manifest column (migration 013_add_artifact_manifest).

The manifest has to name the pushed package and version. A Composer manifest may leave the version out, and its name is compared case-insensitively. An archive that can't be read or whose manifest names something else is refused with 400 and removed from storage.

The version's integrity is now the archive's sha512, which npm clients expect in dist.integrity.

Refs #134
2026-10-14 13:23:19 +02:00

48 lines
1.2 KiB
Go

package server
import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"io"
)
// npmTarball builds an npm package tarball holding manifest as
// package/package.json. Building an archive in memory cannot fail, so errors
// panic.
func npmTarball(manifest string) string {
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
tw := tar.NewWriter(gz)
must(tw.WriteHeader(&tar.Header{Name: "package/package.json", Mode: 0o644, Size: int64(len(manifest))}))
_, err := io.WriteString(tw, manifest)
must(err)
must(tw.Close())
must(gz.Close())
return buf.String()
}
// composerZip builds a Composer dist archive holding manifest as composer.json.
func composerZip(manifest string) string {
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
w, err := zw.Create("composer.json")
must(err)
_, err = io.WriteString(w, manifest)
must(err)
must(zw.Close())
return buf.String()
}
func must(err error) {
if err != nil {
panic(err)
}
}
var (
requestTarball = npmTarball(`{"name":"request","version":"2.88.3","dependencies":{"qs":"~6.5.2"}}`)
nodeTarball = npmTarball(`{"name":"@types/node","version":"20.1.0"}`)
monologZip = composerZip(`{"name":"monolog/monolog","require":{"php":">=8.1","psr/log":"^3.0"}}`)
)