Skip to content

Commit

Permalink
add unarchiver example
Browse files Browse the repository at this point in the history
  • Loading branch information
jm33-m0 committed Oct 24, 2024
1 parent 264c901 commit 80a21ab
Show file tree
Hide file tree
Showing 4 changed files with 483 additions and 2 deletions.
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ The first parameter to `FilesFromDisk()` is an optional options struct, allowing

Extracting an archive, extracting _from_ an archive, and walking an archive are all the same function.

Simply use your format type (e.g. `Zip`) to call `Extract()`. You'll pass in a context (for cancellation), the input stream, the list of files you want out of the archive, and a callback function to handle each file.
Simply use your format type (e.g. `Zip`) to call `Extract()`. You'll pass in a context (for cancellation), the input stream, the list of files you want out of the archive, and a callback function to handle each file.

If you want all the files, pass in a nil list of file paths.

Expand Down Expand Up @@ -167,6 +167,51 @@ if decom, ok := format.(archiver.Decompressor); ok {

`Identify()` works by reading an arbitrary number of bytes from the beginning of the stream (just enough to check for file headers). It buffers them and returns a new reader that lets you re-read them anew.

### Automatically identifying formats and extracting archives

Combining the above two features, you can automatically identify the format of an input stream and extract it:

```go
func Unarchive(tarball, dst string) error {
f, err := os.Open(tarball)
if err != nil {
return fmt.Errorf("open tarball %s: %w", tarball, err)
}
// Identify the format and input stream for the archive
format, input, err := archiver.Identify(tarball, f)
if err != nil {
return fmt.Errorf("identify format: %w", err)
}

// Check if the format supports extraction
extractor, ok := format.(archiver.Extractor)
if !ok {
return fmt.Errorf("unsupported format for extraction")
}

// Ensure the destination directory exists
if err := createDir(dst); err != nil {
return fmt.Errorf("creating destination directory: %w", err)
}

// Extract files using the official handler
handler := func(ctx context.Context, f archiver.File) error {
log.Printf("Processing file: %s", f.NameInArchive)
return handleFile(f, dst) // implement handleFile to write the file to destination
}

// Use the extractor to process all files in the archive
if err := extractor.Extract(context.Background(), input, nil, handler); err != nil {
return fmt.Errorf("extracting files: %w", err)
}

log.Printf("Unarchiving completed successfully.")
return nil
}
```

See the [example](./examples/unarchiver) for details.

### Virtual file systems

This is my favorite feature.
Expand Down Expand Up @@ -257,7 +302,7 @@ http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
// disable range request
writer.Header().Set("Accept-Ranges", "none")
request.Header.Del("Range")

// disable content-type sniffing
ctype := mime.TypeByExtension(filepath.Ext(request.URL.Path))
writer.Header()["Content-Type"] = nil
Expand Down
25 changes: 25 additions & 0 deletions examples/unarchiver/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module unarchiver

go 1.22.7

require github.com/mholt/archiver/v4 v4.0.0-alpha.8

require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bodgit/plumbing v1.2.0 // indirect
github.com/bodgit/sevenzip v1.3.0 // indirect
github.com/bodgit/windows v1.0.0 // indirect
github.com/connesc/cipherio v0.2.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/text v0.3.8 // indirect
)
Loading

0 comments on commit 80a21ab

Please sign in to comment.