Skip to content

Commit

Permalink
Merge pull request #36 from hashicorp/root-is-symlink
Browse files Browse the repository at this point in the history
Resolve root dir if symlink
  • Loading branch information
sebasslash committed Apr 3, 2023
2 parents c17c5a5 + 9695486 commit 4324b28
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 111 deletions.
19 changes: 16 additions & 3 deletions slug.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,29 @@ 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
if p.applyTerraformIgnore {
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 {
Expand Down
241 changes: 133 additions & 108 deletions slug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 4324b28

Please sign in to comment.