mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-19 20:57:53 +02:00
Maybe 3rd time is the charm! This makes the CI build run on windows too, and fix broken tests/featuers on Windows. Most of the changes are related to ignoring certain tests on windows, or making sure to use the right path separators. More work to do in the future, probably! #4293 --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
145 lines
3.6 KiB
Go
145 lines
3.6 KiB
Go
package upx
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"github.com/caarlos0/log"
|
|
"github.com/docker/go-units"
|
|
"github.com/goreleaser/goreleaser/v2/internal/artifact"
|
|
"github.com/goreleaser/goreleaser/v2/internal/pipe"
|
|
"github.com/goreleaser/goreleaser/v2/internal/semerrgroup"
|
|
"github.com/goreleaser/goreleaser/v2/internal/tmpl"
|
|
"github.com/goreleaser/goreleaser/v2/pkg/config"
|
|
"github.com/goreleaser/goreleaser/v2/pkg/context"
|
|
)
|
|
|
|
type Pipe struct{}
|
|
|
|
func (Pipe) String() string { return "upx" }
|
|
func (Pipe) Default(ctx *context.Context) error {
|
|
for i := range ctx.Config.UPXs {
|
|
upx := &ctx.Config.UPXs[i]
|
|
if upx.Binary == "" {
|
|
upx.Binary = "upx"
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
func (Pipe) Skip(ctx *context.Context) bool { return len(ctx.Config.UPXs) == 0 }
|
|
func (Pipe) Run(ctx *context.Context) error {
|
|
g := semerrgroup.NewSkipAware(semerrgroup.New(ctx.Parallelism))
|
|
for _, upx := range ctx.Config.UPXs {
|
|
enabled, err := tmpl.New(ctx).Bool(upx.Enabled)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !enabled {
|
|
return pipe.Skip("upx is not enabled")
|
|
}
|
|
if _, err := exec.LookPath(upx.Binary); err != nil {
|
|
return pipe.Skipf("%s not found in PATH", upx.Binary)
|
|
}
|
|
for _, bin := range findBinaries(ctx, upx) {
|
|
g.Go(func() error {
|
|
sizeBefore := sizeOf(bin.Path)
|
|
args := []string{
|
|
"--quiet",
|
|
}
|
|
switch upx.Compress {
|
|
case "best":
|
|
args = append(args, "--best")
|
|
case "":
|
|
default:
|
|
args = append(args, "-"+upx.Compress)
|
|
}
|
|
if upx.LZMA {
|
|
args = append(args, "--lzma")
|
|
}
|
|
if upx.Brute {
|
|
args = append(args, "--brute")
|
|
}
|
|
args = append(args, bin.Path)
|
|
out, err := exec.CommandContext(ctx, "upx", args...).CombinedOutput()
|
|
if err != nil {
|
|
for _, ke := range knownExceptions {
|
|
if strings.Contains(string(out), ke) {
|
|
log.WithField("binary", bin.Path).
|
|
WithField("exception", ke).
|
|
Warn("could not pack")
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("could not pack %s: %w: %s", bin.Path, err, string(out))
|
|
}
|
|
|
|
sizeAfter := sizeOf(bin.Path)
|
|
|
|
log.
|
|
WithField("before", units.HumanSize(float64(sizeBefore))).
|
|
WithField("after", units.HumanSize(float64(sizeAfter))).
|
|
WithField("ratio", fmt.Sprintf("%d%%", (sizeAfter*100)/sizeBefore)).
|
|
WithField("binary", bin.Path).
|
|
Info("packed")
|
|
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
return g.Wait()
|
|
}
|
|
|
|
var knownExceptions = []string{
|
|
"CantPackException",
|
|
"AlreadyPackedException",
|
|
"NotCompressibleException",
|
|
"UnknownExecutableFormatException",
|
|
"IOException",
|
|
}
|
|
|
|
func findBinaries(ctx *context.Context, upx config.UPX) []*artifact.Artifact {
|
|
filters := []artifact.Filter{
|
|
artifact.Or(
|
|
artifact.ByType(artifact.Binary),
|
|
artifact.ByType(artifact.UniversalBinary),
|
|
),
|
|
}
|
|
if f := orBy(artifact.ByGoos, upx.Goos); f != nil {
|
|
filters = append(filters, f)
|
|
}
|
|
if f := orBy(artifact.ByGoarch, upx.Goarch); f != nil {
|
|
filters = append(filters, f)
|
|
}
|
|
if f := orBy(artifact.ByGoarm, upx.Goarm); f != nil {
|
|
filters = append(filters, f)
|
|
}
|
|
if f := orBy(artifact.ByGoamd64, upx.Goamd64); f != nil {
|
|
filters = append(filters, f)
|
|
}
|
|
if len(upx.IDs) > 0 {
|
|
filters = append(filters, artifact.ByIDs(upx.IDs...))
|
|
}
|
|
return ctx.Artifacts.Filter(artifact.And(filters...)).List()
|
|
}
|
|
|
|
func orBy(fn func(string) artifact.Filter, items []string) artifact.Filter {
|
|
var result []artifact.Filter
|
|
for _, f := range items {
|
|
result = append(result, fn(f))
|
|
}
|
|
if len(result) == 0 {
|
|
return nil
|
|
}
|
|
return artifact.Or(result...)
|
|
}
|
|
|
|
func sizeOf(name string) int64 {
|
|
st, err := os.Stat(name)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return st.Size()
|
|
}
|