feat: boot.img.lz4

This commit is contained in:
Mikaël Cluseau 2018-11-13 14:44:15 +11:00
parent 7ef45a39f9
commit 12ade36fd1
104 changed files with 4963 additions and 127 deletions

View File

@ -1,16 +1,28 @@
from golang:1.10.3 as build # ------------------------------------------------------------------------
env pkg novit.nc/direktil/local-server from golang:1.11.2 as build
add . /go/src/${pkg}
workdir /go/src/${pkg}
run go vet ./... \
&& go test ./... \
&& go install .
from debian:stable env pkg novit.nc/direktil/local-server
entrypoint ["/bin/local-server"] run go get github.com/gobuffalo/packr/packr
copy vendor /go/src/${pkg}/vendor
copy cmd /go/src/${pkg}/cmd
copy assets /go/src/${pkg}/cmd/dkl-local-server/assets
workdir /go/src/${pkg}
run packr -i /go/src/${pkg}/cmd/dkl-local-server \
&& go test ./... \
&& go install ./cmd/...
# ------------------------------------------------------------------------
from debian:stretch
entrypoint ["/bin/dkl-local-server"]
run apt-get update \ run apt-get update \
&& apt-get install -y genisoimage grub grub-pc-bin \ && apt-get install -y genisoimage gdisk dosfstools util-linux udev \
&& apt-get clean && apt-get clean
copy --from=build /go/bin/local-server /bin/ run yes |apt-get install -y grub2 grub-pc-bin grub-efi-amd64-bin \
&& apt-get clean
add scripts /scripts
add assets /assets
add efi-shim/ /shim
copy --from=build /go/bin/ /bin/

11
assets/grub.cfg Normal file
View File

@ -0,0 +1,11 @@
search --no-floppy --set=root --part-label boot --hint $root
insmod all_video
set timeout=3
set bootdev=PARTNAME=boot
menuentry "Direktil" {
linux /current/vmlinuz direktil.boot=$bootdev
initrd /current/initrd
}

BIN
assets/mbr.bin Normal file

Binary file not shown.

View File

@ -0,0 +1,12 @@
// Code generated by github.com/gobuffalo/packr. DO NOT EDIT.
package main
import "github.com/gobuffalo/packr"
// You can use the "packr clean" command to clean up this,
// and any other packr generated files.
func init() {
packr.PackJSONBytes("./assets", "grub.cfg", "\"c2VhcmNoIC0tbm8tZmxvcHB5IC0tc2V0PXJvb3QgLS1wYXJ0LWxhYmVsIGJvb3QKCmluc21vZCBhbGxfdmlkZW8Kc2V0IHRpbWVvdXQ9MwoKc2V0IGJvb3RkZXY9UEFSVE5BTUU9Ym9vdAoKbWVudWVudHJ5ICJEaXJla3RpbCIgewogICAgbGludXggIC9jdXJyZW50L3ZtbGludXogZGlyZWt0aWwuYm9vdD0kYm9vdGRldgogICAgaW5pdHJkIC9jdXJyZW50L2luaXRyZAp9Cg==\"")
packr.PackJSONBytes("./assets", "mbr.bin", "\"62OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAEAQAAAAAAP/6kJD2woB0BfbCcHQCsoDqeXwAADHAjtiO0LwAIPugZHw8/3QCiMJSvoB96BcBvgV8tEG7qlXNE1pScj2B+1WqdTeD4QF0MjHAiUQEQIhE/4lEAscEEABmix5cfGaJXAhmix5gfGaJXAzHRAYAcLRCzRNyBbsAcOt2tAjNE3MNWoTSD4PYAL6LfemCAGYPtsaIZP9AZolEBA+20cHiAojoiPRAiUQID7bCwOgCZokEZqFgfGYJwHVOZqFcfGYx0mb3NIjRMdJm93QEO0QIfTf+wYjFMMDB6AIIwYjQWojGuwBwjsMx27gBAs0Tch6Mw2AeuQABjtsx9r8AgI7G/POlH2H/Jlp8voZ96wO+lX3oNAC+mn3oLgDNGOv+R1JVQiAAR2VvbQBIYXJkIERpc2sAUmVhZAAgRXJyb3INCgC7AQC0Ds0QrDwAdfTDAAAAAAAAAAAAAAAAAACAQQ==\"")
}

View File

@ -0,0 +1,11 @@
package main
import "log"
func asset(name string) []byte {
ba, err := assets.Find(name)
if err != nil {
log.Fatalf("asset find error for %q: %v", name, err)
}
return ba
}

View File

@ -0,0 +1,144 @@
package main
import (
"archive/tar"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"github.com/pierrec/lz4"
)
func buildBootImg(out io.Writer, ctx *renderContext) (err error) {
bootImg, err := ioutil.TempFile(os.TempDir(), "boot.img-")
if err != nil {
return
}
defer rmTempFile(bootImg)
// 2MB + 2GB + 2MB + 34 sectors
bootImg.Truncate(2<<30 + 4<<20 + 34*512)
// partition
err = run("sgdisk",
"--new=0:4096:+2G", "--typecode=0:EF00", "-c", "0:boot",
"--new=0:0:+2M", "--typecode=0:EF02", "-c", "0:BIOS-BOOT",
"--hybrid=1:2", "--print", bootImg.Name())
if err != nil {
return
}
err = setupBootImage(bootImg, ctx)
if err != nil {
return
}
// send the result
bootImg.Seek(0, os.SEEK_SET)
lz4Out := lz4.NewWriter(out)
io.Copy(lz4Out, bootImg)
lz4Out.Close()
return
}
func setupBootImage(bootImg *os.File, ctx *renderContext) (err error) {
devb, err := exec.Command("losetup", "--find", "--show", "--partscan", bootImg.Name()).CombinedOutput()
if err != nil {
return
}
dev := strings.TrimSpace(string(devb))
defer run("losetup", "-d", dev)
log.Print("device: ", dev)
err = run("mkfs.vfat", "-n", "DKLBOOT", dev+"p1")
if err != nil {
return
}
tempDir := bootImg.Name() + ".p1.mount"
err = os.Mkdir(tempDir, 0755)
if err != nil {
return
}
defer func() {
log.Print("Removing ", tempDir)
os.RemoveAll(tempDir)
}()
err = syscall.Mount(dev+"p1", tempDir, "vfat", 0, "")
if err != nil {
return
}
defer func() {
log.Print("Unmounting ", tempDir)
syscall.Unmount(tempDir, 0)
}()
// setup grub
err = run("/scripts/grub_install.sh", bootImg.Name(), dev, tempDir)
if err != nil {
return
}
// add system elements
tarOut, tarIn := io.Pipe()
go func() {
err2 := buildBootTar(tarIn, ctx)
tarIn.Close()
if err2 != nil {
err = err2
}
}()
defer tarOut.Close()
tarRd := tar.NewReader(tarOut)
for {
hdr, err := tarRd.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
log.Print("tar: extracting ", hdr.Name)
outPath := filepath.Join(tempDir, hdr.Name)
os.MkdirAll(filepath.Dir(outPath), 0755)
f, err := os.Create(outPath)
if err != nil {
return err
}
_, err = io.Copy(f, tarRd)
f.Close()
if err != nil {
return err
}
}
return
}
func run(program string, args ...string) (err error) {
cmd := exec.Command(program, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

View File

@ -7,7 +7,6 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
) )
@ -25,53 +24,12 @@ func buildBootTar(out io.Writer, ctx *renderContext) (err error) {
} }
defer rmTempFile(grubCfg) defer rmTempFile(grubCfg)
_, err = grubCfg.WriteString(` _, err = grubCfg.Write(asset("grub.cfg"))
search --no-floppy --set=root --part-label boot
insmod all_video
set timeout=3
set bootdev=PARTNAME=boot
menuentry "Direktil" {
linux /current/vmlinuz direktil.boot=$bootdev
initrd /current/initrd
}
`)
if err != nil { if err != nil {
return return
} }
grubCfg.Close() grubCfg.Close()
// FIXME including in grub memdisk for now...
kernelPath, err := ctx.distFetch("kernels", ctx.Group.Kernel)
initrdPath, err := ctx.distFetch("initrd", ctx.Group.Initrd)
grubMk := func(format string) ([]byte, error) {
grubOut, err := ioutil.TempFile(os.TempDir(), "grub.img-")
if err != nil {
return nil, err
}
defer rmTempFile(grubOut)
if err := grubOut.Close(); err != nil {
return nil, err
}
cmd := exec.Command("grub-mkstandalone",
"--format="+format,
"--output="+grubOut.Name(),
"boot/grub/grub.cfg="+grubCfg.Name(),
"current/vmlinuz="+kernelPath,
"current/initrd="+initrdPath,
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, err
}
return ioutil.ReadFile(grubOut.Name())
}
arch := tar.NewWriter(out) arch := tar.NewWriter(out)
defer arch.Close() defer arch.Close()
@ -84,30 +42,6 @@ menuentry "Direktil" {
return return
} }
ba, err := grubMk("x86_64-efi")
if err != nil {
return err
}
err = archAdd("EFI/boot/bootx64.efi", ba)
if err != nil {
return
}
if false {
// TODO
ba, err = grubMk("i386-pc")
if err != nil {
return err
}
arch.WriteHeader(&tar.Header{
Name: "grub.img",
Size: int64(len(ba)),
})
arch.Write(ba)
}
// config // config
cfgBytes, cfg, err := ctx.Config() cfgBytes, cfg, err := ctx.Config()
if err != nil { if err != nil {
@ -116,15 +50,16 @@ menuentry "Direktil" {
archAdd("config.yaml", cfgBytes) archAdd("config.yaml", cfgBytes)
// kernel and initrd // add "current" elements
type distCopy struct { type distCopy struct {
Src []string Src []string
Dst string Dst string
} }
// kernel and initrd
copies := []distCopy{ copies := []distCopy{
// XXX {Src: []string{"kernels", ctx.Group.Kernel}, Dst: "current/vmlinuz"}, {Src: []string{"kernels", ctx.Group.Kernel}, Dst: "current/vmlinuz"},
// XXX {Src: []string{"initrd", ctx.Group.Initrd}, Dst: "current/initrd"}, {Src: []string{"initrd", ctx.Group.Initrd}, Dst: "current/initrd"},
} }
// layers // layers

View File

@ -165,6 +165,9 @@ func renderHost(w http.ResponseWriter, r *http.Request, what string, host *clust
case "boot.tar": case "boot.tar":
err = renderCtx(w, r, ctx, "boot.tar", buildBootTar) err = renderCtx(w, r, ctx, "boot.tar", buildBootTar)
case "boot.img.lz4":
err = renderCtx(w, r, ctx, what, buildBootImg)
case "config": case "config":
err = renderConfig(w, r, ctx) err = renderConfig(w, r, ctx)

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"github.com/gobuffalo/packr"
"novit.nc/direktil/pkg/cas" "novit.nc/direktil/pkg/cas"
) )
@ -20,11 +21,15 @@ var (
keyFile = flag.String("tls-key", etcDir+"/server.key", "Server TLS key") keyFile = flag.String("tls-key", etcDir+"/server.key", "Server TLS key")
casStore cas.Store casStore cas.Store
assets packr.Box
) )
func main() { func main() {
flag.Parse() flag.Parse()
assets = packr.NewBox("./assets")
if *address == "" && *tlsAddress == "" { if *address == "" && *tlsAddress == "" {
log.Fatal("no listen address given") log.Fatal("no listen address given")
} }

BIN
efi-shim/BOOTIA32.EFI Normal file

Binary file not shown.

BIN
efi-shim/BOOTX64.EFI Normal file

Binary file not shown.

BIN
efi-shim/mmia32.efi Normal file

Binary file not shown.

BIN
efi-shim/mmx64.efi Normal file

Binary file not shown.

16
go.mod
View File

@ -1,28 +1,16 @@
module novit.nc/direktil/local-server module novit.nc/direktil/local-server
require ( require (
cloud.google.com/go v0.24.0 // indirect
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e
github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a
github.com/go-sql-driver/mysql v1.4.0 // indirect github.com/gobuffalo/packr v1.19.0
github.com/golang/protobuf v1.1.0 // indirect github.com/golang/protobuf v1.1.0 // indirect
github.com/google/certificate-transparency-go v1.0.20 // indirect github.com/google/certificate-transparency-go v1.0.20 // indirect
github.com/googleapis/gax-go v1.0.0 // indirect
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-sqlite3 v1.9.0 // indirect github.com/pierrec/lz4 v2.0.5+incompatible
golang.org/x/build v0.0.0-20180706045728-5a0b491d3d31 // indirect
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 // indirect golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 // indirect
golang.org/x/net v0.0.0-20180706051357-32a936f46389 // indirect
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
golang.org/x/tools v0.0.0-20180706162124-435878328fa3 // indirect
google.golang.org/api v0.0.0-20180706000841-61180b1196c9 // indirect
google.golang.org/appengine v1.1.0 // indirect
google.golang.org/grpc v1.13.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 v2.2.1
honnef.co/go/tools v0.0.0-20180628101929-85dde8b51d3a // indirect
k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2 k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2
k8s.io/kubernetes v1.11.2 // indirect
novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d
) )

38
go.sum
View File

@ -1,42 +1,50 @@
cloud.google.com/go v0.24.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e h1:mep9E//vzfjmtYUVBAvRMIW5BKTL88nidNZc8RF2lhA= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e h1:mep9E//vzfjmtYUVBAvRMIW5BKTL88nidNZc8RF2lhA=
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a h1:wbCZ8e4WG5hcfVKSyaqobgvEe/uZeVvkbUBX1zgr9kw= github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a h1:wbCZ8e4WG5hcfVKSyaqobgvEe/uZeVvkbUBX1zgr9kw=
github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cloudflare/cfssl v0.0.0-20180705210102-ff56ab5eb62a/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobuffalo/envy v1.6.7 h1:XMZGuFqTupAXhZTriQ+qO38QvNOSU/0rl3hEPCFci/4=
github.com/gobuffalo/envy v1.6.7/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264 h1:roWyi0eEdiFreSqW9V1wT9pNOVzrpo2NWsxja53slX0=
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
github.com/gobuffalo/packr v1.19.0 h1:3UDmBDxesCOPF8iZdMDBBWKfkBoYujIMIZePnobqIUI=
github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU=
github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/certificate-transparency-go v1.0.20 h1:azETE79toaBOyp+StoEBy8atzQujL0PyBPEmsEeDCXI= github.com/google/certificate-transparency-go v1.0.20 h1:azETE79toaBOyp+StoEBy8atzQujL0PyBPEmsEeDCXI=
github.com/google/certificate-transparency-go v1.0.20/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.0.20/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/googleapis/gax-go v1.0.0/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4 h1:Mlji5gkcpzkqTROyE4ZxZ8hN7osunMb2RuGVrbvMvCc=
github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
golang.org/x/build v0.0.0-20180706045728-5a0b491d3d31/go.mod h1:xwoxzDSBtVMfGm9EGvIEcwZxBYS/6ALXnEvsP1TooIk=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 h1:h7zdf0RiEvWbYBKIx4b+q41xoUVnMmvsGZnIVE5syG8= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 h1:h7zdf0RiEvWbYBKIx4b+q41xoUVnMmvsGZnIVE5syG8=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180706051357-32a936f46389 h1:U+zCn5sqaq+q4hrnMrz9sgrW1yatwEOUgYkGt3u9ZOU= golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc h1:ZMCWScCvS2fUVFw8LOpxyUUW5qiviqr4Dg5NdjLeiLU=
golang.org/x/net v0.0.0-20180706051357-32a936f46389/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/tools v0.0.0-20180706162124-435878328fa3/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/api v0.0.0-20180706000841-61180b1196c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180628101929-85dde8b51d3a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2 h1:w/5Dvht2Wf4vRaXFDb4cWInymI8NkaMJtrs8UsJyZLI= k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2 h1:w/5Dvht2Wf4vRaXFDb4cWInymI8NkaMJtrs8UsJyZLI=
k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20180808233214-a7b7e4de06b2/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/kubernetes v1.11.2 h1:2/lmzYbN17Mr23mX/p4ODMm/MBWTeu2Q1Bvsw82YC40=
k8s.io/kubernetes v1.11.2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d h1:DMk2j7F+mXAQdZD5ouIxWVosY55RmpRevgCWSikRRzU= novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d h1:DMk2j7F+mXAQdZD5ouIxWVosY55RmpRevgCWSikRRzU=
novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d/go.mod h1:rbcL+fuxazzipTdJV8t9MW39YsdaK3pSvvhTdI9SXsc= novit.nc/direktil/pkg v0.0.0-20180707011528-e82b59c0324d/go.mod h1:rbcL+fuxazzipTdJV8t9MW39YsdaK3pSvvhTdI9SXsc=

View File

@ -1,37 +1,37 @@
#! /bin/sh #! /bin/sh
if [ $# -ne 2 ]; then if [ $# -ne 2 ]; then
echo "USAGE: $0 <device> <tar url>" echo "USAGE: $0 <device> <base url>"
fi fi
dev=$1 dev=$1
tar_url=$2 base_url=$2
: ${MP:=/mnt} : ${MP:=/mnt}
set -ex set -ex
mkdir -p $MP
[[ $dev =~ nvme ]] && [[ $dev =~ nvme ]] &&
devp=${dev}p || devp=${dev}p ||
devp=${dev} devp=${dev}
vgdisplay storage || { if vgdisplay storage; then
sgdisk --clear $dev # the system is already installed, just upgrade
sgdisk \ mount -t vfat ${devp}1 $MP
--new=0:4096:+2G --typecode=0:EF00 -c 0:boot \ curl ${base_url}/boot.tar |tar xv -C $MP
--new=0:0:+2M --typecode=0:EF02 -c 0:BIOS-BOOT \ umount $MP
--new=0:0:0 --typecode=0:FFFF -c 0:data \
--hybrid=1:2 \
--print $dev
mkfs.vfat -n DKLBOOT ${devp}1 else
sgdisk --clear $dev
curl ${base_url}/boot.img.lz4 |lz4cat >$dev
sgdisk --move-second-header --new=3:0:0 $dev
pvcreate ${devp}3 pvcreate ${devp}3
vgcreate storage ${devp}3 vgcreate storage ${devp}3
} fi
while umount $MP; do true; done while umount $MP; do true; done
mount -t vfat ${devp}1 $MP
curl $tar_url |tar xv -C $MP
umount $MP

131
scripts/grub_install.sh Executable file
View File

@ -0,0 +1,131 @@
#!/bin/bash
set -e
disk_image="${1}"
LOOP_DEV="${2}"
ESP_DIR="${3}"
# i386-pc or x86_64-efi
target=${4:-x86_64-efi}
export PATH="/opt/grub/bin:/opt/grub/sbin:$PATH"
info() {
echo "INFO:" "$@"
}
warn() {
echo "WARN:" "$@"
}
cleanup() {
if [[ -n "${GRUB_TEMP_DIR}" && -e "${GRUB_TEMP_DIR}" ]]; then
rm -r "${GRUB_TEMP_DIR}"
fi
}
trap cleanup EXIT
info "Installing GRUB in ${disk_image##*/}"
mkdir -p "${ESP_DIR}/grub"
GRUB_TEMP_DIR="$(mktemp -d)"
devmap="${GRUB_TEMP_DIR}/device.map"
cat >${devmap} <<EOF
(hd0) ${LOOP_DEV}
EOF
mkdir -p "${ESP_DIR}/grub"
sed -e "s/{{.FSID}}/$ESP_FSID/g" "/assets/grub.cfg" > "${ESP_DIR}/grub/grub.cfg"
info "Generating grub/load.cfg"
# Include a small initial config in the core image to search for the ESP
# by filesystem ID in case the platform doesn't provide the boot disk.
# The existing $root value is given as a hint so it is searched first.
ESP_FSID=$(grub-probe --device-map=$devmap -t fs_uuid -d "${LOOP_DEV}p1")
cat > "${ESP_DIR}/grub/load.cfg" <<EOF
search.fs_uuid ${ESP_FSID} root \$root
set prefix=(memdisk)
set
EOF
# Generate a memdisk containing the appropriately generated grub.cfg. Doing
# this because we need conflicting default behaviors between verity and
# non-verity images.
info "Generating grub.cfg memdisk"
sed -e "s/{{.FSID}}/$ESP_FSID/g" "/assets/grub.cfg" > "${GRUB_TEMP_DIR}/grub.cfg"
mkdir -p "${ESP_DIR}/grub"
tar cf "${ESP_DIR}/grub/grub.cfg.tar" \
-C "${GRUB_TEMP_DIR}" "grub.cfg"
for target in i386-pc x86_64-efi
do
GRUB_SRC="/usr/lib/grub/${target}"
GRUB_DIR="grub/${target}"
[[ -d "${GRUB_SRC}" ]] || die "GRUB not installed at ${GRUB_SRC}"
info "Compressing modules in ${GRUB_DIR}"
mkdir -p "${ESP_DIR}/${GRUB_DIR}"
for file in "${GRUB_SRC}"/*{.lst,.mod}; do
out="${ESP_DIR}/${GRUB_DIR}/${file##*/}"
gzip --best --stdout "${file}" | cat > "${out}"
done
# Modules required to boot a standard configuration
CORE_MODULES=( normal search test fat part_gpt search_fs_uuid gzio terminal configfile memdisk tar echo read )
#CORE_MODULES+=( search_part_label gptprio )
# Name of the core image, depends on target
CORE_NAME=
case "${target}" in
i386-pc)
CORE_MODULES+=( biosdisk serial linux )
CORE_NAME="core.img"
;;
x86_64-efi)
CORE_MODULES+=( serial linuxefi efi_gop efinet verify http tftp )
#CORE_MODULES+=( getenv smbios )
CORE_NAME="core.efi"
;;
*)
die_notrace "Unknown GRUB target ${target}"
;;
esac
info "Generating grub/${CORE_NAME}"
grub-mkimage \
--compression=auto \
--format "${target}" \
--directory "${GRUB_SRC}" \
--config "${ESP_DIR}/grub/load.cfg" \
--memdisk "${ESP_DIR}/grub/grub.cfg.tar" \
--output "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${CORE_MODULES[@]}"
done
# Now target specific steps to make the system bootable
info "Installing MBR and the BIOS Boot partition."
cp "/usr/lib/grub/i386-pc/boot.img" "${ESP_DIR}/grub/i386-pc"
grub-bios-setup --device-map=$devmap \
--directory="${ESP_DIR}/grub/i386-pc" "${LOOP_DEV}"
# backup the MBR
dd bs=448 count=1 status=none if="${LOOP_DEV}" \
of="${ESP_DIR}/grub/mbr.bin"
info "Installing default x86_64 UEFI bootloader."
mkdir -p "${ESP_DIR}/EFI/boot"
cp "${ESP_DIR}/grub/x86_64-efi/core.efi" \
"${ESP_DIR}/EFI/boot/grubx64.efi"
cp "/shim/BOOTX64.EFI" \
"${ESP_DIR}/EFI/boot/bootx64.efi"
cleanup
trap - EXIT

