mirror of
https://github.com/containers/podman.git
synced 2025-12-03 03:39:44 +08:00
Vendor Buildah 1.10.1
As the title says, vendor Buildah v1.10.1 Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
This commit is contained in:
18
vendor/github.com/containers/storage/Makefile
generated
vendored
18
vendor/github.com/containers/storage/Makefile
generated
vendored
@@ -27,10 +27,16 @@ PACKAGE := github.com/containers/storage
|
||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
|
||||
EPOCH_TEST_COMMIT := 0418ebf59f9e1f564831c0ba9378b7f8e40a1c73
|
||||
NATIVETAGS := exclude_graphdriver_devicemapper exclude_graphdriver_btrfs exclude_graphdriver_overlay
|
||||
NATIVETAGS :=
|
||||
AUTOTAGS := $(shell ./hack/btrfs_tag.sh) $(shell ./hack/libdm_tag.sh) $(shell ./hack/ostree_tag.sh)
|
||||
BUILDFLAGS := -tags "$(AUTOTAGS) $(TAGS)" $(FLAGS)
|
||||
GO := go
|
||||
GO ?= go
|
||||
|
||||
GO_BUILD=$(GO) build
|
||||
# Go module support: set `-mod=vendor` to use the vendored sources
|
||||
ifeq ($(shell $(GO) help mod >/dev/null 2>&1 && echo true), true)
|
||||
GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
|
||||
endif
|
||||
|
||||
RUNINVM := vagrant/runinvm.sh
|
||||
FFJSON := tests/tools/build/ffjson
|
||||
@@ -43,7 +49,7 @@ clean: ## remove all built files
|
||||
sources := $(wildcard *.go cmd/containers-storage/*.go drivers/*.go drivers/*/*.go pkg/*/*.go pkg/*/*/*.go) layers_ffjson.go images_ffjson.go containers_ffjson.go pkg/archive/archive_ffjson.go
|
||||
|
||||
containers-storage: $(sources) ## build using gc on the host
|
||||
$(GO) build -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
|
||||
$(GO_BUILD) -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
|
||||
|
||||
layers_ffjson.go: layers.go
|
||||
$(RM) $@
|
||||
@@ -64,15 +70,15 @@ pkg/archive/archive_ffjson.go: pkg/archive/archive.go
|
||||
binary local-binary: containers-storage
|
||||
|
||||
local-gccgo: ## build using gccgo on the host
|
||||
GCCGO=$(PWD)/hack/gccgo-wrapper.sh $(GO) build -compiler gccgo $(BUILDFLAGS) -o containers-storage.gccgo ./cmd/containers-storage
|
||||
GCCGO=$(PWD)/hack/gccgo-wrapper.sh $(GO_BUILD) -compiler gccgo $(BUILDFLAGS) -o containers-storage.gccgo ./cmd/containers-storage
|
||||
|
||||
local-cross: ## cross build the binaries for arm, darwin, and\nfreebsd
|
||||
@for target in linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64 linux/ppc64le darwin/amd64 windows/amd64 ; do \
|
||||
os=`echo $${target} | cut -f1 -d/` ; \
|
||||
arch=`echo $${target} | cut -f2 -d/` ; \
|
||||
suffix=$${os}.$${arch} ; \
|
||||
echo env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build -compiler gc -tags \"$(NATIVETAGS) $(TAGS)\" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage ; \
|
||||
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build -compiler gc -tags "$(NATIVETAGS) $(TAGS)" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage || exit 1 ; \
|
||||
echo env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO_BUILD) -compiler gc -tags \"$(NATIVETAGS) $(TAGS)\" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage ; \
|
||||
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO_BUILD) -compiler gc -tags "$(NATIVETAGS) $(TAGS)" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage || exit 1 ; \
|
||||
done
|
||||
|
||||
cross: ## cross build the binaries for arm, darwin, and\nfreebsd using VMs
|
||||
|
||||
2
vendor/github.com/containers/storage/VERSION
generated
vendored
2
vendor/github.com/containers/storage/VERSION
generated
vendored
@@ -1 +1 @@
|
||||
1.12.16
|
||||
1.13.1
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package btrfs
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/btrfs/version.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/btrfs/version.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux,!btrfs_noversion
|
||||
// +build linux,!btrfs_noversion,cgo
|
||||
|
||||
package btrfs
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/btrfs/version_none.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/btrfs/version_none.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux,btrfs_noversion
|
||||
// +build !linux btrfs_noversion !cgo
|
||||
|
||||
package btrfs
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/devmapper/device_setup.go
generated
vendored
@@ -1,3 +1,5 @@
|
||||
// +build linux,cgo
|
||||
|
||||
package devmapper
|
||||
|
||||
import (
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package devmapper
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/devmapper/devmapper_doc.go
generated
vendored
@@ -1,3 +1,5 @@
|
||||
// +build linux,cgo
|
||||
|
||||
package devmapper
|
||||
|
||||
// Definition of struct dm_task and sub structures (from lvm2)
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/devmapper/driver.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/devmapper/driver.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package devmapper
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/devmapper/mount.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/devmapper/mount.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package devmapper
|
||||
|
||||
|
||||
1
vendor/github.com/containers/storage/drivers/fsdiff.go
generated
vendored
1
vendor/github.com/containers/storage/drivers/fsdiff.go
generated
vendored
@@ -82,6 +82,7 @@ func (gdw *NaiveDiffDriver) Diff(id string, idMappings *idtools.IDMappings, pare
|
||||
}), nil
|
||||
}
|
||||
|
||||
options.Options = append(options.Options, "ro")
|
||||
parentFs, err := driver.Get(parent, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
53
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
53
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@@ -322,7 +322,7 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
||||
return nil, fmt.Errorf("overlay: ostree_repo specified but support for ostree is missing")
|
||||
}
|
||||
o.ostreeRepo = val
|
||||
case "overlay2.ignore_chown_errors", "overlay.ignore_chown_errors":
|
||||
case ".ignore_chown_errors", "overlay2.ignore_chown_errors", "overlay.ignore_chown_errors":
|
||||
logrus.Debugf("overlay: ignore_chown_errors=%s", val)
|
||||
o.ignoreChownErrors, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
@@ -839,8 +839,17 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
if _, err := os.Stat(dir); err != nil {
|
||||
return "", err
|
||||
}
|
||||
readWrite := true
|
||||
// fuse-overlayfs doesn't support working without an upperdir.
|
||||
if d.options.mountProgram == "" {
|
||||
for _, o := range options.Options {
|
||||
if o == "ro" {
|
||||
readWrite = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diffDir := path.Join(dir, "diff")
|
||||
lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", err
|
||||
@@ -911,16 +920,32 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
|
||||
// If the lowers list is still empty, use an empty lower so that we can still force an
|
||||
// SELinux context for the mount.
|
||||
|
||||
// if we are doing a readOnly mount, and there is only one lower
|
||||
// We should just return the lower directory, no reason to mount.
|
||||
if !readWrite {
|
||||
if len(absLowers) == 0 {
|
||||
return path.Join(dir, "empty"), nil
|
||||
}
|
||||
if len(absLowers) == 1 {
|
||||
return absLowers[0], nil
|
||||
}
|
||||
}
|
||||
if len(absLowers) == 0 {
|
||||
absLowers = append(absLowers, path.Join(dir, "empty"))
|
||||
relLowers = append(relLowers, path.Join(id, "empty"))
|
||||
}
|
||||
|
||||
// user namespace requires this to move a directory from lower to upper.
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
diffDir := path.Join(dir, "diff")
|
||||
if readWrite {
|
||||
if err := idtools.MkdirAllAs(diffDir, 0755, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
mergedDir := path.Join(dir, "merged")
|
||||
// Create the driver merged dir
|
||||
@@ -940,8 +965,12 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
}
|
||||
}()
|
||||
|
||||
workDir := path.Join(dir, "work")
|
||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workDir)
|
||||
var opts string
|
||||
if readWrite {
|
||||
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, path.Join(dir, "work"))
|
||||
} else {
|
||||
opts = fmt.Sprintf("lowerdir=%s", strings.Join(absLowers, ":"))
|
||||
}
|
||||
if len(options.Options) > 0 {
|
||||
opts = fmt.Sprintf("%s,%s", strings.Join(options.Options, ","), opts)
|
||||
} else if d.options.mountOptions != "" {
|
||||
@@ -979,7 +1008,12 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
}
|
||||
} else if len(mountData) > pageSize {
|
||||
//FIXME: We need to figure out to get this to work with additional stores
|
||||
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(relLowers, ":"), path.Join(id, "diff"), path.Join(id, "work"))
|
||||
if readWrite {
|
||||
diffDir := path.Join(id, "diff")
|
||||
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(relLowers, ":"), diffDir, path.Join(id, "work"))
|
||||
} else {
|
||||
opts = fmt.Sprintf("lowerdir=%s", strings.Join(absLowers, ":"))
|
||||
}
|
||||
mountData = label.FormatMountLabel(opts, options.MountLabel)
|
||||
if len(mountData) > pageSize {
|
||||
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
||||
@@ -995,11 +1029,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
return "", fmt.Errorf("error creating overlay mount to %s: %v", mountTarget, err)
|
||||
}
|
||||
|
||||
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
|
||||
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
@@ -1018,7 +1047,7 @@ func (d *Driver) Put(id string) error {
|
||||
if _, err := ioutil.ReadFile(path.Join(dir, lowerFile)); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil {
|
||||
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil && !os.IsNotExist(err) {
|
||||
logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err)
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/quota/projectquota.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/quota/projectquota.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux,!exclude_disk_quota
|
||||
// +build linux,!exclude_disk_quota,cgo
|
||||
|
||||
//
|
||||
// projectquota.go - implements XFS project quota controls
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/quota/projectquota_unsupported.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/quota/projectquota_unsupported.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux,exclude_disk_quota
|
||||
// +build !linux exclude_disk_quota !cgo
|
||||
|
||||
package quota
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/register/register_devicemapper.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/register/register_devicemapper.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !exclude_graphdriver_devicemapper,linux
|
||||
// +build !exclude_graphdriver_devicemapper,linux,cgo
|
||||
|
||||
package register
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/drivers/register/register_overlay.go
generated
vendored
2
vendor/github.com/containers/storage/drivers/register/register_overlay.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !exclude_graphdriver_overlay,linux
|
||||
// +build !exclude_graphdriver_overlay,linux,cgo
|
||||
|
||||
package register
|
||||
|
||||
|
||||
12
vendor/github.com/containers/storage/drivers/vfs/driver.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/vfs/driver.go
generated
vendored
@@ -58,7 +58,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
|
||||
d.ostreeRepo = val
|
||||
case "vfs.mountopt":
|
||||
return nil, fmt.Errorf("vfs driver does not support mount options")
|
||||
case "vfs.ignore_chown_errors":
|
||||
case ".ignore_chown_errors", "vfs.ignore_chown_errors":
|
||||
logrus.Debugf("vfs: ignore_chown_errors=%s", val)
|
||||
var err error
|
||||
d.ignoreChownErrors, err = strconv.ParseBool(val)
|
||||
@@ -226,7 +226,15 @@ func (d *Driver) Remove(id string) error {
|
||||
// Get returns the directory for the given id.
|
||||
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
|
||||
dir := d.dir(id)
|
||||
if len(options.Options) > 0 {
|
||||
switch len(options.Options) {
|
||||
case 0:
|
||||
case 1:
|
||||
if options.Options[0] == "ro" {
|
||||
// ignore "ro" option
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
return "", fmt.Errorf("vfs driver does not support mount options")
|
||||
}
|
||||
if st, err := os.Stat(dir); err != nil {
|
||||
|
||||
10
vendor/github.com/containers/storage/ffjson_deps.go
generated
vendored
Normal file
10
vendor/github.com/containers/storage/ffjson_deps.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package storage
|
||||
|
||||
// NOTE: this is a hack to trick go modules into vendoring the below
|
||||
// dependencies. Those are required during ffjson generation
|
||||
// but do NOT end up in the final file.
|
||||
|
||||
import (
|
||||
_ "github.com/pquerna/ffjson/inception" // nolint:typecheck
|
||||
_ "github.com/pquerna/ffjson/shared" // nolint:typecheck
|
||||
)
|
||||
2
vendor/github.com/containers/storage/go.mod
generated
vendored
2
vendor/github.com/containers/storage/go.mod
generated
vendored
@@ -1,7 +1,5 @@
|
||||
module github.com/containers/storage
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/DataDog/zstd v1.4.0 // indirect
|
||||
|
||||
2
vendor/github.com/containers/storage/layers.go
generated
vendored
2
vendor/github.com/containers/storage/layers.go
generated
vendored
@@ -1,7 +1,6 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -27,6 +26,7 @@ import (
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vbatts/tar-split/archive/tar"
|
||||
"github.com/vbatts/tar-split/tar/asm"
|
||||
"github.com/vbatts/tar-split/tar/storage"
|
||||
)
|
||||
|
||||
11
vendor/github.com/containers/storage/pkg/idtools/idtools.go
generated
vendored
11
vendor/github.com/containers/storage/pkg/idtools/idtools.go
generated
vendored
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/storage/pkg/system"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -296,9 +297,19 @@ func checkChownErr(err error, name string, uid, gid int) error {
|
||||
}
|
||||
|
||||
func SafeChown(name string, uid, gid int) error {
|
||||
if stat, statErr := system.Stat(name); statErr == nil {
|
||||
if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return checkChownErr(os.Chown(name, uid, gid), name, uid, gid)
|
||||
}
|
||||
|
||||
func SafeLchown(name string, uid, gid int) error {
|
||||
if stat, statErr := system.Lstat(name); statErr == nil {
|
||||
if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return checkChownErr(os.Lchown(name, uid, gid), name, uid, gid)
|
||||
}
|
||||
|
||||
2
vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package loopback
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/pkg/loopback/ioctl.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/loopback/ioctl.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package loopback
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/loopback/loop_wrapper.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package loopback
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/pkg/loopback/loopback.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/loopback/loopback.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build linux
|
||||
// +build linux,cgo
|
||||
|
||||
package loopback
|
||||
|
||||
|
||||
1
vendor/github.com/containers/storage/pkg/loopback/loopback_unsupported.go
generated
vendored
Normal file
1
vendor/github.com/containers/storage/pkg/loopback/loopback_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package loopback
|
||||
2
vendor/github.com/containers/storage/pkg/ostree/no_ostree.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/ostree/no_ostree.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !ostree
|
||||
// +build !ostree !cgo
|
||||
|
||||
package ostree
|
||||
|
||||
|
||||
2
vendor/github.com/containers/storage/pkg/ostree/ostree.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/ostree/ostree.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build ostree
|
||||
// +build ostree,cgo
|
||||
|
||||
package ostree
|
||||
|
||||
|
||||
48
vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go
generated
vendored
48
vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go
generated
vendored
@@ -1,47 +1,69 @@
|
||||
package tarlog
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbatts/tar-split/archive/tar"
|
||||
)
|
||||
|
||||
type tarLogger struct {
|
||||
writer *os.File
|
||||
wg sync.WaitGroup
|
||||
writer *io.PipeWriter
|
||||
closeMutex *sync.Mutex
|
||||
stateMutex *sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
// NewLogger returns a writer that, when a tar archive is written to it, calls
|
||||
// `logger` for each file header it encounters in the archive.
|
||||
func NewLogger(logger func(*tar.Header)) (io.WriteCloser, error) {
|
||||
reader, writer, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error creating pipe for tar logger")
|
||||
reader, writer := io.Pipe()
|
||||
t := &tarLogger{
|
||||
writer: writer,
|
||||
closeMutex: new(sync.Mutex),
|
||||
stateMutex: new(sync.Mutex),
|
||||
closed: false,
|
||||
}
|
||||
t := &tarLogger{writer: writer}
|
||||
tr := tar.NewReader(reader)
|
||||
t.wg.Add(1)
|
||||
tr.RawAccounting = true
|
||||
t.closeMutex.Lock()
|
||||
go func() {
|
||||
hdr, err := tr.Next()
|
||||
for err == nil {
|
||||
logger(hdr)
|
||||
hdr, err = tr.Next()
|
||||
|
||||
}
|
||||
reader.Close()
|
||||
t.wg.Done()
|
||||
// Make sure to avoid writes after the reader has been closed.
|
||||
t.stateMutex.Lock()
|
||||
t.closed = true
|
||||
if err := reader.Close(); err != nil {
|
||||
logrus.Errorf("error closing tarlogger reader: %v", err)
|
||||
}
|
||||
t.stateMutex.Unlock()
|
||||
// Unblock the Close().
|
||||
t.closeMutex.Unlock()
|
||||
}()
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (t *tarLogger) Write(b []byte) (int, error) {
|
||||
t.stateMutex.Lock()
|
||||
if t.closed {
|
||||
// We cannot use os.Pipe() as this alters the tar's digest. Using
|
||||
// io.Pipe() requires this workaround as it does not allow for writes
|
||||
// after close.
|
||||
t.stateMutex.Unlock()
|
||||
return len(b), nil
|
||||
}
|
||||
t.stateMutex.Unlock()
|
||||
return t.writer.Write(b)
|
||||
}
|
||||
|
||||
func (t *tarLogger) Close() error {
|
||||
err := t.writer.Close()
|
||||
t.wg.Wait()
|
||||
// Wait for the reader to finish.
|
||||
t.closeMutex.Lock()
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user