mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-29 21:47:01 +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"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"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/artifact"
|
||||||
"github.com/goreleaser/goreleaser/internal/ids"
|
"github.com/goreleaser/goreleaser/internal/ids"
|
||||||
"github.com/goreleaser/goreleaser/internal/semerrgroup"
|
"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)
|
a = NewEnhancedArchive(a, wrap)
|
||||||
defer a.Close()
|
defer a.Close()
|
||||||
|
|
||||||
files, err := findFiles(template, arch.Files)
|
files, err := archivefiles.Eval(template, arch.Files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to find files to archive: %w", err)
|
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
|
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 {
|
func packageFormat(archive config.Archive, platform string) string {
|
||||||
for _, override := range archive.FormatOverrides {
|
for _, override := range archive.FormatOverrides {
|
||||||
if strings.HasPrefix(platform, override.Goos) {
|
if strings.HasPrefix(platform, override.Goos) {
|
||||||
|
@ -9,11 +9,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
|
||||||
"github.com/goreleaser/goreleaser/pkg/archive"
|
"github.com/goreleaser/goreleaser/pkg/archive"
|
||||||
"github.com/goreleaser/goreleaser/pkg/config"
|
"github.com/goreleaser/goreleaser/pkg/config"
|
||||||
"github.com/goreleaser/goreleaser/pkg/context"
|
"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")
|
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) {
|
func TestArchive_globbing(t *testing.T) {
|
||||||
assertGlob := func(t *testing.T, files []config.File, expected []string) {
|
assertGlob := func(t *testing.T, files []config.File, expected []string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user