5
vendor/github.com/gobuffalo/envy/.env generated vendored Normal file
View File

@ -0,0 +1,5 @@
# This is a comment
# We can use equal or colon notation
DIR: root
FLAVOUR: none
INSIDE_FOLDER=false

29
vendor/github.com/gobuffalo/envy/.gitignore generated vendored Normal file
View File

@ -0,0 +1,29 @@
*.log
.DS_Store
doc
tmp
pkg
*.gem
*.pid
coverage
coverage.data
build/*
*.pbxuser
*.mode1v3
.svn
profile
.console_history
.sass-cache/*
.rake_tasks~
*.log.lck
solr/
.jhw-cache/
jhw.*
*.sublime*
node_modules/
dist/
generated/
.vendor/
bin/*
gin-bin
.idea/

3
vendor/github.com/gobuffalo/envy/.gometalinter.json generated vendored Normal file
View File

@ -0,0 +1,3 @@
{
"Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
}

26
vendor/github.com/gobuffalo/envy/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,26 @@
language: go
sudo: false
matrix:
include:
- go: "1.9.x"
- go: "1.10.x"
- go: "1.11.x"
env:
- GO111MODULE=off
- go: "1.11.x"
env:
- GO111MODULE=on
- go: "tip"
env:
- GO111MODULE=off
- go: "tip"
env:
- GO111MODULE=on
allow_failures:
- go: "tip"
install: make deps
script: make ci-test

8
vendor/github.com/gobuffalo/envy/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2018 Mark Bates
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.

46
vendor/github.com/gobuffalo/envy/Makefile generated vendored Normal file
View File

@ -0,0 +1,46 @@
TAGS ?= "sqlite"
GO_BIN ?= go
install:
packr
$(GO_BIN) install -v .
deps:
$(GO_BIN) get github.com/gobuffalo/release
$(GO_BIN) get github.com/gobuffalo/packr/packr
$(GO_BIN) get -tags ${TAGS} -t ./...
ifeq ($(GO111MODULE),on)
$(GO_BIN) mod tidy
endif
build:
packr
$(GO_BIN) build -v .
test:
packr
$(GO_BIN) test -tags ${TAGS} ./...
ci-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
lint:
gometalinter --vendor ./... --deadline=1m --skip=internal
update:
$(GO_BIN) get -u -tags ${TAGS}
ifeq ($(GO111MODULE),on)
$(GO_BIN) mod tidy
endif
packr
make test
make install
ifeq ($(GO111MODULE),on)
$(GO_BIN) mod tidy
endif
release-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
release:
release -y -f version.go

93
vendor/github.com/gobuffalo/envy/README.md generated vendored Normal file
View File

@ -0,0 +1,93 @@
# envy
[![Build Status](https://travis-ci.org/gobuffalo/envy.svg?branch=master)](https://travis-ci.org/gobuffalo/envy)
Envy makes working with ENV variables in Go trivial.
* Get ENV variables with default values.
* Set ENV variables safely without affecting the underlying system.
* Temporarily change ENV vars; useful for testing.
* Map all of the key/values in the ENV.
* Loads .env files (by using [godotenv](https://github.com/joho/godotenv/))
* More!
## Installation
```text
$ go get -u github.com/gobuffalo/envy
```
## Usage
```go
func Test_Get(t *testing.T) {
r := require.New(t)
r.NotZero(os.Getenv("GOPATH"))
r.Equal(os.Getenv("GOPATH"), envy.Get("GOPATH", "foo"))
r.Equal("bar", envy.Get("IDONTEXIST", "bar"))
}
func Test_MustGet(t *testing.T) {
r := require.New(t)
r.NotZero(os.Getenv("GOPATH"))
v, err := envy.MustGet("GOPATH")
r.NoError(err)
r.Equal(os.Getenv("GOPATH"), v)
_, err = envy.MustGet("IDONTEXIST")
r.Error(err)
}
func Test_Set(t *testing.T) {
r := require.New(t)
_, err := envy.MustGet("FOO")
r.Error(err)
envy.Set("FOO", "foo")
r.Equal("foo", envy.Get("FOO", "bar"))
}
func Test_Temp(t *testing.T) {
r := require.New(t)
_, err := envy.MustGet("BAR")
r.Error(err)
envy.Temp(func() {
envy.Set("BAR", "foo")
r.Equal("foo", envy.Get("BAR", "bar"))
_, err = envy.MustGet("BAR")
r.NoError(err)
})
_, err = envy.MustGet("BAR")
r.Error(err)
}
```
## .env files support
Envy now supports loading `.env` files by using the [godotenv library](https://github.com/joho/godotenv/).
That means one can use and define multiple `.env` files which will be loaded on-demand. By default, no env files will be loaded. To load one or more, you need to call the `envy.Load` function in one of the following ways:
```go
envy.Load() // 1
envy.Load("MY_ENV_FILE") // 2
envy.Load(".env", ".env.prod") // 3
envy.Load(".env", "NON_EXISTING_FILE") // 4
// 5
envy.Load(".env")
envy.Load("NON_EXISTING_FILE")
// 6
envy.Load(".env", "NON_EXISTING_FILE", ".env.prod")
```
1. Will load the default `.env` file
2. Will load the file `MY_ENV_FILE`, **but not** `.env`
3. Will load the file `.env`, and after that will load the `.env.prod` file. If any variable is redefined in `. env.prod` it will be overwritten (will contain the `env.prod` value)
4. Will load the `.env` file and return an error as the second file does not exist. The values in `.env` will be loaded and available.
5. Same as 4
6. Will load the `.env` file and return an error as the second file does not exist. The values in `.env` will be loaded and available, **but the ones in** `.env.prod` **won't**.

249
vendor/github.com/gobuffalo/envy/envy.go generated vendored Normal file
View File

@ -0,0 +1,249 @@
/*
package envy makes working with ENV variables in Go trivial.
* Get ENV variables with default values.
* Set ENV variables safely without affecting the underlying system.
* Temporarily change ENV vars; useful for testing.
* Map all of the key/values in the ENV.
* Loads .env files (by using [godotenv](https://github.com/joho/godotenv/))
* More!
*/
package envy
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"github.com/joho/godotenv"
)
var gil = &sync.RWMutex{}
var env = map[string]string{}
// GO111MODULE is ENV for turning mods on/off
const GO111MODULE = "GO111MODULE"
func init() {
Load()
loadEnv()
}
// Load the ENV variables to the env map
func loadEnv() {
gil.Lock()
defer gil.Unlock()
// Detect the Go version on the user system, not the one that was used to compile the binary
v := ""
out, err := exec.Command("go", "version").Output()
if err == nil {
// This will break when Go 2 lands
v = strings.Split(string(out), " ")[2][4:]
} else {
v = runtime.Version()[4:]
}
goRuntimeVersion, _ := strconv.ParseFloat(runtime.Version()[4:], 64)
goVersion, err := strconv.ParseFloat(v, 64)
if err != nil {
goVersion = goRuntimeVersion
}
if os.Getenv("GO_ENV") == "" {
// if the flag "test.v" is *defined*, we're running as a unit test. Note that we don't care
// about v.Value (verbose test mode); we just want to know if the test environment has defined
// it. It's also possible that the flags are not yet fully parsed (i.e. flag.Parsed() == false),
// so we could not depend on v.Value anyway.
//
if v := flag.Lookup("test.v"); v != nil {
env["GO_ENV"] = "test"
}
}
// set the GOPATH if using >= 1.8 and the GOPATH isn't set
if goVersion >= 8 && os.Getenv("GOPATH") == "" {
out, err := exec.Command("go", "env", "GOPATH").Output()
if err == nil {
gp := strings.TrimSpace(string(out))
os.Setenv("GOPATH", gp)
}
}
for _, e := range os.Environ() {
pair := strings.Split(e, "=")
env[pair[0]] = os.Getenv(pair[0])
}
}
func Mods() bool {
return Get(GO111MODULE, "off") == "on"
}
// Reload the ENV variables. Useful if
// an external ENV manager has been used
func Reload() {
env = map[string]string{}
loadEnv()
}
// Load .env files. Files will be loaded in the same order that are received.
// Redefined vars will override previously existing values.
// IE: envy.Load(".env", "test_env/.env") will result in DIR=test_env
// If no arg passed, it will try to load a .env file.
func Load(files ...string) error {
// If no files received, load the default one
if len(files) == 0 {
err := godotenv.Overload()
if err == nil {
Reload()
}
return err
}
// We received a list of files
for _, file := range files {
// Check if it exists or we can access
if _, err := os.Stat(file); err != nil {
// It does not exist or we can not access.
// Return and stop loading
return err
}
// It exists and we have permission. Load it
if err := godotenv.Overload(file); err != nil {
return err
}
// Reload the env so all new changes are noticed
Reload()
}
return nil
}
// Get a value from the ENV. If it doesn't exist the
// default value will be returned.
func Get(key string, value string) string {
gil.RLock()
defer gil.RUnlock()
if v, ok := env[key]; ok {
return v
}
return value
}
// Get a value from the ENV. If it doesn't exist
// an error will be returned
func MustGet(key string) (string, error) {
gil.RLock()
defer gil.RUnlock()
if v, ok := env[key]; ok {
return v, nil
}
return "", fmt.Errorf("could not find ENV var with %s", key)
}
// Set a value into the ENV. This is NOT permanent. It will
// only affect values accessed through envy.
func Set(key string, value string) {
gil.Lock()
defer gil.Unlock()
env[key] = value
}
// MustSet the value into the underlying ENV, as well as envy.
// This may return an error if there is a problem setting the
// underlying ENV value.
func MustSet(key string, value string) error {
gil.Lock()
defer gil.Unlock()
err := os.Setenv(key, value)
if err != nil {
return err
}
env[key] = value
return nil
}
// Map all of the keys/values set in envy.
func Map() map[string]string {
gil.RLock()
defer gil.RUnlock()
cp := map[string]string{}
for k, v := range env {
cp[k] = v
}
return env
}
// Temp makes a copy of the values and allows operation on
// those values temporarily during the run of the function.
// At the end of the function run the copy is discarded and
// the original values are replaced. This is useful for testing.
// Warning: This function is NOT safe to use from a goroutine or
// from code which may access any Get or Set function from a goroutine
func Temp(f func()) {
oenv := env
env = map[string]string{}
for k, v := range oenv {
env[k] = v
}
defer func() { env = oenv }()
f()
}
func GoPath() string {
return Get("GOPATH", "")
}
func GoBin() string {
return Get("GO_BIN", "go")
}
// GoPaths returns all possible GOPATHS that are set.
func GoPaths() []string {
gp := Get("GOPATH", "")
if runtime.GOOS == "windows" {
return strings.Split(gp, ";") // Windows uses a different separator
}
return strings.Split(gp, ":")
}
func importPath(path string) string {
for _, gopath := range GoPaths() {
srcpath := filepath.Join(gopath, "src")
rel, err := filepath.Rel(srcpath, path)
if err == nil {
return filepath.ToSlash(rel)
}
}
// fallback to trim
rel := strings.TrimPrefix(path, filepath.Join(GoPath(), "src"))
rel = strings.TrimPrefix(rel, string(filepath.Separator))
return filepath.ToSlash(rel)
}
func CurrentPackage() string {
pwd, _ := os.Getwd()
return importPath(pwd)
}
func Environ() []string {
gil.RLock()
defer gil.RUnlock()
var e []string
for k, v := range env {
e = append(e, fmt.Sprintf("%s=%s", k, v))
}
return e
}

