You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2025-11-28 10:24:03 +03:00
Refactor repository layout and convert build system to Mage.
This commit implements a massive refactor of the repository, and moves the build system over to use Mage (magefile.org) which should allow seamless building across multiple platforms.
This commit is contained in:
21
vendor/github.com/mholt/archiver/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mholt/archiver/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Matthew Holt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
83
vendor/github.com/mholt/archiver/README.md
generated
vendored
Normal file
83
vendor/github.com/mholt/archiver/README.md
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
archiver [](https://godoc.org/github.com/mholt/archiver) [](https://travis-ci.org/mholt/archiver) [](https://ci.appveyor.com/project/mholt/archiver)
|
||||
========
|
||||
|
||||
Package archiver makes it trivially easy to make and extract common archive formats such as .zip, and .tar.gz. Simply name the input and output file(s).
|
||||
|
||||
Files are put into the root of the archive; directories are recursively added, preserving structure.
|
||||
|
||||
The `archiver` command runs the same cross-platform and has no external dependencies (not even libc); powered by the Go standard library, [dsnet/compress](https://github.com/dsnet/compress), [nwaples/rardecode](https://github.com/nwaples/rardecode), and [ulikunitz/xz](https://github.com/ulikunitz/xz). Enjoy!
|
||||
|
||||
Supported formats/extensions:
|
||||
|
||||
- .zip
|
||||
- .tar
|
||||
- .tar.gz & .tgz
|
||||
- .tar.bz2 & .tbz2
|
||||
- .tar.xz & .txz
|
||||
- .tar.lz4 & .tlz4
|
||||
- .tar.sz & .tsz
|
||||
- .rar (open only)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
go get github.com/mholt/archiver/cmd/archiver
|
||||
```
|
||||
|
||||
Or download binaries from the [releases](https://github.com/mholt/archiver/releases) page.
|
||||
|
||||
|
||||
## Command Use
|
||||
|
||||
Make a new archive:
|
||||
|
||||
```bash
|
||||
$ archiver make [archive name] [input files...]
|
||||
```
|
||||
|
||||
(At least one input file is required.)
|
||||
|
||||
To extract an archive:
|
||||
|
||||
```bash
|
||||
$ archiver open [archive name] [destination]
|
||||
```
|
||||
|
||||
(The destination path is optional; default is current directory.)
|
||||
|
||||
The archive name must end with a supported file extension—this is how it knows what kind of archive to make. Run `archiver -h` for more help.
|
||||
|
||||
|
||||
## Library Use
|
||||
|
||||
```go
|
||||
import "github.com/mholt/archiver"
|
||||
```
|
||||
|
||||
Create a .zip file:
|
||||
|
||||
```go
|
||||
err := archiver.Zip.Make("output.zip", []string{"file.txt", "folder"})
|
||||
```
|
||||
|
||||
Extract a .zip file:
|
||||
|
||||
```go
|
||||
err := archiver.Zip.Open("input.zip", "output_folder")
|
||||
```
|
||||
|
||||
Working with other file formats is exactly the same, but with [their own Archiver implementations](https://godoc.org/github.com/mholt/archiver#Archiver).
|
||||
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
#### Can I list a file in one folder to go into a different folder in the archive?
|
||||
|
||||
No. This works just like your OS would make an archive in the file explorer: organize your input files to mirror the structure you want in the archive.
|
||||
|
||||
|
||||
#### Can it add files to an existing archive?
|
||||
|
||||
Nope. This is a simple tool; it just makes new archives or extracts existing ones.
|
||||
32
vendor/github.com/mholt/archiver/appveyor.yml
generated
vendored
Normal file
32
vendor/github.com/mholt/archiver/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
version: "{build}"
|
||||
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\mholt\archiver
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
CGO_ENABLED: 0
|
||||
|
||||
install:
|
||||
- rmdir c:\go /s /q
|
||||
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.1.windows-amd64.zip
|
||||
- 7z x go1.7.1.windows-amd64.zip -y -oC:\ > NUL
|
||||
- go version
|
||||
- go env
|
||||
- go get -t ./...
|
||||
- go get github.com/golang/lint/golint
|
||||
- go get github.com/gordonklaus/ineffassign
|
||||
- set PATH=%GOPATH%\bin;%PATH%
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- go vet ./...
|
||||
- go test ./...
|
||||
- ineffassign .
|
||||
|
||||
after_test:
|
||||
- golint ./...
|
||||
|
||||
deploy: off
|
||||
107
vendor/github.com/mholt/archiver/archiver.go
generated
vendored
Normal file
107
vendor/github.com/mholt/archiver/archiver.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Archiver represent a archive format
|
||||
type Archiver interface {
|
||||
// Match checks supported files
|
||||
Match(filename string) bool
|
||||
// Make makes an archive file on disk.
|
||||
Make(destination string, sources []string) error
|
||||
// Open extracts an archive file on disk.
|
||||
Open(source, destination string) error
|
||||
// Write writes an archive to a Writer.
|
||||
Write(output io.Writer, sources []string) error
|
||||
// Read reads an archive from a Reader.
|
||||
Read(input io.Reader, destination string) error
|
||||
}
|
||||
|
||||
// SupportedFormats contains all supported archive formats
|
||||
var SupportedFormats = map[string]Archiver{}
|
||||
|
||||
// RegisterFormat adds a supported archive format
|
||||
func RegisterFormat(name string, format Archiver) {
|
||||
if _, ok := SupportedFormats[name]; ok {
|
||||
log.Printf("Format %s already exists, skip!\n", name)
|
||||
return
|
||||
}
|
||||
SupportedFormats[name] = format
|
||||
}
|
||||
|
||||
// MatchingFormat returns the first archive format that matches
|
||||
// the given file, or nil if there is no match
|
||||
func MatchingFormat(fpath string) Archiver {
|
||||
for _, fmt := range SupportedFormats {
|
||||
if fmt.Match(fpath) {
|
||||
return fmt
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeNewFile(fpath string, in io.Reader, fm os.FileMode) error {
|
||||
err := os.MkdirAll(filepath.Dir(fpath), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
|
||||
}
|
||||
|
||||
out, err := os.Create(fpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: creating new file: %v", fpath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
err = out.Chmod(fm)
|
||||
if err != nil && runtime.GOOS != "windows" {
|
||||
return fmt.Errorf("%s: changing file mode: %v", fpath, err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: writing file: %v", fpath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeNewSymbolicLink(fpath string, target string) error {
|
||||
err := os.MkdirAll(filepath.Dir(fpath), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
|
||||
}
|
||||
|
||||
err = os.Symlink(target, fpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making symbolic link for: %v", fpath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeNewHardLink(fpath string, target string) error {
|
||||
err := os.MkdirAll(filepath.Dir(fpath), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
|
||||
}
|
||||
|
||||
err = os.Link(target, fpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making hard link for: %v", fpath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mkdir(dirPath string) error {
|
||||
err := os.MkdirAll(dirPath, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making directory: %v", dirPath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
21
vendor/github.com/mholt/archiver/build.bash
generated
vendored
Executable file
21
vendor/github.com/mholt/archiver/build.bash
generated
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
# This script builds archiver for most common platforms.
|
||||
|
||||
export CGO_ENABLED=0
|
||||
|
||||
cd cmd/archiver
|
||||
GOOS=linux GOARCH=386 go build -o ../../builds/archiver_linux_386
|
||||
GOOS=linux GOARCH=amd64 go build -o ../../builds/archiver_linux_amd64
|
||||
GOOS=linux GOARCH=arm go build -o ../../builds/archiver_linux_arm7
|
||||
GOOS=linux GOARCH=arm64 go build -o ../../builds/archiver_linux_arm64
|
||||
GOOS=darwin GOARCH=amd64 go build -o ../../builds/archiver_mac_amd64
|
||||
GOOS=windows GOARCH=386 go build -o ../../builds/archiver_windows_386.exe
|
||||
GOOS=windows GOARCH=amd64 go build -o ../../builds/archiver_windows_amd64.exe
|
||||
GOOS=freebsd GOARCH=386 go build -o ../../builds/archiver_freebsd_386
|
||||
GOOS=freebsd GOARCH=amd64 go build -o ../../builds/archiver_freebsd_amd64
|
||||
GOOS=freebsd GOARCH=arm go build -o ../../builds/archiver_freebsd_arm7
|
||||
GOOS=openbsd GOARCH=386 go build -o ../../builds/archiver_openbsd_386
|
||||
GOOS=openbsd GOARCH=amd64 go build -o ../../builds/archiver_openbsd_amd64
|
||||
cd ../..
|
||||
109
vendor/github.com/mholt/archiver/rar.go
generated
vendored
Normal file
109
vendor/github.com/mholt/archiver/rar.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/nwaples/rardecode"
|
||||
)
|
||||
|
||||
// Rar is for RAR archive format
|
||||
var Rar rarFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("Rar", Rar)
|
||||
}
|
||||
|
||||
type rarFormat struct{}
|
||||
|
||||
func (rarFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".rar") || isRar(filename)
|
||||
}
|
||||
|
||||
// isRar checks the file has the RAR 1.5 or 5.0 format signature by reading its
|
||||
// beginning bytes and matching it
|
||||
func isRar(rarPath string) bool {
|
||||
f, err := os.Open(rarPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
buf := make([]byte, 8)
|
||||
if n, err := f.Read(buf); err != nil || n < 8 {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(buf[:7], []byte("Rar!\x1a\x07\x00")) || // ver 1.5
|
||||
bytes.Equal(buf, []byte("Rar!\x1a\x07\x01\x00")) // ver 5.0
|
||||
}
|
||||
|
||||
// Write outputs a .rar archive, but this is not implemented because
|
||||
// RAR is a proprietary format. It is here only for symmetry with
|
||||
// the other archive formats in this package.
|
||||
func (rarFormat) Write(output io.Writer, filePaths []string) error {
|
||||
return fmt.Errorf("write: RAR not implemented (proprietary format)")
|
||||
}
|
||||
|
||||
// Make makes a .rar archive, but this is not implemented because
|
||||
// RAR is a proprietary format. It is here only for symmetry with
|
||||
// the other archive formats in this package.
|
||||
func (rarFormat) Make(rarPath string, filePaths []string) error {
|
||||
return fmt.Errorf("make %s: RAR not implemented (proprietary format)", rarPath)
|
||||
}
|
||||
|
||||
// Read extracts the RAR file read from input and puts the contents
|
||||
// into destination.
|
||||
func (rarFormat) Read(input io.Reader, destination string) error {
|
||||
rr, err := rardecode.NewReader(input, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("read: failed to create reader: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
header, err := rr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if header.IsDir {
|
||||
err = mkdir(filepath.Join(destination, header.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// if files come before their containing folders, then we must
|
||||
// create their folders before writing the file
|
||||
err = mkdir(filepath.Dir(filepath.Join(destination, header.Name)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeNewFile(filepath.Join(destination, header.Name), rr, header.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open extracts the RAR file at source and puts the contents
|
||||
// into destination.
|
||||
func (rarFormat) Open(source, destination string) error {
|
||||
rf, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open file: %v", source, err)
|
||||
}
|
||||
defer rf.Close()
|
||||
|
||||
return Rar.Read(rf, destination)
|
||||
}
|
||||
234
vendor/github.com/mholt/archiver/tar.go
generated
vendored
Normal file
234
vendor/github.com/mholt/archiver/tar.go
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Tar is for Tar format
|
||||
var Tar tarFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("Tar", Tar)
|
||||
}
|
||||
|
||||
type tarFormat struct{}
|
||||
|
||||
func (tarFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar") || isTar(filename)
|
||||
}
|
||||
|
||||
const tarBlockSize int = 512
|
||||
|
||||
// isTar checks the file has the Tar format header by reading its beginning
|
||||
// block.
|
||||
func isTar(tarPath string) bool {
|
||||
f, err := os.Open(tarPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
buf := make([]byte, tarBlockSize)
|
||||
if _, err = io.ReadFull(f, buf); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// hasTarHeader checks passed bytes has a valid tar header or not. buf must
|
||||
// contain at least 512 bytes and if not, it always returns false.
|
||||
func hasTarHeader(buf []byte) bool {
|
||||
if len(buf) < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
b := buf[148:156]
|
||||
b = bytes.Trim(b, " \x00") // clean up all spaces and null bytes
|
||||
if len(b) == 0 {
|
||||
return false // unknown format
|
||||
}
|
||||
hdrSum, err := strconv.ParseUint(string(b), 8, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// According to the go official archive/tar, Sun tar uses signed byte
|
||||
// values so this calcs both signed and unsigned
|
||||
var usum uint64
|
||||
var sum int64
|
||||
for i, c := range buf {
|
||||
if 148 <= i && i < 156 {
|
||||
c = ' ' // checksum field itself is counted as branks
|
||||
}
|
||||
usum += uint64(uint8(c))
|
||||
sum += int64(int8(c))
|
||||
}
|
||||
|
||||
if hdrSum != usum && int64(hdrSum) != sum {
|
||||
return false // invalid checksum
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Write outputs a .tar file to a Writer containing the
|
||||
// contents of files listed in filePaths. File paths can
|
||||
// be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarFormat) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTar(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar file at tarPath containing the
|
||||
// contents of files listed in filePaths. File paths can
|
||||
// be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarFormat) Make(tarPath string, filePaths []string) error {
|
||||
out, err := os.Create(tarPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", tarPath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTar(filePaths, out, tarPath)
|
||||
}
|
||||
|
||||
func writeTar(filePaths []string, output io.Writer, dest string) error {
|
||||
tarWriter := tar.NewWriter(output)
|
||||
defer tarWriter.Close()
|
||||
|
||||
return tarball(filePaths, tarWriter, dest)
|
||||
}
|
||||
|
||||
// tarball writes all files listed in filePaths into tarWriter, which is
|
||||
// writing into a file located at dest.
|
||||
func tarball(filePaths []string, tarWriter *tar.Writer, dest string) error {
|
||||
for _, fpath := range filePaths {
|
||||
err := tarFile(tarWriter, fpath, dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// tarFile writes the file at source into tarWriter. It does so
|
||||
// recursively for directories.
|
||||
func tarFile(tarWriter *tar.Writer, source, dest string) error {
|
||||
sourceInfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: stat: %v", source, err)
|
||||
}
|
||||
|
||||
var baseDir string
|
||||
if sourceInfo.IsDir() {
|
||||
baseDir = filepath.Base(source)
|
||||
}
|
||||
|
||||
return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error walking to %s: %v", path, err)
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making header: %v", path, err)
|
||||
}
|
||||
|
||||
if baseDir != "" {
|
||||
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
|
||||
}
|
||||
|
||||
if header.Name == dest {
|
||||
// our new tar file is inside the directory being archived; skip it
|
||||
return nil
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
}
|
||||
|
||||
err = tarWriter.WriteHeader(header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: writing header: %v", path, err)
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if header.Typeflag == tar.TypeReg {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: open: %v", path, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.CopyN(tarWriter, file, info.Size())
|
||||
if err != nil && err != io.EOF {
|
||||
return fmt.Errorf("%s: copying contents: %v", path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Read untars a .tar file read from a Reader and puts
|
||||
// the contents into destination.
|
||||
func (tarFormat) Read(input io.Reader, destination string) error {
|
||||
return untar(tar.NewReader(input), destination)
|
||||
}
|
||||
|
||||
// Open untars source and puts the contents into destination.
|
||||
func (tarFormat) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return Tar.Read(f, destination)
|
||||
}
|
||||
|
||||
// untar un-tarballs the contents of tr into destination.
|
||||
func untar(tr *tar.Reader, destination string) error {
|
||||
for {
|
||||
header, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := untarFile(tr, header, destination); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// untarFile untars a single file from tr with header header into destination.
|
||||
func untarFile(tr *tar.Reader, header *tar.Header, destination string) error {
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
return mkdir(filepath.Join(destination, header.Name))
|
||||
case tar.TypeReg, tar.TypeRegA, tar.TypeChar, tar.TypeBlock, tar.TypeFifo:
|
||||
return writeNewFile(filepath.Join(destination, header.Name), tr, header.FileInfo().Mode())
|
||||
case tar.TypeSymlink:
|
||||
return writeNewSymbolicLink(filepath.Join(destination, header.Name), header.Linkname)
|
||||
case tar.TypeLink:
|
||||
return writeNewHardLink(filepath.Join(destination, header.Name), filepath.Join(destination, header.Linkname))
|
||||
default:
|
||||
return fmt.Errorf("%s: unknown type flag: %c", header.Name, header.Typeflag)
|
||||
}
|
||||
}
|
||||
106
vendor/github.com/mholt/archiver/tarbz2.go
generated
vendored
Normal file
106
vendor/github.com/mholt/archiver/tarbz2.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dsnet/compress/bzip2"
|
||||
)
|
||||
|
||||
// TarBz2 is for TarBz2 format
|
||||
var TarBz2 tarBz2Format
|
||||
|
||||
func init() {
|
||||
RegisterFormat("TarBz2", TarBz2)
|
||||
}
|
||||
|
||||
type tarBz2Format struct{}
|
||||
|
||||
func (tarBz2Format) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar.bz2") ||
|
||||
strings.HasSuffix(strings.ToLower(filename), ".tbz2") ||
|
||||
isTarBz2(filename)
|
||||
}
|
||||
|
||||
// isTarBz2 checks the file has the bzip2 compressed Tar format header by
|
||||
// reading its beginning block.
|
||||
func isTarBz2(tarbz2Path string) bool {
|
||||
f, err := os.Open(tarbz2Path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
bz2r, err := bzip2.NewReader(f, nil)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer bz2r.Close()
|
||||
|
||||
buf := make([]byte, tarBlockSize)
|
||||
n, err := bz2r.Read(buf)
|
||||
if err != nil || n < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// Write outputs a .tar.bz2 file to a Writer containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarBz2Format) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTarBz2(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar.bz2 file at tarbz2Path containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarBz2Format) Make(tarbz2Path string, filePaths []string) error {
|
||||
out, err := os.Create(tarbz2Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", tarbz2Path, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTarBz2(filePaths, out, tarbz2Path)
|
||||
}
|
||||
|
||||
func writeTarBz2(filePaths []string, output io.Writer, dest string) error {
|
||||
bz2w, err := bzip2.NewWriter(output, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error compressing bzip2: %v", err)
|
||||
}
|
||||
defer bz2w.Close()
|
||||
|
||||
return writeTar(filePaths, bz2w, dest)
|
||||
}
|
||||
|
||||
// Read untars a .tar.bz2 file read from a Reader and decompresses
|
||||
// the contents into destination.
|
||||
func (tarBz2Format) Read(input io.Reader, destination string) error {
|
||||
bz2r, err := bzip2.NewReader(input, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decompressing bzip2: %v", err)
|
||||
}
|
||||
defer bz2r.Close()
|
||||
|
||||
return Tar.Read(bz2r, destination)
|
||||
}
|
||||
|
||||
// Open untars source and decompresses the contents into destination.
|
||||
func (tarBz2Format) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return TarBz2.Read(f, destination)
|
||||
}
|
||||
98
vendor/github.com/mholt/archiver/targz.go
generated
vendored
Normal file
98
vendor/github.com/mholt/archiver/targz.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TarGz is for TarGz format
|
||||
var TarGz tarGzFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("TarGz", TarGz)
|
||||
}
|
||||
|
||||
type tarGzFormat struct{}
|
||||
|
||||
func (tarGzFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar.gz") ||
|
||||
strings.HasSuffix(strings.ToLower(filename), ".tgz") ||
|
||||
isTarGz(filename)
|
||||
}
|
||||
|
||||
// isTarGz checks the file has the gzip compressed Tar format header by reading
|
||||
// its beginning block.
|
||||
func isTarGz(targzPath string) bool {
|
||||
f, err := os.Open(targzPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
gzr, err := gzip.NewReader(f)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer gzr.Close()
|
||||
|
||||
buf := make([]byte, tarBlockSize)
|
||||
n, err := gzr.Read(buf)
|
||||
if err != nil || n < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// Write outputs a .tar.gz file to a Writer containing
|
||||
// the contents of files listed in filePaths. It works
|
||||
// the same way Tar does, but with gzip compression.
|
||||
func (tarGzFormat) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTarGz(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar.gz file at targzPath containing
|
||||
// the contents of files listed in filePaths. It works
|
||||
// the same way Tar does, but with gzip compression.
|
||||
func (tarGzFormat) Make(targzPath string, filePaths []string) error {
|
||||
out, err := os.Create(targzPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", targzPath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTarGz(filePaths, out, targzPath)
|
||||
}
|
||||
|
||||
func writeTarGz(filePaths []string, output io.Writer, dest string) error {
|
||||
gzw := gzip.NewWriter(output)
|
||||
defer gzw.Close()
|
||||
|
||||
return writeTar(filePaths, gzw, dest)
|
||||
}
|
||||
|
||||
// Read untars a .tar.gz file read from a Reader and decompresses
|
||||
// the contents into destination.
|
||||
func (tarGzFormat) Read(input io.Reader, destination string) error {
|
||||
gzr, err := gzip.NewReader(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decompressing: %v", err)
|
||||
}
|
||||
defer gzr.Close()
|
||||
|
||||
return Tar.Read(gzr, destination)
|
||||
}
|
||||
|
||||
// Open untars source and decompresses the contents into destination.
|
||||
func (tarGzFormat) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return TarGz.Read(f, destination)
|
||||
}
|
||||
92
vendor/github.com/mholt/archiver/tarlz4.go
generated
vendored
Normal file
92
vendor/github.com/mholt/archiver/tarlz4.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pierrec/lz4"
|
||||
)
|
||||
|
||||
// TarLz4 is for TarLz4 format
|
||||
var TarLz4 tarLz4Format
|
||||
|
||||
func init() {
|
||||
RegisterFormat("TarLz4", TarLz4)
|
||||
}
|
||||
|
||||
type tarLz4Format struct{}
|
||||
|
||||
func (tarLz4Format) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar.lz4") || strings.HasSuffix(strings.ToLower(filename), ".tlz4") || isTarLz4(filename)
|
||||
}
|
||||
|
||||
// isTarLz4 checks the file has the lz4 compressed Tar format header by
|
||||
// reading its beginning block.
|
||||
func isTarLz4(tarlz4Path string) bool {
|
||||
f, err := os.Open(tarlz4Path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
lz4r := lz4.NewReader(f)
|
||||
buf := make([]byte, tarBlockSize)
|
||||
n, err := lz4r.Read(buf)
|
||||
if err != nil || n < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// Write outputs a .tar.lz4 file to a Writer containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarLz4Format) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTarLz4(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar.lz4 file at tarlz4Path containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarLz4Format) Make(tarlz4Path string, filePaths []string) error {
|
||||
out, err := os.Create(tarlz4Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", tarlz4Path, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTarLz4(filePaths, out, tarlz4Path)
|
||||
}
|
||||
|
||||
func writeTarLz4(filePaths []string, output io.Writer, dest string) error {
|
||||
lz4w := lz4.NewWriter(output)
|
||||
defer lz4w.Close()
|
||||
|
||||
return writeTar(filePaths, lz4w, dest)
|
||||
}
|
||||
|
||||
// Read untars a .tar.xz file read from a Reader and decompresses
|
||||
// the contents into destination.
|
||||
func (tarLz4Format) Read(input io.Reader, destination string) error {
|
||||
lz4r := lz4.NewReader(input)
|
||||
|
||||
return Tar.Read(lz4r, destination)
|
||||
}
|
||||
|
||||
// Open untars source and decompresses the contents into destination.
|
||||
func (tarLz4Format) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return TarLz4.Read(f, destination)
|
||||
}
|
||||
92
vendor/github.com/mholt/archiver/tarsz.go
generated
vendored
Normal file
92
vendor/github.com/mholt/archiver/tarsz.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
)
|
||||
|
||||
// TarSz is for TarSz format
|
||||
var TarSz tarSzFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("TarSz", TarSz)
|
||||
}
|
||||
|
||||
type tarSzFormat struct{}
|
||||
|
||||
func (tarSzFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar.sz") || strings.HasSuffix(strings.ToLower(filename), ".tsz") || isTarSz(filename)
|
||||
}
|
||||
|
||||
// isTarSz checks the file has the sz compressed Tar format header by
|
||||
// reading its beginning block.
|
||||
func isTarSz(tarszPath string) bool {
|
||||
f, err := os.Open(tarszPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
szr := snappy.NewReader(f)
|
||||
buf := make([]byte, tarBlockSize)
|
||||
n, err := szr.Read(buf)
|
||||
if err != nil || n < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// Write outputs a .tar.sz file to a Writer containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarSzFormat) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTarSz(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar.sz file at tarszPath containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (tarSzFormat) Make(tarszPath string, filePaths []string) error {
|
||||
out, err := os.Create(tarszPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", tarszPath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTarSz(filePaths, out, tarszPath)
|
||||
}
|
||||
|
||||
func writeTarSz(filePaths []string, output io.Writer, dest string) error {
|
||||
szw := snappy.NewBufferedWriter(output)
|
||||
defer szw.Close()
|
||||
|
||||
return writeTar(filePaths, szw, dest)
|
||||
}
|
||||
|
||||
// Read untars a .tar.sz file read from a Reader and decompresses
|
||||
// the contents into destination.
|
||||
func (tarSzFormat) Read(input io.Reader, destination string) error {
|
||||
szr := snappy.NewReader(input)
|
||||
|
||||
return Tar.Read(szr, destination)
|
||||
}
|
||||
|
||||
// Open untars source and decompresses the contents into destination.
|
||||
func (tarSzFormat) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return TarSz.Read(f, destination)
|
||||
}
|
||||
105
vendor/github.com/mholt/archiver/tarxz.go
generated
vendored
Normal file
105
vendor/github.com/mholt/archiver/tarxz.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ulikunitz/xz"
|
||||
)
|
||||
|
||||
// TarXZ is for TarXZ format
|
||||
var TarXZ xzFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("TarXZ", TarXZ)
|
||||
}
|
||||
|
||||
type xzFormat struct{}
|
||||
|
||||
// Match returns whether filename matches this format.
|
||||
func (xzFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".tar.xz") ||
|
||||
strings.HasSuffix(strings.ToLower(filename), ".txz") ||
|
||||
isTarXz(filename)
|
||||
}
|
||||
|
||||
// isTarXz checks the file has the xz compressed Tar format header by reading
|
||||
// its beginning block.
|
||||
func isTarXz(tarxzPath string) bool {
|
||||
f, err := os.Open(tarxzPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
xzr, err := xz.NewReader(f)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
buf := make([]byte, tarBlockSize)
|
||||
n, err := xzr.Read(buf)
|
||||
if err != nil || n < tarBlockSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return hasTarHeader(buf)
|
||||
}
|
||||
|
||||
// Write outputs a .tar.xz file to a Writer containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
func (xzFormat) Write(output io.Writer, filePaths []string) error {
|
||||
return writeTarXZ(filePaths, output, "")
|
||||
}
|
||||
|
||||
// Make creates a .tar.xz file at xzPath containing
|
||||
// the contents of files listed in filePaths. File
|
||||
// paths can be those of regular files or directories.
|
||||
// Regular files are stored at the 'root' of the
|
||||
// archive, and directories are recursively added.
|
||||
func (xzFormat) Make(xzPath string, filePaths []string) error {
|
||||
out, err := os.Create(xzPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", xzPath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return writeTarXZ(filePaths, out, xzPath)
|
||||
}
|
||||
|
||||
func writeTarXZ(filePaths []string, output io.Writer, dest string) error {
|
||||
xzw, err := xz.NewWriter(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error compressing xz: %v", err)
|
||||
}
|
||||
defer xzw.Close()
|
||||
|
||||
return writeTar(filePaths, xzw, dest)
|
||||
}
|
||||
|
||||
// Read untars a .tar.xz file read from a Reader and decompresses
|
||||
// the contents into destination.
|
||||
func (xzFormat) Read(input io.Reader, destination string) error {
|
||||
xzr, err := xz.NewReader(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decompressing xz: %v", err)
|
||||
}
|
||||
|
||||
return Tar.Read(xzr, destination)
|
||||
}
|
||||
|
||||
// Open untars source and decompresses the contents into destination.
|
||||
func (xzFormat) Open(source, destination string) error {
|
||||
f, err := os.Open(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to open archive: %v", source, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return TarXZ.Read(f, destination)
|
||||
}
|
||||
233
vendor/github.com/mholt/archiver/zip.go
generated
vendored
Normal file
233
vendor/github.com/mholt/archiver/zip.go
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// Package archiver makes it super easy to create and open .zip,
|
||||
// .tar.gz, and .tar.bz2 files.
|
||||
package archiver
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Zip is for Zip format
|
||||
var Zip zipFormat
|
||||
|
||||
func init() {
|
||||
RegisterFormat("Zip", Zip)
|
||||
}
|
||||
|
||||
type zipFormat struct{}
|
||||
|
||||
func (zipFormat) Match(filename string) bool {
|
||||
return strings.HasSuffix(strings.ToLower(filename), ".zip") || isZip(filename)
|
||||
}
|
||||
|
||||
// isZip checks the file has the Zip format signature by reading its beginning
|
||||
// bytes and matching it against "PK\x03\x04"
|
||||
func isZip(zipPath string) bool {
|
||||
f, err := os.Open(zipPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
buf := make([]byte, 4)
|
||||
if n, err := f.Read(buf); err != nil || n < 4 {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(buf, []byte("PK\x03\x04"))
|
||||
}
|
||||
|
||||
// Write outputs a .zip file to the given writer with
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
//
|
||||
// Files with an extension for formats that are already
|
||||
// compressed will be stored only, not compressed.
|
||||
func (zipFormat) Write(output io.Writer, filePaths []string) error {
|
||||
w := zip.NewWriter(output)
|
||||
for _, fpath := range filePaths {
|
||||
if err := zipFile(w, fpath); err != nil {
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return w.Close()
|
||||
}
|
||||
|
||||
// Make creates a .zip file in the location zipPath containing
|
||||
// the contents of files listed in filePaths. File paths
|
||||
// can be those of regular files or directories. Regular
|
||||
// files are stored at the 'root' of the archive, and
|
||||
// directories are recursively added.
|
||||
//
|
||||
// Files with an extension for formats that are already
|
||||
// compressed will be stored only, not compressed.
|
||||
func (zipFormat) Make(zipPath string, filePaths []string) error {
|
||||
out, err := os.Create(zipPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %v", zipPath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
return Zip.Write(out, filePaths)
|
||||
}
|
||||
|
||||
func zipFile(w *zip.Writer, source string) error {
|
||||
sourceInfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: stat: %v", source, err)
|
||||
}
|
||||
|
||||
var baseDir string
|
||||
if sourceInfo.IsDir() {
|
||||
baseDir = filepath.Base(source)
|
||||
}
|
||||
|
||||
return filepath.Walk(source, func(fpath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("walking to %s: %v", fpath, err)
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: getting header: %v", fpath, err)
|
||||
}
|
||||
|
||||
if baseDir != "" {
|
||||
name, err := filepath.Rel(source, fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = path.Join(baseDir, filepath.ToSlash(name))
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
header.Method = zip.Store
|
||||
} else {
|
||||
ext := strings.ToLower(path.Ext(header.Name))
|
||||
if _, ok := compressedFormats[ext]; ok {
|
||||
header.Method = zip.Store
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
}
|
||||
|
||||
writer, err := w.CreateHeader(header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making header: %v", fpath, err)
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if header.Mode().IsRegular() {
|
||||
file, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: opening: %v", fpath, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.CopyN(writer, file, info.Size())
|
||||
if err != nil && err != io.EOF {
|
||||
return fmt.Errorf("%s: copying contents: %v", fpath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Read unzips the .zip file read from the input Reader into destination.
|
||||
func (zipFormat) Read(input io.Reader, destination string) error {
|
||||
buf, err := ioutil.ReadAll(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rdr := bytes.NewReader(buf)
|
||||
r, err := zip.NewReader(rdr, rdr.Size())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return unzipAll(r, destination)
|
||||
}
|
||||
|
||||
// Open unzips the .zip file at source into destination.
|
||||
func (zipFormat) Open(source, destination string) error {
|
||||
r, err := zip.OpenReader(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
return unzipAll(&r.Reader, destination)
|
||||
}
|
||||
|
||||
func unzipAll(r *zip.Reader, destination string) error {
|
||||
for _, zf := range r.File {
|
||||
if err := unzipFile(zf, destination); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unzipFile(zf *zip.File, destination string) error {
|
||||
if strings.HasSuffix(zf.Name, "/") {
|
||||
return mkdir(filepath.Join(destination, zf.Name))
|
||||
}
|
||||
|
||||
rc, err := zf.Open()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: open compressed file: %v", zf.Name, err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
return writeNewFile(filepath.Join(destination, zf.Name), rc, zf.FileInfo().Mode())
|
||||
}
|
||||
|
||||
// compressedFormats is a (non-exhaustive) set of lowercased
|
||||
// file extensions for formats that are typically already
|
||||
// compressed. Compressing already-compressed files often
|
||||
// results in a larger file, so when possible, we check this
|
||||
// set to avoid that.
|
||||
var compressedFormats = map[string]struct{}{
|
||||
".7z": {},
|
||||
".avi": {},
|
||||
".bz2": {},
|
||||
".cab": {},
|
||||
".gif": {},
|
||||
".gz": {},
|
||||
".jar": {},
|
||||
".jpeg": {},
|
||||
".jpg": {},
|
||||
".lz": {},
|
||||
".lzma": {},
|
||||
".mov": {},
|
||||
".mp3": {},
|
||||
".mp4": {},
|
||||
".mpeg": {},
|
||||
".mpg": {},
|
||||
".png": {},
|
||||
".rar": {},
|
||||
".tbz2": {},
|
||||
".tgz": {},
|
||||
".txz": {},
|
||||
".xz": {},
|
||||
".zip": {},
|
||||
".zipx": {},
|
||||
}
|
||||
Reference in New Issue
Block a user