archives

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2024 License: LGPL-3.0 Imports: 15 Imported by: 0

README

archives

Latest Version License Github Workflow Status Codecov

Go library for extracting archives (tar, zip, etc.)

Supported Archive Types

  • tar
    • tar.xz - xz
    • tar.bz2 - bzip2
    • tar.gz - gzip
    • tar.zst - zstd
  • zip

Usage

For complete documentation and examples, see our pkg.go.dev documentation.

Extracting Archives

Extracting archives is simple with this package. Simply provide an io.Reader and the extension (which you can use archives.Ext to get!) and you're good to go.

resp, err := http.Get("https://getsamplefiles.com/download/zip/sample-1.zip")
if err != nil {}
defer resp.Body.Close()

err := archives.Extract(resp.Body, "dir-to-extract-into", &archives.ExtractOptions{
  Extension: archives.Ext("sample-1.zip"),
})
if err != nil {}

// Do something with the files in dir-to-extract-into
Picking a File out of an Archive

Sometimes you want to only grab a single file out of an archive. archives.Pick is helpful here.

resp, err := http.Get("https://getsamplefiles.com/download/zip/sample-1.zip")
if err != nil {}
defer resp.Body.Close()

a, err := archives.Open(resp.Body, &archives.OpenOptions{
  Extension: archives.Ext("sample-1.zip"),
})
if err != nil {}

// Pick a single file out of the zip archive
r, err := archives.Pick(a, archives.PickFilterByName("sample-1/sample-1.webp"))
if err != nil {}

// Do something with the returned [io.Reader] (r).
Working with Archives

You can also work with an archive directly, much like tar.Reader.

resp, err := http.Get("https://getsamplefiles.com/download/tar/sample-1.tar")
if err != nil {}
defer resp.Body.Close()

a, err := archives.Open(resp.Body, &archives.OpenOptions{
  Extension: archives.Ext("sample-1.tar"),
})
if err != nil {}

h, err := a.Next()
if err != nil {}

// Read the current file using `a` ([Archive]) which is an io.Reader,
// or only handle the `h` ([Header]). Your choice!

// Close out the archiver parser(s).
a.Close()
CGO

CGO is used for extracting xz archives by default. If you wish to not use CGO, simply set CGO_ENABLED to 0. This library will automatically use a pure-Go implementation instead.

License

LGPL-3.0

Documentation

Overview

Package archives provides functions for working with compressed archives.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Ext

func Ext(name string) string

Ext returns the extension of a file name based on the supported extensions in this package. If the extension is not supported, the output of filepath.Ext will be returned instead.

Examples:

archives.Ext("file.tar.gz")   // ".tar.gz"
archives.Ext("file.zip")      // ".zip"
archives.Ext("file.unknown")  // ".unknown"

func Extract

func Extract(r io.Reader, dest string, opts ExtractOptions) error

Extract extracts an archive to the provided destination. The underlying Archiver is determined by the extension of the archive.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/jaredallard/archives"
	"github.com/jaredallard/archives/internal/tartest"
)

func main() {
	tarArchive, err := tartest.Create()
	if err != nil {
		panic(err)
	}

	// Create a temporary directory to extract the archive to.
	tmpDir, err := os.MkdirTemp("", "archives-test")
	if err != nil {
		panic(err)
	}
	defer os.RemoveAll(tmpDir) // Remove the temporary directory when done.

	// Open the archive.
	if err := archives.Extract(tarArchive, tmpDir, archives.ExtractOptions{
		Extension: ".tar",
	}); err != nil {
		panic(err)
	}

	// Read the extracted file.
	got, err := os.ReadFile(filepath.Join(tmpDir, "file.txt"))
	if err != nil {
		panic(err)
	}

	fmt.Println(string(got))

}
Output:

hello world

func Pick

func Pick(a Archive, filter PickFilterFn) (io.Reader, error)

Pick returns an io.Reader that returns a specific file from the provided Archive. The file is determined by the provided filter function.

If the caller intends to pick one file from an archive, they should also make sure to close the archive after they are done with the returned io.Reader to prevent resource leaks.

Example
package main

import (
	"fmt"
	"io"

	"github.com/jaredallard/archives"
	"github.com/jaredallard/archives/internal/tartest"
)

func main() {
	tarArchive, err := tartest.Create()
	if err != nil {
		panic(err)
	}

	// Open the archive.
	a, err := archives.Open(tarArchive, archives.OpenOptions{
		Extension: ".tar",
	})
	if err != nil {
		panic(err)
	}

	// Pick a single file from the archive.
	r, err := archives.Pick(a, archives.PickFilterByName("file.txt"))
	if err != nil {
		panic(err)
	}

	// Do something with the reader.
	b, err := io.ReadAll(r)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))

}
Output:

hello world

Types

type Archive

type Archive interface {
	io.Reader

	// Close closes the archive. No other methods should be called after
	// this.
	Close() error

	// Next returns a header for the next file in the archive. If there
	// are no more files, it will return io.EOF. When called, the embedded
	// [io.Reader] will target the file in the returned [Header].
	Next() (*Header, error)
}

Archive represents an archive containing folders and files.

func Open

func Open(r io.Reader, opts OpenOptions) (Archive, error)

Open opens an archive from the provided reader. The underlying Archiver is determined by the extension of the archive.

type Archiver

type Archiver interface {
	// Open opens the provided reader and returns an archive. Depending on
	// the implementation, this may read the entire archive into memory
	// (e.g., zip).
	Open(r io.Reader, ext string) (Archive, error)

	// Extensions should return a list of supported extensions for this
	// extractor.
	Extensions() []string
}

Archiver is an interface for interacting with creating [Archive]s from [io.Reader]s.

type ExtractOptions

type ExtractOptions struct {
	// Extension is the extension of the archive to extract. This is
	// required.
	//
	// Extension should be complete, including the leading period. For
	// example:
	//		 .tar
	// 		 .tar.gz
	Extension string

	// PreservePermissions, if set, will preserve the permissions of the
	// files in the archive.
	//
	// Defaults to true.
	PreservePermissions *bool

	// PreserveOwnership, if set, will preserve the ownership of the files
	// in the archive. If false, the files will be owned by the user
	// running the program.
	//
	// Defaults to false.
	PreserveOwnership bool
}

ExtractOptions contains the options for extracting an archive.

type Header struct {
	// Name is the name of the file or directory.
	Name string

	// Type is the type of header.
	Type HeaderType

	// Size is the size of the file. If the header is a directory, this
	// will be 0.
	Size int64

	// Mode is the file mode.
	Mode os.FileMode

	// AccessTime is the time the file was last accessed.
	AccessTime time.Time

	// ModTime is the time the file was last modified.
	ModTime time.Time

	// UID is the user ID of the file.
	UID int

	// GID is the group ID of the file.
	GID int
}

Header represents metadata about a file in an archive.

type HeaderType

type HeaderType int

HeaderType denotes a type of header. Not all extractors may support all header types.

const (
	HeaderFile HeaderType = iota
	HeaderDir
)

Contains the supported header types.

type OpenOptions

type OpenOptions struct {
	// Extension is the extension of the archive to extract. This is
	// required.
	//
	// Extension should be complete, including the leading period. This
	// should be the output of [Ext] to ensure that the extension contains
	// all formats (e.g., .tar.gz and .zip). If you opt to use
	// [filepath.Ext] it will not include the second extension.
	Extension string
}

OpenOptions contains the options for opening an archive.

type PickFilterFn

type PickFilterFn func(*Header) bool

PickFilterFn is a function that filters files in an archive.

func PickFilterByName

func PickFilterByName(name string) PickFilterFn

PickFilterByName returns a PickFilterFn that filters files by name.

Directories

Path Synopsis
internal
tartest
Package tartest contains helpers for creating tar archives for usage in tests in the archives package.
Package tartest contains helpers for creating tar archives for usage in tests in the archives package.

Jump to

Keyboard shortcuts

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