mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-25 21:29:14 +02:00
refactor: evaluate archive files in another package (#3101)
* refactor: evaluate archive files in another package would be used in #2911 Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com> * test: fixes Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
parent
5d9110ab43
commit
9c426a7b16
74
internal/archivefiles/archivefiles.go
Normal file
74
internal/archivefiles/archivefiles.go
Normal file
@ -0,0 +1,74 @@
|
||||
// Package archivefiles can evaluate a list of config.Files into their final form.
|
||||
package archivefiles
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/fileglob"
|
||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
)
|
||||
|
||||
// Eval evaluates the given list of files to their final form.
|
||||
func Eval(template *tmpl.Template, files []config.File) ([]config.File, error) {
|
||||
var result []config.File
|
||||
for _, f := range files {
|
||||
replaced, err := template.Apply(f.Source)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to apply template %s: %w", f.Source, err)
|
||||
}
|
||||
|
||||
files, err := fileglob.Glob(replaced)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("globbing failed for pattern %s: %w", f.Source, err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
result = append(result, config.File{
|
||||
Source: file,
|
||||
Destination: destinationFor(f, file),
|
||||
Info: f.Info,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].Destination < result[j].Destination
|
||||
})
|
||||
|
||||
return unique(result), nil
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
func unique(in []config.File) []config.File {
|
||||
var result []config.File
|
||||
exist := map[string]string{}
|
||||
for _, f := range in {
|
||||
if current := exist[f.Destination]; current != "" {
|
||||
log.Warnf(
|
||||
"file '%s' already exists in archive as '%s' - '%s' will be ignored",
|
||||
f.Destination,
|
||||
current,
|
||||
f.Source,
|
||||
)
|
||||
continue
|
||||
}
|
||||
exist[f.Destination] = f.Source
|
||||
result = append(result, f)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func destinationFor(f config.File, path string) string {
|
||||
if f.Destination == "" {
|
||||
return path
|
||||
}
|
||||
if f.StripParent {
|
||||
return filepath.Join(f.Destination, filepath.Base(path))
|
||||
}
|
||||
return filepath.Join(f.Destination, path)
|
||||
}
|
133
internal/archivefiles/archivefiles_test.go
Normal file
133
internal/archivefiles/archivefiles_test.go
Normal file
@ -0,0 +1,133 @@
|
||||
package archivefiles
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEval(t *testing.T) {
|
||||
now := time.Now().Truncate(time.Second)
|
||||
tmpl := tmpl.New(context.New(config.Project{}))
|
||||
|
||||
t.Run("single file", func(t *testing.T) {
|
||||
result, err := Eval(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/**/d.txt",
|
||||
Destination: "var/foobar/d.txt",
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "var/foobar/d.txt/testdata/a/b/c/d.txt",
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree without destination", func(t *testing.T) {
|
||||
result, err := Eval(tmpl, []config.File{{Source: "./testdata/a"}})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{Source: "testdata/a/a.txt", Destination: "testdata/a/a.txt"},
|
||||
{Source: "testdata/a/b/a.txt", Destination: "testdata/a/b/a.txt"},
|
||||
{Source: "testdata/a/b/c/d.txt", Destination: "testdata/a/b/c/d.txt"},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree specific destination", func(t *testing.T) {
|
||||
result, err := Eval(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/a",
|
||||
Destination: "usr/local/test",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/a.txt",
|
||||
Destination: "usr/local/test/testdata/a/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/a.txt",
|
||||
Destination: "usr/local/test/testdata/a/b/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "usr/local/test/testdata/a/b/c/d.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree specific destination stripping parents", func(t *testing.T) {
|
||||
result, err := Eval(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/a",
|
||||
Destination: "usr/local/test",
|
||||
StripParent: true,
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/a.txt",
|
||||
Destination: "usr/local/test/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "usr/local/test/d.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
}
|
0
internal/archivefiles/testdata/a/a.txt
vendored
Normal file
0
internal/archivefiles/testdata/a/a.txt
vendored
Normal file
0
internal/archivefiles/testdata/a/b/a.txt
vendored
Normal file
0
internal/archivefiles/testdata/a/b/a.txt
vendored
Normal file
0
internal/archivefiles/testdata/a/b/c/d.txt
vendored
Normal file
0
internal/archivefiles/testdata/a/b/c/d.txt
vendored
Normal file
@ -8,12 +8,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/fileglob"
|
||||
"github.com/goreleaser/goreleaser/internal/archivefiles"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/ids"
|
||||
"github.com/goreleaser/goreleaser/internal/semerrgroup"
|
||||
@ -171,7 +170,7 @@ func doCreate(ctx *context.Context, arch config.Archive, binaries []*artifact.Ar
|
||||
a = NewEnhancedArchive(a, wrap)
|
||||
defer a.Close()
|
||||
|
||||
files, err := findFiles(template, arch.Files)
|
||||
files, err := archivefiles.Eval(template, arch.Files)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find files to archive: %w", err)
|
||||
}
|
||||
@ -262,66 +261,6 @@ func skip(ctx *context.Context, archive config.Archive, binaries []*artifact.Art
|
||||
return nil
|
||||
}
|
||||
|
||||
func findFiles(template *tmpl.Template, files []config.File) ([]config.File, error) {
|
||||
var result []config.File
|
||||
for _, f := range files {
|
||||
replaced, err := template.Apply(f.Source)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to apply template %s: %w", f.Source, err)
|
||||
}
|
||||
|
||||
files, err := fileglob.Glob(replaced)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("globbing failed for pattern %s: %w", f.Source, err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
result = append(result, config.File{
|
||||
Source: file,
|
||||
Destination: destinationFor(f, file),
|
||||
Info: f.Info,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].Destination < result[j].Destination
|
||||
})
|
||||
|
||||
return unique(result), nil
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
func unique(in []config.File) []config.File {
|
||||
var result []config.File
|
||||
exist := map[string]string{}
|
||||
for _, f := range in {
|
||||
if current := exist[f.Destination]; current != "" {
|
||||
log.Warnf(
|
||||
"file '%s' already exists in archive as '%s' - '%s' will be ignored",
|
||||
f.Destination,
|
||||
current,
|
||||
f.Source,
|
||||
)
|
||||
continue
|
||||
}
|
||||
exist[f.Destination] = f.Source
|
||||
result = append(result, f)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func destinationFor(f config.File, path string) string {
|
||||
if f.Destination == "" {
|
||||
return path
|
||||
}
|
||||
if f.StripParent {
|
||||
return filepath.Join(f.Destination, filepath.Base(path))
|
||||
}
|
||||
return filepath.Join(f.Destination, path)
|
||||
}
|
||||
|
||||
func packageFormat(archive config.Archive, platform string) string {
|
||||
for _, override := range archive.FormatOverrides {
|
||||
if strings.HasPrefix(platform, override.Goos) {
|
||||
|
@ -9,11 +9,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
||||
"github.com/goreleaser/goreleaser/pkg/archive"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
@ -953,128 +951,6 @@ func TestSeveralArchivesWithTheSameID(t *testing.T) {
|
||||
require.EqualError(t, Pipe{}.Default(ctx), "found 2 archives with the ID 'a', please fix your config")
|
||||
}
|
||||
|
||||
func TestFindFiles(t *testing.T) {
|
||||
now := time.Now().Truncate(time.Second)
|
||||
tmpl := tmpl.New(context.New(config.Project{}))
|
||||
|
||||
t.Run("single file", func(t *testing.T) {
|
||||
result, err := findFiles(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/**/d.txt",
|
||||
Destination: "var/foobar/d.txt",
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "var/foobar/d.txt/testdata/a/b/c/d.txt",
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree without destination", func(t *testing.T) {
|
||||
result, err := findFiles(tmpl, []config.File{{Source: "./testdata/a"}})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{Source: "testdata/a/a.txt", Destination: "testdata/a/a.txt"},
|
||||
{Source: "testdata/a/b/a.txt", Destination: "testdata/a/b/a.txt"},
|
||||
{Source: "testdata/a/b/c/d.txt", Destination: "testdata/a/b/c/d.txt"},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree specific destination", func(t *testing.T) {
|
||||
result, err := findFiles(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/a",
|
||||
Destination: "usr/local/test",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/a.txt",
|
||||
Destination: "usr/local/test/testdata/a/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/a.txt",
|
||||
Destination: "usr/local/test/testdata/a/b/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "usr/local/test/testdata/a/b/c/d.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
|
||||
t.Run("match multiple files within tree specific destination stripping parents", func(t *testing.T) {
|
||||
result, err := findFiles(tmpl, []config.File{
|
||||
{
|
||||
Source: "./testdata/a",
|
||||
Destination: "usr/local/test",
|
||||
StripParent: true,
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []config.File{
|
||||
{
|
||||
Source: "testdata/a/a.txt",
|
||||
Destination: "usr/local/test/a.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
{
|
||||
Source: "testdata/a/b/c/d.txt",
|
||||
Destination: "usr/local/test/d.txt",
|
||||
Info: config.FileInfo{
|
||||
Owner: "carlos",
|
||||
Group: "users",
|
||||
Mode: 0o755,
|
||||
MTime: now,
|
||||
},
|
||||
},
|
||||
}, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestArchive_globbing(t *testing.T) {
|
||||
assertGlob := func(t *testing.T, files []config.File, expected []string) {
|
||||
t.Helper()
|
||||
|
Loading…
x
Reference in New Issue
Block a user