You've already forked goreleaser
mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-07-17 01:42:37 +02:00
feat: docker - added linker for extra directories
When adding extra files to docker using a hard link it is impossible to add a directory because only files can be linked hard. For directories I added a linker that recursively linkes all files in a directory and re- creates the directory structure in the dist directory.
This commit is contained in:
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/context"
|
"github.com/goreleaser/goreleaser/context"
|
||||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||||
"github.com/goreleaser/goreleaser/pipeline"
|
"github.com/goreleaser/goreleaser/pipeline"
|
||||||
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNoDocker is shown when docker cannot be found in $PATH
|
// ErrNoDocker is shown when docker cannot be found in $PATH
|
||||||
@ -127,7 +128,7 @@ func process(ctx *context.Context, docker config.Docker, artifact artifact.Artif
|
|||||||
return errors.Wrap(err, "failed to link dockerfile")
|
return errors.Wrap(err, "failed to link dockerfile")
|
||||||
}
|
}
|
||||||
for _, file := range docker.Files {
|
for _, file := range docker.Files {
|
||||||
if err := os.Link(file, filepath.Join(root, filepath.Base(file))); err != nil {
|
if err := link(file, filepath.Join(root, filepath.Base(file))); err != nil {
|
||||||
return errors.Wrapf(err, "failed to link extra file '%s'", file)
|
return errors.Wrapf(err, "failed to link extra file '%s'", file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,6 +144,62 @@ func process(ctx *context.Context, docker config.Docker, artifact artifact.Artif
|
|||||||
return publish(ctx, docker, image, latest)
|
return publish(ctx, docker, image, latest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// link a file or directory hard
|
||||||
|
func link(src, dest string) error {
|
||||||
|
info, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return directoryLink(src, dest, info)
|
||||||
|
}
|
||||||
|
return fileLink(src, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// directoryLink recursively creates all subdirectories and links all files hard
|
||||||
|
func directoryLink(src, dest string, info os.FileInfo) error {
|
||||||
|
if info == nil {
|
||||||
|
i, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
info = i
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(dest, info.Mode()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
infos, err := ioutil.ReadDir(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, info := range infos {
|
||||||
|
if info.IsDir() {
|
||||||
|
err := directoryLink(
|
||||||
|
filepath.Join(src, info.Name()),
|
||||||
|
filepath.Join(dest, info.Name()),
|
||||||
|
info,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fileLink(
|
||||||
|
filepath.Join(src, info.Name()),
|
||||||
|
filepath.Join(dest, info.Name()),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fileLink links a file hard
|
||||||
|
func fileLink(src, dest string) error {
|
||||||
|
return os.Link(src, dest)
|
||||||
|
}
|
||||||
|
|
||||||
func publish(ctx *context.Context, docker config.Docker, image, latest string) error {
|
func publish(ctx *context.Context, docker config.Docker, image, latest string) error {
|
||||||
// TODO: improve this so it can log it to stdout
|
// TODO: improve this so it can log it to stdout
|
||||||
if !ctx.Publish {
|
if !ctx.Publish {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||||
"github.com/goreleaser/goreleaser/pipeline"
|
"github.com/goreleaser/goreleaser/pipeline"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func killAndRm(t *testing.T) {
|
func killAndRm(t *testing.T) {
|
||||||
@ -236,3 +237,60 @@ func TestDefaultSet(t *testing.T) {
|
|||||||
assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
|
assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
|
||||||
assert.Equal(t, "Dockerfile.foo", docker.Dockerfile)
|
assert.Equal(t, "Dockerfile.foo", docker.Dockerfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLinkFile(t *testing.T) {
|
||||||
|
const srcFile = "/tmp/test"
|
||||||
|
const dstFile = "/tmp/linked"
|
||||||
|
err := ioutil.WriteFile(srcFile, []byte("foo"), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Cannot setup test file")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
err = link(srcFile, dstFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Failed to link: ", err)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if inode(srcFile) != inode(dstFile) {
|
||||||
|
t.Log("Inodes do not match, destination file is not a link")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
// cleanup
|
||||||
|
os.Remove(srcFile)
|
||||||
|
os.Remove(dstFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLinkDirectory(t *testing.T) {
|
||||||
|
const srcDir = "/tmp/testdir"
|
||||||
|
const testFile = "test"
|
||||||
|
const dstDir = "/tmp/linkedDir"
|
||||||
|
|
||||||
|
os.Mkdir(srcDir, 0755)
|
||||||
|
err := ioutil.WriteFile(srcDir+"/"+testFile, []byte("foo"), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Cannot setup test file")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
err = directoryLink(srcDir, dstDir, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Failed to link: ", err)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if inode(srcDir+"/"+testFile) != inode(dstDir+"/"+testFile) {
|
||||||
|
t.Log("Inodes do not match, destination file is not a link")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
os.RemoveAll(srcDir)
|
||||||
|
os.RemoveAll(dstDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func inode(file string) uint64 {
|
||||||
|
fileInfo, err := os.Stat(file)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
stat := fileInfo.Sys().(*syscall.Stat_t)
|
||||||
|
return stat.Ino
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user