~tsileo/blobstash

876db623aa0eaf183cc2efc3bf3e3601cd42ebf9 — Thomas Sileo 2 months ago 1d5ac72
deps: update deps
M go.mod => go.mod +5 -4
@@ 1,15 1,15 @@
module a4.io/blobstash

// replace a4.io/gluapp v0.0.0-20200222094913-718c6afb9cbe => /home/thomas/Proj/gluapp
// replace a4.io/gluapp v0.0.0-20200308213855-74e393b208ff => /home/thomas/Proj/gluapp

require (
	a4.io/blobsfile v0.3.8
	a4.io/gluapp v0.0.0-20200308213855-74e393b208ff
	a4.io/gluapp v0.0.0-20200311203905-eb3c48991ada
	a4.io/gluarequire2 v0.0.0-20200222094423-7528d5a10bc1
	a4.io/go/indieauth v1.0.0
	a4.io/ssse v0.0.0-20181202155639-1949828a8689
	bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc
	github.com/aws/aws-sdk-go v1.29.20
	github.com/aws/aws-sdk-go v1.29.22
	github.com/blevesearch/segment v0.0.0-20160915185041-762005e7a34f
	github.com/carbocation/interpose v0.0.0-20161206215253-723534742ba3
	github.com/dave/jennifer v1.4.0


@@ 23,6 23,7 @@ require (
	github.com/gorilla/sessions v1.2.0
	github.com/hashicorp/golang-lru v0.5.4
	github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1
	github.com/jmespath/go-jmespath v0.0.0-20200310193758-2437e8417af5 // indirect
	github.com/mattn/go-colorable v0.1.6 // indirect
	github.com/mitchellh/go-ps v1.0.0
	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646


@@ 38,7 39,7 @@ require (
	github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 // indirect
	github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
	github.com/zpatrick/rbac v0.0.0-20180829190353-d2c4f050cf28
	golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
	golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
	golang.org/x/net v0.0.0-20200301022130-244492dfa37a
	golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
	gopkg.in/inconshreveable/log15.v2 v2.0.0-20200109203555-b30bc20e4fd1

M go.sum => go.sum +9 -0
@@ 29,6 29,8 @@ a4.io/gluapp v0.0.0-20200222094913-718c6afb9cbe h1:WqcaAdZzWCWLn6jwiOkWR1SIQ/rOZ
a4.io/gluapp v0.0.0-20200222094913-718c6afb9cbe/go.mod h1:A3U6Yc1zqp5Bnsz7PxrlYmbZ4iEN/LBKeuuwaxpLBMY=
a4.io/gluapp v0.0.0-20200308213855-74e393b208ff h1:HXHJfbkddS+0KQAcfO4+IAJ3OkSh9wt7emnsKJWGkjY=
a4.io/gluapp v0.0.0-20200308213855-74e393b208ff/go.mod h1:A3U6Yc1zqp5Bnsz7PxrlYmbZ4iEN/LBKeuuwaxpLBMY=
a4.io/gluapp v0.0.0-20200311203905-eb3c48991ada h1:t7D1dBddA0Joo/MKSIj9GJsv0iGerABouNrNP220PVg=
a4.io/gluapp v0.0.0-20200311203905-eb3c48991ada/go.mod h1:A3U6Yc1zqp5Bnsz7PxrlYmbZ4iEN/LBKeuuwaxpLBMY=
a4.io/gluarequire2 v0.0.0-20170611121149-66e0eb2c6a9f h1:mfEWN0Dd2AfIXU5WO5ZfqbFVk63Qz5M/CANs182pm+U=
a4.io/gluarequire2 v0.0.0-20170611121149-66e0eb2c6a9f/go.mod h1:t7OhwCmPQfuUf8cjm7n8chSbZt5CTILu+dTLu1MQKjQ=
a4.io/gluarequire2 v0.0.0-20200222094423-7528d5a10bc1 h1:prvtjU2SK4PCsJnvY39+DkQyLzxq39E5q0kOimBZsaY=


@@ 81,6 83,8 @@ github.com/aws/aws-sdk-go v1.29.19 h1:+jifYixffn6kzWygtGWFWQMv0tDGyISZHNwugF9V2s
github.com/aws/aws-sdk-go v1.29.19/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/aws/aws-sdk-go v1.29.20 h1:vAHJhARpdbdeJstTVaugeHgvVj5lBnfz3blbbD24gfo=
github.com/aws/aws-sdk-go v1.29.20/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/aws/aws-sdk-go v1.29.22 h1:3WmsCj3C30l6/4f50mPkDZoTPWSvaRCjcVJOWdCJoIE=
github.com/aws/aws-sdk-go v1.29.22/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/blevesearch/segment v0.0.0-20160915185041-762005e7a34f h1:kqbi9lqXLLs+zfWlgo1PIiRQ86n33K1JKotjj4rSYOg=
github.com/blevesearch/segment v0.0.0-20160915185041-762005e7a34f/go.mod h1:IInt5XRvpiGE09KOk9mmCMLjHhydIhNPKPPFLFBB7L8=
github.com/carbocation/handlers v0.0.0-20140528190747-c939c6d9ef31 h1:SDMgCFII5drFRIyAaihze9ceRMpTt1FW6Q5jjpc2u4c=


@@ 220,6 224,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20200310193758-2437e8417af5 h1:uHQ3zN9bw90YSNUeGWrboinB/fjXSDA7dNSg7Dznw18=
github.com/jmespath/go-jmespath v0.0.0-20200310193758-2437e8417af5/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/justinas/nosurf v0.0.0-20181122113328-3af30e51c05b h1:fWjiIutptAhQwIoCjCEsyCx6KtaHJ6WyqCLdmFJ3udQ=
github.com/justinas/nosurf v0.0.0-20181122113328-3af30e51c05b/go.mod h1:Aucr5I5chr4OCuuVB4LTuHVrKHBuyRSo7vM2hqrcb7E=
github.com/justinas/nosurf v1.1.0 h1:qqV6FJmnDBJ6F9pOzhZgZitAZWBYonMOXglof7TtdZw=


@@ 349,6 355,7 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=


@@ 430,6 437,8 @@ golang.org/x/crypto v0.0.0-20200221170553-0f24fbd83dfb h1:Bg7BRk6M/6/zfhJrglNmi/
golang.org/x/crypto v0.0.0-20200221170553-0f24fbd83dfb/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181213202711-891ebc4b82d6 h1:gT0Y6H7hbVPUtvtk0YGxMXPgN+p8fYlqWkgJeUCZcaQ=

M vendor/a4.io/gluapp/gluapp.go => vendor/a4.io/gluapp/gluapp.go +24 -2
@@ 2,6 2,7 @@ package gluapp // import "a4.io/gluapp"

import (
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"



@@ 46,6 47,8 @@ type Config struct {

	// Stack trace will be displayed in debug mode
	Debug bool

	TemplateFuncMap template.FuncMap
}

// Setup "global" metatable (used by multiple modules)


@@ 80,6 83,21 @@ func setupMetatable(L *lua.LState) {
	}))
}

func getFuncMaps(fm template.FuncMap) template.FuncMap {
	finalFuncs := template.FuncMap{}
	for k, v := range funcs {
		finalFuncs[k] = v
	}
	if fm != nil {
		for k, v := range fm {
			finalFuncs[k] = v
		}
	} else {
		finalFuncs = funcs
	}
	return finalFuncs
}

func setupState(L *lua.LState, conf *Config, w http.ResponseWriter, r *http.Request) (*Response, error) {
	// Update the path if needed
	if conf.Path != "" {


@@ 157,7 175,9 @@ func setupState(L *lua.LState, conf *Config, w http.ResponseWriter, r *http.Requ
	L.PreloadModule("http", setupHTTP(client, conf.Path))

	L.PreloadModule("form", setupForm()) // must be executed after setupHTTP
	L.PreloadModule("template", setupTemplate(filepath.Join(conf.Path, "templates")))
	finalFuncs := getFuncMaps(conf.TemplateFuncMap)

	L.PreloadModule("template", setupTemplate(filepath.Join(conf.Path, "templates"), finalFuncs))
	// TODO(tsileo): a read/write file module for the data/ directory???

	// Setup additional modules provided by the user


@@ 233,7 253,9 @@ func SetupGlue(L *lua.LState, conf *Config) error {
	L.PreloadModule("http", setupHTTP(client, conf.Path))

	L.PreloadModule("form", setupForm()) // must be executed after setupHTTP
	L.PreloadModule("template", setupTemplate(filepath.Join(conf.Path, "templates")))

	finalFuncs := getFuncMaps(conf.TemplateFuncMap)
	L.PreloadModule("template", setupTemplate(filepath.Join(conf.Path, "templates"), finalFuncs))
	// TODO(tsileo): a read/write file module for the data/ directory???

	// Setup additional modules provided by the user

M vendor/a4.io/gluapp/template.go => vendor/a4.io/gluapp/template.go +3 -3
@@ 58,13 58,13 @@ var funcs = template.FuncMap{
	},
}

func setupTemplate(path string) func(*lua.LState) int {
func setupTemplate(path string, funcMap template.FuncMap) func(*lua.LState) int {
	return func(L *lua.LState) int {
		// Setup the router module
		mod := L.SetFuncs(L.NewTable(), map[string]lua.LGFunction{
			"render_string": func(L *lua.LState) int {
				var out bytes.Buffer
				tpl, err := template.New("").Funcs(funcs).Parse(L.ToString(1))
				tpl, err := template.New("").Funcs(funcMap).Parse(L.ToString(1))
				if err != nil {
					// TODO(tsileo): return error?
					return 0


@@ 85,7 85,7 @@ func setupTemplate(path string) func(*lua.LState) int {
					templates = append(templates, filepath.Join(path, string(L.ToString(i))))
				}

				tmpl, err := template.New("").Funcs(funcs).ParseFiles(templates...)
				tmpl, err := template.New("").Funcs(funcMap).ParseFiles(templates...)
				if err != nil {
					L.Push(lua.LString(err.Error()))
					return 1

M vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go => vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go +3 -1
@@ 19,7 19,9 @@ type StaticProvider struct {
}

// NewStaticCredentials returns a pointer to a new Credentials object
// wrapping a static credentials value provider.
// wrapping a static credentials value provider. Token is only required
// for temporary security credentials retrieved via STS, otherwise an empty
// string can be passed for this parameter.
func NewStaticCredentials(id, secret, token string) *Credentials {
	return NewCredentials(&StaticProvider{Value: Value{
		AccessKeyID:     id,

M vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go => vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go +9 -1
@@ 3,6 3,7 @@ package session
import (
	"fmt"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"


@@ 206,7 207,14 @@ func credsFromAssumeRole(cfg aws.Config,
		sharedCfg.RoleARN,
		func(opt *stscreds.AssumeRoleProvider) {
			opt.RoleSessionName = sharedCfg.RoleSessionName
			opt.Duration = sessOpts.AssumeRoleDuration

			if sessOpts.AssumeRoleDuration == 0 &&
				sharedCfg.AssumeRoleDuration != nil &&
				*sharedCfg.AssumeRoleDuration/time.Minute > 15 {
				opt.Duration = *sharedCfg.AssumeRoleDuration
			} else if sessOpts.AssumeRoleDuration != 0 {
				opt.Duration = sessOpts.AssumeRoleDuration
			}

			// Assume role with external ID
			if len(sharedCfg.ExternalID) > 0 {

M vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go => vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go +18 -10
@@ 2,6 2,7 @@ package session

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"


@@ 16,12 17,13 @@ const (
	sessionTokenKey = `aws_session_token`     // optional

	// Assume Role Credentials group
	roleArnKey          = `role_arn`          // group required
	sourceProfileKey    = `source_profile`    // group required (or credential_source)
	credentialSourceKey = `credential_source` // group required (or source_profile)
	externalIDKey       = `external_id`       // optional
	mfaSerialKey        = `mfa_serial`        // optional
	roleSessionNameKey  = `role_session_name` // optional
	roleArnKey             = `role_arn`          // group required
	sourceProfileKey       = `source_profile`    // group required (or credential_source)
	credentialSourceKey    = `credential_source` // group required (or source_profile)
	externalIDKey          = `external_id`       // optional
	mfaSerialKey           = `mfa_serial`        // optional
	roleSessionNameKey     = `role_session_name` // optional
	roleDurationSecondsKey = "duration_seconds"  // optional

	// CSM options
	csmEnabledKey  = `csm_enabled`


@@ 73,10 75,11 @@ type sharedConfig struct {
	CredentialProcess    string
	WebIdentityTokenFile string

	RoleARN         string
	RoleSessionName string
	ExternalID      string
	MFASerial       string
	RoleARN            string
	RoleSessionName    string
	ExternalID         string
	MFASerial          string
	AssumeRoleDuration *time.Duration

	SourceProfileName string
	SourceProfile     *sharedConfig


@@ 274,6 277,11 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, e
		updateString(&cfg.CredentialSource, section, credentialSourceKey)
		updateString(&cfg.Region, section, regionKey)

		if section.Has(roleDurationSecondsKey) {
			d := time.Duration(section.Int(roleDurationSecondsKey)) * time.Second
			cfg.AssumeRoleDuration = &d
		}

		if v := section.String(stsRegionalEndpointSharedKey); len(v) != 0 {
			sre, err := endpoints.GetSTSRegionalEndpoint(v)
			if err != nil {

M vendor/github.com/aws/aws-sdk-go/aws/version.go => vendor/github.com/aws/aws-sdk-go/aws/version.go +1 -1
@@ 5,4 5,4 @@ package aws
const SDKName = "aws-sdk-go"

// SDKVersion is the version of this SDK
const SDKVersion = "1.29.20"
const SDKVersion = "1.29.22"

A vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/pool.go => vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/pool.go +244 -0
@@ 0,0 1,244 @@
package s3manager

import (
	"fmt"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
)

type byteSlicePool interface {
	Get(aws.Context) (*[]byte, error)
	Put(*[]byte)
	ModifyCapacity(int)
	SliceSize() int64
	Close()
}

type maxSlicePool struct {
	// allocator is defined as a function pointer to allow
	// for test cases to instrument custom tracers when allocations
	// occur.
	allocator sliceAllocator

	slices         chan *[]byte
	allocations    chan struct{}
	capacityChange chan struct{}

	max       int
	sliceSize int64

	mtx sync.RWMutex
}

func newMaxSlicePool(sliceSize int64) *maxSlicePool {
	p := &maxSlicePool{sliceSize: sliceSize}
	p.allocator = p.newSlice

	return p
}

var errZeroCapacity = fmt.Errorf("get called on zero capacity pool")

func (p *maxSlicePool) Get(ctx aws.Context) (*[]byte, error) {
	// check if context is canceled before attempting to get a slice
	// this ensures priority is given to the cancel case first
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	p.mtx.RLock()

	for {
		select {
		case bs, ok := <-p.slices:
			p.mtx.RUnlock()
			if !ok {
				// attempt to get on a zero capacity pool
				return nil, errZeroCapacity
			}
			return bs, nil
		case _, ok := <-p.allocations:
			p.mtx.RUnlock()
			if !ok {
				// attempt to get on a zero capacity pool
				return nil, errZeroCapacity
			}
			return p.allocator(), nil
		case <-ctx.Done():
			p.mtx.RUnlock()
			return nil, ctx.Err()
		default:
			// In the event that there are no slices or allocations available
			// This prevents some deadlock situations that can occur around sync.RWMutex
			// When a lock request occurs on ModifyCapacity, no new readers are allowed to acquire a read lock.
			// By releasing the read lock here and waiting for a notification, we prevent a deadlock situation where
			// Get could hold the read lock indefinitely waiting for capacity, ModifyCapacity is waiting for a write lock,
			// and a Put is blocked trying to get a read-lock which is blocked by ModifyCapacity.

			// Short-circuit if the pool capacity is zero.
			if p.max == 0 {
				p.mtx.RUnlock()
				return nil, errZeroCapacity
			}

			// Since we will be releasing the read-lock we need to take the reference to the channel.
			// Since channels are references we will still get notified if slices are added, or if
			// the channel is closed due to a capacity modification. This specifically avoids a data race condition
			// where ModifyCapacity both closes a channel and initializes a new one while we don't have a read-lock.
			c := p.capacityChange

			p.mtx.RUnlock()

			select {
			case _ = <-c:
				p.mtx.RLock()
			case <-ctx.Done():
				return nil, ctx.Err()
			}
		}
	}
}

func (p *maxSlicePool) Put(bs *[]byte) {
	p.mtx.RLock()
	defer p.mtx.RUnlock()

	if p.max == 0 {
		return
	}

	select {
	case p.slices <- bs:
		p.notifyCapacity()
	default:
		// If the new channel when attempting to add the slice then we drop the slice.
		// The logic here is to prevent a deadlock situation if channel is already at max capacity.
		// Allows us to reap allocations that are returned and are no longer needed.
	}
}

func (p *maxSlicePool) ModifyCapacity(delta int) {
	if delta == 0 {
		return
	}

	p.mtx.Lock()
	defer p.mtx.Unlock()

	p.max += delta

	if p.max == 0 {
		p.empty()
		return
	}

	if p.capacityChange != nil {
		close(p.capacityChange)
	}
	p.capacityChange = make(chan struct{}, p.max)

	origAllocations := p.allocations
	p.allocations = make(chan struct{}, p.max)

	newAllocs := len(origAllocations) + delta
	for i := 0; i < newAllocs; i++ {
		p.allocations <- struct{}{}
	}

	if origAllocations != nil {
		close(origAllocations)
	}

	origSlices := p.slices
	p.slices = make(chan *[]byte, p.max)
	if origSlices == nil {
		return
	}

	close(origSlices)
	for bs := range origSlices {
		select {
		case p.slices <- bs:
		default:
			// If the new channel blocks while adding slices from the old channel
			// then we drop the slice. The logic here is to prevent a deadlock situation
			// if the new channel has a smaller capacity then the old.
		}
	}
}

func (p *maxSlicePool) notifyCapacity() {
	select {
	case p.capacityChange <- struct{}{}:
	default:
		// This *shouldn't* happen as the channel is both buffered to the max pool capacity size and is resized
		// on capacity modifications. This is just a safety to ensure that a blocking situation can't occur.
	}
}

func (p *maxSlicePool) SliceSize() int64 {
	return p.sliceSize
}

func (p *maxSlicePool) Close() {
	p.mtx.Lock()
	defer p.mtx.Unlock()
	p.empty()
}

func (p *maxSlicePool) empty() {
	p.max = 0

	if p.capacityChange != nil {
		close(p.capacityChange)
		p.capacityChange = nil
	}

	if p.allocations != nil {
		close(p.allocations)
		for range p.allocations {
			// drain channel
		}
		p.allocations = nil
	}

	if p.slices != nil {
		close(p.slices)
		for range p.slices {
			// drain channel
		}
		p.slices = nil
	}
}

func (p *maxSlicePool) newSlice() *[]byte {
	bs := make([]byte, p.sliceSize)
	return &bs
}

type returnCapacityPoolCloser struct {
	byteSlicePool
	returnCapacity int
}

func (n *returnCapacityPoolCloser) ModifyCapacity(delta int) {
	if delta > 0 {
		n.returnCapacity = -1 * delta
	}
	n.byteSlicePool.ModifyCapacity(delta)
}

func (n *returnCapacityPoolCloser) Close() {
	if n.returnCapacity < 0 {
		n.byteSlicePool.ModifyCapacity(n.returnCapacity)
	}
}

type sliceAllocator func() *[]byte

var newByteSlicePool = func(sliceSize int64) byteSlicePool {
	return newMaxSlicePool(sliceSize)
}

M vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go => vendor/github.com/aws/aws-sdk-go/service/s3/s3manager/upload.go +15 -42
@@ 366,6 366,7 @@ func (u *uploader) upload() (*UploadOutput, error) {
	if err := u.init(); err != nil {
		return nil, awserr.New("ReadRequestBody", "unable to initialize upload", err)
	}
	defer u.cfg.partPool.Close()

	if u.cfg.PartSize < MinUploadPartSize {
		msg := fmt.Sprintf("part size must be at least %d bytes", MinUploadPartSize)


@@ 404,8 405,13 @@ func (u *uploader) init() error {

	// If PartSize was changed or partPool was never setup then we need to allocated a new pool
	// so that we return []byte slices of the correct size
	if u.cfg.partPool == nil || u.cfg.partPool.Size() != u.cfg.PartSize {
	poolCap := u.cfg.Concurrency + 1
	if u.cfg.partPool == nil || u.cfg.partPool.SliceSize() != u.cfg.PartSize {
		u.cfg.partPool = newByteSlicePool(u.cfg.PartSize)
		u.cfg.partPool.ModifyCapacity(poolCap)
	} else {
		u.cfg.partPool = &returnCapacityPoolCloser{byteSlicePool: u.cfg.partPool}
		u.cfg.partPool.ModifyCapacity(poolCap)
	}

	return nil


@@ 441,10 447,6 @@ func (u *uploader) initSize() error {
// does not need to be wrapped in a mutex because nextReader is only called
// from the main thread.
func (u *uploader) nextReader() (io.ReadSeeker, int, func(), error) {
	type readerAtSeeker interface {
		io.ReaderAt
		io.ReadSeeker
	}
	switch r := u.in.Body.(type) {
	case readerAtSeeker:
		var err error


@@ 476,7 478,11 @@ func (u *uploader) nextReader() (io.ReadSeeker, int, func(), error) {
		return reader, int(n), cleanup, err

	default:
		part := u.cfg.partPool.Get()
		part, err := u.cfg.partPool.Get(u.ctx)
		if err != nil {
			return nil, 0, func() {}, err
		}

		n, err := readFillBuf(r, *part)
		u.readerPos += int64(n)



@@ 764,40 770,7 @@ func (u *multiuploader) complete() *s3.CompleteMultipartUploadOutput {
	return resp
}

type byteSlicePool interface {
	Get() *[]byte
	Put(*[]byte)
	Size() int64
}

type partPool struct {
	partSize int64
	sync.Pool
}

func (p *partPool) Get() *[]byte {
	return p.Pool.Get().(*[]byte)
}

func (p *partPool) Put(b *[]byte) {
	p.Pool.Put(b)
}

func (p *partPool) Size() int64 {
	return p.partSize
}

func newPartPool(partSize int64) *partPool {
	p := &partPool{partSize: partSize}

	p.New = func() interface{} {
		bs := make([]byte, p.partSize)
		return &bs
	}

	return p
}

var newByteSlicePool = func(partSize int64) byteSlicePool {
	return newPartPool(partSize)
type readerAtSeeker interface {
	io.ReaderAt
	io.ReadSeeker
}

M vendor/github.com/jmespath/go-jmespath/.travis.yml => vendor/github.com/jmespath/go-jmespath/.travis.yml +14 -1
@@ 3,7 3,20 @@ language: go
sudo: false

go:
  - 1.4
  - 1.5.x
  - 1.6.x
  - 1.7.x
  - 1.8.x
  - 1.9.x
  - 1.10.x
  - 1.11.x
  - 1.12.x
  - 1.13.x
  - 1.14.x
  - tip

allow_failures:
  - go: tip

install: go get -v -t ./...
script: make test

M vendor/github.com/jmespath/go-jmespath/README.md => vendor/github.com/jmespath/go-jmespath/README.md +81 -1
@@ 4,4 4,84 @@



See http://jmespath.org for more info.
go-jmespath is a GO implementation of JMESPath,
which is a query language for JSON.  It will take a JSON
document and transform it into another JSON document
through a JMESPath expression.

Using go-jmespath is really easy.  There's a single function
you use, `jmespath.search`:


```go
> import "github.com/jmespath/go-jmespath"
>
> var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.Search("foo.bar.baz[2]", data)
result = 2
```

In the example we gave the ``search`` function input data of
`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}` as well as the JMESPath
expression `foo.bar.baz[2]`, and the `search` function evaluated
the expression against the input data to produce the result ``2``.

The JMESPath language can do a lot more than select an element
from a list.  Here are a few more examples:

```go
> var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search("foo.bar", data)
result = { "baz": [ 0, 1, 2, 3, 4 ] }


> var jsondata  = []byte(`{"foo": [{"first": "a", "last": "b"},
                           {"first": "c", "last": "d"}]}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search({"foo[*].first", data)
result [ 'a', 'c' ]


> var jsondata = []byte(`{"foo": [{"age": 20}, {"age": 25},
                           {"age": 30}, {"age": 35},
                           {"age": 40}]}`) // your data
> var data interface{}
> err := json.Unmarshal(jsondata, &data)
> result, err := jmespath.search("foo[?age > `30`]")
result = [ { age: 35 }, { age: 40 } ]
```

You can also pre-compile your query. This is usefull if 
you are going to run multiple searches with it:

```go
	> var jsondata = []byte(`{"foo": "bar"}`)
	> var data interface{}
    > err := json.Unmarshal(jsondata, &data)
	> precompiled, err := Compile("foo")
	> if err != nil{
    >   // ... handle the error
    > }
    > result, err := precompiled.Search(data)
	result = "bar"
```

## More Resources

The example above only show a small amount of what
a JMESPath expression can do.  If you want to take a
tour of the language, the *best* place to go is the
[JMESPath Tutorial](http://jmespath.org/tutorial.html).

One of the best things about JMESPath is that it is
implemented in many different programming languages including
python, ruby, php, lua, etc.  To see a complete list of libraries,
check out the [JMESPath libraries page](http://jmespath.org/libraries.html).

And finally, the full JMESPath specification can be found
on the [JMESPath site](http://jmespath.org/specification.html).

M vendor/github.com/jmespath/go-jmespath/api.go => vendor/github.com/jmespath/go-jmespath/api.go +1 -1
@@ 2,7 2,7 @@ package jmespath

import "strconv"

// JMESPath is the epresentation of a compiled JMES path query. A JMESPath is
// JMESPath is the representation of a compiled JMES path query. A JMESPath is
// safe for concurrent use by multiple goroutines.
type JMESPath struct {
	ast  ASTNode

A vendor/github.com/jmespath/go-jmespath/go.mod => vendor/github.com/jmespath/go-jmespath/go.mod +5 -0
@@ 0,0 1,5 @@
module github.com/jmespath/go-jmespath

go 1.14

require github.com/stretchr/testify v1.5.1

A vendor/github.com/jmespath/go-jmespath/go.sum => vendor/github.com/jmespath/go-jmespath/go.sum +11 -0
@@ 0,0 1,11 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

M vendor/github.com/jmespath/go-jmespath/parser.go => vendor/github.com/jmespath/go-jmespath/parser.go +1 -1
@@ 137,7 137,7 @@ func (p *Parser) Parse(expression string) (ASTNode, error) {
	}
	if p.current() != tEOF {
		return ASTNode{}, p.syntaxError(fmt.Sprintf(
			"Unexpected token at the end of the expresssion: %s", p.current()))
			"Unexpected token at the end of the expression: %s", p.current()))
	}
	return parsed, nil
}

M vendor/modules.txt => vendor/modules.txt +5 -4
@@ 1,7 1,7 @@
# a4.io/blobsfile v0.3.8
## explicit
a4.io/blobsfile
# a4.io/gluapp v0.0.0-20200308213855-74e393b208ff
# a4.io/gluapp v0.0.0-20200311203905-eb3c48991ada
## explicit
a4.io/gluapp
a4.io/gluapp/util


@@ 50,7 50,7 @@ github.com/alecthomas/chroma/lexers/w
github.com/alecthomas/chroma/lexers/x
github.com/alecthomas/chroma/lexers/y
github.com/alecthomas/chroma/styles
# github.com/aws/aws-sdk-go v1.29.20
# github.com/aws/aws-sdk-go v1.29.22
## explicit
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/arn


@@ 164,7 164,8 @@ github.com/inconshreveable/log15
github.com/inconshreveable/log15/ext
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/jbenet/go-context/io
# github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
# github.com/jmespath/go-jmespath v0.0.0-20200310193758-2437e8417af5
## explicit
github.com/jmespath/go-jmespath
# github.com/justinas/nosurf v1.1.0
github.com/justinas/nosurf


@@ 276,7 277,7 @@ github.com/yuin/gopher-lua/pm
# github.com/zpatrick/rbac v0.0.0-20180829190353-d2c4f050cf28
## explicit
github.com/zpatrick/rbac
# golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
# golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
## explicit
golang.org/x/crypto/acme
golang.org/x/crypto/acme/autocert