vacation

package
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 15, 2021 License: Apache-2.0 Imports: 12 Imported by: 1

Documentation

Overview

Package vacation provides a set of functions that enable input stream decompression logic from several popular decompression formats. This allows from decompression from either a file or any other byte stream, which is useful for decompressing files that are being downloaded.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Archive added in v0.2.8

type Archive struct {
	// contains filtered or unexported fields
}

An Archive decompresses tar, gzip, xz, and bzip2 compressed tar, and zip files from an input stream.

Example
package main

import (
	"archive/tar"
	"archive/zip"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	tarBuffer := bytes.NewBuffer(nil)
	tw := tar.NewWriter(tarBuffer)

	tarFiles := []ArchiveFile{
		{Name: "some-tar-dir/"},
		{Name: "some-tar-dir/some-tar-file", Content: []byte("some-tar-dir/some-tar-file")},
		{Name: "tar-file", Content: []byte("tar-file")},
	}

	for _, file := range tarFiles {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()

	zipBuffer := bytes.NewBuffer(nil)
	zw := zip.NewWriter(zipBuffer)

	zipFiles := []ArchiveFile{
		{Name: "some-zip-dir/"},
		{Name: "some-zip-dir/some-zip-file", Content: []byte("some-zip-dir/some-zip-file")},
		{Name: "zip-file", Content: []byte("zip-file")},
	}

	for _, file := range zipFiles {
		header := &zip.FileHeader{Name: file.Name}
		header.SetMode(0755)

		f, err := zw.CreateHeader(header)
		if err != nil {
			log.Fatal(err)
		}

		if _, err := f.Write(file.Content); err != nil {
			log.Fatal(err)
		}
	}

	zw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewArchive(bytes.NewReader(tarBuffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	archive = vacation.NewArchive(bytes.NewReader(zipBuffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-tar-dir/some-tar-file
some-zip-dir/some-zip-file
tar-file
zip-file

func NewArchive added in v0.2.8

func NewArchive(inputReader io.Reader) Archive

NewArchive returns a new Archive that reads from inputReader.

func (Archive) Decompress added in v0.2.8

func (a Archive) Decompress(destination string) error

Decompress reads from Archive, determines the archive type of the input stream, and writes files into the destination specified.

Archive decompression will also handle files that are types "text/plain; charset=utf-8" and write the contents of the input stream to a file name specified by the `Archive.WithName()` option (or defaults to "artifact") in the destination directory.

func (Archive) StripComponents added in v0.2.8

func (a Archive) StripComponents(components int) Archive

StripComponents behaves like the --strip-components flag on tar command removing the first n levels from the final decompression destination. Setting this is a no-op for archive types that do not use --strip-components (such as zip).

Example
package main

import (
	"archive/tar"
	"archive/zip"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	tarBuffer := bytes.NewBuffer(nil)
	tw := tar.NewWriter(tarBuffer)

	tarFiles := []ArchiveFile{
		{Name: "some-tar-dir/"},
		{Name: "some-tar-dir/some-tar-file", Content: []byte("some-tar-dir/some-tar-file")},
		{Name: "tar-file", Content: []byte("tar-file")},
	}

	for _, file := range tarFiles {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()

	zipBuffer := bytes.NewBuffer(nil)
	zw := zip.NewWriter(zipBuffer)

	zipFiles := []ArchiveFile{
		{Name: "some-zip-dir/"},
		{Name: "some-zip-dir/some-zip-file", Content: []byte("some-zip-dir/some-zip-file")},
		{Name: "zip-file", Content: []byte("zip-file")},
	}

	for _, file := range zipFiles {
		header := &zip.FileHeader{Name: file.Name}
		header.SetMode(0755)

		f, err := zw.CreateHeader(header)
		if err != nil {
			log.Fatal(err)
		}

		if _, err := f.Write(file.Content); err != nil {
			log.Fatal(err)
		}
	}

	zw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewArchive(bytes.NewReader(tarBuffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	archive = vacation.NewArchive(bytes.NewReader(zipBuffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-tar-file
some-zip-file

func (Archive) WithName added in v0.14.0

func (a Archive) WithName(name string) Archive

WithName provides a way of overriding the name of the file that the decompressed file will be copied into.

type Decompressor added in v0.14.0

type Decompressor interface {
	Decompress(destination string) error
}

type NopArchive added in v0.14.0

type NopArchive struct {
	// contains filtered or unexported fields
}

A NopArchive implements the common archive interface, but acts as a no-op, simply copying the reader to the destination.

func NewNopArchive added in v0.14.0

func NewNopArchive(r io.Reader) NopArchive

NewNopArchive returns a new NopArchive

func (NopArchive) Decompress added in v0.14.0

func (na NopArchive) Decompress(destination string) error

Decompress copies the reader contents into the destination specified.

type TarArchive

type TarArchive struct {
	// contains filtered or unexported fields
}

A TarArchive decompresses tar files from an input stream.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	tw := tar.NewWriter(buffer)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarArchive(bytes.NewReader(buffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

first
second
some-dir/some-other-dir/some-file
third

func NewTarArchive

func NewTarArchive(inputReader io.Reader) TarArchive

NewTarArchive returns a new TarArchive that reads from inputReader.

func (TarArchive) Decompress

func (ta TarArchive) Decompress(destination string) error

Decompress reads from TarArchive and writes files into the destination specified.

func (TarArchive) StripComponents

func (ta TarArchive) StripComponents(components int) TarArchive

StripComponents behaves like the --strip-components flag on tar command removing the first n levels from the final decompression destination.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	tw := tar.NewWriter(buffer)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarArchive(bytes.NewReader(buffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-other-dir/some-file

type TarBzip2Archive added in v0.12.1

type TarBzip2Archive struct {
	// contains filtered or unexported fields
}

A TarBzip2Archive decompresses bzip2 files from an input stream.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	dsnetBzip2 "github.com/dsnet/compress/bzip2"
	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)

	// Using the dsnet library because the Go compression library does not
	// have a writer. There is recent discussion on this issue
	// https://github.com/golang/go/issues/4828 to add an encoder. The
	// library should be removed once there is a native encoder
	bz, err := dsnetBzip2.NewWriter(buffer, nil)
	if err != nil {
		log.Fatal(err)
	}

	tw := tar.NewWriter(bz)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	bz.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarBzip2Archive(bytes.NewReader(buffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

first
second
some-dir/some-other-dir/some-file
third

func NewTarBzip2Archive added in v0.12.1

func NewTarBzip2Archive(inputReader io.Reader) TarBzip2Archive

NewTarBzip2Archive returns a new Bzip2Archive that reads from inputReader.

func (TarBzip2Archive) Decompress added in v0.12.1

func (tbz TarBzip2Archive) Decompress(destination string) error

Decompress reads from TarBzip2Archive and writes files into the destination specified.

func (TarBzip2Archive) StripComponents added in v0.12.1

func (tbz TarBzip2Archive) StripComponents(components int) TarBzip2Archive

StripComponents behaves like the --strip-components flag on tar command removing the first n levels from the final decompression destination.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	dsnetBzip2 "github.com/dsnet/compress/bzip2"
	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)

	// Using the dsnet library because the Go compression library does not
	// have a writer. There is recent discussion on this issue
	// https://github.com/golang/go/issues/4828 to add an encoder. The
	// library should be removed once there is a native encoder
	bz, err := dsnetBzip2.NewWriter(buffer, nil)
	if err != nil {
		log.Fatal(err)
	}

	tw := tar.NewWriter(bz)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	bz.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarBzip2Archive(bytes.NewReader(buffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-other-dir/some-file

type TarGzipArchive

type TarGzipArchive struct {
	// contains filtered or unexported fields
}

A TarGzipArchive decompresses gziped tar files from an input stream.

Example
package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	gw := gzip.NewWriter(buffer)
	tw := tar.NewWriter(gw)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	gw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarGzipArchive(bytes.NewReader(buffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

first
second
some-dir/some-other-dir/some-file
third

func NewTarGzipArchive

func NewTarGzipArchive(inputReader io.Reader) TarGzipArchive

NewTarGzipArchive returns a new TarGzipArchive that reads from inputReader.

func (TarGzipArchive) Decompress

func (gz TarGzipArchive) Decompress(destination string) error

Decompress reads from TarGzipArchive and writes files into the destination specified.

func (TarGzipArchive) StripComponents

func (gz TarGzipArchive) StripComponents(components int) TarGzipArchive

StripComponents behaves like the --strip-components flag on tar command removing the first n levels from the final decompression destination.

Example
package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	gw := gzip.NewWriter(buffer)
	tw := tar.NewWriter(gw)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	gw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarGzipArchive(bytes.NewReader(buffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-other-dir/some-file

type TarXZArchive

type TarXZArchive struct {
	// contains filtered or unexported fields
}

A TarXZArchive decompresses xz tar files from an input stream.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
	"github.com/ulikunitz/xz"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	xw, err := xz.NewWriter(buffer)
	if err != nil {
		log.Fatal(err)
	}

	tw := tar.NewWriter(xw)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	xw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarXZArchive(bytes.NewReader(buffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

first
second
some-dir/some-other-dir/some-file
third

func NewTarXZArchive

func NewTarXZArchive(inputReader io.Reader) TarXZArchive

NewTarXZArchive returns a new TarXZArchive that reads from inputReader.

func (TarXZArchive) Decompress

func (txz TarXZArchive) Decompress(destination string) error

Decompress reads from TarXZArchive and writes files into the destination specified.

func (TarXZArchive) StripComponents

func (txz TarXZArchive) StripComponents(components int) TarXZArchive

StripComponents behaves like the --strip-components flag on tar command removing the first n levels from the final decompression destination.

Example
package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
	"github.com/ulikunitz/xz"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	xw, err := xz.NewWriter(buffer)
	if err != nil {
		log.Fatal(err)
	}

	tw := tar.NewWriter(xw)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		err := tw.WriteHeader(&tar.Header{Name: file.Name, Mode: 0755, Size: int64(len(file.Content))})
		if err != nil {
			log.Fatal(err)
		}

		_, err = tw.Write(file.Content)
		if err != nil {
			log.Fatal(err)
		}
	}

	tw.Close()
	xw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewTarXZArchive(bytes.NewReader(buffer.Bytes())).StripComponents(1)
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

some-other-dir/some-file

type ZipArchive

type ZipArchive struct {
	// contains filtered or unexported fields
}

A ZipArchive decompresses zip files from an input stream.

Example
package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/paketo-buildpacks/packit/vacation"
)

type ArchiveFile struct {
	Name    string
	Content []byte
}

func main() {
	buffer := bytes.NewBuffer(nil)
	zw := zip.NewWriter(buffer)

	files := []ArchiveFile{
		{Name: "some-dir/"},
		{Name: "some-dir/some-other-dir/"},
		{Name: "some-dir/some-other-dir/some-file", Content: []byte("some-dir/some-other-dir/some-file")},
		{Name: "first", Content: []byte("first")},
		{Name: "second", Content: []byte("second")},
		{Name: "third", Content: []byte("third")},
	}

	for _, file := range files {
		header := &zip.FileHeader{Name: file.Name}
		header.SetMode(0755)

		f, err := zw.CreateHeader(header)
		if err != nil {
			log.Fatal(err)
		}

		if _, err := f.Write(file.Content); err != nil {
			log.Fatal(err)
		}
	}

	zw.Close()

	destination, err := os.MkdirTemp("", "destination")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(destination)

	archive := vacation.NewZipArchive(bytes.NewReader(buffer.Bytes()))
	if err := archive.Decompress(destination); err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(destination, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			rel, err := filepath.Rel(destination, path)
			if err != nil {
				log.Fatal(err)
			}

			fmt.Printf("%s\n", rel)
			return nil
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

first
second
some-dir/some-other-dir/some-file
third

func NewZipArchive

func NewZipArchive(inputReader io.Reader) ZipArchive

NewZipArchive returns a new ZipArchive that reads from inputReader.

func (ZipArchive) Decompress

func (z ZipArchive) Decompress(destination string) error

Decompress reads from ZipArchive and writes files into the destination specified.

func (ZipArchive) StripComponents added in v0.14.2

func (z ZipArchive) StripComponents(components int) ZipArchive

StripComponents removes the first n levels from the final decompression destination.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL