Fix handling of Debian files with trailing slash (#26087)
Fixes #26022 - Fix handling of files with trailing slash - Fix handling of duplicate package file errors - Added test for both
This commit is contained in:
parent
4211efe8b7
commit
6aa30af724
4 changed files with 67 additions and 47 deletions
|
@ -80,7 +80,9 @@ func ParsePackage(r io.Reader) (*Package, error) {
|
||||||
|
|
||||||
if strings.HasPrefix(hd.Name, controlTar) {
|
if strings.HasPrefix(hd.Name, controlTar) {
|
||||||
var inner io.Reader
|
var inner io.Reader
|
||||||
switch hd.Name[len(controlTar):] {
|
// https://man7.org/linux/man-pages/man5/deb-split.5.html#FORMAT
|
||||||
|
// The file names might contain a trailing slash (since dpkg 1.15.6).
|
||||||
|
switch strings.TrimSuffix(hd.Name[len(controlTar):], "/") {
|
||||||
case "":
|
case "":
|
||||||
inner = arr
|
inner = arr
|
||||||
case ".gz":
|
case ".gz":
|
||||||
|
|
|
@ -69,59 +69,73 @@ func TestParsePackage(t *testing.T) {
|
||||||
tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n"))
|
tw.Write([]byte("Package: gitea\nVersion: 1.0.0\nArchitecture: amd64\n"))
|
||||||
tw.Close()
|
tw.Close()
|
||||||
|
|
||||||
t.Run("None", func(t *testing.T) {
|
cases := []struct {
|
||||||
data := createArchive(map[string][]byte{"control.tar": buf.Bytes()})
|
Extension string
|
||||||
|
WriterFactory func(io.Writer) io.WriteCloser
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Extension: "",
|
||||||
|
WriterFactory: func(w io.Writer) io.WriteCloser {
|
||||||
|
return nopCloser{w}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Extension: ".gz",
|
||||||
|
WriterFactory: func(w io.Writer) io.WriteCloser {
|
||||||
|
return gzip.NewWriter(w)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Extension: ".xz",
|
||||||
|
WriterFactory: func(w io.Writer) io.WriteCloser {
|
||||||
|
xw, _ := xz.NewWriter(w)
|
||||||
|
return xw
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Extension: ".zst",
|
||||||
|
WriterFactory: func(w io.Writer) io.WriteCloser {
|
||||||
|
zw, _ := zstd.NewWriter(w)
|
||||||
|
return zw
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
p, err := ParsePackage(data)
|
for _, c := range cases {
|
||||||
assert.NotNil(t, p)
|
t.Run(c.Extension, func(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
var cbuf bytes.Buffer
|
||||||
assert.Equal(t, "gitea", p.Name)
|
w := c.WriterFactory(&cbuf)
|
||||||
})
|
w.Write(buf.Bytes())
|
||||||
|
w.Close()
|
||||||
|
|
||||||
t.Run("gz", func(t *testing.T) {
|
data := createArchive(map[string][]byte{"control.tar" + c.Extension: cbuf.Bytes()})
|
||||||
var zbuf bytes.Buffer
|
|
||||||
zw := gzip.NewWriter(&zbuf)
|
|
||||||
zw.Write(buf.Bytes())
|
|
||||||
zw.Close()
|
|
||||||
|
|
||||||
data := createArchive(map[string][]byte{"control.tar.gz": zbuf.Bytes()})
|
p, err := ParsePackage(data)
|
||||||
|
assert.NotNil(t, p)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "gitea", p.Name)
|
||||||
|
|
||||||
p, err := ParsePackage(data)
|
t.Run("TrailingSlash", func(t *testing.T) {
|
||||||
assert.NotNil(t, p)
|
data := createArchive(map[string][]byte{"control.tar" + c.Extension + "/": cbuf.Bytes()})
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, "gitea", p.Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("xz", func(t *testing.T) {
|
p, err := ParsePackage(data)
|
||||||
var xbuf bytes.Buffer
|
assert.NotNil(t, p)
|
||||||
xw, _ := xz.NewWriter(&xbuf)
|
assert.NoError(t, err)
|
||||||
xw.Write(buf.Bytes())
|
assert.Equal(t, "gitea", p.Name)
|
||||||
xw.Close()
|
})
|
||||||
|
})
|
||||||
data := createArchive(map[string][]byte{"control.tar.xz": xbuf.Bytes()})
|
}
|
||||||
|
|
||||||
p, err := ParsePackage(data)
|
|
||||||
assert.NotNil(t, p)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, "gitea", p.Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("zst", func(t *testing.T) {
|
|
||||||
var zbuf bytes.Buffer
|
|
||||||
zw, _ := zstd.NewWriter(&zbuf)
|
|
||||||
zw.Write(buf.Bytes())
|
|
||||||
zw.Close()
|
|
||||||
|
|
||||||
data := createArchive(map[string][]byte{"control.tar.zst": zbuf.Bytes()})
|
|
||||||
|
|
||||||
p, err := ParsePackage(data)
|
|
||||||
assert.NotNil(t, p)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, "gitea", p.Name)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nopCloser struct {
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nopCloser) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseControlFile(t *testing.T) {
|
func TestParseControlFile(t *testing.T) {
|
||||||
buildContent := func(name, version, architecture string) *bytes.Buffer {
|
buildContent := func(name, version, architecture string) *bytes.Buffer {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
|
@ -187,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) {
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case packages_model.ErrDuplicatePackageVersion:
|
case packages_model.ErrDuplicatePackageVersion, packages_model.ErrDuplicatePackageFile:
|
||||||
apiError(ctx, http.StatusBadRequest, err)
|
apiError(ctx, http.StatusBadRequest, err)
|
||||||
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
|
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
|
||||||
apiError(ctx, http.StatusForbidden, err)
|
apiError(ctx, http.StatusForbidden, err)
|
||||||
|
|
|
@ -144,6 +144,10 @@ func TestPackageDebian(t *testing.T) {
|
||||||
}
|
}
|
||||||
return seen
|
return seen
|
||||||
})
|
})
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "PUT", uploadURL, createArchive(packageName, packageVersion, architecture))
|
||||||
|
AddBasicAuthHeader(req, user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Download", func(t *testing.T) {
|
t.Run("Download", func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue