Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize relative paths to an absolute path #44

Merged
merged 2 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion slug.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ func (p *Packer) Pack(src string, w io.Writer) (*Meta, error) {
ignoreRules = parseIgnoreFile(src)
}

// Ensure the source path provided is absolute
src, err = filepath.Abs(src)
if err != nil {
return nil, fmt.Errorf("failed to read absolute path for source: %w", err)
}

// Walk the tree of files.
err = filepath.Walk(src, p.packWalkFn(src, src, src, tarW, meta, ignoreRules))
if err != nil {
Expand Down Expand Up @@ -264,7 +270,7 @@ func (p *Packer) packWalkFn(root, src, dst string, tarW *tar.Writer, meta *Meta,
// If the target is a directory we can recurse into the target
// directory by calling the packWalkFn with updated arguments.
if resolved.info.IsDir() {
return filepath.Walk(resolved.absTarget, p.packWalkFn(root, resolved.target, path, tarW, meta, ignoreRules))
return filepath.Walk(resolved.absTarget, p.packWalkFn(root, resolved.absTarget, path, tarW, meta, ignoreRules))
}

// Dereference this symlink by updating the header with the target file
Expand Down
64 changes: 56 additions & 8 deletions slug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,43 @@ func TestPack_rootIsSymlink(t *testing.T) {
}
}

func TestPack_absoluteSrcRelativeSymlinks(t *testing.T) {
var path string
var err error

// In instances we run within CI, we want to fetch
// the absolute path where our test is located
if workDir, ok := os.LookupEnv("GITHUB_WORKSPACE"); ok {
path = workDir
} else {
path, err = os.Getwd()
if err != nil {
t.Fatalf("could not determine the working dir: %v", err)
}
}

// One last check, if this variable is empty we'll error
// since we need the absolute path for the source
if path == "" {
t.Fatal("Home directory could not be determined")
}

path = filepath.Join(path, "testdata/archive-dir-absolute/dev")
slug := bytes.NewBuffer(nil)
_, err = Pack(path, slug, true)
if err != nil {
// We simply want to ensure paths can be resolved while
// traversing the source directory
t.Fatalf("err: %v", err)
}

// Cannot pack without dereferencing
_, err = Pack(path, slug, false)
if !strings.HasPrefix(err.Error(), "illegal slug error:") {
t.Fatalf("expected illegal slug error, got %q", err)
}
}

func TestPackWithoutIgnoring(t *testing.T) {
slug := bytes.NewBuffer(nil)

Expand Down Expand Up @@ -1057,7 +1094,8 @@ func assertArchiveFixture(t *testing.T, slug *bytes.Buffer, got *Meta) {

tarR := tar.NewReader(gzipR)
var (
symFound bool
sym1Found bool
sym2Found bool
externalTargetFound bool
fileList []string
slugSize int64
Expand All @@ -1084,25 +1122,35 @@ func assertArchiveFixture(t *testing.T, slug *bytes.Buffer, got *Meta) {
if hdr.Linkname != "../bar.txt" {
t.Fatalf("expect target of '../bar.txt', got %q", hdr.Linkname)
}
symFound = true
sym1Found = true
}

if hdr.Name == "example.tf" {
if hdr.Name == "sub2/bar.txt" {
if hdr.Typeflag != tar.TypeSymlink {
t.Fatalf("expected symlink file 'example.tf'")
t.Fatalf("expect symlink for file 'sub2/bar.txt'")
}
if hdr.Linkname != "../sub/bar.txt" {
t.Fatalf("expect target of '../sub/bar.txt', got %q", hdr.Linkname)
}
sym2Found = true
}

if hdr.Name == "example.tf" {
if hdr.Typeflag != tar.TypeReg {
t.Fatalf("expected symlink to be dereferenced 'example.tf'")
brandonc marked this conversation as resolved.
Show resolved Hide resolved
}
externalTargetFound = true
}
}

// Make sure we saw and handled a symlink
if !symFound {
t.Fatal("expected to find symlink")
if !sym1Found || !sym2Found {
t.Fatal("expected to find two symlinks")
}

// Make sure we saw and handled a nested symlink
// Make sure we saw and handled a dereferenced symlink
if !externalTargetFound {
t.Fatal("expected to find nested symlink")
t.Fatal("expected to find dereferenced symlink")
}

// Make sure the .git directory is ignored
Expand Down
2 changes: 2 additions & 0 deletions testdata/archive-dir-absolute/_common/extra-files/bar.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
echo "bar"
2 changes: 2 additions & 0 deletions testdata/archive-dir-absolute/_common/extra-files/foo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
echo "foo"
3 changes: 3 additions & 0 deletions testdata/archive-dir-absolute/_common/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
app = "service-01"
}
7 changes: 7 additions & 0 deletions testdata/archive-dir-absolute/_common/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
locals {
files = fileset("${path.module}/extra-files", "*.sh")
}

output "scripts" {
value = local.files
}
3 changes: 3 additions & 0 deletions testdata/archive-dir-absolute/_common/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
terraform {
required_version = "~> 1.2"
}
10 changes: 10 additions & 0 deletions testdata/archive-dir-absolute/dev/backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
remote "backend" {
hostname = "foobar.terraform.io"
organization = "hashicorp"

workspaces {
name = "dev-service-02"
}
}
}
1 change: 1 addition & 0 deletions testdata/archive-dir-absolute/dev/extra-files
1 change: 1 addition & 0 deletions testdata/archive-dir-absolute/dev/locals.tf
1 change: 1 addition & 0 deletions testdata/archive-dir-absolute/dev/output.tf
4 changes: 4 additions & 0 deletions testdata/archive-dir-absolute/dev/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
locals {
env = "dev"
region = "us-east-2"
}
1 change: 1 addition & 0 deletions testdata/archive-dir-absolute/dev/versions.tf