From 9695486982cbf75764456bb5136b519ffa662538 Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Wed, 15 Mar 2023 13:18:15 -0400 Subject: [PATCH] Resolve root dir if symlink --- slug.go | 19 +++- slug_test.go | 241 ++++++++++++++++++++++++++++----------------------- 2 files changed, 149 insertions(+), 111 deletions(-) diff --git a/slug.go b/slug.go index 86ea281..886ae21 100644 --- a/slug.go +++ b/slug.go @@ -126,6 +126,22 @@ func (p *Packer) Pack(src string, w io.Writer) (*Meta, error) { // Tar the file contents. tarW := tar.NewWriter(gzipW) + // Track the metadata details as we go. + meta := &Meta{} + + info, err := os.Lstat(src) + if err != nil { + return nil, err + } + + // Check if the root (src) is a symlink + if info.Mode()&os.ModeSymlink != 0 { + src, err = os.Readlink(src) + if err != nil { + return nil, err + } + } + // Load the ignore rule configuration, which will use // defaults if no .terraformignore is configured var ignoreRules []rule @@ -133,9 +149,6 @@ func (p *Packer) Pack(src string, w io.Writer) (*Meta, error) { ignoreRules = parseIgnoreFile(src) } - // Track the metadata details as we go. - meta := &Meta{} - // Walk the tree of files. err = filepath.Walk(src, p.packWalkFn(src, src, src, tarW, meta, ignoreRules)) if err != nil { diff --git a/slug_test.go b/slug_test.go index 6639414..33d90ce 100644 --- a/slug_test.go +++ b/slug_test.go @@ -17,126 +17,33 @@ import ( func TestPack(t *testing.T) { slug := bytes.NewBuffer(nil) - meta, err := Pack("testdata/archive-dir", slug, true) if err != nil { t.Fatalf("err: %v", err) } - gzipR, err := gzip.NewReader(slug) + assertArchiveFixture(t, slug, meta) +} + +func TestPack_rootIsSymlink(t *testing.T) { + err := os.Symlink("testdata/archive-dir", "testdata/archive-dir-symlink") if err != nil { - t.Fatalf("err: %v", err) + t.Fatalf("Failed creating dir symlink: %v", err) } - - tarR := tar.NewReader(gzipR) - var ( - symFound bool - fileList []string - slugSize int64 - ) - - for { - hdr, err := tarR.Next() - if err == io.EOF { - break - } + t.Cleanup(func() { + err := os.Remove("testdata/archive-dir-symlink") if err != nil { - t.Fatalf("err: %v", err) - } - - fileList = append(fileList, hdr.Name) - if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { - slugSize += hdr.Size - } - - if hdr.Name == "sub/bar.txt" { - if hdr.Typeflag != tar.TypeSymlink { - t.Fatalf("expect symlink for file 'sub/bar.txt'") - } - if hdr.Linkname != "../bar.txt" { - t.Fatalf("expect target of '../bar.txt', got %q", hdr.Linkname) - } - symFound = true - } - } - - // Make sure we saw and handled a symlink - if !symFound { - t.Fatal("expected to find symlink") - } - - // Make sure the .git directory is ignored - for _, file := range fileList { - if strings.Contains(file, ".git") { - t.Fatalf("unexpected .git content: %s", file) - } - } - - // Make sure the .terraform directory is ignored, - // except for the .terraform/modules subdirectory. - for _, file := range fileList { - if strings.HasPrefix(file, ".terraform"+string(filepath.Separator)) && - !strings.HasPrefix(file, filepath.Clean(".terraform/modules")) { - t.Fatalf("unexpected .terraform content: %s", file) - } - } - - // Make sure .terraform/modules is included. - moduleDir := false - for _, file := range fileList { - if strings.HasPrefix(file, filepath.Clean(".terraform/modules")) { - moduleDir = true - break + t.Fatalf("failed removing testdata/archive-dir-symlink: %v", err) } - } - if !moduleDir { - t.Fatal("expected to include .terraform/modules") - } + }) - // Make sure .terraformrc is included. - terraformrc := false - for _, file := range fileList { - if file == ".terraformrc" { - terraformrc = true - break - } - } - if !terraformrc { - t.Fatal("expected to include .terraformrc") - } - - // Make sure foo.terraform/bar.txt is included. - fooTerraformDir := false - for _, file := range fileList { - if file == filepath.Clean("foo.terraform/bar.txt") { - fooTerraformDir = true - break - } - } - if !fooTerraformDir { - t.Fatal("expected to include foo.terraform/bar.txt") - } - - // Make sure baz.txt is excluded. - bazTxt := false - for _, file := range fileList { - if file == filepath.Clean("baz.txt") { - bazTxt = true - break - } - } - if bazTxt { - t.Fatal("should not include baz.txt") + slug := bytes.NewBuffer(nil) + meta, err := Pack("testdata/archive-dir-symlink", slug, true) + if err != nil { + t.Fatalf("err: %v", err) } - // Check the metadata - expect := &Meta{ - Files: fileList, - Size: slugSize, - } - if !reflect.DeepEqual(meta, expect) { - t.Fatalf("\nexpect:\n%#v\n\nactual:\n%#v", expect, meta) - } + assertArchiveFixture(t, slug, meta) } func TestPackWithoutIgnoring(t *testing.T) { @@ -1101,6 +1008,124 @@ func TestNewPacker(t *testing.T) { } } +// This is a reusable assertion for when packing testdata/archive-dir +func assertArchiveFixture(t *testing.T, slug *bytes.Buffer, got *Meta) { + gzipR, err := gzip.NewReader(slug) + if err != nil { + t.Fatalf("err: %v", err) + } + + tarR := tar.NewReader(gzipR) + var ( + symFound bool + fileList []string + slugSize int64 + ) + + for { + hdr, err := tarR.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("err: %v", err) + } + + fileList = append(fileList, hdr.Name) + if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { + slugSize += hdr.Size + } + + if hdr.Name == "sub/bar.txt" { + if hdr.Typeflag != tar.TypeSymlink { + t.Fatalf("expect symlink for file 'sub/bar.txt'") + } + if hdr.Linkname != "../bar.txt" { + t.Fatalf("expect target of '../bar.txt', got %q", hdr.Linkname) + } + symFound = true + } + } + + // Make sure we saw and handled a symlink + if !symFound { + t.Fatal("expected to find symlink") + } + + // Make sure the .git directory is ignored + for _, file := range fileList { + if strings.Contains(file, ".git") { + t.Fatalf("unexpected .git content: %s", file) + } + } + + // Make sure the .terraform directory is ignored, + // except for the .terraform/modules subdirectory. + for _, file := range fileList { + if strings.HasPrefix(file, ".terraform"+string(filepath.Separator)) && + !strings.HasPrefix(file, filepath.Clean(".terraform/modules")) { + t.Fatalf("unexpected .terraform content: %s", file) + } + } + + // Make sure .terraform/modules is included. + moduleDir := false + for _, file := range fileList { + if strings.HasPrefix(file, filepath.Clean(".terraform/modules")) { + moduleDir = true + break + } + } + if !moduleDir { + t.Fatal("expected to include .terraform/modules") + } + + // Make sure .terraformrc is included. + terraformrc := false + for _, file := range fileList { + if file == ".terraformrc" { + terraformrc = true + break + } + } + if !terraformrc { + t.Fatal("expected to include .terraformrc") + } + + // Make sure foo.terraform/bar.txt is included. + fooTerraformDir := false + for _, file := range fileList { + if file == filepath.Clean("foo.terraform/bar.txt") { + fooTerraformDir = true + break + } + } + if !fooTerraformDir { + t.Fatal("expected to include foo.terraform/bar.txt") + } + + // Make sure baz.txt is excluded. + bazTxt := false + for _, file := range fileList { + if file == filepath.Clean("baz.txt") { + bazTxt = true + break + } + } + if bazTxt { + t.Fatal("should not include baz.txt") + } + + // Check the metadata + expect := &Meta{ + Files: fileList, + Size: slugSize, + } + if !reflect.DeepEqual(got, expect) { + t.Fatalf("\nexpect:\n%#v\n\nactual:\n%#v", expect, got) + } +} + func verifyFile(t *testing.T, path string, mode os.FileMode, expect string) { info, err := os.Lstat(path) if err != nil {