mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-04 03:11:55 +02:00
feat: xz compression (#1422)
* feat: xz compression * remove .xz feature * fix: format code with gofmt * use larger dict for better compression * Update pkg/archive/tarxz/tarxz.go Co-authored-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
parent
a5f0343368
commit
081430bcc7
1
go.mod
1
go.mod
@ -19,6 +19,7 @@ require (
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/ulikunitz/xz v0.5.6
|
||||
github.com/xanzy/go-gitlab v0.29.0
|
||||
gocloud.dev v0.19.0
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/goreleaser/goreleaser/pkg/archive/gzip"
|
||||
"github.com/goreleaser/goreleaser/pkg/archive/targz"
|
||||
"github.com/goreleaser/goreleaser/pkg/archive/tarxz"
|
||||
"github.com/goreleaser/goreleaser/pkg/archive/zip"
|
||||
)
|
||||
|
||||
@ -24,6 +25,9 @@ func New(file *os.File) Archive {
|
||||
if strings.HasSuffix(file.Name(), ".gz") {
|
||||
return gzip.New(file)
|
||||
}
|
||||
if strings.HasSuffix(file.Name(), ".tar.xz") {
|
||||
return tarxz.New(file)
|
||||
}
|
||||
if strings.HasSuffix(file.Name(), ".zip") {
|
||||
return zip.New(file)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func TestArchive(t *testing.T) {
|
||||
assert.NoError(err)
|
||||
assert.NoError(os.Mkdir(folder+"/folder-inside", 0755))
|
||||
|
||||
for _, format := range []string{"tar.gz", "zip", "gz", "willbeatargzanyway"} {
|
||||
for _, format := range []string{"tar.gz", "zip", "gz", "tar.xz", "willbeatargzanyway"} {
|
||||
format := format
|
||||
t.Run(format, func(t *testing.T) {
|
||||
var archive = newArchive(folder, format, t)
|
||||
|
61
pkg/archive/tarxz/tarxz.go
Normal file
61
pkg/archive/tarxz/tarxz.go
Normal file
@ -0,0 +1,61 @@
|
||||
// Package tarxz implements the Archive interface providing tar.xz archiving
|
||||
// and compression.
|
||||
package tarxz
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/ulikunitz/xz"
|
||||
)
|
||||
|
||||
// Archive as tar.xz
|
||||
type Archive struct {
|
||||
xzw *xz.Writer
|
||||
tw *tar.Writer
|
||||
}
|
||||
|
||||
// Close all closeables
|
||||
func (a Archive) Close() error {
|
||||
if err := a.tw.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return a.xzw.Close()
|
||||
}
|
||||
|
||||
// New tar.xz archive
|
||||
func New(target io.Writer) Archive {
|
||||
xzw, _ := xz.WriterConfig{DictCap: 16 * 1024 * 1024}.NewWriter(target)
|
||||
tw := tar.NewWriter(xzw)
|
||||
return Archive{
|
||||
xzw: xzw,
|
||||
tw: tw,
|
||||
}
|
||||
}
|
||||
|
||||
// Add file to the archive
|
||||
func (a Archive) Add(name, path string) error {
|
||||
file, err := os.Open(path) // #nosec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close() // nolint: errcheck
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header, err := tar.FileInfoHeader(info, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = name
|
||||
if err = a.tw.WriteHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
_, err = io.Copy(a.tw, file)
|
||||
return err
|
||||
}
|
72
pkg/archive/tarxz/tarxz_test.go
Normal file
72
pkg/archive/tarxz/tarxz_test.go
Normal file
@ -0,0 +1,72 @@
|
||||
package tarxz
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/ulikunitz/xz"
|
||||
)
|
||||
|
||||
func TestTarXzFile(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
tmp, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
f, err := os.Create(filepath.Join(tmp, "test.tar.xz"))
|
||||
assert.NoError(err)
|
||||
defer f.Close() // nolint: errcheck
|
||||
archive := New(f)
|
||||
|
||||
assert.Error(archive.Add("nope.txt", "../testdata/nope.txt"))
|
||||
assert.NoError(archive.Add("foo.txt", "../testdata/foo.txt"))
|
||||
assert.NoError(archive.Add("sub1", "../testdata/sub1"))
|
||||
assert.NoError(archive.Add("sub1/bar.txt", "../testdata/sub1/bar.txt"))
|
||||
assert.NoError(archive.Add("sub1/executable", "../testdata/sub1/executable"))
|
||||
assert.NoError(archive.Add("sub1/sub2", "../testdata/sub1/sub2"))
|
||||
assert.NoError(archive.Add("sub1/sub2/subfoo.txt", "../testdata/sub1/sub2/subfoo.txt"))
|
||||
|
||||
assert.NoError(archive.Close())
|
||||
assert.Error(archive.Add("tar.go", "tar.go"))
|
||||
assert.NoError(f.Close())
|
||||
|
||||
t.Log(f.Name())
|
||||
f, err = os.Open(f.Name())
|
||||
assert.NoError(err)
|
||||
defer f.Close() // nolint: errcheck
|
||||
|
||||
info, err := f.Stat()
|
||||
assert.NoError(err)
|
||||
assert.Truef(info.Size() < 500, "archived file should be smaller than %d", info.Size())
|
||||
|
||||
xzf, err := xz.NewReader(f)
|
||||
assert.NoError(err)
|
||||
//defer xzf.Close() // nolint: errcheck
|
||||
|
||||
var paths []string
|
||||
r := tar.NewReader(xzf)
|
||||
for {
|
||||
next, err := r.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
assert.NoError(err)
|
||||
paths = append(paths, next.Name)
|
||||
t.Logf("%s: %v", next.Name, next.FileInfo().Mode())
|
||||
if next.Name == "sub1/executable" {
|
||||
var ex = next.FileInfo().Mode() | 0111
|
||||
assert.Equal(next.FileInfo().Mode().String(), ex.String())
|
||||
}
|
||||
}
|
||||
assert.Equal([]string{
|
||||
"foo.txt",
|
||||
"sub1",
|
||||
"sub1/bar.txt",
|
||||
"sub1/executable",
|
||||
"sub1/sub2",
|
||||
"sub1/sub2/subfoo.txt",
|
||||
}, paths)
|
||||
}
|
Loading…
Reference in New Issue
Block a user