1
1
Fork 0
mirror of https://github.com/goreleaser/nfpm synced 2024-05-12 18:56:16 +02:00

fix: destinations for files containing matchers when globbing is disabled (#410)

* Fix destinations for files containing matchers when globbing is disabled.

* Change test case to be compatible with Windows filesystem
This commit is contained in:
Erik Geiser 2021-12-01 15:38:50 +01:00 committed by GitHub
parent e959f1d7c3
commit 206d797843
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 21 deletions

View File

@ -8,7 +8,6 @@ import (
"strings"
"time"
"github.com/goreleaser/fileglob"
"github.com/goreleaser/nfpm/v2/internal/glob"
)
@ -143,11 +142,6 @@ func (c *Content) Sys() interface{} {
// ExpandContentGlobs gathers all of the real files to be copied into the package.
func ExpandContentGlobs(contents Contents, disableGlobbing bool) (files Contents, err error) {
options := []fileglob.OptFunc{fileglob.MatchDirectoryIncludesContents}
if disableGlobbing {
options = append(options, fileglob.QuoteMeta)
}
for _, f := range contents {
var globbed map[string]string
@ -157,7 +151,7 @@ func ExpandContentGlobs(contents Contents, disableGlobbing bool) (files Contents
// them because they do not really exist
files = append(files, f.WithFileInfoDefaults())
default:
globbed, err = glob.Glob(f.Source, f.Destination, options...)
globbed, err = glob.Glob(f.Source, f.Destination, disableGlobbing)
if err != nil {
return nil, err
}

View File

@ -2,6 +2,7 @@ package files_test
import (
"os"
"strconv"
"strings"
"sync"
"testing"
@ -198,3 +199,52 @@ func TestCollision(t *testing.T) {
require.ErrorIs(t, err, files.ErrContentCollision)
})
}
func TestDisableGlobbing(t *testing.T) {
testCases := []files.Content{
{
Source: "testdata/{test}/bar",
Destination: "/etc/{test}/bar",
},
{
Source: "testdata/{test}/[f]oo",
Destination: "testdata/{test}/[f]oo",
},
{
Source: "testdata/globtest/a.txt",
Destination: "testdata/globtest/a.txt",
},
{
Source: "testdata/globtest/a.txt",
Destination: "/etc/a.txt",
},
}
disableGlobbing := true
for i, testCase := range testCases {
content := testCase
t.Run(strconv.Itoa(i), func(t *testing.T) {
result, err := files.ExpandContentGlobs(files.Contents{&content}, disableGlobbing)
if err != nil {
t.Fatalf("expand content globs: %v", err)
}
if len(result) != 1 {
t.Fatalf("unexpected result length: %d, expected one", len(result))
}
actualContent := result[0]
// we expect the result content to be identical to the input content
if actualContent.Source != content.Source {
t.Fatalf("unexpected content source: %q, expected %q", actualContent.Source, content.Source)
}
if actualContent.Destination != content.Destination {
t.Fatalf("unexpected content destination: %q, expected %q", actualContent.Destination, content.Destination)
}
})
}
}

0
files/testdata/{test}/[f]oo vendored Normal file
View File

0
files/testdata/{test}/bar vendored Normal file
View File

View File

@ -51,7 +51,12 @@ func (e ErrGlobNoMatch) Error() string {
// Glob returns a map with source file path as keys and destination as values.
// First the longest common prefix (lcp) of all globbed files is found. The destination
// for each globbed file is then dst joined with src with the lcp trimmed off.
func Glob(pattern, dst string, options ...fileglob.OptFunc) (map[string]string, error) {
func Glob(pattern, dst string, ignoreMatchers bool) (map[string]string, error) {
options := []fileglob.OptFunc{fileglob.MatchDirectoryIncludesContents}
if ignoreMatchers {
options = append(options, fileglob.QuoteMeta)
}
if strings.HasPrefix(pattern, "../") {
p, err := filepath.Abs(pattern)
if err != nil {
@ -59,21 +64,24 @@ func Glob(pattern, dst string, options ...fileglob.OptFunc) (map[string]string,
}
pattern = filepath.ToSlash(p)
}
matches, err := fileglob.Glob(pattern, append(options, fileglob.MaybeRootFS)...)
if errors.Is(err, os.ErrNotExist) {
return nil, err
}
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil, err
}
return nil, fmt.Errorf("glob failed: %s: %w", pattern, err)
}
if len(matches) == 0 {
return nil, ErrGlobNoMatch{pattern}
}
files := make(map[string]string)
prefix := pattern
// the prefix may not be a complete path or may use glob patterns, in that case use the parent directory
if _, err := os.Stat(prefix); os.IsNotExist(err) || fileglob.ContainsMatchers(pattern) {
if _, err := os.Stat(prefix); os.IsNotExist(err) || (fileglob.ContainsMatchers(pattern) && !ignoreMatchers) {
prefix = filepath.Dir(longestCommonPrefix(matches))
}
@ -82,13 +90,16 @@ func Glob(pattern, dst string, options ...fileglob.OptFunc) (map[string]string,
if f, err := os.Stat(src); err == nil && f.Mode().IsDir() {
continue
}
relpath, err := filepath.Rel(prefix, src)
if err != nil {
// since prefix is a prefix of src a relative path should always be found
panic(err)
return nil, err
}
globdst := filepath.ToSlash(filepath.Join(dst, relpath))
files[src] = globdst
}
return files, nil
}

View File

@ -40,7 +40,7 @@ func TestLongestCommonPrefix(t *testing.T) {
func TestGlob(t *testing.T) {
t.Run("simple", func(t *testing.T) {
files, err := Glob("./testdata/dir_a/dir_*/*", "/foo/bar")
files, err := Glob("./testdata/dir_a/dir_*/*", "/foo/bar", false)
require.NoError(t, err)
require.Len(t, files, 2)
require.Equal(t, "/foo/bar/dir_b/test_b.txt", files["testdata/dir_a/dir_b/test_b.txt"])
@ -51,47 +51,47 @@ func TestGlob(t *testing.T) {
pattern := "../../testdata/fake"
abs, err := filepath.Abs(pattern)
require.NoError(t, err)
files, err := Glob(pattern, "/foo/fake")
files, err := Glob(pattern, "/foo/fake", false)
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "/foo/fake", files[filepath.ToSlash(abs)])
})
t.Run("single file", func(t *testing.T) {
files, err := Glob("testdata/dir_a/dir_b/*", "/foo/bar")
files, err := Glob("testdata/dir_a/dir_b/*", "/foo/bar", false)
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "/foo/bar/test_b.txt", files["testdata/dir_a/dir_b/test_b.txt"])
})
t.Run("double star", func(t *testing.T) {
files, err := Glob("testdata/**/test*.txt", "/foo/bar")
files, err := Glob("testdata/**/test*.txt", "/foo/bar", false)
require.NoError(t, err)
require.Len(t, files, 3)
require.Equal(t, "/foo/bar/dir_a/dir_b/test_b.txt", files["testdata/dir_a/dir_b/test_b.txt"])
})
t.Run("nil value", func(t *testing.T) {
files, err := Glob("does/not/exist", "/foo/bar")
files, err := Glob("does/not/exist", "/foo/bar", false)
require.EqualError(t, err, "matching \"./does/not/exist\": file does not exist")
require.Nil(t, files)
})
t.Run("no matches", func(t *testing.T) {
files, err := Glob("testdata/nothing*", "/foo/bar")
files, err := Glob("testdata/nothing*", "/foo/bar", false)
require.Nil(t, files)
require.EqualError(t, err, "glob failed: testdata/nothing*: no matching files")
})
t.Run("escaped brace", func(t *testing.T) {
files, err := Glob("testdata/\\{dir_d\\}/*", "/foo/bar")
files, err := Glob("testdata/\\{dir_d\\}/*", "/foo/bar", false)
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "/foo/bar/test_brace.txt", files["testdata/{dir_d}/test_brace.txt"])
})
t.Run("no glob", func(t *testing.T) {
files, err := Glob("testdata/dir_a/dir_b/test_b.txt", "/foo/bar/dest.dat")
files, err := Glob("testdata/dir_a/dir_b/test_b.txt", "/foo/bar/dest.dat", false)
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "/foo/bar/dest.dat", files["testdata/dir_a/dir_b/test_b.txt"])