8
vendor/github.com/gobuffalo/envy/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/gobuffalo/envy
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/joho/godotenv v1.3.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
)

8
vendor/github.com/gobuffalo/envy/go.sum generated vendored Normal file
View File

@ -0,0 +1,8 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

10
vendor/github.com/gobuffalo/envy/shoulders.md generated vendored Normal file
View File

@ -0,0 +1,10 @@
# github.com/gobuffalo/envy Stands on the Shoulders of Giants
github.com/gobuffalo/envy does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
Thank you to the following **GIANTS**:
* [github.com/gobuffalo/envy](https://godoc.org/github.com/gobuffalo/envy)
* [github.com/joho/godotenv](https://godoc.org/github.com/joho/godotenv)

3
vendor/github.com/gobuffalo/envy/version.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
package envy
const Version = "v1.6.7"

29
vendor/github.com/gobuffalo/packd/.gitignore generated vendored Normal file
View File

@ -0,0 +1,29 @@
*.log
.DS_Store
doc
tmp
pkg
*.gem
*.pid
coverage
coverage.data
build/*
*.pbxuser
*.mode1v3
.svn
profile
.console_history
.sass-cache/*
.rake_tasks~
*.log.lck
solr/
.jhw-cache/
jhw.*
*.sublime*
node_modules/
dist/
generated/
.vendor/
bin/*
gin-bin
.idea/

3
vendor/github.com/gobuffalo/packd/.gometalinter.json generated vendored Normal file
View File

@ -0,0 +1,3 @@
{
"Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
}

26
vendor/github.com/gobuffalo/packd/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,26 @@
language: go
sudo: false
matrix:
include:
- go: "1.9.x"
- go: "1.10.x"
- go: "1.11.x"
env:
- GO111MODULE=off
- go: "1.11.x"
env:
- GO111MODULE=on
- go: "tip"
env:
- GO111MODULE=off
- go: "tip"
env:
- GO111MODULE=on
allow_failures:
- go: "tip"
install: make deps
script: make ci-test

21
vendor/github.com/gobuffalo/packd/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Mark Bates
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.

55
vendor/github.com/gobuffalo/packd/Makefile generated vendored Normal file
View File

@ -0,0 +1,55 @@
TAGS ?= "sqlite"
GO_BIN ?= go
install:
packr
$(GO_BIN) install -tags ${TAGS} -v .
make tidy
tidy:
ifeq ($(GO111MODULE),on)
$(GO_BIN) mod tidy
else
echo skipping go mod tidy
endif
deps:
$(GO_BIN) get github.com/gobuffalo/release
$(GO_BIN) get github.com/gobuffalo/packr/packr
$(GO_BIN) get -tags ${TAGS} -t ./...
make tidy
build:
packr
$(GO_BIN) build -v .
make tidy
test:
packr
$(GO_BIN) test -tags ${TAGS} ./...
make tidy
ci-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
make tidy
lint:
gometalinter --vendor ./... --deadline=1m --skip=internal
make tidy
update:
$(GO_BIN) get -u -tags ${TAGS}
make tidy
packr
make test
make install
make tidy
release-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
make tidy
release:
make tidy
release -y -f version.go
make tidy

24
vendor/github.com/gobuffalo/packd/README.md generated vendored Normal file
View File

@ -0,0 +1,24 @@
<p align="center"><img src="https://github.com/gobuffalo/buffalo/blob/master/logo.svg" width="360"></p>
<p align="center">
<a href="https://godoc.org/github.com/gobuffalo/packd"><img src="https://godoc.org/github.com/gobuffalo/packd?status.svg" alt="GoDoc" /></a>
<a href="https://travis-ci.org/gobuffalo/packd"><img src="https://travis-ci.org/gobuffalo/packd.svg?branch=master" alt="Build Status" /></a>
<a href="https://goreportcard.com/report/github.com/gobuffalo/packd"><img src="https://goreportcard.com/badge/github.com/gobuffalo/packd" alt="Go Report Card" /></a>
</p>
# github.com/gobuffalo/packd
This is a collection of interfaces designed to make using [github.com/gobuffalo/packr](https://github.com/gobuffalo/packr) easier, and to make the transition between v1 and v2 as seamless as possible.
They can, and should, be used for testing, alternate Box implementations, etc...
## Installation
```bash
$ go get -u -v github.com/gobuffalo/packd
```
## Memory Box
The [`packd#MemoryBox`](https://godoc.org/github.com/gobuffalo/packd#MemoryBox) is a complete, thread-safe, implementation of [`packd#Box`](https://godoc.org/github.com/gobuffalo/packd#Box)

104
vendor/github.com/gobuffalo/packd/file.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
package packd
import (
"bytes"
"fmt"
"io"
"os"
"time"
"github.com/pkg/errors"
)
var _ File = &virtualFile{}
var _ io.Reader = &virtualFile{}
var _ io.Writer = &virtualFile{}
var _ fmt.Stringer = &virtualFile{}
type virtualFile struct {
buf *bytes.Buffer
name string
info fileInfo
}
func (f virtualFile) Name() string {
return f.name
}
func (f virtualFile) Seek(offset int64, whence int) (int64, error) {
return -1, nil
}
func (f virtualFile) FileInfo() (os.FileInfo, error) {
return f.info, nil
}
func (f virtualFile) Close() error {
return nil
}
func (f virtualFile) Readdir(count int) ([]os.FileInfo, error) {
return []os.FileInfo{f.info}, nil
}
func (f virtualFile) Stat() (os.FileInfo, error) {
return f.info, nil
}
func (s *virtualFile) String() string {
return s.buf.String()
}
func (s *virtualFile) Read(p []byte) (int, error) {
return s.buf.Read(p)
}
func (s *virtualFile) Write(p []byte) (int, error) {
bb := &bytes.Buffer{}
i, err := bb.Write(p)
if err != nil {
return i, errors.WithStack(err)
}
s.buf = bb
s.info = fileInfo{
Path: s.name,
Contents: bb.Bytes(),
size: int64(bb.Len()),
modTime: time.Now(),
}
return i, nil
}
// NewDir returns a new "virtual" file
func NewFile(name string, r io.Reader) (File, error) {
bb := &bytes.Buffer{}
if r != nil {
io.Copy(bb, r)
}
return &virtualFile{
buf: bb,
name: name,
info: fileInfo{
Path: name,
Contents: bb.Bytes(),
size: int64(bb.Len()),
modTime: time.Now(),
},
}, nil
}
// NewDir returns a new "virtual" directory
func NewDir(name string) (File, error) {
bb := &bytes.Buffer{}
return &virtualFile{
buf: bb,
name: name,
info: fileInfo{
Path: name,
Contents: bb.Bytes(),
size: int64(bb.Len()),
modTime: time.Now(),
isDir: true,
},
}, nil
}

40
vendor/github.com/gobuffalo/packd/file_info.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
package packd
import (
"os"
"time"
)
var _ os.FileInfo = fileInfo{}
type fileInfo struct {
Path string
Contents []byte
size int64
modTime time.Time
isDir bool
}
func (f fileInfo) Name() string {
return f.Path
}
func (f fileInfo) Size() int64 {
return f.size
}
func (f fileInfo) Mode() os.FileMode {
return 0444
}
func (f fileInfo) ModTime() time.Time {
return f.modTime
}
func (f fileInfo) IsDir() bool {
return f.isDir
}
func (f fileInfo) Sys() interface{} {
return nil
}

8
vendor/github.com/gobuffalo/packd/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/gobuffalo/packd
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
)

8
vendor/github.com/gobuffalo/packd/go.sum generated vendored Normal file
View File

@ -0,0 +1,8 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

79
vendor/github.com/gobuffalo/packd/interfaces.go generated vendored Normal file
View File

@ -0,0 +1,79 @@
package packd
import (
"fmt"
"io"
"net/http"
"os"
)
type WalkFunc func(string, File) error
// Box represents the entirety of the necessary
// interfaces to form a "full" box.
// github.com/gobuffalo/packr#Box is an example of this interface.
type Box interface {
HTTPBox
Lister
Addable
Finder
Walkable
Haser
}
type Haser interface {
Has(string) bool
}
type Walkable interface {
Walk(wf WalkFunc) error
WalkPrefix(prefix string, wf WalkFunc) error
}
type Finder interface {
Find(string) ([]byte, error)
FindString(name string) (string, error)
}
type HTTPBox interface {
Open(name string) (http.File, error)
}
type Lister interface {
List() []string
}
type Addable interface {
AddString(path string, t string) error
AddBytes(path string, t []byte) error
}
type SimpleFile interface {
fmt.Stringer
io.Reader
io.Writer
Name() string
}
type HTTPFile interface {
SimpleFile
io.Closer
io.Seeker
Readdir(count int) ([]os.FileInfo, error)
Stat() (os.FileInfo, error)
}
type File interface {
HTTPFile
FileInfo() (os.FileInfo, error)
}
// LegacyBox represents deprecated methods
// that older Box implementations might have had.
// github.com/gobuffalo/packr v1 is an example of a LegacyBox.
type LegacyBox interface {
String(name string) string
MustString(name string) (string, error)
Bytes(name string) []byte
MustBytes(name string) ([]byte, error)
}

148
vendor/github.com/gobuffalo/packd/memory_box.go generated vendored Normal file
View File

@ -0,0 +1,148 @@
package packd
import (
"bytes"
"fmt"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"sync"
)
var _ Addable = NewMemoryBox()
var _ Finder = NewMemoryBox()
var _ Lister = NewMemoryBox()
var _ HTTPBox = NewMemoryBox()
var _ Haser = NewMemoryBox()
var _ Walkable = NewMemoryBox()
var _ Box = NewMemoryBox()
// MemoryBox is a thread-safe, in-memory, implementation of the Box interface.
type MemoryBox struct {
files *sync.Map
}
func (m *MemoryBox) Has(path string) bool {
_, ok := m.files.Load(path)
return ok
}
func (m *MemoryBox) List() []string {
var names []string
m.files.Range(func(key interface{}, value interface{}) bool {
if s, ok := key.(string); ok {
names = append(names, s)
}
return true
})
sort.Strings(names)
return names
}
func (m *MemoryBox) Open(path string) (http.File, error) {
cpath := strings.TrimPrefix(path, "/")
if filepath.Ext(cpath) == "" {
// it's a directory
return NewDir(path)
}
if len(cpath) == 0 {
cpath = "index.html"
}
b, err := m.Find(cpath)
if err != nil {
return nil, err
}
cpath = filepath.FromSlash(cpath)
f, err := NewFile(cpath, bytes.NewReader(b))
if err != nil {
return nil, err
}
return f, nil
}
func (m *MemoryBox) FindString(path string) (string, error) {
bb, err := m.Find(path)
return string(bb), err
}
func (m *MemoryBox) Find(path string) ([]byte, error) {
res, ok := m.files.Load(strings.ToLower(path))
if !ok {
return nil, os.ErrNotExist
}
b, ok := res.([]byte)
if !ok {
return nil, fmt.Errorf("expected []byte got %T", res)
}
return b, nil
}
func (m *MemoryBox) AddString(path string, t string) error {
return m.AddBytes(path, []byte(t))
}
func (m *MemoryBox) AddBytes(path string, t []byte) error {
m.files.Store(strings.ToLower(path), t)
return nil
}
func (m *MemoryBox) Walk(wf WalkFunc) error {
var err error
m.files.Range(func(key interface{}, res interface{}) bool {
path, ok := key.(string)
if !ok {
err = fmt.Errorf("expected string got %T", key)
return false
}
b, ok := res.([]byte)
if !ok {
err = fmt.Errorf("expected []byte got %T", res)
return false
}
var f File
f, err = NewFile(path, bytes.NewReader(b))
if err != nil {
return false
}
err = wf(path, f)
if err != nil {
return false
}
return true
})
return err
}
func (m *MemoryBox) WalkPrefix(pre string, wf WalkFunc) error {
return m.Walk(func(path string, file File) error {
if strings.HasPrefix(path, pre) {
return wf(path, file)
}
return nil
})
}
func (m *MemoryBox) Remove(path string) {
m.files.Delete(path)
}
// NewMemoryBox returns a configured *MemoryBox
func NewMemoryBox() *MemoryBox {
return &MemoryBox{
files: &sync.Map{},
}
}

4
vendor/github.com/gobuffalo/packd/version.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
package packd
// Version of packd
const Version = "v0.0.1"

20
vendor/github.com/gobuffalo/packr/.codeclimate.yml generated vendored Normal file
View File

@ -0,0 +1,20 @@
---
engines:
golint:
enabled: true
checks:
GoLint/Naming/MixedCaps:
enabled: false
govet:
enabled: true
gofmt:
enabled: true
fixme:
enabled: true
ratings:
paths:
- "**.go"
exclude_paths:
- "**/*_test.go"
- "*_test.go"
- "fixtures/"

33
vendor/github.com/gobuffalo/packr/.gitignore generated vendored Normal file
View File

@ -0,0 +1,33 @@
*.log
.DS_Store
doc
tmp
pkg
*.gem
*.pid
coverage
coverage.data
build/*
*.pbxuser
*.mode1v3
.svn
profile
.console_history
.sass-cache/*
.rake_tasks~
*.log.lck
solr/
.jhw-cache/
jhw.*
*.sublime*
node_modules/
dist/
generated/
.vendor/
bin/*
gin-bin
/packr_darwin_amd64
/packr_linux_amd64
.vscode/
debug.test
.grifter/

46
vendor/github.com/gobuffalo/packr/.goreleaser.yml generated vendored Normal file
View File

@ -0,0 +1,46 @@
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
builds:
-
goos:
- darwin
- linux
- windows
env:
- CGO_ENABLED=0
main: ./packr/main.go
binary: packr
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ .Tag }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
brew:
github:
owner: gobuffalo
name: homebrew-tap

16
vendor/github.com/gobuffalo/packr/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,16 @@
language: go
sudo: false
go:
- 1.9
- "1.10"
- "1.11"
- tip
matrix:
allow_failures:
- go: 'tip'
script:
- make ci-test

8
vendor/github.com/gobuffalo/packr/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2016 Mark Bates
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.

36
vendor/github.com/gobuffalo/packr/Makefile generated vendored Normal file
View File

@ -0,0 +1,36 @@
TAGS ?= "sqlite"
GO_BIN ?= go
install: deps
packr
$(GO_BIN) install -v .
deps:
$(GO_BIN) get github.com/gobuffalo/packr/packr
$(GO_BIN) get -tags ${TAGS} -t ./...
build: deps
packr
$(GO_BIN) build -v .
test:
packr
$(GO_BIN) test -tags ${TAGS} ./...
ci-test: deps
$(GO_BIN) test -tags ${TAGS} -race ./...
lint:
gometalinter --vendor ./... --deadline=1m --skip=internal
update:
$(GO_BIN) get -u
$(GO_BIN) mod tidy
packr
make test
release-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
release:
release -y -f version.go

198
vendor/github.com/gobuffalo/packr/README.md generated vendored Normal file
View File

@ -0,0 +1,198 @@
# packr
[![GoDoc](https://godoc.org/github.com/gobuffalo/packr?status.svg)](https://godoc.org/github.com/gobuffalo/packr)
Packr is a simple solution for bundling static assets inside of Go binaries. Most importantly it does it in a way that is friendly to developers while they are developing.
## Intro Video
To get an idea of the what and why of packr, please enjoy this short video: [https://vimeo.com/219863271](https://vimeo.com/219863271).
## Installation
To install Packr utility
```text
$ go get -u github.com/gobuffalo/packr/packr
```
To get the dependency
```text
$ go get -u github.com/gobuffalo/packr
```
## Usage
### In Code
The first step in using Packr is to create a new box. A box represents a folder on disk. Once you have a box you can get `string` or `[]byte` representations of the file.
```go
// set up a new box by giving it a (relative) path to a folder on disk:
box := packr.NewBox("./templates")
// Get the string representation of a file, or an error if it doesn't exist:
html, err := box.FindString("index.html")
// Get the []byte representation of a file, or an error if it doesn't exist:
html, err := box.FindBytes("index.html")
```
### What is a Box?
A box represents a folder, and any sub-folders, on disk that you want to have access to in your binary. When compiling a binary using the `packr` CLI the contents of the folder will be converted into Go files that can be compiled inside of a "standard" go binary. Inside of the compiled binary the files will be read from memory. When working locally the files will be read directly off of disk. This is a seamless switch that doesn't require any special attention on your part.
#### Example
Assume the follow directory structure:
```
├── main.go
└── templates
├── admin
│   └── index.html
└── index.html
```
The following program will read the `./templates/admin/index.html` file and print it out.
```go
package main
import (
"fmt"
"github.com/gobuffalo/packr"
)
func main() {
box := packr.NewBox("./templates")
s := box.String("admin/index.html")
fmt.Println(s)
}
```
### Development Made Easy
In order to get static files into a Go binary, those files must first be converted to Go code. To do that, Packr, ships with a few tools to help build binaries. See below.
During development, however, it is painful to have to keep running a tool to compile those files.
Packr uses the following resolution rules when looking for a file:
1. Look for the file in-memory (inside a Go binary)
1. Look for the file on disk (during development)
Because Packr knows how to fall through to the file system, developers don't need to worry about constantly compiling their static files into a binary. They can work unimpeded.
Packr takes file resolution a step further. When declaring a new box you use a relative path, `./templates`. When Packr receives this call it calculates out the absolute path to that directory. By doing this it means you can be guaranteed that Packr can find your files correctly, even if you're not running in the directory that the box was created in. This helps with the problem of testing, where Go changes the `pwd` for each package, making relative paths difficult to work with. This is not a problem when using Packr.
---
## Usage with HTTP
A box implements the [`http.FileSystem`](https://golang.org/pkg/net/http/#FileSystemhttps://golang.org/pkg/net/http/#FileSystem) interface, meaning it can be used to serve static files.
```go
package main
import (
"net/http"
"github.com/gobuffalo/packr"
)
func main() {
box := packr.NewBox("./templates")
http.Handle("/", http.FileServer(box))
http.ListenAndServe(":3000", nil)
}
```
---
## Building a Binary (the easy way)
When it comes time to build, or install, your Go binary, simply use `packr build` or `packr install` just as you would `go build` or `go install`. All flags for the `go` tool are supported and everything works the way you expect, the only difference is your static assets are now bundled in the generated binary. If you want more control over how this happens, looking at the following section on building binaries (the hard way).
## Building a Binary (the hard way)
Before you build your Go binary, run the `packr` command first. It will look for all the boxes in your code and then generate `.go` files that pack the static files into bytes that can be bundled into the Go binary.
```
$ packr
```
Then run your `go build command` like normal.
*NOTE*: It is not recommended to check-in these generated `-packr.go` files. They can be large, and can easily become out of date if not careful. It is recommended that you always run `packr clean` after running the `packr` tool.
#### Cleaning Up
When you're done it is recommended that you run the `packr clean` command. This will remove all of the generated files that Packr created for you.
```
$ packr clean
```
Why do you want to do this? Packr first looks to the information stored in these generated files, if the information isn't there it looks to disk. This makes it easy to work with in development.
---
## Building/Moving a portable release
When it comes to building multiple releases you typically want that release to be built in a specific directory.
For example: `./releases`
However, because passing a `.go` file requires absolute paths, we must compile the release in the appropriate absolute path.
```bash
GOOS=linux GOARCH=amd64 packr build
```
Now your `project_name` binary will be built at the root of your project dir. Great!
All that is left to do is to move that binary to your release dir:
Linux/macOS/Windows (bash)
```bash
mv ./project_name ./releases
```
Windows (cmd):
```cmd
move ./project_name ./releases
```
Powershell:
```powershell
Move-Item -Path .\project_name -Destination .\releases\
```
If you _target_ for Windows when building don't forget that it's `project_name.exe`
Now you can make multiple releases and all of your needed static files will be available!
#### Summing it up:
Example Script for building to 3 common targets:
```bash
GOOS=darwin GOARCH=amd64 packr build && mv ./project_name ./releases/darwin-project_name \
&& GOOS=linux GOARCH=amd64 packr build && mv ./project_name ./releases/linux-project_name \
&& GOOS=windows GOARCH=386 packr build && mv ./project_name.exe ./releases/project_name.exe \
&& packr clean
```
---
## Debugging
The `packr` command passes all arguments down to the underlying `go` command, this includes the `-v` flag to print out `go build` information. Packr looks for the `-v` flag, and will turn on its own verbose logging. This is very useful for trying to understand what the `packr` command is doing when it is run.

231
vendor/github.com/gobuffalo/packr/box.go generated vendored Normal file
View File

@ -0,0 +1,231 @@
package packr
import (
"bytes"
"compress/gzip"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"github.com/gobuffalo/packd"
"github.com/markbates/oncer"
"github.com/pkg/errors"
)
var (
// ErrResOutsideBox gets returned in case of the requested resources being outside the box
ErrResOutsideBox = errors.New("Can't find a resource outside the box")
)
var _ packd.Box = Box{}
var _ packd.HTTPBox = Box{}
var _ packd.Lister = Box{}
var _ packd.Addable = Box{}
var _ packd.Walkable = Box{}
var _ packd.Finder = Box{}
var _ packd.LegacyBox = Box{}
// NewBox returns a Box that can be used to
// retrieve files from either disk or the embedded
// binary.
func NewBox(path string) Box {
var cd string
if !filepath.IsAbs(path) {
_, filename, _, _ := runtime.Caller(1)
cd = filepath.Dir(filename)
}
// this little hack courtesy of the `-cover` flag!!
cov := filepath.Join("_test", "_obj_test")
cd = strings.Replace(cd, string(filepath.Separator)+cov, "", 1)
if !filepath.IsAbs(cd) && cd != "" {
cd = filepath.Join(GoPath(), "src", cd)
}
return Box{
Path: path,
callingDir: cd,
data: map[string][]byte{},
}
}
// Box represent a folder on a disk you want to
// have access to in the built Go binary.
type Box struct {
Path string
callingDir string
data map[string][]byte
directories map[string]bool
}
// AddString converts t to a byteslice and delegates to AddBytes to add to b.data
func (b Box) AddString(path string, t string) error {
b.AddBytes(path, []byte(t))
return nil
}
// AddBytes sets t in b.data by the given path
func (b Box) AddBytes(path string, t []byte) error {
b.data[path] = t
return nil
}
// String is deprecated. Use Find instead
func (b Box) String(name string) string {
oncer.Deprecate(0, "github.com/gobuffalo/packr#Box.String", "Use github.com/gobuffalo/packr#Box.FindString instead.")
bb, _ := b.FindString(name)
return bb
}
// MustString is deprecated. Use FindString instead
func (b Box) MustString(name string) (string, error) {
oncer.Deprecate(0, "github.com/gobuffalo/packr#Box.MustString", "Use github.com/gobuffalo/packr#Box.FindString instead.")
return b.FindString(name)
}
// Bytes is deprecated. Use Find instead
func (b Box) Bytes(name string) []byte {
oncer.Deprecate(0, "github.com/gobuffalo/packr#Box.Bytes", "Use github.com/gobuffalo/packr#Box.Find instead.")
bb, _ := b.Find(name)
return bb
}
// Bytes is deprecated. Use Find instead
func (b Box) MustBytes(name string) ([]byte, error) {
oncer.Deprecate(0, "github.com/gobuffalo/packr#Box.MustBytes", "Use github.com/gobuffalo/packr#Box.Find instead.")
return b.Find(name)
}
// FindString returns either the string of the requested
// file or an error if it can not be found.
func (b Box) FindString(name string) (string, error) {
bb, err := b.Find(name)
return string(bb), err
}
// Find returns either the byte slice of the requested
// file or an error if it can not be found.
func (b Box) Find(name string) ([]byte, error) {
f, err := b.find(name)
if err == nil {
bb := &bytes.Buffer{}
bb.ReadFrom(f)
return bb.Bytes(), err
}
return nil, err
}
// Has returns true if the resource exists in the box
func (b Box) Has(name string) bool {
_, err := b.find(name)
if err != nil {
return false
}
return true
}
func (b Box) decompress(bb []byte) []byte {
reader, err := gzip.NewReader(bytes.NewReader(bb))
if err != nil {
return bb
}
data, err := ioutil.ReadAll(reader)
if err != nil {
return bb
}
return data
}
func (b Box) find(name string) (File, error) {
if bb, ok := b.data[name]; ok {
return packd.NewFile(name, bytes.NewReader(bb))
}
if b.directories == nil {
b.indexDirectories()
}
cleanName := filepath.ToSlash(filepath.Clean(name))
// Ensure name is not outside the box
if strings.HasPrefix(cleanName, "../") {
return nil, ErrResOutsideBox
}
// Absolute name is considered as relative to the box root
cleanName = strings.TrimPrefix(cleanName, "/")
if _, ok := data[b.Path]; ok {
if bb, ok := data[b.Path][cleanName]; ok {
bb = b.decompress(bb)
return packd.NewFile(cleanName, bytes.NewReader(bb))
}
if _, ok := b.directories[cleanName]; ok {
return packd.NewDir(cleanName)
}
if filepath.Ext(cleanName) != "" {
// The Handler created by http.FileSystem checks for those errors and
// returns http.StatusNotFound instead of http.StatusInternalServerError.
return nil, os.ErrNotExist
}
return nil, os.ErrNotExist
}
// Not found in the box virtual fs, try to get it from the file system
cleanName = filepath.FromSlash(cleanName)
p := filepath.Join(b.callingDir, b.Path, cleanName)
return fileFor(p, cleanName)
}
// Open returns a File using the http.File interface
func (b Box) Open(name string) (http.File, error) {
return b.find(name)
}
// List shows "What's in the box?"
func (b Box) List() []string {
var keys []string
if b.data == nil || len(b.data) == 0 {
b.Walk(func(path string, info File) error {
finfo, _ := info.FileInfo()
if !finfo.IsDir() {
keys = append(keys, finfo.Name())
}
return nil
})
} else {
for k := range b.data {
keys = append(keys, k)
}
}
return keys
}
func (b *Box) indexDirectories() {
b.directories = map[string]bool{}
if _, ok := data[b.Path]; ok {
for name := range data[b.Path] {
prefix, _ := path.Split(name)
// Even on Windows the suffix appears to be a /
prefix = strings.TrimSuffix(prefix, "/")
b.directories[prefix] = true
}
}
}
func fileFor(p string, name string) (File, error) {
fi, err := os.Stat(p)
if err != nil {
return nil, err
}
if fi.IsDir() {
return packd.NewDir(p)
}
if bb, err := ioutil.ReadFile(p); err == nil {
return packd.NewFile(name, bytes.NewReader(bb))
}
return nil, os.ErrNotExist
}

13
vendor/github.com/gobuffalo/packr/env.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package packr
import (
"github.com/gobuffalo/envy"
)
// GoPath returns the current GOPATH env var
// or if it's missing, the default.
var GoPath = envy.GoPath
// GoBin returns the current GO_BIN env var
// or if it's missing, a default of "go"
var GoBin = envy.GoBin

5
vendor/github.com/gobuffalo/packr/file.go generated vendored Normal file
View File

@ -0,0 +1,5 @@
package packr
import "github.com/gobuffalo/packd"
type File = packd.File

14
vendor/github.com/gobuffalo/packr/go.mod generated vendored Normal file
View File

@ -0,0 +1,14 @@
module github.com/gobuffalo/packr
require (
github.com/gobuffalo/envy v1.6.7
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4
github.com/pkg/errors v0.8.0
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect
github.com/stretchr/testify v1.2.2
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
)

26
vendor/github.com/gobuffalo/packr/go.sum generated vendored Normal file
View File

@ -0,0 +1,26 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobuffalo/envy v1.6.7 h1:XMZGuFqTupAXhZTriQ+qO38QvNOSU/0rl3hEPCFci/4=
github.com/gobuffalo/envy v1.6.7/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264 h1:roWyi0eEdiFreSqW9V1wT9pNOVzrpo2NWsxja53slX0=
github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4 h1:Mlji5gkcpzkqTROyE4ZxZ8hN7osunMb2RuGVrbvMvCc=
github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc h1:ZMCWScCvS2fUVFw8LOpxyUUW5qiviqr4Dg5NdjLeiLU=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

74
vendor/github.com/gobuffalo/packr/packr.go generated vendored Normal file
View File

@ -0,0 +1,74 @@
package packr
import (
"bytes"
"compress/gzip"
"encoding/json"
"runtime"
"strings"
"sync"
)
var gil = &sync.Mutex{}
var data = map[string]map[string][]byte{}
// PackBytes packs bytes for a file into a box.
func PackBytes(box string, name string, bb []byte) {
gil.Lock()
defer gil.Unlock()
if _, ok := data[box]; !ok {
data[box] = map[string][]byte{}
}
data[box][name] = bb
}
// PackBytesGzip packets the gzipped compressed bytes into a box.
func PackBytesGzip(box string, name string, bb []byte) error {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
_, err := w.Write(bb)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
PackBytes(box, name, buf.Bytes())
return nil
}
// PackJSONBytes packs JSON encoded bytes for a file into a box.
func PackJSONBytes(box string, name string, jbb string) error {
var bb []byte
err := json.Unmarshal([]byte(jbb), &bb)
if err != nil {
return err
}
PackBytes(box, name, bb)
return nil
}
// UnpackBytes unpacks bytes for specific box.
func UnpackBytes(box string) {
gil.Lock()
defer gil.Unlock()
delete(data, box)
}
func osPaths(paths ...string) []string {
if runtime.GOOS == "windows" {
for i, path := range paths {
paths[i] = strings.Replace(path, "/", "\\", -1)
}
}
return paths
}
func osPath(path string) string {
if runtime.GOOS == "windows" {
return strings.Replace(path, "/", "\\", -1)
}
return path
}

18
vendor/github.com/gobuffalo/packr/shoulders.md generated vendored Normal file
View File

@ -0,0 +1,18 @@
# github.com/gobuffalo/packr Stands on the Shoulders of Giants
github.com/gobuffalo/packr does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
Thank you to the following **GIANTS**:
* [github.com/gobuffalo/envy](https://godoc.org/github.com/gobuffalo/envy)
* [github.com/gobuffalo/packd](https://godoc.org/github.com/gobuffalo/packd)
* [github.com/gobuffalo/packr](https://godoc.org/github.com/gobuffalo/packr)
* [github.com/joho/godotenv](https://godoc.org/github.com/joho/godotenv)
* [github.com/markbates/oncer](https://godoc.org/github.com/markbates/oncer)
* [github.com/pkg/errors](https://godoc.org/github.com/pkg/errors)

3
vendor/github.com/gobuffalo/packr/version.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
package packr
const Version = "v1.19.0"

64
vendor/github.com/gobuffalo/packr/walk.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package packr
import (
"os"
"path/filepath"
"strings"
"github.com/gobuffalo/packd"
"github.com/pkg/errors"
)
type WalkFunc = packd.WalkFunc
// Walk will traverse the box and call the WalkFunc for each file in the box/folder.
func (b Box) Walk(wf WalkFunc) error {
if data[b.Path] == nil {
base, err := filepath.EvalSymlinks(filepath.Join(b.callingDir, b.Path))
if err != nil {
return errors.WithStack(err)
}
return filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
cleanName, err := filepath.Rel(base, path)
if err != nil {
cleanName = strings.TrimPrefix(path, base)
}
cleanName = filepath.ToSlash(filepath.Clean(cleanName))
cleanName = strings.TrimPrefix(cleanName, "/")
cleanName = filepath.FromSlash(cleanName)
if info == nil || info.IsDir() {
return nil
}
file, err := fileFor(path, cleanName)
if err != nil {
return err
}
return wf(cleanName, file)
})
}
for n := range data[b.Path] {
f, err := b.find(n)
if err != nil {
return err
}
err = wf(n, f)
if err != nil {
return err
}
}
return nil
}
// WalkPrefix will call box.Walk and call the WalkFunc when it finds paths that have a matching prefix
func (b Box) WalkPrefix(prefix string, wf WalkFunc) error {
opre := osPath(prefix)
return b.Walk(func(path string, f File) error {
if strings.HasPrefix(osPath(path), opre) {
if err := wf(path, f); err != nil {
return errors.WithStack(err)
}
}
return nil
})
}

1
vendor/github.com/joho/godotenv/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

8
vendor/github.com/joho/godotenv/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,8 @@
language: go
go:
- 1.x
os:
- linux
- osx

23
vendor/github.com/joho/godotenv/LICENCE generated vendored Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2013 John Barton
MIT License
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.

163
vendor/github.com/joho/godotenv/README.md generated vendored Normal file
View File

@ -0,0 +1,163 @@
# GoDotEnv [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4?svg=true)](https://ci.appveyor.com/project/joho/godotenv) [![Go Report Card](https://goreportcard.com/badge/github.com/joho/godotenv)](https://goreportcard.com/report/github.com/joho/godotenv)
A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file)
From the original Library:
> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environmentssuch as resource handles for databases or credentials for external servicesshould be extracted from the code into environment variables.
>
> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
It can be used as a library (for loading in env for your own daemons etc) or as a bin command.
There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows.
## Installation
As a library
```shell
go get github.com/joho/godotenv
```
or if you want to use it as a bin command
```shell
go get github.com/joho/godotenv/cmd/godotenv
```
## Usage
Add your application configuration to your `.env` file in the root of your project:
```shell
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
```
Then in your Go app you can do something like
```go
package main
import (
"github.com/joho/godotenv"
"log"
"os"
)
func main() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
s3Bucket := os.Getenv("S3_BUCKET")
secretKey := os.Getenv("SECRET_KEY")
// now do something with s3 or whatever
}
```
If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import
```go
import _ "github.com/joho/godotenv/autoload"
```
While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit
```go
_ = godotenv.Load("somerandomfile")
_ = godotenv.Load("filenumberone.env", "filenumbertwo.env")
```
If you want to be really fancy with your env file you can do comments and exports (below is a valid env file)
```shell
# I am a comment and that is OK
SOME_VAR=someval
FOO=BAR # comments at line end are OK too
export BAR=BAZ
```
Or finally you can do YAML(ish) style
```yaml
FOO: bar
BAR: baz
```
as a final aside, if you don't want godotenv munging your env you can just get a map back instead
```go
var myEnv map[string]string
myEnv, err := godotenv.Read()
s3Bucket := myEnv["S3_BUCKET"]
```
... or from an `io.Reader` instead of a local file
```go
reader := getRemoteFile()
myEnv, err := godotenv.Parse(reader)
```
... or from a `string` if you so desire
```go
content := getRemoteFileContent()
myEnv, err := godotenv.Unmarshal(content)
```
### Command Mode
Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH`
```
godotenv -f /some/path/to/.env some_command with some args
```
If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD`
### Writing Env Files
Godotenv can also write a map representing the environment to a correctly-formatted and escaped file
```go
env, err := godotenv.Unmarshal("KEY=value")
err := godotenv.Write(env, "./.env")
```
... or to a string
```go
env, err := godotenv.Unmarshal("KEY=value")
content, err := godotenv.Marshal(env)
```
## Contributing
Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases.
*code changes without tests will not be accepted*
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## Releases
Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`.
Use [annotated tags for all releases](https://github.com/joho/godotenv/issues/30). Example `git tag -a v1.2.1`
## CI
Linux: [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4)](https://ci.appveyor.com/project/joho/godotenv)
## Who?
The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library.

346
vendor/github.com/joho/godotenv/godotenv.go generated vendored Normal file
View File

@ -0,0 +1,346 @@
// Package godotenv is a go port of the ruby dotenv library (https://github.com/bkeepers/dotenv)
//
// Examples/readme can be found on the github page at https://github.com/joho/godotenv
//
// The TL;DR is that you make a .env file that looks something like
//
// SOME_ENV_VAR=somevalue
//
// and then in your go code you can call
//
// godotenv.Load()
//
// and all the env vars declared in .env will be available through os.Getenv("SOME_ENV_VAR")
package godotenv
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"sort"
"strings"
)
const doubleQuoteSpecialChars = "\\\n\r\"!$`"
// Load will read your env file(s) and load them into ENV for this process.
//
// Call this function as close as possible to the start of your program (ideally in main)
//
// If you call Load without any args it will default to loading .env in the current path
//
// You can otherwise tell it which files to load (there can be more than one) like
//
// godotenv.Load("fileone", "filetwo")
//
// It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults
func Load(filenames ...string) (err error) {
filenames = filenamesOrDefault(filenames)
for _, filename := range filenames {
err = loadFile(filename, false)
if err != nil {
return // return early on a spazout
}
}
return
}
// Overload will read your env file(s) and load them into ENV for this process.
//
// Call this function as close as possible to the start of your program (ideally in main)
//
// If you call Overload without any args it will default to loading .env in the current path
//
// You can otherwise tell it which files to load (there can be more than one) like
//
// godotenv.Overload("fileone", "filetwo")
//
// It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefilly set all vars.
func Overload(filenames ...string) (err error) {
filenames = filenamesOrDefault(filenames)
for _, filename := range filenames {
err = loadFile(filename, true)
if err != nil {
return // return early on a spazout
}
}
return
}
// Read all env (with same file loading semantics as Load) but return values as
// a map rather than automatically writing values into env
func Read(filenames ...string) (envMap map[string]string, err error) {
filenames = filenamesOrDefault(filenames)
envMap = make(map[string]string)
for _, filename := range filenames {
individualEnvMap, individualErr := readFile(filename)
if individualErr != nil {
err = individualErr
return // return early on a spazout
}
for key, value := range individualEnvMap {
envMap[key] = value
}
}
return
}
// Parse reads an env file from io.Reader, returning a map of keys and values.
func Parse(r io.Reader) (envMap map[string]string, err error) {
envMap = make(map[string]string)
var lines []string
scanner := bufio.NewScanner(r)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err = scanner.Err(); err != nil {
return
}
for _, fullLine := range lines {
if !isIgnoredLine(fullLine) {
var key, value string
key, value, err = parseLine(fullLine, envMap)
if err != nil {
return
}
envMap[key] = value
}
}
return
}
//Unmarshal reads an env file from a string, returning a map of keys and values.
func Unmarshal(str string) (envMap map[string]string, err error) {
return Parse(strings.NewReader(str))
}
// Exec loads env vars from the specified filenames (empty map falls back to default)
// then executes the cmd specified.
//
// Simply hooks up os.Stdin/err/out to the command and calls Run()
//
// If you want more fine grained control over your command it's recommended
// that you use `Load()` or `Read()` and the `os/exec` package yourself.
func Exec(filenames []string, cmd string, cmdArgs []string) error {
Load(filenames...)
command := exec.Command(cmd, cmdArgs...)
command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr
return command.Run()
}
// Write serializes the given environment and writes it to a file
func Write(envMap map[string]string, filename string) error {
content, error := Marshal(envMap)
if error != nil {
return error
}
file, error := os.Create(filename)
if error != nil {
return error
}
_, err := file.WriteString(content)
return err
}
// Marshal outputs the given environment as a dotenv-formatted environment file.
// Each line is in the format: KEY="VALUE" where VALUE is backslash-escaped.
func Marshal(envMap map[string]string) (string, error) {
lines := make([]string, 0, len(envMap))
for k, v := range envMap {
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, doubleQuoteEscape(v)))
}
sort.Strings(lines)
return strings.Join(lines, "\n"), nil
}
func filenamesOrDefault(filenames []string) []string {
if len(filenames) == 0 {
return []string{".env"}
}
return filenames
}
func loadFile(filename string, overload bool) error {
envMap, err := readFile(filename)
if err != nil {
return err
}
currentEnv := map[string]bool{}
rawEnv := os.Environ()
for _, rawEnvLine := range rawEnv {
key := strings.Split(rawEnvLine, "=")[0]
currentEnv[key] = true
}
for key, value := range envMap {
if !currentEnv[key] || overload {
os.Setenv(key, value)
}
}
return nil
}
func readFile(filename string) (envMap map[string]string, err error) {
file, err := os.Open(filename)
if err != nil {
return
}
defer file.Close()
return Parse(file)
}
func parseLine(line string, envMap map[string]string) (key string, value string, err error) {
if len(line) == 0 {
err = errors.New("zero length string")
return
}
// ditch the comments (but keep quoted hashes)
if strings.Contains(line, "#") {
segmentsBetweenHashes := strings.Split(line, "#")
quotesAreOpen := false
var segmentsToKeep []string
for _, segment := range segmentsBetweenHashes {
if strings.Count(segment, "\"") == 1 || strings.Count(segment, "'") == 1 {
if quotesAreOpen {
quotesAreOpen = false
segmentsToKeep = append(segmentsToKeep, segment)
} else {
quotesAreOpen = true
}
}
if len(segmentsToKeep) == 0 || quotesAreOpen {
segmentsToKeep = append(segmentsToKeep, segment)
}
}
line = strings.Join(segmentsToKeep, "#")
}
firstEquals := strings.Index(line, "=")
firstColon := strings.Index(line, ":")
splitString := strings.SplitN(line, "=", 2)
if firstColon != -1 && (firstColon < firstEquals || firstEquals == -1) {
//this is a yaml-style line
splitString = strings.SplitN(line, ":", 2)
}
if len(splitString) != 2 {
err = errors.New("Can't separate key from value")
return
}
// Parse the key
key = splitString[0]
if strings.HasPrefix(key, "export") {
key = strings.TrimPrefix(key, "export")
}
key = strings.Trim(key, " ")
// Parse the value
value = parseValue(splitString[1], envMap)
return
}
func parseValue(value string, envMap map[string]string) string {
// trim
value = strings.Trim(value, " ")
// check if we've got quoted values or possible escapes
if len(value) > 1 {
rs := regexp.MustCompile(`\A'(.*)'\z`)
singleQuotes := rs.FindStringSubmatch(value)
rd := regexp.MustCompile(`\A"(.*)"\z`)
doubleQuotes := rd.FindStringSubmatch(value)
if singleQuotes != nil || doubleQuotes != nil {
// pull the quotes off the edges
value = value[1 : len(value)-1]
}
if doubleQuotes != nil {
// expand newlines
escapeRegex := regexp.MustCompile(`\\.`)
value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string {
c := strings.TrimPrefix(match, `\`)
switch c {
case "n":
return "\n"
case "r":
return "\r"
default:
return match
}
})
// unescape characters
e := regexp.MustCompile(`\\([^$])`)
value = e.ReplaceAllString(value, "$1")
}
if singleQuotes == nil {
value = expandVariables(value, envMap)
}
}
return value
}
func expandVariables(v string, m map[string]string) string {
r := regexp.MustCompile(`(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?`)
return r.ReplaceAllStringFunc(v, func(s string) string {
submatch := r.FindStringSubmatch(s)
if submatch == nil {
return s
}
if submatch[1] == "\\" || submatch[2] == "(" {
return submatch[0][1:]
} else if submatch[4] != "" {
return m[submatch[4]]
}
return s
})
}
func isIgnoredLine(line string) bool {
trimmedLine := strings.Trim(line, " \n\t")
return len(trimmedLine) == 0 || strings.HasPrefix(trimmedLine, "#")
}
func doubleQuoteEscape(line string) string {
for _, c := range doubleQuoteSpecialChars {
toReplace := "\\" + string(c)
if c == '\n' {
toReplace = `\n`
}
if c == '\r' {
toReplace = `\r`
}
line = strings.Replace(line, string(c), toReplace, -1)
}
return line
}

29
vendor/github.com/markbates/oncer/.gitignore generated vendored Normal file
View File

@ -0,0 +1,29 @@
*.log
.DS_Store
doc
tmp
pkg
*.gem
*.pid
coverage
coverage.data
build/*
*.pbxuser
*.mode1v3
.svn
profile
.console_history
.sass-cache/*
.rake_tasks~
*.log.lck
solr/
.jhw-cache/
jhw.*
*.sublime*
node_modules/
dist/
generated/
.vendor/
bin/*
gin-bin
.idea/

21
vendor/github.com/markbates/oncer/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Mark Bates
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.

40
vendor/github.com/markbates/oncer/Makefile generated vendored Normal file
View File

@ -0,0 +1,40 @@
TAGS ?= "sqlite"
GO_BIN ?= go
install:
packr
$(GO_BIN) install -v .
deps:
$(GO_BIN) get github.com/gobuffalo/release
$(GO_BIN) get github.com/gobuffalo/packr/packr
$(GO_BIN) get -tags ${TAGS} -t ./...
$(GO_BIN) mod tidy
build:
packr
$(GO_BIN) build -v .
test:
packr
$(GO_BIN) test -tags ${TAGS} ./...
ci-test: deps
$(GO_BIN) test -tags ${TAGS} -race ./...
lint:
gometalinter --vendor ./... --deadline=1m --skip=internal
update:
$(GO_BIN) get -u -tags ${TAGS}
$(GO_BIN) mod tidy
packr
make test
make install
$(GO_BIN) mod tidy
release-test:
$(GO_BIN) test -tags ${TAGS} -race ./...
release:
release -y -f version.go

20
vendor/github.com/markbates/oncer/deprecate.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
package oncer
import (
"fmt"
"io"
"os"
)
const deprecated = "DEPRECATED"
var deprecationWriter io.Writer = os.Stdout
func Deprecate(depth int, name string, msg string) {
Do(deprecated+name, func() {
fmt.Fprintf(deprecationWriter, "[%s] %s has been deprecated.\n", deprecated, name)
if len(msg) > 0 {
fmt.Fprintf(deprecationWriter, "\t%s\n", msg)
}
})
}

7
vendor/github.com/markbates/oncer/go.mod generated vendored Normal file
View File

@ -0,0 +1,7 @@
module github.com/markbates/oncer
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
)

6
vendor/github.com/markbates/oncer/go.sum generated vendored Normal file
View File

@ -0,0 +1,6 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

26
vendor/github.com/markbates/oncer/oncer.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
package oncer
import (
"sync"
)
var onces = &sync.Map{}
func Do(name string, fn func()) {
o, _ := onces.LoadOrStore(name, &sync.Once{})
if once, ok := o.(*sync.Once); ok {
once.Do(fn)
}
}
func Reset(names ...string) {
if len(names) == 0 {
onces = &sync.Map{}
return
}
for _, n := range names {
onces.Delete(n)
onces.Delete(deprecated + n)
}
}

33
vendor/github.com/pierrec/lz4/.gitignore generated vendored Normal file
View File

@ -0,0 +1,33 @@
# Created by https://www.gitignore.io/api/macos
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# End of https://www.gitignore.io/api/macos
lz4c/lz4c

18
vendor/github.com/pierrec/lz4/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,18 @@
language: go
go:
- 1.8.x
- 1.9.x
- 1.10.x
- master
matrix:
fast_finish: true
allow_failures:
- go: master
sudo: false
script:
- go test -v -cpu=2
- go test -v -cpu=2 -race

28
vendor/github.com/pierrec/lz4/LICENSE generated vendored Normal file
View File

@ -0,0 +1,28 @@
Copyright (c) 2015, Pierre Curto
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of xxHash nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

24
vendor/github.com/pierrec/lz4/README.md generated vendored Normal file
View File

@ -0,0 +1,24 @@
[![godoc](https://godoc.org/github.com/pierrec/lz4?status.png)](https://godoc.org/github.com/pierrec/lz4)
# lz4
LZ4 compression and decompression in pure Go.
## Usage
```go
import "github.com/pierrec/lz4"
```
## Description
Package lz4 implements reading and writing lz4 compressed data (a frame),
as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html.
This package is **compatible with the LZ4 frame format** although the block level compression
and decompression functions are exposed and are fully compatible with the lz4 block format
definition, they are low level and should not be used directly.
For a complete description of an lz4 compressed block, see:
http://fastcompression.blogspot.fr/2011/05/lz4-explained.html
See https://github.com/Cyan4973/lz4 for the reference C implementation.

397
vendor/github.com/pierrec/lz4/block.go generated vendored Normal file
View File

@ -0,0 +1,397 @@
package lz4
import (
"encoding/binary"
"errors"
)
var (
// ErrInvalidSourceShortBuffer is returned by UncompressBlock or CompressBLock when a compressed
// block is corrupted or the destination buffer is not large enough for the uncompressed data.
ErrInvalidSourceShortBuffer = errors.New("lz4: invalid source or destination buffer too short")
// ErrInvalid is returned when reading an invalid LZ4 archive.
ErrInvalid = errors.New("lz4: bad magic number")
)
// blockHash hashes 4 bytes into a value < winSize.
func blockHash(x uint32) uint32 {
const hasher uint32 = 2654435761 // Knuth multiplicative hash.
return x * hasher >> hashShift
}
// CompressBlockBound returns the maximum size of a given buffer of size n, when not compressible.
func CompressBlockBound(n int) int {
return n + n/255 + 16
}
// UncompressBlock uncompresses the source buffer into the destination one,
// and returns the uncompressed size.
//
// The destination buffer must be sized appropriately.
//
// An error is returned if the source data is invalid or the destination buffer is too small.
func UncompressBlock(src, dst []byte) (si int, err error) {
defer func() {
// It is now faster to let the runtime panic and recover on out of bound slice access
// than checking indices as we go along.
if recover() != nil {
err = ErrInvalidSourceShortBuffer
}
}()
sn := len(src)
if sn == 0 {
return 0, nil
}
var di int
for {
// Literals and match lengths (token).
b := int(src[si])
si++
// Literals.
if lLen := b >> 4; lLen > 0 {
if lLen == 0xF {
for src[si] == 0xFF {
lLen += 0xFF
si++
}
lLen += int(src[si])
si++
}
i := si
si += lLen
di += copy(dst[di:], src[i:si])
if si >= sn {
return di, nil
}
}
si++
_ = src[si] // Bound check elimination.
offset := int(src[si-1]) | int(src[si])<<8
si++
// Match.
mLen := b & 0xF
if mLen == 0xF {
for src[si] == 0xFF {
mLen += 0xFF
si++
}
mLen += int(src[si])
si++
}
mLen += minMatch
// Copy the match.
i := di - offset
if offset > 0 && mLen >= offset {
// Efficiently copy the match dst[di-offset:di] into the dst slice.
bytesToCopy := offset * (mLen / offset)
expanded := dst[i:]
for n := offset; n <= bytesToCopy+offset; n *= 2 {
copy(expanded[n:], expanded[:n])
}
di += bytesToCopy
mLen -= bytesToCopy
}
di += copy(dst[di:], dst[i:i+mLen])
}
}
// CompressBlock compresses the source buffer into the destination one.
// This is the fast version of LZ4 compression and also the default one.
// The size of hashTable must be at least 64Kb.
//
// The size of the compressed data is returned. If it is 0 and no error, then the data is incompressible.
//
// An error is returned if the destination buffer is too small.
func CompressBlock(src, dst []byte, hashTable []int) (di int, err error) {
defer func() {
if recover() != nil {
err = ErrInvalidSourceShortBuffer
}
}()
sn, dn := len(src)-mfLimit, len(dst)
if sn <= 0 || dn == 0 {
return 0, nil
}
var si int
// Fast scan strategy: the hash table only stores the last 4 bytes sequences.
// const accInit = 1 << skipStrength
anchor := si // Position of the current literals.
// acc := accInit // Variable step: improves performance on non-compressible data.
for si < sn {
// Hash the next 4 bytes (sequence)...
match := binary.LittleEndian.Uint32(src[si:])
h := blockHash(match)
ref := hashTable[h]
hashTable[h] = si
if ref >= sn { // Invalid reference (dirty hashtable).
si++
continue
}
offset := si - ref
if offset <= 0 || offset >= winSize || // Out of window.
match != binary.LittleEndian.Uint32(src[ref:]) { // Hash collision on different matches.
// si += acc >> skipStrength
// acc++
si++
continue
}
// Match found.
// acc = accInit
lLen := si - anchor // Literal length.
// Encode match length part 1.
si += minMatch
mLen := si // Match length has minMatch already.
// Find the longest match, first looking by batches of 8 bytes.
for si < sn && binary.LittleEndian.Uint64(src[si:]) == binary.LittleEndian.Uint64(src[si-offset:]) {
si += 8
}
// Then byte by byte.
for si < sn && src[si] == src[si-offset] {
si++
}
mLen = si - mLen
if mLen < 0xF {
dst[di] = byte(mLen)
} else {
dst[di] = 0xF
}
// Encode literals length.
if lLen < 0xF {
dst[di] |= byte(lLen << 4)
} else {
dst[di] |= 0xF0
di++
l := lLen - 0xF
for ; l >= 0xFF; l -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(l)
}
di++
// Literals.
copy(dst[di:], src[anchor:anchor+lLen])
di += lLen + 2
anchor = si
// Encode offset.
_ = dst[di] // Bound check elimination.
dst[di-2], dst[di-1] = byte(offset), byte(offset>>8)
// Encode match length part 2.
if mLen >= 0xF {
for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(mLen)
di++
}
}
if anchor == 0 {
// Incompressible.
return 0, nil
}
// Last literals.
lLen := len(src) - anchor
if lLen < 0xF {
dst[di] = byte(lLen << 4)
} else {
dst[di] = 0xF0
di++
for lLen -= 0xF; lLen >= 0xFF; lLen -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(lLen)
}
di++
// Write the last literals.
if di >= anchor {
// Incompressible.
return 0, nil
}
di += copy(dst[di:], src[anchor:])
return di, nil
}
// CompressBlockHC compresses the source buffer src into the destination dst
// with max search depth (use 0 or negative value for no max).
//
// CompressBlockHC compression ratio is better than CompressBlock but it is also slower.
//
// The size of the compressed data is returned. If it is 0 and no error, then the data is not compressible.
//
// An error is returned if the destination buffer is too small.
func CompressBlockHC(src, dst []byte, depth int) (di int, err error) {
defer func() {
if recover() != nil {
err = ErrInvalidSourceShortBuffer
}
}()
sn, dn := len(src)-mfLimit, len(dst)
if sn <= 0 || dn == 0 {
return 0, nil
}
var si int
// hashTable: stores the last position found for a given hash
// chaingTable: stores previous positions for a given hash
var hashTable, chainTable [winSize]int
if depth <= 0 {
depth = winSize
}
anchor := si
for si < sn {
// Hash the next 4 bytes (sequence).
match := binary.LittleEndian.Uint32(src[si:])
h := blockHash(match)
// Follow the chain until out of window and give the longest match.
mLen := 0
offset := 0
for next, try := hashTable[h], depth; try > 0 && next > 0 && si-next < winSize; next = chainTable[next&winMask] {
// The first (mLen==0) or next byte (mLen>=minMatch) at current match length
// must match to improve on the match length.
if src[next+mLen] != src[si+mLen] {
continue
}
ml := 0
// Compare the current position with a previous with the same hash.
for ml < sn-si && binary.LittleEndian.Uint64(src[next+ml:]) == binary.LittleEndian.Uint64(src[si+ml:]) {
ml += 8
}
for ml < sn-si && src[next+ml] == src[si+ml] {
ml++
}
if ml+1 < minMatch || ml <= mLen {
// Match too small (<minMath) or smaller than the current match.
continue
}
// Found a longer match, keep its position and length.
mLen = ml
offset = si - next
// Try another previous position with the same hash.
try--
}
chainTable[si&winMask] = hashTable[h]
hashTable[h] = si
// No match found.
if mLen == 0 {
si++
continue
}
// Match found.
// Update hash/chain tables with overlapping bytes:
// si already hashed, add everything from si+1 up to the match length.
winStart := si + 1
if ws := si + mLen - winSize; ws > winStart {
winStart = ws
}
for si, ml := winStart, si+mLen; si < ml; {
match >>= 8
match |= uint32(src[si+3]) << 24
h := blockHash(match)
chainTable[si&winMask] = hashTable[h]
hashTable[h] = si
si++
}
lLen := si - anchor
si += mLen
mLen -= minMatch // Match length does not include minMatch.
if mLen < 0xF {
dst[di] = byte(mLen)
} else {
dst[di] = 0xF
}
// Encode literals length.
if lLen < 0xF {
dst[di] |= byte(lLen << 4)
} else {
dst[di] |= 0xF0
di++
l := lLen - 0xF
for ; l >= 0xFF; l -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(l)
}
di++
// Literals.
copy(dst[di:], src[anchor:anchor+lLen])
di += lLen
anchor = si
// Encode offset.
di += 2
dst[di-2], dst[di-1] = byte(offset), byte(offset>>8)
// Encode match length part 2.
if mLen >= 0xF {
for mLen -= 0xF; mLen >= 0xFF; mLen -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(mLen)
di++
}
}
if anchor == 0 {
// Incompressible.
return 0, nil
}
// Last literals.
lLen := len(src) - anchor
if lLen < 0xF {
dst[di] = byte(lLen << 4)
} else {
dst[di] = 0xF0
di++
lLen -= 0xF
for ; lLen >= 0xFF; lLen -= 0xFF {
dst[di] = 0xFF
di++
}
dst[di] = byte(lLen)
}
di++
// Write the last literals.
if di >= anchor {
// Incompressible.
return 0, nil
}
di += copy(dst[di:], src[anchor:])
return di, nil
}

23
vendor/github.com/pierrec/lz4/debug.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
// +build lz4debug
package lz4
import (
"fmt"
"os"
"path/filepath"
"runtime"
)
const debugFlag = true
func debug(args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
file = filepath.Base(file)
f := fmt.Sprintf("LZ4: %s:%d %s", file, line, args[0])
if f[len(f)-1] != '\n' {
f += "\n"
}
fmt.Fprintf(os.Stderr, f, args[1:]...)
}

7
vendor/github.com/pierrec/lz4/debug_stub.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// +build !lz4debug
package lz4
const debugFlag = false
func debug(args ...interface{}) {}

View File

@ -0,0 +1,222 @@
// Package xxh32 implements the very fast XXH hashing algorithm (32 bits version).
// (https://github.com/Cyan4973/XXH/)
package xxh32
import (
"encoding/binary"
)
const (
prime32_1 uint32 = 2654435761
prime32_2 uint32 = 2246822519
prime32_3 uint32 = 3266489917
prime32_4 uint32 = 668265263
prime32_5 uint32 = 374761393
prime32_1plus2 uint32 = 606290984
prime32_minus1 uint32 = 1640531535
)
// XXHZero represents an xxhash32 object with seed 0.
type XXHZero struct {
v1 uint32
v2 uint32
v3 uint32
v4 uint32
totalLen uint64
buf [16]byte
bufused int
}
// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
func (xxh XXHZero) Sum(b []byte) []byte {
h32 := xxh.Sum32()
return append(b, byte(h32), byte(h32>>8), byte(h32>>16), byte(h32>>24))
}
// Reset resets the Hash to its initial state.
func (xxh *XXHZero) Reset() {
xxh.v1 = prime32_1plus2
xxh.v2 = prime32_2
xxh.v3 = 0
xxh.v4 = prime32_minus1
xxh.totalLen = 0
xxh.bufused = 0
}
// Size returns the number of bytes returned by Sum().
func (xxh *XXHZero) Size() int {
return 4
}
// BlockSize gives the minimum number of bytes accepted by Write().
func (xxh *XXHZero) BlockSize() int {
return 1
}
// Write adds input bytes to the Hash.
// It never returns an error.
func (xxh *XXHZero) Write(input []byte) (int, error) {
if xxh.totalLen == 0 {
xxh.Reset()
}
n := len(input)
m := xxh.bufused
xxh.totalLen += uint64(n)
r := len(xxh.buf) - m
if n < r {
copy(xxh.buf[m:], input)
xxh.bufused += len(input)
return n, nil
}
p := 0
// Causes compiler to work directly from registers instead of stack:
v1, v2, v3, v4 := xxh.v1, xxh.v2, xxh.v3, xxh.v4
if m > 0 {
// some data left from previous update
copy(xxh.buf[xxh.bufused:], input[:r])
xxh.bufused += len(input) - r
// fast rotl(13)
buf := xxh.buf[:16] // BCE hint.
v1 = rol13(v1+binary.LittleEndian.Uint32(buf[:])*prime32_2) * prime32_1
v2 = rol13(v2+binary.LittleEndian.Uint32(buf[4:])*prime32_2) * prime32_1
v3 = rol13(v3+binary.LittleEndian.Uint32(buf[8:])*prime32_2) * prime32_1
v4 = rol13(v4+binary.LittleEndian.Uint32(buf[12:])*prime32_2) * prime32_1
p = r
xxh.bufused = 0
}
for n := n - 16; p <= n; p += 16 {
sub := input[p:][:16] //BCE hint for compiler
v1 = rol13(v1+binary.LittleEndian.Uint32(sub[:])*prime32_2) * prime32_1
v2 = rol13(v2+binary.LittleEndian.Uint32(sub[4:])*prime32_2) * prime32_1
v3 = rol13(v3+binary.LittleEndian.Uint32(sub[8:])*prime32_2) * prime32_1
v4 = rol13(v4+binary.LittleEndian.Uint32(sub[12:])*prime32_2) * prime32_1
}
xxh.v1, xxh.v2, xxh.v3, xxh.v4 = v1, v2, v3, v4
copy(xxh.buf[xxh.bufused:], input[p:])
xxh.bufused += len(input) - p
return n, nil
}
// Sum32 returns the 32 bits Hash value.
func (xxh *XXHZero) Sum32() uint32 {
h32 := uint32(xxh.totalLen)
if h32 >= 16 {
h32 += rol1(xxh.v1) + rol7(xxh.v2) + rol12(xxh.v3) + rol18(xxh.v4)
} else {
h32 += prime32_5
}
p := 0
n := xxh.bufused
buf := xxh.buf
for n := n - 4; p <= n; p += 4 {
h32 += binary.LittleEndian.Uint32(buf[p:p+4]) * prime32_3
h32 = rol17(h32) * prime32_4
}
for ; p < n; p++ {
h32 += uint32(buf[p]) * prime32_5
h32 = rol11(h32) * prime32_1
}
h32 ^= h32 >> 15
h32 *= prime32_2
h32 ^= h32 >> 13
h32 *= prime32_3
h32 ^= h32 >> 16
return h32
}
// ChecksumZero returns the 32bits Hash value.
func ChecksumZero(input []byte) uint32 {
n := len(input)
h32 := uint32(n)
if n < 16 {
h32 += prime32_5
} else {
v1 := prime32_1plus2
v2 := prime32_2
v3 := uint32(0)
v4 := prime32_minus1
p := 0
for n := n - 16; p <= n; p += 16 {
sub := input[p:][:16] //BCE hint for compiler
v1 = rol13(v1+binary.LittleEndian.Uint32(sub[:])*prime32_2) * prime32_1
v2 = rol13(v2+binary.LittleEndian.Uint32(sub[4:])*prime32_2) * prime32_1
v3 = rol13(v3+binary.LittleEndian.Uint32(sub[8:])*prime32_2) * prime32_1
v4 = rol13(v4+binary.LittleEndian.Uint32(sub[12:])*prime32_2) * prime32_1
}
input = input[p:]
n -= p
h32 += rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
}
p := 0
for n := n - 4; p <= n; p += 4 {
h32 += binary.LittleEndian.Uint32(input[p:p+4]) * prime32_3
h32 = rol17(h32) * prime32_4
}
for p < n {
h32 += uint32(input[p]) * prime32_5
h32 = rol11(h32) * prime32_1
p++
}
h32 ^= h32 >> 15
h32 *= prime32_2
h32 ^= h32 >> 13
h32 *= prime32_3
h32 ^= h32 >> 16
return h32
}
// Uint32Zero hashes x with seed 0.
func Uint32Zero(x uint32) uint32 {
h := prime32_5 + 4 + x*prime32_3
h = rol17(h) * prime32_4
h ^= h >> 15
h *= prime32_2
h ^= h >> 13
h *= prime32_3
h ^= h >> 16
return h
}
func rol1(u uint32) uint32 {
return u<<1 | u>>31
}
func rol7(u uint32) uint32 {
return u<<7 | u>>25
}
func rol11(u uint32) uint32 {
return u<<11 | u>>21
}
func rol12(u uint32) uint32 {
return u<<12 | u>>20
}
func rol13(u uint32) uint32 {
return u<<13 | u>>19
}
func rol17(u uint32) uint32 {
return u<<17 | u>>15
}
func rol18(u uint32) uint32 {
return u<<18 | u>>14
}

68
vendor/github.com/pierrec/lz4/lz4.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
// Package lz4 implements reading and writing lz4 compressed data (a frame),
// as specified in http://fastcompression.blogspot.fr/2013/04/lz4-streaming-format-final.html.
//
// Although the block level compression and decompression functions are exposed and are fully compatible
// with the lz4 block format definition, they are low level and should not be used directly.
// For a complete description of an lz4 compressed block, see:
// http://fastcompression.blogspot.fr/2011/05/lz4-explained.html
//
// See https://github.com/Cyan4973/lz4 for the reference C implementation.
//
package lz4
const (
// Extension is the LZ4 frame file name extension
Extension = ".lz4"
// Version is the LZ4 frame format version
Version = 1
frameMagic uint32 = 0x184D2204
frameSkipMagic uint32 = 0x184D2A50
// The following constants are used to setup the compression algorithm.
minMatch = 4 // the minimum size of the match sequence size (4 bytes)
winSizeLog = 16 // LZ4 64Kb window size limit
winSize = 1 << winSizeLog
winMask = winSize - 1 // 64Kb window of previous data for dependent blocks
compressedBlockFlag = 1 << 31
compressedBlockMask = compressedBlockFlag - 1
// hashLog determines the size of the hash table used to quickly find a previous match position.
// Its value influences the compression speed and memory usage, the lower the faster,
// but at the expense of the compression ratio.
// 16 seems to be the best compromise.
hashLog = 16
hashTableSize = 1 << hashLog
hashShift = uint((minMatch * 8) - hashLog)
mfLimit = 8 + minMatch // The last match cannot start within the last 12 bytes.
skipStrength = 6 // variable step for fast scan
)
// map the block max size id with its value in bytes: 64Kb, 256Kb, 1Mb and 4Mb.
var (
bsMapID = map[byte]int{4: 64 << 10, 5: 256 << 10, 6: 1 << 20, 7: 4 << 20}
bsMapValue = make(map[int]byte, len(bsMapID))
)
// Reversed.
func init() {
for i, v := range bsMapID {
bsMapValue[v] = i
}
}
// Header describes the various flags that can be set on a Writer or obtained from a Reader.
// The default values match those of the LZ4 frame format definition
// (http://fastcompression.blogspot.com/2013/04/lz4-streaming-format-final.html).
//
// NB. in a Reader, in case of concatenated frames, the Header values may change between Read() calls.
// It is the caller responsibility to check them if necessary.
type Header struct {
BlockChecksum bool // Compressed blocks checksum flag.
NoChecksum bool // Frame checksum flag.
BlockMaxSize int // Size of the uncompressed data block (one of [64KB, 256KB, 1MB, 4MB]). Default=4MB.
Size uint64 // Frame total size. It is _not_ computed by the Writer.
CompressionLevel int // Compression level (higher is better, use 0 for fastest compression).
done bool // Header processed flag (Read or Write and checked).
}

29
vendor/github.com/pierrec/lz4/lz4_go1.10.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
//+build go1.10
package lz4
import (
"fmt"
"strings"
)
func (h Header) String() string {
var s strings.Builder
s.WriteString(fmt.Sprintf("%T{", h))
if h.BlockChecksum {
s.WriteString("BlockChecksum: true ")
}
if h.NoChecksum {
s.WriteString("NoChecksum: true ")
}
if bs := h.BlockMaxSize; bs != 0 && bs != 4<<20 {
s.WriteString(fmt.Sprintf("BlockMaxSize: %d ", bs))
}
if l := h.CompressionLevel; l != 0 {
s.WriteString(fmt.Sprintf("CompressionLevel: %d ", l))
}
s.WriteByte('}')
return s.String()
}

29
vendor/github.com/pierrec/lz4/lz4_notgo1.10.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
//+build !go1.10
package lz4
import (
"bytes"
"fmt"
)
func (h Header) String() string {
var s bytes.Buffer
s.WriteString(fmt.Sprintf("%T{", h))
if h.BlockChecksum {
s.WriteString("BlockChecksum: true ")
}
if h.NoChecksum {
s.WriteString("NoChecksum: true ")
}
if bs := h.BlockMaxSize; bs != 0 && bs != 4<<20 {
s.WriteString(fmt.Sprintf("BlockMaxSize: %d ", bs))
}
if l := h.CompressionLevel; l != 0 {
s.WriteString(fmt.Sprintf("CompressionLevel: %d ", l))
}
s.WriteByte('}')
return s.String()
}

295
vendor/github.com/pierrec/lz4/reader.go generated vendored Normal file
View File

@ -0,0 +1,295 @@
package lz4
import (
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"github.com/pierrec/lz4/internal/xxh32"
)
// Reader implements the LZ4 frame decoder.
// The Header is set after the first call to Read().
// The Header may change between Read() calls in case of concatenated frames.
type Reader struct {
Header
buf [8]byte // Scrap buffer.
pos int64 // Current position in src.
src io.Reader // Source.
zdata []byte // Compressed data.
data []byte // Uncompressed data.
idx int // Index of unread bytes into data.
checksum xxh32.XXHZero // Frame hash.
}
// NewReader returns a new LZ4 frame decoder.
// No access to the underlying io.Reader is performed.
func NewReader(src io.Reader) *Reader {
r := &Reader{src: src}
return r
}
// readHeader checks the frame magic number and parses the frame descriptoz.
// Skippable frames are supported even as a first frame although the LZ4
// specifications recommends skippable frames not to be used as first frames.
func (z *Reader) readHeader(first bool) error {
defer z.checksum.Reset()
buf := z.buf[:]
for {
magic, err := z.readUint32()
if err != nil {
z.pos += 4
if !first && err == io.ErrUnexpectedEOF {
return io.EOF
}
return err
}
if magic == frameMagic {
break
}
if magic>>8 != frameSkipMagic>>8 {
return ErrInvalid
}
skipSize, err := z.readUint32()
if err != nil {
return err
}
z.pos += 4
m, err := io.CopyN(ioutil.Discard, z.src, int64(skipSize))
if err != nil {
return err
}
z.pos += m
}
// Header.
if _, err := io.ReadFull(z.src, buf[:2]); err != nil {
return err
}
z.pos += 8
b := buf[0]
if v := b >> 6; v != Version {
return fmt.Errorf("lz4: invalid version: got %d; expected %d", v, Version)
}
if b>>5&1 == 0 {
return fmt.Errorf("lz4: block dependency not supported")
}
z.BlockChecksum = b>>4&1 > 0
frameSize := b>>3&1 > 0
z.NoChecksum = b>>2&1 == 0
bmsID := buf[1] >> 4 & 0x7
bSize, ok := bsMapID[bmsID]
if !ok {
return fmt.Errorf("lz4: invalid block max size ID: %d", bmsID)
}
z.BlockMaxSize = bSize
// Allocate the compressed/uncompressed buffers.
// The compressed buffer cannot exceed the uncompressed one.
if n := 2 * bSize; cap(z.zdata) < n {
z.zdata = make([]byte, n, n)
}
if debugFlag {
debug("header block max size id=%d size=%d", bmsID, bSize)
}
z.zdata = z.zdata[:bSize]
z.data = z.zdata[:cap(z.zdata)][bSize:]
z.idx = len(z.data)
z.checksum.Write(buf[0:2])
if frameSize {
buf := buf[:8]
if _, err := io.ReadFull(z.src, buf); err != nil {
return err
}
z.Size = binary.LittleEndian.Uint64(buf)
z.pos += 8
z.checksum.Write(buf)
}
// Header checksum.
if _, err := io.ReadFull(z.src, buf[:1]); err != nil {
return err
}
z.pos++
if h := byte(z.checksum.Sum32() >> 8 & 0xFF); h != buf[0] {
return fmt.Errorf("lz4: invalid header checksum: got %x; expected %x", buf[0], h)
}
z.Header.done = true
if debugFlag {
debug("header read: %v", z.Header)
}
return nil
}
// Read decompresses data from the underlying source into the supplied buffer.
//
// Since there can be multiple streams concatenated, Header values may
// change between calls to Read(). If that is the case, no data is actually read from
// the underlying io.Reader, to allow for potential input buffer resizing.
func (z *Reader) Read(buf []byte) (int, error) {
if debugFlag {
debug("Read buf len=%d", len(buf))
}
if !z.Header.done {
if err := z.readHeader(true); err != nil {
return 0, err
}
if debugFlag {
debug("header read OK compressed buffer %d / %d uncompressed buffer %d : %d index=%d",
len(z.zdata), cap(z.zdata), len(z.data), cap(z.data), z.idx)
}
}
if len(buf) == 0 {
return 0, nil
}
if z.idx == len(z.data) {
// No data ready for reading, process the next block.
if debugFlag {
debug("reading block from writer")
}
// Block length: 0 = end of frame, highest bit set: uncompressed.
bLen, err := z.readUint32()
if err != nil {
return 0, err
}
z.pos += 4
if bLen == 0 {
// End of frame reached.
if !z.NoChecksum {
// Validate the frame checksum.
checksum, err := z.readUint32()
if err != nil {
return 0, err
}
if debugFlag {
debug("frame checksum got=%x / want=%x", z.checksum.Sum32(), checksum)
}
z.pos += 4
if h := z.checksum.Sum32(); checksum != h {
return 0, fmt.Errorf("lz4: invalid frame checksum: got %x; expected %x", h, checksum)
}
}
// Get ready for the next concatenated frame and keep the position.
pos := z.pos
z.Reset(z.src)
z.pos = pos
// Since multiple frames can be concatenated, check for more.
return 0, z.readHeader(false)
}
if debugFlag {
debug("raw block size %d", bLen)
}
if bLen&compressedBlockFlag > 0 {
// Uncompressed block.
bLen &= compressedBlockMask
if debugFlag {
debug("uncompressed block size %d", bLen)
}
if int(bLen) > cap(z.data) {
return 0, fmt.Errorf("lz4: invalid block size: %d", bLen)
}
z.data = z.data[:bLen]
if _, err := io.ReadFull(z.src, z.data); err != nil {
return 0, err
}
z.pos += int64(bLen)
if z.BlockChecksum {
checksum, err := z.readUint32()
if err != nil {
return 0, err
}
z.pos += 4
if h := xxh32.ChecksumZero(z.data); h != checksum {
return 0, fmt.Errorf("lz4: invalid block checksum: got %x; expected %x", h, checksum)
}
}
} else {
// Compressed block.
if debugFlag {
debug("compressed block size %d", bLen)
}
if int(bLen) > cap(z.data) {
return 0, fmt.Errorf("lz4: invalid block size: %d", bLen)
}
zdata := z.zdata[:bLen]
if _, err := io.ReadFull(z.src, zdata); err != nil {
return 0, err
}
z.pos += int64(bLen)
if z.BlockChecksum {
checksum, err := z.readUint32()
if err != nil {
return 0, err
}
z.pos += 4
if h := xxh32.ChecksumZero(zdata); h != checksum {
return 0, fmt.Errorf("lz4: invalid block checksum: got %x; expected %x", h, checksum)
}
}
n, err := UncompressBlock(zdata, z.data)
if err != nil {
return 0, err
}
z.data = z.data[:n]
}
if !z.NoChecksum {
z.checksum.Write(z.data)
if debugFlag {
debug("current frame checksum %x", z.checksum.Sum32())
}
}
z.idx = 0
}
n := copy(buf, z.data[z.idx:])
z.idx += n
if debugFlag {
debug("copied %d bytes to input", n)
}
return n, nil
}
// Reset discards the Reader's state and makes it equivalent to the
// result of its original state from NewReader, but reading from r instead.
// This permits reusing a Reader rather than allocating a new one.
func (z *Reader) Reset(r io.Reader) {
z.Header = Header{}
z.pos = 0
z.src = r
z.zdata = z.zdata[:0]
z.data = z.data[:0]
z.idx = 0
z.checksum.Reset()
}
// readUint32 reads an uint32 into the supplied buffer.
// The idea is to make use of the already allocated buffers avoiding additional allocations.
func (z *Reader) readUint32() (uint32, error) {
buf := z.buf[:4]
_, err := io.ReadFull(z.src, buf)
x := binary.LittleEndian.Uint32(buf)
return x, err
}

267
vendor/github.com/pierrec/lz4/writer.go generated vendored Normal file
View File

@ -0,0 +1,267 @@
package lz4
import (
"encoding/binary"
"fmt"
"io"
"github.com/pierrec/lz4/internal/xxh32"
)
// Writer implements the LZ4 frame encoder.
type Writer struct {
Header
buf [19]byte // magic number(4) + header(flags(2)+[Size(8)+DictID(4)]+checksum(1)) does not exceed 19 bytes
dst io.Writer // Destination.
checksum xxh32.XXHZero // Frame checksum.
zdata []byte // Compressed data.
data []byte // Data to be compressed.
idx int // Index into data.
hashtable [winSize]int // Hash table used in CompressBlock().
}
// NewWriter returns a new LZ4 frame encoder.
// No access to the underlying io.Writer is performed.
// The supplied Header is checked at the first Write.
// It is ok to change it before the first Write but then not until a Reset() is performed.
func NewWriter(dst io.Writer) *Writer {
return &Writer{dst: dst}
}
// writeHeader builds and writes the header (magic+header) to the underlying io.Writer.
func (z *Writer) writeHeader() error {
// Default to 4Mb if BlockMaxSize is not set.
if z.Header.BlockMaxSize == 0 {
z.Header.BlockMaxSize = bsMapID[7]
}
// The only option that needs to be validated.
bSize := z.Header.BlockMaxSize
bSizeID, ok := bsMapValue[bSize]
if !ok {
return fmt.Errorf("lz4: invalid block max size: %d", bSize)
}
// Allocate the compressed/uncompressed buffers.
// The compressed buffer cannot exceed the uncompressed one.
if n := 2 * bSize; cap(z.zdata) < n {
z.zdata = make([]byte, n, n)
}
z.zdata = z.zdata[:bSize]
z.data = z.zdata[:cap(z.zdata)][bSize:]
z.idx = 0
// Size is optional.
buf := z.buf[:]
// Set the fixed size data: magic number, block max size and flags.
binary.LittleEndian.PutUint32(buf[0:], frameMagic)
flg := byte(Version << 6)
flg |= 1 << 5 // No block dependency.
if z.Header.BlockChecksum {
flg |= 1 << 4
}
if z.Header.Size > 0 {
flg |= 1 << 3
}
if !z.Header.NoChecksum {
flg |= 1 << 2
}
buf[4] = flg
buf[5] = bSizeID << 4
// Current buffer size: magic(4) + flags(1) + block max size (1).
n := 6
// Optional items.
if z.Header.Size > 0 {
binary.LittleEndian.PutUint64(buf[n:], z.Header.Size)
n += 8
}
// The header checksum includes the flags, block max size and optional Size.
buf[n] = byte(xxh32.ChecksumZero(buf[4:n]) >> 8 & 0xFF)
z.checksum.Reset()
// Header ready, write it out.
if _, err := z.dst.Write(buf[0 : n+1]); err != nil {
return err
}
z.Header.done = true
if debugFlag {
debug("wrote header %v", z.Header)
}
return nil
}
// Write compresses data from the supplied buffer into the underlying io.Writer.
// Write does not return until the data has been written.
func (z *Writer) Write(buf []byte) (int, error) {
if !z.Header.done {
if err := z.writeHeader(); err != nil {
return 0, err
}
}
if debugFlag {
debug("input buffer len=%d index=%d", len(buf), z.idx)
}
zn := len(z.data)
var n int
for len(buf) > 0 {
if z.idx == 0 && len(buf) >= zn {
// Avoid a copy as there is enough data for a block.
if err := z.compressBlock(buf[:zn]); err != nil {
return n, err
}
n += zn
buf = buf[zn:]
continue
}
// Accumulate the data to be compressed.
m := copy(z.data[z.idx:], buf)
n += m
z.idx += m
buf = buf[m:]
if debugFlag {
debug("%d bytes copied to buf, current index %d", n, z.idx)
}
if z.idx < len(z.data) {
// Buffer not filled.
if debugFlag {
debug("need more data for compression")
}
return n, nil
}
// Buffer full.
if err := z.compressBlock(z.data); err != nil {
return n, err
}
z.idx = 0
}
return n, nil
}
// compressBlock compresses a block.
func (z *Writer) compressBlock(data []byte) error {
if !z.NoChecksum {
z.checksum.Write(data)
}
// The compressed block size cannot exceed the input's.
var zn int
var err error
if level := z.Header.CompressionLevel; level != 0 {
zn, err = CompressBlockHC(data, z.zdata, level)
} else {
zn, err = CompressBlock(data, z.zdata, z.hashtable[:])
}
var zdata []byte
var bLen uint32
if debugFlag {
debug("block compression %d => %d", len(data), zn)
}
if err == nil && zn > 0 && zn < len(data) {
// Compressible and compressed size smaller than uncompressed: ok!
bLen = uint32(zn)
zdata = z.zdata[:zn]
} else {
// Uncompressed block.
bLen = uint32(len(data)) | compressedBlockFlag
zdata = data
}
if debugFlag {
debug("block compression to be written len=%d data len=%d", bLen, len(zdata))
}
// Write the block.
if err := z.writeUint32(bLen); err != nil {
return err
}
if _, err := z.dst.Write(zdata); err != nil {
return err
}
if z.BlockChecksum {
checksum := xxh32.ChecksumZero(zdata)
if debugFlag {
debug("block checksum %x", checksum)
}
if err := z.writeUint32(checksum); err != nil {
return err
}
}
if debugFlag {
debug("current frame checksum %x", z.checksum.Sum32())
}
return nil
}
// Flush flushes any pending compressed data to the underlying writer.
// Flush does not return until the data has been written.
// If the underlying writer returns an error, Flush returns that error.
func (z *Writer) Flush() error {
if debugFlag {
debug("flush with index %d", z.idx)
}
if z.idx == 0 {
return nil
}
return z.compressBlock(z.data[:z.idx])
}
// Close closes the Writer, flushing any unwritten data to the underlying io.Writer, but does not close the underlying io.Writer.
func (z *Writer) Close() error {
if !z.Header.done {
if err := z.writeHeader(); err != nil {
return err
}
}
if err := z.Flush(); err != nil {
return err
}
if debugFlag {
debug("writing last empty block")
}
if err := z.writeUint32(0); err != nil {
return err
}
if !z.NoChecksum {
checksum := z.checksum.Sum32()
if debugFlag {
debug("stream checksum %x", checksum)
}
if err := z.writeUint32(checksum); err != nil {
return err
}
}
return nil
}
// Reset clears the state of the Writer z such that it is equivalent to its
// initial state from NewWriter, but instead writing to w.
// No access to the underlying io.Writer is performed.
func (z *Writer) Reset(w io.Writer) {
z.Header = Header{}
z.dst = w
z.checksum.Reset()
z.zdata = z.zdata[:0]
z.data = z.data[:0]
z.idx = 0
}
// writeUint32 writes a uint32 to the underlying writer.
func (z *Writer) writeUint32(x uint32) error {
buf := z.buf[:4]
binary.LittleEndian.PutUint32(buf, x)
_, err := z.dst.Write(buf)
return err
}

24
vendor/github.com/pkg/errors/.gitignore generated vendored Normal file
View File

@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof

11
vendor/github.com/pkg/errors/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,11 @@
language: go
go_import_path: github.com/pkg/errors
go:
- 1.4.3
- 1.5.4
- 1.6.2
- 1.7.1
- tip
script:
- go test -v ./...

23
vendor/github.com/pkg/errors/LICENSE generated vendored Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

52
vendor/github.com/pkg/errors/README.md generated vendored Normal file
View File

@ -0,0 +1,52 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
Package errors provides simple error handling primitives.
`go get github.com/pkg/errors`
The traditional error handling idiom in Go is roughly akin to
```go
if err != nil {
return err
}
```
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
## Adding context to an error
The errors.Wrap function returns a new error that adds context to the original error. For example
```go
_, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrap(err, "read failed")
}
```
## Retrieving the cause of an error
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
```go
type causer interface {
Cause() error
}
```
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
```go
switch err := errors.Cause(err).(type) {
case *MyError:
// handle specifically
default:
// unknown error
}
```
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
## Contributing
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
Before proposing a change, please discuss your change by raising an issue.
## Licence
BSD-2-Clause

Some files were not shown because too many files have changed in this diff Show More