Compare commits
57 Commits
Author | SHA1 | Date |
---|---|---|
Vincent Batts | 1adae81a54 | |
Vincent Batts | 9de8611e15 | |
Vincent Batts | d02dbc5725 | |
Vincent Batts | ae608839f1 | |
Vincent Batts | e8d42c3634 | |
Vincent Batts | 8f06855856 | |
Vincent Batts | 66fcc4c2f9 | |
Vincent Batts | 8653fc588a | |
Vincent Batts | 0e749301e9 | |
Vincent Batts | 4d95ad8fcf | |
Vincent Batts | 3d350a825e | |
Vincent Batts | ced0ce3470 | |
Ubuntu | f2de0fb1a3 | |
Vincent Batts | e34c4f37a7 | |
Vincent Batts | 2e000987c5 | |
Vincent Batts | d6df813dbc | |
Tycho Andersen | f0ebb0ab5b | |
Vincent Batts | 2b899d3655 | |
Vincent Batts | ba9a13f463 | |
Vincent Batts | f849a9299a | |
Vincent Batts | 6912c50eda | |
Vincent Batts | 7ce6c9c696 | |
Vincent Batts | 8b6de6073c | |
Vincent Batts | 4885a690ee | |
Vincent Batts | 656cd41822 | |
Vincent Batts | 9be05594fe | |
Vincent Batts | 94a6c46bde | |
Vincent Batts | 134ba041d7 | |
Tycho Andersen | d8d43cd807 | |
Vincent Batts | 53e54ea2f7 | |
Vincent Batts | 40f4ce8108 | |
Vincent Batts | abf4d54fb2 | |
Vincent Batts | 367008df78 | |
Vincent Batts | 4ae4c48dc0 | |
Vincent Batts | acd3fa49ea | |
Aleksa Sarai | 4766cebac0 | |
Vincent Batts | 37d776ac40 | |
Vincent Batts | 03270d3d9e | |
Vincent Batts | 2f374a383e | |
Vincent Batts | f34a2e0d2b | |
Vincent Batts | dce9629991 | |
Vincent Batts | 68a6d43233 | |
Vincent Batts | 1bcf4de08f | |
Aleksa Sarai | be3abf053a | |
Aleksa Sarai | ffb4a05860 | |
Vincent Batts | 16da0f86ee | |
Vincent Batts | 144242ef1e | |
Vincent Batts | 005af4d18f | |
W. Trevor King | 72ac04e7ca | |
Vincent Batts | 03983e2cdc | |
Vincent Batts | de69569d25 | |
Vincent Batts | 2352d84626 | |
Vincent Batts | 3a0105dc85 | |
Vincent Batts | a30ab86d71 | |
Tobias Klauser | 3fe21921b5 | |
Tobias Klauser | 7742183cd4 | |
Vincent Batts | 8bcd48e401 |
|
@ -1,21 +1,13 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.x
|
||||
- 1.8.x
|
||||
- 1.7.x
|
||||
- 1.6.3
|
||||
|
||||
sudo: false
|
||||
|
||||
before_install:
|
||||
kind: pipeline
|
||||
name: default
|
||||
steps:
|
||||
steps:
|
||||
- name: build
|
||||
image: golang
|
||||
commands:
|
||||
- git config --global url."https://".insteadOf git://
|
||||
- go get -u github.com/golang/lint/golint
|
||||
- go get -u github.com/Masterminds/glide
|
||||
- make install.tools
|
||||
- mkdir -p $GOPATH/src/github.com/vbatts && ln -sf $(pwd) $GOPATH/src/github.com/vbatts/go-mtree
|
||||
|
||||
install: true
|
||||
|
||||
script:
|
||||
- make validation
|
||||
- make validation.tags
|
||||
- make build.arches
|
|
@ -0,0 +1,28 @@
|
|||
name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
|
||||
- name: Build
|
||||
run: make
|
||||
|
||||
- name: Test
|
||||
run: make validation
|
||||
|
||||
- name: Build.Arches
|
||||
run: make build.arches
|
22
Makefile
22
Makefile
|
@ -6,6 +6,7 @@ SOURCE_FILES := $(shell find . -type f -name "*.go")
|
|||
CLEAN_FILES := *~
|
||||
TAGS :=
|
||||
ARCHES := linux,386 linux,amd64 linux,arm linux,arm64 openbsd,amd64 windows,amd64 darwin,amd64
|
||||
GO_VER := go1.14
|
||||
|
||||
default: build validation
|
||||
|
||||
|
@ -19,12 +20,13 @@ validation.tags: .test.tags .vet.tags .cli.test
|
|||
test: .test
|
||||
|
||||
CLEAN_FILES += .test .test.tags
|
||||
NO_VENDOR_DIR := $(shell find . -type f -name '*.go' ! -path './vendor*' ! -path './.git*' ! -path './.vscode*' -exec dirname "{}" \; | sort -u)
|
||||
|
||||
.test: $(SOURCE_FILES)
|
||||
go test -v $$(glide novendor) && touch $@
|
||||
go test -v $(NO_VENDOR_DIR) && touch $@
|
||||
|
||||
.test.tags: $(SOURCE_FILES)
|
||||
set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $$(glide novendor) ; done && touch $@
|
||||
set -e ; for tag in $(TAGS) ; do go test -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@
|
||||
|
||||
.PHONY: lint
|
||||
lint: .lint
|
||||
|
@ -32,7 +34,11 @@ lint: .lint
|
|||
CLEAN_FILES += .lint
|
||||
|
||||
.lint: $(SOURCE_FILES)
|
||||
set -e ; for dir in $$(glide novendor) ; do golint -set_exit_status $$dir ; done && touch $@
|
||||
@if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \
|
||||
set -e ; for dir in $(NO_VENDOR_DIR) ; do golint -set_exit_status $$dir ; done && touch $@ \
|
||||
else \
|
||||
touch $@ ; \
|
||||
fi
|
||||
|
||||
.PHONY: vet
|
||||
vet: .vet .vet.tags
|
||||
|
@ -40,10 +46,10 @@ vet: .vet .vet.tags
|
|||
CLEAN_FILES += .vet .vet.tags
|
||||
|
||||
.vet: $(SOURCE_FILES)
|
||||
go vet $$(glide novendor) && touch $@
|
||||
go vet $(NO_VENDOR_DIR) && touch $@
|
||||
|
||||
.vet.tags: $(SOURCE_FILES)
|
||||
set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $$(glide novendor) ; done && touch $@
|
||||
set -e ; for tag in $(TAGS) ; do go vet -tags $$tag -v $(NO_VENDOR_DIR) ; done && touch $@
|
||||
|
||||
.PHONY: cli.test
|
||||
cli.test: .cli.test
|
||||
|
@ -62,6 +68,12 @@ build: $(BUILD)
|
|||
$(BUILD): $(SOURCE_FILES)
|
||||
go build -o $(BUILD) $(BUILDPATH)
|
||||
|
||||
install.tools:
|
||||
@go get -u github.com/fatih/color ; \
|
||||
if [ "$(findstring $(GO_VER),$(shell go version))" != "" ] ; then \
|
||||
go get -u golang.org/x/lint/golint ;\
|
||||
fi
|
||||
|
||||
./bin:
|
||||
mkdir -p $@
|
||||
|
||||
|
|
10
check.go
10
check.go
|
@ -18,13 +18,3 @@ func Check(root string, dh *DirectoryHierarchy, keywords []Keyword, fs FsEval) (
|
|||
|
||||
return Compare(dh, newDh, keywords)
|
||||
}
|
||||
|
||||
// TarCheck is the tar equivalent of checking a file hierarchy spec against a
|
||||
// tar stream to determine if files have been changed. This is precisely
|
||||
// equivalent to Compare(dh, tarDH, keywords).
|
||||
func TarCheck(tarDH, dh *DirectoryHierarchy, keywords []Keyword) ([]InodeDelta, error) {
|
||||
if keywords == nil {
|
||||
return Compare(dh, tarDH, dh.UsedKeywords())
|
||||
}
|
||||
return Compare(dh, tarDH, keywords)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbatts/go-mtree"
|
||||
)
|
||||
|
||||
|
|
123
compare.go
123
compare.go
|
@ -30,6 +30,10 @@ const (
|
|||
// manifests).
|
||||
Modified DifferenceType = "modified"
|
||||
|
||||
// Same represents the case where two files are the same. These are
|
||||
// only generated from CompareSame().
|
||||
Same DifferenceType = "same"
|
||||
|
||||
// ErrorDifference represents an attempted update to the values of
|
||||
// a keyword that failed
|
||||
ErrorDifference DifferenceType = "errored"
|
||||
|
@ -157,10 +161,10 @@ func (k KeyDelta) Old() *string {
|
|||
|
||||
// New returns the value of the KeyDeltaVal entry in the "new" DirectoryHierarchy
|
||||
// (as determined by the ordering of parameters to Compare). Returns nil if
|
||||
// there was no entry in the "old" DirectoryHierarchy.
|
||||
// there was no entry in the "new" DirectoryHierarchy.
|
||||
func (k KeyDelta) New() *string {
|
||||
if k.diff == Modified || k.diff == Extra {
|
||||
return sPtr(k.old)
|
||||
return sPtr(k.new)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -313,21 +317,8 @@ func compareEntry(oldEntry, newEntry Entry) ([]KeyDelta, error) {
|
|||
return results, nil
|
||||
}
|
||||
|
||||
// Compare compares two directory hierarchy manifests, and returns the
|
||||
// list of discrepancies between the two. All of the entries in the
|
||||
// manifest are considered, with differences being generated for
|
||||
// RelativeType and FullType entries. Differences in structure (such as
|
||||
// the way /set and /unset are written) are not considered to be
|
||||
// discrepancies. The list of differences are all filesystem objects.
|
||||
//
|
||||
// keys controls which keys will be compared, but if keys is nil then all
|
||||
// possible keys will be compared between the two manifests (allowing for
|
||||
// missing entries and the like). A missing or extra key is treated as a
|
||||
// Modified type.
|
||||
//
|
||||
// NB: The order of the parameters matters (old, new) because Extra and
|
||||
// Missing are considered as different discrepancy types.
|
||||
func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
||||
// compare is the actual workhorse for Compare() and CompareSame()
|
||||
func compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword, same bool) ([]InodeDelta, error) {
|
||||
// Represents the new and old states for an entry.
|
||||
type stateT struct {
|
||||
Old *Entry
|
||||
|
@ -338,43 +329,47 @@ func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, er
|
|||
// map to make sure we don't start comparing unrelated entries.
|
||||
diffs := map[string]*stateT{}
|
||||
|
||||
// First, iterate over the old hierarchy.
|
||||
for _, e := range oldDh.Entries {
|
||||
if e.Type == RelativeType || e.Type == FullType {
|
||||
path, err := e.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// First, iterate over the old hierarchy. If nil, pretend it's empty.
|
||||
if oldDh != nil {
|
||||
for _, e := range oldDh.Entries {
|
||||
if e.Type == RelativeType || e.Type == FullType {
|
||||
path, err := e.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Cannot take &kv because it's the iterator.
|
||||
copy := new(Entry)
|
||||
*copy = e
|
||||
// Cannot take &kv because it's the iterator.
|
||||
cEntry := new(Entry)
|
||||
*cEntry = e
|
||||
|
||||
_, ok := diffs[path]
|
||||
if !ok {
|
||||
diffs[path] = &stateT{}
|
||||
_, ok := diffs[path]
|
||||
if !ok {
|
||||
diffs[path] = &stateT{}
|
||||
}
|
||||
diffs[path].Old = cEntry
|
||||
}
|
||||
diffs[path].Old = copy
|
||||
}
|
||||
}
|
||||
|
||||
// Then, iterate over the new hierarchy.
|
||||
for _, e := range newDh.Entries {
|
||||
if e.Type == RelativeType || e.Type == FullType {
|
||||
path, err := e.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Then, iterate over the new hierarchy. If nil, pretend it's empty.
|
||||
if newDh != nil {
|
||||
for _, e := range newDh.Entries {
|
||||
if e.Type == RelativeType || e.Type == FullType {
|
||||
path, err := e.Path()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Cannot take &kv because it's the iterator.
|
||||
copy := new(Entry)
|
||||
*copy = e
|
||||
// Cannot take &kv because it's the iterator.
|
||||
cEntry := new(Entry)
|
||||
*cEntry = e
|
||||
|
||||
_, ok := diffs[path]
|
||||
if !ok {
|
||||
diffs[path] = &stateT{}
|
||||
_, ok := diffs[path]
|
||||
if !ok {
|
||||
diffs[path] = &stateT{}
|
||||
}
|
||||
diffs[path].New = cEntry
|
||||
}
|
||||
diffs[path].New = copy
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,9 +425,47 @@ func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, er
|
|||
new: *diff.New,
|
||||
keys: changed,
|
||||
})
|
||||
} else if same {
|
||||
// this means that nothing changed, i.e. that
|
||||
// the files are the same.
|
||||
results = append(results, InodeDelta{
|
||||
diff: Same,
|
||||
path: path,
|
||||
old: *diff.Old,
|
||||
new: *diff.New,
|
||||
keys: changed,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// Compare compares two directory hierarchy manifests, and returns the
|
||||
// list of discrepancies between the two. All of the entries in the
|
||||
// manifest are considered, with differences being generated for
|
||||
// RelativeType and FullType entries. Differences in structure (such as
|
||||
// the way /set and /unset are written) are not considered to be
|
||||
// discrepancies. The list of differences are all filesystem objects.
|
||||
//
|
||||
// keys controls which keys will be compared, but if keys is nil then all
|
||||
// possible keys will be compared between the two manifests (allowing for
|
||||
// missing entries and the like). A missing or extra key is treated as a
|
||||
// Modified type.
|
||||
//
|
||||
// If oldDh or newDh are empty, we assume they are a hierarchy that is
|
||||
// completely empty. This is purely for helping callers create synthetic
|
||||
// InodeDeltas.
|
||||
//
|
||||
// NB: The order of the parameters matters (old, new) because Extra and
|
||||
// Missing are considered as different discrepancy types.
|
||||
func Compare(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
||||
return compare(oldDh, newDh, keys, false)
|
||||
}
|
||||
|
||||
// CompareSame is the same as Compare, except it also includes the entries
|
||||
// that are the same with a Same DifferenceType.
|
||||
func CompareSame(oldDh, newDh *DirectoryHierarchy, keys []Keyword) ([]InodeDelta, error) {
|
||||
return compare(oldDh, newDh, keys, true)
|
||||
}
|
||||
|
|
39
entry.go
39
entry.go
|
@ -2,6 +2,7 @@ package mtree
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
@ -67,6 +68,39 @@ func (e Entry) Ascend() *Entry {
|
|||
return e.Parent
|
||||
}
|
||||
|
||||
// CleanPath makes a path safe for use with filepath.Join. This is done by not
|
||||
// only cleaning the path, but also (if the path is relative) adding a leading
|
||||
// '/' and cleaning it (then removing the leading '/'). This ensures that a
|
||||
// path resulting from prepending another path will always resolve to lexically
|
||||
// be a subdirectory of the prefixed path. This is all done lexically, so paths
|
||||
// that include symlinks won't be safe as a result of using CleanPath.
|
||||
//
|
||||
// This code was copied from runc/libcontainer/utils/utils.go. It was
|
||||
// originally written by myself, so I am dual-licensing it for the purpose of
|
||||
// this project.
|
||||
func CleanPath(path string) string {
|
||||
// Deal with empty strings nicely.
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Ensure that all paths are cleaned (especially problematic ones like
|
||||
// "/../../../../../" which can cause lots of issues).
|
||||
path = filepath.Clean(path)
|
||||
|
||||
// If the path isn't absolute, we need to do more processing to fix paths
|
||||
// such as "../../../../<etc>/some/path". We also shouldn't convert absolute
|
||||
// paths to relative ones.
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Clean(string(os.PathSeparator) + path)
|
||||
// This can't fail, as (by definition) all paths are relative to root.
|
||||
path, _ = filepath.Rel(string(os.PathSeparator), path)
|
||||
}
|
||||
|
||||
// Clean the path again for good measure.
|
||||
return filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Path provides the full path of the file, despite RelativeType or FullType. It
|
||||
// will be in Unvis'd form.
|
||||
func (e Entry) Path() (string, error) {
|
||||
|
@ -74,14 +108,15 @@ func (e Entry) Path() (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
decodedName = CleanPath(decodedName)
|
||||
if e.Parent == nil || e.Type == FullType {
|
||||
return filepath.Clean(decodedName), nil
|
||||
return decodedName, nil
|
||||
}
|
||||
parentName, err := e.Parent.Path()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Clean(filepath.Join(parentName, decodedName)), nil
|
||||
return CleanPath(filepath.Join(parentName, decodedName)), nil
|
||||
}
|
||||
|
||||
// String joins a file with its associated keywords. The file name will be the
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
hash: c4cfd3ace8e3926093aacecfa0f22fbeb5b2a7cb53e0b12a48b5108f6c83d9b8
|
||||
updated: 2017-06-24T14:24:17.116476656-04:00
|
||||
imports:
|
||||
- name: github.com/Sirupsen/logrus
|
||||
version: 202f25545ea4cf9b191ff7f846df5d87c9382c2b
|
||||
- name: golang.org/x/crypto
|
||||
version: adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d
|
||||
subpackages:
|
||||
- ripemd160
|
||||
- name: golang.org/x/sys
|
||||
version: c23410a886927bab8ca5e80b08af6a56faeb330d
|
||||
subpackages:
|
||||
- unix
|
||||
testImports: []
|
10
glide.yaml
10
glide.yaml
|
@ -1,10 +0,0 @@
|
|||
package: github.com/vbatts/go-mtree
|
||||
description: File systems verification utility and library, in likeness of mtree(8)
|
||||
homepage: https://github.com/vbatts/go-mtree
|
||||
license: BSD-3-Clause
|
||||
import:
|
||||
- package: golang.org/x/crypto
|
||||
subpackages:
|
||||
- ripemd160
|
||||
- package: github.com/Sirupsen/logrus
|
||||
version: ^1.0.0
|
|
@ -0,0 +1,11 @@
|
|||
module github.com/vbatts/go-mtree
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/fatih/color v1.12.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
)
|
|
@ -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/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
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/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
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/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
@ -26,30 +26,32 @@ type KeywordFunc func(path string, info os.FileInfo, r io.Reader) ([]KeyVal, err
|
|||
var (
|
||||
// KeywordFuncs is the map of all keywords (and the functions to produce them)
|
||||
KeywordFuncs = map[Keyword]KeywordFunc{
|
||||
"size": sizeKeywordFunc, // The size, in bytes, of the file
|
||||
"type": typeKeywordFunc, // The type of the file
|
||||
"time": timeKeywordFunc, // The last modification time of the file
|
||||
"link": linkKeywordFunc, // The target of the symbolic link when type=link
|
||||
"uid": uidKeywordFunc, // The file owner as a numeric value
|
||||
"gid": gidKeywordFunc, // The file group as a numeric value
|
||||
"nlink": nlinkKeywordFunc, // The number of hard links the file is expected to have
|
||||
"uname": unameKeywordFunc, // The file owner as a symbolic name
|
||||
"gname": gnameKeywordFunc, // The file group as a symbolic name
|
||||
"mode": modeKeywordFunc, // The current file's permissions as a numeric (octal) or symbolic value
|
||||
"cksum": cksumKeywordFunc, // The checksum of the file using the default algorithm specified by the cksum(1) utility
|
||||
"md5": hasherKeywordFunc("md5digest", md5.New), // The MD5 message digest of the file
|
||||
"md5digest": hasherKeywordFunc("md5digest", md5.New), // A synonym for `md5`
|
||||
"rmd160": hasherKeywordFunc("ripemd160digest", ripemd160.New), // The RIPEMD160 message digest of the file
|
||||
"rmd160digest": hasherKeywordFunc("ripemd160digest", ripemd160.New), // A synonym for `rmd160`
|
||||
"ripemd160digest": hasherKeywordFunc("ripemd160digest", ripemd160.New), // A synonym for `rmd160`
|
||||
"sha1": hasherKeywordFunc("sha1digest", sha1.New), // The SHA1 message digest of the file
|
||||
"sha1digest": hasherKeywordFunc("sha1digest", sha1.New), // A synonym for `sha1`
|
||||
"sha256": hasherKeywordFunc("sha256digest", sha256.New), // The SHA256 message digest of the file
|
||||
"sha256digest": hasherKeywordFunc("sha256digest", sha256.New), // A synonym for `sha256`
|
||||
"sha384": hasherKeywordFunc("sha384digest", sha512.New384), // The SHA384 message digest of the file
|
||||
"sha384digest": hasherKeywordFunc("sha384digest", sha512.New384), // A synonym for `sha384`
|
||||
"sha512": hasherKeywordFunc("sha512digest", sha512.New), // The SHA512 message digest of the file
|
||||
"sha512digest": hasherKeywordFunc("sha512digest", sha512.New), // A synonym for `sha512`
|
||||
"size": sizeKeywordFunc, // The size, in bytes, of the file
|
||||
"type": typeKeywordFunc, // The type of the file
|
||||
"time": timeKeywordFunc, // The last modification time of the file
|
||||
"link": linkKeywordFunc, // The target of the symbolic link when type=link
|
||||
"uid": uidKeywordFunc, // The file owner as a numeric value
|
||||
"gid": gidKeywordFunc, // The file group as a numeric value
|
||||
"nlink": nlinkKeywordFunc, // The number of hard links the file is expected to have
|
||||
"uname": unameKeywordFunc, // The file owner as a symbolic name
|
||||
"gname": gnameKeywordFunc, // The file group as a symbolic name
|
||||
"mode": modeKeywordFunc, // The current file's permissions as a numeric (octal) or symbolic value
|
||||
"cksum": cksumKeywordFunc, // The checksum of the file using the default algorithm specified by the cksum(1) utility
|
||||
"md5": hasherKeywordFunc("md5digest", md5.New), // The MD5 message digest of the file
|
||||
"md5digest": hasherKeywordFunc("md5digest", md5.New), // A synonym for `md5`
|
||||
"rmd160": hasherKeywordFunc("ripemd160digest", ripemd160.New), // The RIPEMD160 message digest of the file
|
||||
"rmd160digest": hasherKeywordFunc("ripemd160digest", ripemd160.New), // A synonym for `rmd160`
|
||||
"ripemd160digest": hasherKeywordFunc("ripemd160digest", ripemd160.New), // A synonym for `rmd160`
|
||||
"sha1": hasherKeywordFunc("sha1digest", sha1.New), // The SHA1 message digest of the file
|
||||
"sha1digest": hasherKeywordFunc("sha1digest", sha1.New), // A synonym for `sha1`
|
||||
"sha256": hasherKeywordFunc("sha256digest", sha256.New), // The SHA256 message digest of the file
|
||||
"sha256digest": hasherKeywordFunc("sha256digest", sha256.New), // A synonym for `sha256`
|
||||
"sha384": hasherKeywordFunc("sha384digest", sha512.New384), // The SHA384 message digest of the file
|
||||
"sha384digest": hasherKeywordFunc("sha384digest", sha512.New384), // A synonym for `sha384`
|
||||
"sha512": hasherKeywordFunc("sha512digest", sha512.New), // The SHA512 message digest of the file
|
||||
"sha512digest": hasherKeywordFunc("sha512digest", sha512.New), // A synonym for `sha512`
|
||||
"sha512256": hasherKeywordFunc("sha512digest", sha512.New512_256), // The SHA512/256 message digest of the file
|
||||
"sha512256digest": hasherKeywordFunc("sha512digest", sha512.New512_256), // A synonym for `sha512256`
|
||||
|
||||
"flags": flagsKeywordFunc, // NOTE: this is a noop, but here to support the presence of the "flags" keyword.
|
||||
|
||||
|
|
|
@ -316,6 +316,8 @@ func KeywordSynonym(name string) Keyword {
|
|||
retname = "sha384digest"
|
||||
case "sha512":
|
||||
retname = "sha512digest"
|
||||
case "sha512256":
|
||||
retname = "sha512256digest"
|
||||
case "xattrs":
|
||||
retname = "xattr"
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// +build darwin dragonfly freebsd openbsd linux netbsd solaris
|
||||
|
||||
package mtree
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func lchtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
utimes := []unix.Timespec{
|
||||
unix.NsecToTimespec(atime.UnixNano()),
|
||||
unix.NsecToTimespec(mtime.UnixNano()),
|
||||
}
|
||||
if e := unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes, unix.AT_SYMLINK_NOFOLLOW); e != nil {
|
||||
return &os.PathError{Op: "chtimes", Path: name, Err: e}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// +build windows
|
||||
|
||||
package mtree
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func lchtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return nil
|
||||
}
|
|
@ -4,25 +4,48 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
var (
|
||||
testFiles = []string{"testdata/source.mtree"}
|
||||
numEntries = map[EntryType]int{
|
||||
FullType: 0,
|
||||
RelativeType: 45,
|
||||
CommentType: 37,
|
||||
SpecialType: 7,
|
||||
DotDotType: 17,
|
||||
BlankType: 34,
|
||||
testFiles = []struct {
|
||||
Name string
|
||||
Counts map[EntryType]int
|
||||
Len int64
|
||||
}{
|
||||
{
|
||||
Name: "testdata/source.mtree",
|
||||
Counts: map[EntryType]int{
|
||||
FullType: 0,
|
||||
RelativeType: 45,
|
||||
CommentType: 37,
|
||||
SpecialType: 7,
|
||||
DotDotType: 17,
|
||||
BlankType: 34,
|
||||
},
|
||||
Len: int64(7887),
|
||||
},
|
||||
{
|
||||
Name: "testdata/source.casync-mtree",
|
||||
Counts: map[EntryType]int{
|
||||
FullType: 744,
|
||||
RelativeType: 56,
|
||||
CommentType: 37,
|
||||
SpecialType: 7,
|
||||
DotDotType: 17,
|
||||
BlankType: 34,
|
||||
},
|
||||
Len: int64(168439),
|
||||
},
|
||||
}
|
||||
expectedLength = int64(7887)
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
for _, file := range testFiles {
|
||||
for i, tf := range testFiles {
|
||||
_ = i
|
||||
func() {
|
||||
fh, err := os.Open(file)
|
||||
fh, err := os.Open(tf.Name)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
|
@ -33,8 +56,17 @@ func TestParser(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if i == 1 {
|
||||
spew.Dump(dh)
|
||||
//buf, err := xml.MarshalIndent(dh, "", " ")
|
||||
//if err == nil {
|
||||
//t.Error(string(buf))
|
||||
//}
|
||||
}
|
||||
|
||||
gotNums := countTypes(dh)
|
||||
for typ, num := range numEntries {
|
||||
for typ, num := range tf.Counts {
|
||||
if gNum, ok := gotNums[typ]; ok {
|
||||
if num != gNum {
|
||||
t.Errorf("for type %s: expected %d, got %d", typ, num, gNum)
|
||||
|
@ -46,8 +78,8 @@ func TestParser(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if i != expectedLength {
|
||||
t.Errorf("expected to write %d, but wrote %d", expectedLength, i)
|
||||
if i != tf.Len {
|
||||
t.Errorf("expected to write %d, but wrote %d", tf.Len, i)
|
||||
}
|
||||
|
||||
}()
|
||||
|
|
2
tar.go
2
tar.go
|
@ -9,7 +9,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbatts/go-mtree/pkg/govis"
|
||||
)
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ func TestTar(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := TarCheck(tdh, dh, append(DefaultKeywords, "sha1"))
|
||||
res, err := Compare(tdh, dh, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ func TestArchiveCreation(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test the tar manifest against itself
|
||||
res, err = TarCheck(tdh, tdh, []Keyword{"sha1"})
|
||||
res, err = Compare(tdh, tdh, []Keyword{"sha1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func TestArchiveCreation(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res, err = TarCheck(tdh, dh, []Keyword{"sha1"})
|
||||
res, err = Compare(tdh, dh, []Keyword{"sha1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ func TestTreeTraversal(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := TarCheck(tdh, tdh, []Keyword{"sha1"})
|
||||
res, err := Compare(tdh, tdh, []Keyword{"sha1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
11
test/cli.go
11
test/cli.go
|
@ -1,3 +1,5 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -5,10 +7,14 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
red := color.New(color.FgRed).SprintFunc()
|
||||
|
||||
failed := 0
|
||||
for _, arg := range flag.Args() {
|
||||
|
@ -20,11 +26,12 @@ func main() {
|
|||
cmd.Stdout = os.Stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
failed++
|
||||
fmt.Fprintf(os.Stderr, "FAILED: %s\n", arg)
|
||||
fmt.Fprintf(os.Stderr, red("FAILED: %s\n"), arg)
|
||||
}
|
||||
}
|
||||
if failed > 0 {
|
||||
fmt.Fprintf(os.Stderr, "%d FAILED tests\n", failed)
|
||||
fmt.Fprintf(os.Stderr, red("%d FAILED tests\n"), failed)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, green("SUCCESS: no cli tests failed\n"))
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
# This test is for basic running check of manifest, and check against tar and file system
|
||||
|
@ -12,33 +12,33 @@ echo "[${name}] Running in ${t}"
|
|||
|
||||
pushd ${root}
|
||||
|
||||
git archive --format=tar HEAD^{tree} . > ${t}/${name}.tar
|
||||
git archive --format=tar -o "${t}/${name}.tar" HEAD^{tree}
|
||||
|
||||
prev_umask=$(umask)
|
||||
umask 0 # this is so the tar command can set the mode's properly
|
||||
mkdir -p ${t}/extract
|
||||
tar -C ${t}/extract/ -xf ${t}/${name}.tar
|
||||
tar -C ${t}/extract/ -xf "${t}/${name}.tar"
|
||||
umask ${prev_umask}
|
||||
|
||||
# create manifest from tar
|
||||
${gomtree} -K sha256digest -c -T ${t}/${name}.tar > ${t}/${name}.mtree
|
||||
${gomtree} -K sha256digest -c -T "${t}/${name}.tar" > "${t}/${name}.mtree"
|
||||
|
||||
# check tar-manifest against the tar
|
||||
${gomtree} -f ${t}/${name}.mtree -T ${t}/${name}.tar
|
||||
${gomtree} -f ${t}/${name}.mtree -T "${t}/${name}.tar"
|
||||
|
||||
# check tar-manifest against the filesystem
|
||||
# git archive makes the uid/gid as 0, so don't check them for this test
|
||||
${gomtree} -k size,sha256digest,mode,type -f ${t}/${name}.mtree -p ${t}/extract/
|
||||
${gomtree} -k size,sha256digest,mode,type -f "${t}/${name}.mtree" -p ${t}/extract/
|
||||
|
||||
# create a manifest from filesystem
|
||||
${gomtree} -K sha256digest -c -p ${t}/extract/ > ${t}/${name}.mtree
|
||||
${gomtree} -K sha256digest -c -p "${t}/extract/" > "${t}/${name}.mtree"
|
||||
|
||||
# check filesystem-manifest against the filesystem
|
||||
${gomtree} -f ${t}/${name}.mtree -p ${t}/extract/
|
||||
${gomtree} -f "${t}/${name}.mtree" -p "${t}/extract/"
|
||||
|
||||
# check filesystem-manifest against the tar
|
||||
# git archive makes the uid/gid as 0, so don't check them for this test
|
||||
${gomtree} -k size,sha256digest,mode,type -f ${t}/${name}.mtree -T ${t}/${name}.tar
|
||||
${gomtree} -k size,sha256digest,mode,type -f "${t}/${name}.mtree" -T "${t}/${name}.tar"
|
||||
|
||||
popd
|
||||
rm -rf ${t}
|
||||
|
|
|
@ -3,8 +3,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
# This test is for basic running check of manifest, and check against tar and file system
|
||||
|
|
|
@ -3,10 +3,10 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
setfattr -n user.has.xattrs -v "true" "${t}" || exit 0
|
||||
setfattr -n user.has.xattrs -v "true" "${t}" || exit 0
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
# This test is for basic running check of manifest, and check against tar and file system
|
||||
|
|
|
@ -3,9 +3,9 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
left=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
right=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
left=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
right=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${left} and ${right}"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d /tmp/go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
|
|
@ -3,8 +3,8 @@ set -e
|
|||
|
||||
name=$(basename $0)
|
||||
root="$(dirname $(dirname $(dirname $0)))"
|
||||
gomtree=$(readlink -f ${root}/gomtree)
|
||||
t=$(mktemp -t -d go-mtree.XXXXXX)
|
||||
gomtree=$(go run ${root}/test/realpath.go ${root}/gomtree)
|
||||
t=$(mktemp -d -t go-mtree.XXXXXX)
|
||||
|
||||
echo "[${name}] Running in ${t}"
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package test
|
||||
|
||||
// place holder for test helpers
|
|
@ -0,0 +1,22 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
for _, arg := range flag.Args() {
|
||||
path, err := filepath.Abs(arg)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%s", path)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,800 @@
|
|||
. type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513088963.690901011
|
||||
.git type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513089565.023874273
|
||||
.git/FETCH_HEAD type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513089402.952611958 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
.git/HEAD type=file mode=0664 size=23 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036 sha512256digest=459551401449a0555a2c1a1ef57f17eab8b70afccd1ae2fb089e1fe216d92041
|
||||
.git/branches type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723
|
||||
.git/config type=file mode=0664 size=259 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.420901030 sha512256digest=18c4f2a977a0a6fb1039082eea88c34a7722f711f9bb40141eeae811077511ea
|
||||
.git/description type=file mode=0664 size=73 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=52f9f7b626fcc7377e618c29c72d2adfb40659bad81aa9cabe69b1ef7e48ec15
|
||||
.git/hooks type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807
|
||||
.git/hooks/applypatch-msg.sample type=file mode=0775 size=478 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=50e4870022c7e5ea0c9fd2556b9de3ea9741e5cc6bbca86d7749532e091f94aa
|
||||
.git/hooks/commit-msg.sample type=file mode=0775 size=896 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=b131f0eacbaf7d6f5e45bc59413bedebc000006554d37d0f6387f94bff3d7ba4
|
||||
.git/hooks/post-update.sample type=file mode=0775 size=189 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=a861e78221dd2aee9ef902e918279d18d5776f45ff2f08f2d6d85def3e879c20
|
||||
.git/hooks/pre-applypatch.sample type=file mode=0775 size=424 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=ef5dc4dd0d72149edaa2240740936d256c30fa43f0f175c3e03db7684d8b1a5d
|
||||
.git/hooks/pre-commit.sample type=file mode=0775 size=1642 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=ac3a75622c41756863cfb0e6a5eac2f9247e0aa2de287fcebf3fd059bfe7b423
|
||||
.git/hooks/pre-push.sample type=file mode=0775 size=1348 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.793867723 sha512256digest=5cb63a560e7dab995cdffe1fcd1b7ddbadc434b0e5adae360e0d5daa79e41bd5
|
||||
.git/hooks/pre-rebase.sample type=file mode=0775 size=4898 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=575537b3286d2ffcf1f129cb674b49e995b6f3843b32fb213c8372d59fd588f8
|
||||
.git/hooks/pre-receive.sample type=file mode=0775 size=544 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=3c068c42aee0de45188ba1180c447f9b9387c1551ee486caba4511e8b40f7573
|
||||
.git/hooks/prepare-commit-msg.sample type=file mode=0775 size=1239 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=9d96b773060e0260d7d7face6b1daee38ec0ad977a0f74f9d45520905e3f830e
|
||||
.git/hooks/update.sample type=file mode=0775 size=3610 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=7990f12495cee686e19080c5633b7cd18a40fdca1120be1a6128937f5568aac0
|
||||
.git/index type=file mode=0664 size=76425 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513087136.393593011 sha512256digest=83b6bbe228b1b181ef87269fd937adc615bf7f18940697807d864dff3f95b66b
|
||||
.git/info type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807
|
||||
.git/info/exclude type=file mode=0664 size=240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807 sha512256digest=b5a32a7a25ad2254f517806d1600ff2498e2f91fe501cb54f9dd517e9693bf7c
|
||||
.git/logs type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036
|
||||
.git/logs/HEAD type=file mode=0664 size=186 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036 sha512256digest=6ba5a37eb3a8363ce228172998c9120800d2099e59ff0365f8095e437c4e7e72
|
||||
.git/logs/refs type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036
|
||||
.git/logs/refs/heads type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.420901030
|
||||
.git/logs/refs/heads/master type=file mode=0664 size=186 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.420901030 sha512256digest=6ba5a37eb3a8363ce228172998c9120800d2099e59ff0365f8095e437c4e7e72
|
||||
.git/logs/refs/remotes type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.418901041
|
||||
.git/logs/refs/remotes/origin type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.418901041
|
||||
.git/logs/refs/remotes/origin/HEAD type=file mode=0664 size=186 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036 sha512256digest=6ba5a37eb3a8363ce228172998c9120800d2099e59ff0365f8095e437c4e7e72
|
||||
.git/objects type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807
|
||||
.git/objects/info type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807
|
||||
.git/objects/pack type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.420901030
|
||||
.git/objects/pack/pack-6002ca434fbc0435338603c137c716144940e3ac.idx type=file mode=0444 size=64128 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774393.883903855 sha512256digest=22029d26bebf556cfc42e05b2803631e69913316cfdc4f93f81bf0b811422965
|
||||
.git/objects/pack/pack-6002ca434fbc0435338603c137c716144940e3ac.pack type=file mode=0444 size=2847104 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774393.883903855 sha512256digest=edcbdb76328491490433392cc9d73473d7ed3c4b9d730071eadafff7bcbbe322
|
||||
.git/packed-refs type=file mode=0664 size=980 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.418901041 sha512256digest=64272b5a7707bc9de1644ffe9f4ea331e0b27edfe2afa46051765d650e4f027d
|
||||
.git/refs type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.418901041
|
||||
.git/refs/heads type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.420901030
|
||||
.git/refs/heads/master type=file mode=0664 size=41 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036 sha512256digest=ff968619a51a3545a1b690defeb0e496221e87f44d7842f21e4479cd8323e2b3
|
||||
.git/refs/remotes type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.418901041
|
||||
.git/refs/remotes/origin type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036
|
||||
.git/refs/remotes/origin/HEAD type=file mode=0664 size=32 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.419901036 sha512256digest=59c99dd84367c1f79cc6e2fc932283a596ed1351f89a378f473bf223a1bce4a6
|
||||
.git/refs/tags type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512773804.794867807
|
||||
.gitignore type=file mode=0664 size=38 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020 sha512256digest=da309c361a1906cf290acfe3f9737761809f4651398f51e8ba3b595ce3890d8a
|
||||
.travis.yml type=file mode=0664 size=418 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020 sha512256digest=4cc236b9fd00e9e1d7e77c06d5387fc78b88d37fcc138a97f889afea77237809
|
||||
.vscode type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020
|
||||
.vscode/tasks.json type=file mode=0664 size=1903 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020 sha512256digest=0f618420497f07ab3c52fb914a2a017f9c8f6cecb827139000d83d3924945bba
|
||||
LICENSE type=file mode=0664 size=1502 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020 sha512256digest=a38c5d130d16a578fadb5b64272dfa21bc3ee81a170ddfaef602c889ad0e5f47
|
||||
Makefile type=file mode=0664 size=1842 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.422901020 sha512256digest=bee7d37dc3d204d42316f6970ec8394cac8797f41fd033230543c669ae65eb10
|
||||
README.md type=file mode=0664 size=6458 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=a0f4fff9726af7e296dbacde210abb160f8d3ffe3a13eac3eae315804fbefdf7
|
||||
Session.vim type=file mode=0644 size=6088 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513025969.072229243 sha512256digest=ac49e25a69333d34faa213ea419bba40afc971880e6433a031ad93b7e91cda73
|
||||
check.go type=file mode=0664 size=1066 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=36d6f22adfdb787d2c66dcc7847339146c0e9b239bbdd6e36628264b0a9f6bfb
|
||||
check_test.go type=file mode=0664 size=6668 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=dc8562fc88ab21aa1e1c2eb77caa0c07bedf0801d8e2cb315cab71c4d63b0de0
|
||||
cksum.go type=file mode=0664 size=727 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=a16b170014a48532ee0fe3ea61bbe6a45cfd20a984bcceaed0c71524652fe4d3
|
||||
cksum_test.go type=file mode=0664 size=606 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=ff9857d71266a4939b453900155da931122e35187500535d826656a15ad9ba41
|
||||
cmd type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015
|
||||
cmd/gomtree type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015
|
||||
cmd/gomtree/main.go type=file mode=0664 size=12826 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=81195682a5fbdd6a324e2cfa7c61ddf9e14eea6d92c3133da4a858ffadadf6b0
|
||||
compare.go type=file mode=0664 size=12077 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=e0a79e38e03830d965271f4b37dbc6567998a277011437dfb270fb39030b8147
|
||||
compare_test.go type=file mode=0664 size=10837 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=39d0b9638b0b869cf20310a5b0e16ae979b690f3e795eafc1da4502c86c3d601
|
||||
creator.go type=file mode=0664 size=188 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=ef1e8b19255cdc090719bcd947937555c7454b36df7ca501be9c617f1d66d693
|
||||
entry.go type=file mode=0664 size=4645 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=e267d8bcb083acacf43318a038cb50a6fff4658f1c7cfb2d3ebd881d294647b4
|
||||
fseval.go type=file mode=0664 size=1903 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=aa0911e07f7607ce3e4912e37109400d17a905837975f4da48cb225af347afb1
|
||||
fseval_test.go type=file mode=0664 size=3692 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=337e96a382b8a1d4c6fc8c3b57bb5c5598f2de52c33017ddbd9087a8a8cdb235
|
||||
glide.lock type=file mode=0664 size=455 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=1ef63ba5b06290869c7bcf6bfa225fc646645f293d6b8b84844359e10a71d9dd
|
||||
glide.yaml type=file mode=0664 size=415 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=1ca9b54955195442592840664081368529c919ae2d1d7dabbb2bf6c236ba443d
|
||||
hierarchy.go type=file mode=0664 size=1109 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=25d9d887b37972e923656c907a72a0ab40f525704657ed51718b15b1d9030b08
|
||||
hierarchy_test.go type=file mode=0664 size=1427 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.423901015 sha512256digest=cbb37bbaa235cb30670af42d5ae1fff018eee4d97d83628670cc85cda0a8eec8
|
||||
keywordfunc.go type=file mode=0664 size=7790 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=972ef809068af40d0f4d931c179c09e3387652e493ff3badcdb1336ad03c0034
|
||||
keywordfuncs_bsd.go type=file mode=0664 size=2167 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=3d5442bc82156768131be11b491f0a196cb40ef4845026ffef230047c10a84dc
|
||||
keywordfuncs_linux.go type=file mode=0664 size=3129 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=774f8189932431f2903fcc292e7bc6bb0e0e478fcd0d18d21710398fa196de84
|
||||
keywordfuncs_unsupported.go type=file mode=0664 size=1440 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=4062bfa6539d920fd470c459cf91b903135ee41384d4addcd0635c1b8b248fd8
|
||||
keywords.go type=file mode=0664 size=8255 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=1bd20d1919c02036b8f969c73e0dc391dcc9fef5f003b5c5da36b434e4640b15
|
||||
keywords_linux_test.go type=file mode=0664 size=1777 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=6b009753d97b46d3dd7d0209b1866d0da50327c102ef9becb1a80a5d770b4008
|
||||
keywords_test.go type=file mode=0664 size=4084 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=c6fe584af730c805033c85db2a422b608f7cf034fe1d5bac732a354676328cb3
|
||||
lchtimes_unix.go type=file mode=0664 size=484 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=56cf8545358550958badaa966a41e5a07cbd15138d42e19997936e7ae6c330cd
|
||||
lchtimes_unsupported.go type=file mode=0664 size=137 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=a0d24dbf1ffe27dce9e2dcd72c2189c0ba8d9b445fb1d6efea3ef6f43372b141
|
||||
lookup_new.go type=file mode=0664 size=94 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=98317093a5e1d05d3829935c4c68ac09887fff4ad9257760d6cb80051ec6c793
|
||||
lookup_old.go type=file mode=0664 size=2670 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=3d4410b652c64fb4079e7219435aa2de828d7ef0cec2a8dabe9c3e95709c5cba
|
||||
mtree_test.go type=file mode=0664 size=1628 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513089487.302748479 sha512256digest=b205a894416221a6459b1f57688007b6ea29a7e25ee07f867acb16ca4481b281
|
||||
parse.go type=file mode=0664 size=2404 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=dacb3ab6f3a2c2a84ee1eef603f2943561c905947bd75dd8711a944bd646a75a
|
||||
pkg type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009
|
||||
pkg/govis type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004
|
||||
pkg/govis/COPYING type=file mode=0664 size=11358 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=84e99c21df3d69d6bcb82420dc1c5ab9e877aa19ca516fa2644cd2f1e6c35840
|
||||
pkg/govis/README.md type=file mode=0664 size=966 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=e84c3fc90fec0e85d707689c7859535ddced586627d42281a8f33d89698c77ed
|
||||
pkg/govis/govis.go type=file mode=0664 size=1784 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=d942950dfa287f81605b726e95e995db1e309c2ad211d236648eeab5b6840b49
|
||||
pkg/govis/govis_test.go type=file mode=0664 size=6727 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=9a75d86c248a307c026b311fb0513a689138d3806137b342ed255d4f9ce166c2
|
||||
pkg/govis/unvis.go type=file mode=0664 size=6889 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=eeba6c37bb098970d1ecbf53aa32ecd3d161ca5ed52e6ca0d1e7280495f3082a
|
||||
pkg/govis/unvis_test.go type=file mode=0664 size=5302 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.424901009 sha512256digest=d995e7aa0846ab698cbd4b3ae0aa54d0b1bf628def1e76689ab2d908e4113097
|
||||
pkg/govis/vis.go type=file mode=0664 size=5034 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=4ff0d8874456bafff63d14227a56732fe8296993eb7ff827d2c3388174c7c040
|
||||
pkg/govis/vis_test.go type=file mode=0664 size=8862 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=b93c8a5d205abb50a8bda7ed9101011856d664d3abee187a8d223ccfaf0bce32
|
||||
releases.md type=file mode=0664 size=422 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=67b517b1725f58d3f5680d33f303825d15e651df6644f7ebfc7f8c6822069c82
|
||||
stat_unix.go type=file mode=0664 size=311 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=031b6589306025dde40c3bc9502bd8e01900550ded8f63a92ee2d1dbeefcb6d8
|
||||
stat_windows.go type=file mode=0664 size=177 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=5478d5912535771b76cfce0d4f8b6629d745cb4d7c76060b42f6ca9422da7307
|
||||
tar.go type=file mode=0664 size=12908 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=6e108ec0cce2c4845db2280aa0e800ced879a9263a91d5bb9d1c346386e58cfc
|
||||
tar_test.go type=file mode=0664 size=9332 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=5da79852086430337df7f87266e290d4888dc78a39e139d38a4bc96957bd9b5b
|
||||
test type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004
|
||||
test/cli type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004
|
||||
test/cli/0001.sh type=file mode=0664 size=1340 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=7c78b4d73ec17dbf77a1af6903fe2347fc3841f7dbb15cbd6a1bbc8b133350b3
|
||||
test/cli/0002.sh type=file mode=0664 size=614 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=1ef56e3423025f1eb7bbf965abd99399498cd5804c9983815bc13ca638336ca5
|
||||
test/cli/0003.sh type=file mode=0664 size=995 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=e9dc80a37f6ffb633024b394c621cb7f49e06828400703bfd1044b4f6776921c
|
||||
test/cli/0004.sh type=file mode=0664 size=660 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=22fad78aa558af47ca5839966cb5d49320ee8fd23b7414e26d7871991a29fcd0
|
||||
test/cli/0005.sh type=file mode=0664 size=440 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=e9a705d3fb58f37655070a29749c955d89c5f5897d20df63e8703aa046285121
|
||||
test/cli/0006.sh type=file mode=0664 size=860 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=fe5c5b969ae47ebf00855cb163acd2ee8e73fd0ce4506aab74315b1aecf8ddda
|
||||
test/cli/0007.sh type=file mode=0664 size=454 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=cedf7d50bd3d774d5d286148ac363e548e1b2bc39718cc3775c1e5018b196baf
|
||||
test/cli/0008.sh type=file mode=0664 size=562 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=1f0947e3f92c24a607c91d8e6bc4ca7a5d919fe860f5a8759b40fe966302ef16
|
||||
test/cli/0009.sh type=file mode=0664 size=1683 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=31ced90180929e0bb3297b196cd927644038e9c446d8fe85e6ceafa839264abe
|
||||
test/cli.go type=file mode=0664 size=508 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=7058ca6366fdf79c23531a4b4cb22bef2dc6de24ba0ef08ac9fd5ef4974341ab
|
||||
testdata type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513088963.690901011
|
||||
testdata/collection type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir1 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir1/file1 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/collection/dir2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir2/file2 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/collection/dir3 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir3/file3 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/collection/dir4 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir4/file4 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/collection/dir5 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir5/dir6 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir5/dir6/dir7 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/collection/dir5/dir6/dir7/lonelyfile type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/collection/file1 type=file mode=0664 size=3 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=f1015369e7da404777803c72d48afdbe3a0d1bd2c5feb2a9d5b3db5ac78e9b9c
|
||||
testdata/collection/file2 type=file mode=0664 size=6 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=7f3f0c0d5219f51459578305ed2bbc198588758da85d08024c79c1195d1cd611
|
||||
testdata/collection/file3 type=file mode=0664 size=12 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=1b88acd5ac9d970535991a5fbfbe6c1c5ca3434cea31cd8f9fc7de83e798e678
|
||||
testdata/collection.tar type=file mode=0664 size=10240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.425901004 sha512256digest=9d5eed555694f1de43a60a1f5b282d0e63b20edda06cbd10430edde8b74803ad
|
||||
testdata/dirwithbrokenlink type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/\040file\040with\040spaces\040 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/deepdir type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/deepfile type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/dir5 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/dir5/dir6 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/dir5/dir6/deeperfile type=file mode=0664 size=19 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=b3b48f5ca2cfd0f9426432fbaaedb57ad2750b1bfe3235c712098e8953b96fbb
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/dir5/dir7 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/dir4/dir5/dir7/deeperfile type=file mode=0664 size=15 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c2c4f516ee9fef3b2ecf1e2aba9c3f4d4d793d5b7140532da6ba5468f69a5f4f
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/file type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/file6 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/deepdir/dir3/file7 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/deepdir/this_is_a_file type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/dir1 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/dir1/.hiddenfile type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/dir1/badlink type=link mode=0777 link=badfile uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/dir1/dir2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/dir1/dir2/.hidden type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/dir1/dir2/.hidden/goodlink type=link mode=0777 link=../../goodfile uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999
|
||||
testdata/dirwithbrokenlink/dir1/goodfile type=file mode=0664 size=10 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=3b69a4f25d23a1a184f5d32e7d8a5a1e19f1062cefe57fd1ccc7dfd9c702fd8d
|
||||
testdata/dirwithbrokenlink/file1 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/dirwithbrokenlink/file2 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/hardlinks.tar type=file mode=0664 size=10240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.426900999 sha512256digest=33d43be8aa1f5ad9ff90ac2c3ba732f89de25fef7ee6cc6233bce2cf8e7b7a92
|
||||
testdata/singlefile type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993
|
||||
testdata/singlefile/dir2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993
|
||||
testdata/singlefile/dir2/dir3 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993
|
||||
testdata/singlefile/dir2/dir3/file type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/singlefile.tar type=file mode=0664 size=10240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993 sha512256digest=c06b6d2223c9a35951d9e6cbbaea9a46565ca3ae7bba1339051019681820a39c
|
||||
testdata/source.mtree type=file mode=0664 size=9110 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.427900993 sha512256digest=ae80aea4b907dcd2ac567a201f39694e18b0f6cef76f71a154f5581446f33945
|
||||
testdata/test.tar type=file mode=0664 size=20480 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=f5624efd93b66b7bd144bdb2a7dc1f0af833bbfd23f0691a671a53704e620a9b
|
||||
testdata/traversal type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988
|
||||
testdata/traversal/dir2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988
|
||||
testdata/traversal/dir2/dir3 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988
|
||||
testdata/traversal/dir2/dir3/actualdir1 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988
|
||||
testdata/traversal/dir2/dir3/actualdir1/file1 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/traversal/dir2/dir3/actualdir1/file2 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/traversal/dir2/dir3/actualdir2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988
|
||||
testdata/traversal/dir2/dir3/actualdir2/a type=file mode=0664 size=6 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=7f3f0c0d5219f51459578305ed2bbc198588758da85d08024c79c1195d1cd611
|
||||
testdata/traversal/dir2/dir3/actualdir2/b type=file mode=0664 size=4 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=9e591fb9c0c021fd8639eb5a44fa29e62835381c94cfd0d7db3ebef83fc2ce18
|
||||
testdata/traversal/dir2/dir3/actualdir2/c type=file mode=0664 size=12 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=1b88acd5ac9d970535991a5fbfbe6c1c5ca3434cea31cd8f9fc7de83e798e678
|
||||
testdata/traversal/dir2/dir3/file type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/traversal/dir2/dir3/file3 type=file mode=0664 size=0 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
|
||||
testdata/traversal.tar type=file mode=0664 size=10240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.428900988 sha512256digest=a69da7826437471c45c2ca6fad6860835ac2c5df5f652380bf316b2d0580a4aa
|
||||
testdata/xattr.casync-mtree type=file mode=0664 size=28672 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513089579.719898057 sha512256digest=d51e93315715b31a254cd21d1bb028bab6b9dec2653f4f7ba6557f89a7e5a153
|
||||
update.go type=file mode=0664 size=3865 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=f0bfc79f2f0dde387139117c6a1e5d5aa69c06aac233d53b0fc2be1e55cfba32
|
||||
update_linux_test.go type=file mode=0664 size=2330 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=c708daffa3d4c4869df009891af3c18a9b6ba6b200a28bed45b567b116dd117a
|
||||
update_test.go type=file mode=0664 size=2848 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=b5e0093cecd9f799fbebd651a3c63b159079bd86e31e02b1329078f78dd7219b
|
||||
updatefuncs.go type=file mode=0664 size=5049 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=b8a066b3544f745eb6233978f4322f9da15e30e9e009bcfd738a07f4ff12ef88
|
||||
updatefuncs_linux.go type=file mode=0664 size=391 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=de5d27e36de90d33f9efac533330f3cafb302cb1886ce63970107985dc2ab67b
|
||||
updatefuncs_unsupported.go type=file mode=0664 size=151 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=adec393ac2f40975877645a58fb43b01c5b94090f70bec2470b9b30efc9c821a
|
||||
vendor type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972
|
||||
vendor/github.com type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983
|
||||
vendor/github.com/sirupsen type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983
|
||||
vendor/github.com/sirupsen/logrus type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972
|
||||
vendor/github.com/sirupsen/logrus/.gitignore type=file mode=0664 size=7 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=004bbd91c2e11a52b6c11ef24a5c2578e653b9d25e60f28b077fb11b3b06af75
|
||||
vendor/github.com/sirupsen/logrus/.travis.yml type=file mode=0664 size=313 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=e7e6345826dfa1b3624659022f1e768ccfe3e9e16834dd8e7a443591fddc8ac5
|
||||
vendor/github.com/sirupsen/logrus/CHANGELOG.md type=file mode=0664 size=2509 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=49b7c9aec18b26e851c301f273001ddf6d6cefc3633b025b5391bcc88c4524f1
|
||||
vendor/github.com/sirupsen/logrus/LICENSE type=file mode=0664 size=1082 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=f163519149dc1ca924d74e9d228bee482ea4c939c89d7e9c53aa5c48b9e1bce5
|
||||
vendor/github.com/sirupsen/logrus/README.md type=file mode=0664 size=22063 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=29672a4ceb7a04cbb54b8c425d70d05bc2633597037bb8617259d74b0d381de5
|
||||
vendor/github.com/sirupsen/logrus/alt_exit.go type=file mode=0664 size=2246 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=707edd5510b2aa3780fcfd6fcf51471f5c9c9aee00b84814d1a6498847abe548
|
||||
vendor/github.com/sirupsen/logrus/alt_exit_test.go type=file mode=0664 size=1623 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=36cbdb077b1389d44178a47fa507c2acf008f4306785696ba8f6557ef9ef569e
|
||||
vendor/github.com/sirupsen/logrus/appveyor.yml type=file mode=0664 size=281 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=ca5a031100d1f288ebf376a86f63c66ee092c560a569d8a43344b39ade7278b1
|
||||
vendor/github.com/sirupsen/logrus/doc.go type=file mode=0664 size=586 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=80339eeb074e45314d9e38ec03e08fa587124f713483bf96de4246f3e5742d3a
|
||||
vendor/github.com/sirupsen/logrus/entry.go type=file mode=0664 size=6963 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=42adbbdf08f60a86e7415f160a0d69c0507d8cef72de4f449d750f4174be819e
|
||||
vendor/github.com/sirupsen/logrus/entry_test.go type=file mode=0664 size=1459 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=a729abde18f325b18ca396e22598bd0f51ccc677624e7fc1d27a832b8ab96370
|
||||
vendor/github.com/sirupsen/logrus/example_basic_test.go type=file mode=0664 size=2042 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=c8ea083f4a98401602895fa178ea5b74acd1b32a70236ba2e361d97eb75372cb
|
||||
vendor/github.com/sirupsen/logrus/example_hook_test.go type=file mode=0664 size=1001 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.429900983 sha512256digest=195cffcc9c4483ce0e4920803cc8bb9924045d39807c7495979e658825ef6cf7
|
||||
vendor/github.com/sirupsen/logrus/exported.go type=file mode=0664 size=4880 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=e229a9b34fb85ae1920db8e421dba771d7128cdc6712838fb3876a212b5c504b
|
||||
vendor/github.com/sirupsen/logrus/formatter.go type=file mode=0664 size=1368 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=cc8189494c6cae97fbe5e7dde3c9e9dcde2d1d8398b28271264949173d6e58c7
|
||||
vendor/github.com/sirupsen/logrus/formatter_bench_test.go type=file mode=0664 size=2143 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=e4db7f602a583206c8d730a826d0766263b2ea28838c129af21a967ff197bbcc
|
||||
vendor/github.com/sirupsen/logrus/hook_test.go type=file mode=0664 size=2128 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=8e050faa00cf410935bc0f7191ab3a9635e276e9bb865163d6d6ece954009e8d
|
||||
vendor/github.com/sirupsen/logrus/hooks type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978
|
||||
vendor/github.com/sirupsen/logrus/hooks/syslog type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978
|
||||
vendor/github.com/sirupsen/logrus/hooks/syslog/README.md type=file mode=0664 size=926 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=7f829c411b7ba02a3a07c022eeb012198b7502f5d832a97e910e3fdd0b79cc31
|
||||
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go type=file mode=0664 size=1311 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=7237f9f92f9a7df0d434ca5186689a5a7334df38579e661db54037fd14af4128
|
||||
vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go type=file mode=0664 size=533 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=3d54002343235ab97738a8d2480bf9d602ac337951e62faac706456064d60ebe
|
||||
vendor/github.com/sirupsen/logrus/hooks/test type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978
|
||||
vendor/github.com/sirupsen/logrus/hooks/test/test.go type=file mode=0664 size=2096 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=0c4d6b7f985f366c427bca638347676dc3838c24f7aedc56b2e62df69156be1e
|
||||
vendor/github.com/sirupsen/logrus/hooks/test/test_test.go type=file mode=0664 size=907 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=9af8e14bec05237f73a048e3e77155315d223a8c5fb40d9c8e1f4602a743d2db
|
||||
vendor/github.com/sirupsen/logrus/hooks.go type=file mode=0664 size=1101 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=5708f971359b96da0b6d72189fe2d678b10048d3b023eadd7497b42d950ceb47
|
||||
vendor/github.com/sirupsen/logrus/json_formatter.go type=file mode=0664 size=1885 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=f049f1fb554fc95cae2a86a1103b1fdc098ac6cf1d65e41b62acb866fef18acd
|
||||
vendor/github.com/sirupsen/logrus/json_formatter_test.go type=file mode=0664 size=4492 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=fdb45612b177b289fd2e35d4dd8af009e167f8b9e01acc641f6d84100d084af8
|
||||
vendor/github.com/sirupsen/logrus/logger.go type=file mode=0664 size=7946 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=00b348ea5157129bdbab52c5bddad4f3d8895a7d7d83c173c1c53ab64a7b6b4f
|
||||
vendor/github.com/sirupsen/logrus/logger_bench_test.go type=file mode=0664 size=1344 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=ca5ccdae3164b30d0ed27ad002b60be443e459f0354b5f044b39e5644b8b118f
|
||||
vendor/github.com/sirupsen/logrus/logrus.go type=file mode=0664 size=3667 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=0a890ae067dc1c3f045787919c61d8297dc5b93834fcc39e8a30303b93acd680
|
||||
vendor/github.com/sirupsen/logrus/logrus_test.go type=file mode=0664 size=9160 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=2417c7d6f8397020046b12b868124cb22ea00456d60daceac1572f4593eed03d
|
||||
vendor/github.com/sirupsen/logrus/terminal_bsd.go type=file mode=0664 size=186 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=588ed9e26de1dc3f7de02f746a0975a292a54929183df26232f8181b91cd17b5
|
||||
vendor/github.com/sirupsen/logrus/terminal_linux.go type=file mode=0664 size=320 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=745de29db1cd82e46345904126f4175a05ba4d1646e40940f78fa5281a1c8a8b
|
||||
vendor/github.com/sirupsen/logrus/text_formatter.go type=file mode=0664 size=4349 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.430900978 sha512256digest=f8c203f7e13ee9ca132d07a29ae243105f3776b2a03a4c28170f9d43f97a56be
|
||||
vendor/github.com/sirupsen/logrus/text_formatter_test.go type=file mode=0664 size=3726 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=49dbdae1731e825fff63074bc1b92906bdb7a47db5c753b44bcd02cc7e918eba
|
||||
vendor/github.com/sirupsen/logrus/writer.go type=file mode=0664 size=1269 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=a40e7c61fc44d312f71d0fe7ffd07d79098909c9c2d121631205e2e7259e262e
|
||||
vendor/golang.org type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972
|
||||
vendor/golang.org/x type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/.gitattributes type=file mode=0664 size=345 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=121f311806f70b4e9278a7a7178bbb73cb8afc0ce20d6134f24cf6a9f637cf85
|
||||
vendor/golang.org/x/crypto/.gitignore type=file mode=0664 size=84 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=c1bc3cda1eb014d25dbebe52e50c7231f60762092811d111e2b60b2a847984d5
|
||||
vendor/golang.org/x/crypto/AUTHORS type=file mode=0664 size=173 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=2e6b61f243b5f5e42e480c2d4588f1538ff08617ce66c01e99589333d4199a2e
|
||||
vendor/golang.org/x/crypto/CONTRIBUTING.md type=file mode=0664 size=1031 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=9f99f8daf18ff8de732527ac23231c253c9800139002bf2b03250fce7372fdfb
|
||||
vendor/golang.org/x/crypto/CONTRIBUTORS type=file mode=0664 size=170 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=261a74c469ed7777fd933f3cd1544b351d162ad51d5cedb570aab4da0fbc62d7
|
||||
vendor/golang.org/x/crypto/LICENSE type=file mode=0664 size=1479 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=ea1cff0ac6655ef2801edc8f18ba083c7fae87b0fb0c542ea1d9628e46992f19
|
||||
vendor/golang.org/x/crypto/PATENTS type=file mode=0664 size=1303 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=2ea07f77ca1c22dc417acfa6942f0faf5f545f44bca4c9387dab0e6e5ca442af
|
||||
vendor/golang.org/x/crypto/README type=file mode=0664 size=145 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=0ac9ce2faeed2023c29348f068fab8049c29403430d37a0be5132b0bf762f8b9
|
||||
vendor/golang.org/x/crypto/bcrypt type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972
|
||||
vendor/golang.org/x/crypto/bcrypt/base64.go type=file mode=0664 size=817 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=44021e633e2cb964c43373d30380f1efacf8b115a5e3419697a3decd3d1e336a
|
||||
vendor/golang.org/x/crypto/bcrypt/bcrypt.go type=file mode=0664 size=7880 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=ddd672a8e6874c38ea15edc4b962e0a3ede43e090ef7f6f8199c6a0c7d37400d
|
||||
vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go type=file mode=0664 size=6372 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=cd047b3a9a3d46c20774c10439572842c6270dcd7d48ee8c5fae8e12ce15491a
|
||||
vendor/golang.org/x/crypto/blowfish type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972
|
||||
vendor/golang.org/x/crypto/blowfish/block.go type=file mode=0664 size=6161 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=895b2605173026d2a411c25bdcacaec1793d31d5d5cdd84c4126a1887b47f058
|
||||
vendor/golang.org/x/crypto/blowfish/blowfish_test.go type=file mode=0664 size=10197 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=3683841d3b3eb3fc63fa79353f94a889e19e32b08c3b9e04e20e60c0f628717b
|
||||
vendor/golang.org/x/crypto/blowfish/cipher.go type=file mode=0664 size=3109 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=c99ed894413ef3a4fed02a8f0cf6606bbd7975e93b956f60b05adb435c250d87
|
||||
vendor/golang.org/x/crypto/blowfish/const.go type=file mode=0664 size=13131 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.431900972 sha512256digest=496b0f019d93c6bd67e526f7fe118619e2b7a1c7c308476d057c71776b1a22fc
|
||||
vendor/golang.org/x/crypto/bn256 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967
|
||||
vendor/golang.org/x/crypto/bn256/bn256.go type=file mode=0664 size=9621 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=9ff55812c49b84d5f07c63259b6ff6a5dce62ccd66d3e6b7f791995e8311054b
|
||||
vendor/golang.org/x/crypto/bn256/bn256_test.go type=file mode=0664 size=6696 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=a93b06fb3af2e227c99a7e2132e173de17e33343aa14d1343322276976966cb5
|
||||
vendor/golang.org/x/crypto/bn256/constants.go type=file mode=0664 size=2472 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=5df09cc395bc759610a4e8b135f77a27026160cdb7b8c878b27763efc4fb3c7d
|
||||
vendor/golang.org/x/crypto/bn256/curve.go type=file mode=0664 size=5477 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=e71600cb0f39d7fbad38eee3baee48eba90e223592846634b483d68a5d38b992
|
||||
vendor/golang.org/x/crypto/bn256/example_test.go type=file mode=0664 size=1163 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=69a4f1428227126eb577faff064fb8cbf2226598523e21306cf09252931030ee
|
||||
vendor/golang.org/x/crypto/bn256/gfp12.go type=file mode=0664 size=3645 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=2e0c360c93c85f2caeb396a3b886524c9e0be65a0eb7123b5acd07131d6bf2c1
|
||||
vendor/golang.org/x/crypto/bn256/gfp2.go type=file mode=0664 size=3792 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=911f33cfa4e32c62faa65ebe0af7b54edcbbfd50375209f14273fe35ce6a405f
|
||||
vendor/golang.org/x/crypto/bn256/gfp6.go type=file mode=0664 size=5777 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=e4b37174a01be9bbf18ef0b058452de8a733266fe2793e1dfe9967ddb0563515
|
||||
vendor/golang.org/x/crypto/bn256/optate.go type=file mode=0664 size=8667 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=06e551794879e82a39a69f2eb74844f55bd36d20924e3a7380d7be58c960a872
|
||||
vendor/golang.org/x/crypto/bn256/twist.go type=file mode=0664 size=5306 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=5f78e24a835bd60ebd5af4d556ac1108f4f361300d7069aa4d242c028fb76cb3
|
||||
vendor/golang.org/x/crypto/cast5 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967
|
||||
vendor/golang.org/x/crypto/cast5/cast5.go type=file mode=0664 size=32541 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=c36e5698d13994bd8e27e4b7a15ff063db1c1fd4b3fc4d86920958df9167a4f3
|
||||
vendor/golang.org/x/crypto/cast5/cast5_test.go type=file mode=0664 size=2624 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=6088d6e97f054dff9ce1480afae0b91aa248e73a48faf1c6acf210d2b8557098
|
||||
vendor/golang.org/x/crypto/curve25519 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/curve25519/const_amd64.s type=file mode=0664 size=597 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=8d7059b5263f3e64abb06e8e1d4abf8315f2a0c16495e84f69424a2630721006
|
||||
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s type=file mode=0664 size=1541 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=37da1fbe15113a31497643b79165687a7e4163afc0ac0ea36c3d7628de7d3078
|
||||
vendor/golang.org/x/crypto/curve25519/curve25519.go type=file mode=0664 size=22032 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.432900967 sha512256digest=2e24c7ca245ecd4d9b656338a801c3fab5875b7dc8eb7f0ad14062346b077d4d
|
||||
vendor/golang.org/x/crypto/curve25519/curve25519_test.go type=file mode=0664 size=605 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=53ef3c52714a7c3f9901b53f22c6dd4b3691b6471a588e55e78105adb71b7b4c
|
||||
vendor/golang.org/x/crypto/curve25519/doc.go type=file mode=0664 size=1043 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=e668799e8efdfb7b1a0f706346ed658e36513bfbef63f7191b79f35b9e6475b3
|
||||
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s type=file mode=0664 size=1540 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=83cece5a83eff41c06d265e07de0c79b8cea0f0eba2a54c0c92980eb88cc241e
|
||||
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s type=file mode=0664 size=20422 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=2009f13488ed4b547210c86886f5dd840c15427d1067eb2d856b20e088430aa8
|
||||
vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go type=file mode=0664 size=5262 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=cdf4d03529d6a11d2cec2309fa920524a90f2c4fbb0eaeafdf396982fb30d32c
|
||||
vendor/golang.org/x/crypto/curve25519/mul_amd64.s type=file mode=0664 size=2869 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=8bb1581d8282d94dbf37983f7fa2778690fa9b37027404ead7efe8672b037d91
|
||||
vendor/golang.org/x/crypto/curve25519/square_amd64.s type=file mode=0664 size=2349 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=cc7355e0f4f3c1624276af40d2e100b7897510f2ae95be56a025df1a489a54ce
|
||||
vendor/golang.org/x/crypto/hkdf type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/hkdf/example_test.go type=file mode=0664 size=1498 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=e4044f70276a817e4595b1b5dd8bc89bb0764bc586c069d34c0f488418427b35
|
||||
vendor/golang.org/x/crypto/hkdf/hkdf.go type=file mode=0664 size=1837 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=10cc33ce4c7bcba4145bb235a8400564b4a632cfd081feede850100af33ac7af
|
||||
vendor/golang.org/x/crypto/hkdf/hkdf_test.go type=file mode=0664 size=10871 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=0aac96303c4b2e30ed07cc01d2d81e13c943454cad859a2265b6b5b94b03ad7c
|
||||
vendor/golang.org/x/crypto/md4 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/md4/md4.go type=file mode=0664 size=2124 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=198ecc800bb0b351aa4f2cdf2fb490c720038e7bed43c2b64f2e8e8fde22ca78
|
||||
vendor/golang.org/x/crypto/md4/md4_test.go type=file mode=0664 size=3307 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=95a1a27481451dadb75aa8418636ab99f59d42ea72bf7fd14a402dbb042b5d4f
|
||||
vendor/golang.org/x/crypto/md4/md4block.go type=file mode=0664 size=2036 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=5a7049b30a80f749120670f187e71f5affd5333f8d2d8d8c4e47b935c3e43463
|
||||
vendor/golang.org/x/crypto/nacl type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/nacl/box type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/nacl/box/box.go type=file mode=0664 size=3264 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=dd140b441292a6c700a07ed5ec5a97f0be88b863a067840c7cfc67c13cf80ce4
|
||||
vendor/golang.org/x/crypto/nacl/box/box_test.go type=file mode=0664 size=1904 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=1869dc20e30b0f6288c60b15c3cb896c1132f2303339f5d110e03bb6d0b75704
|
||||
vendor/golang.org/x/crypto/nacl/secretbox type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962
|
||||
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go type=file mode=0664 size=4747 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=44472e52cac37ba9fbc929e02cf9d130ded2ed1bb98feecb351c4c5d3b28262d
|
||||
vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go type=file mode=0664 size=2065 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.433900962 sha512256digest=8ce4c36c2bb550845f13ff92668e20bedb2be0025a8fb75c2530f618de9586ad
|
||||
vendor/golang.org/x/crypto/ocsp type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957
|
||||
vendor/golang.org/x/crypto/ocsp/ocsp.go type=file mode=0664 size=17554 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=f4e66e3d111b30cbdc478ca68b4ebe6640a97266559d91a652db2e9e93b4418f
|
||||
vendor/golang.org/x/crypto/ocsp/ocsp_test.go type=file mode=0664 size=23500 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=85e9086879f3109d028909b97fecab89c09dc1ed50cf421fe7522ca04e948c12
|
||||
vendor/golang.org/x/crypto/openpgp type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941
|
||||
vendor/golang.org/x/crypto/openpgp/armor type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957
|
||||
vendor/golang.org/x/crypto/openpgp/armor/armor.go type=file mode=0664 size=5026 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=fd714e357b5ef7bab37830118cbdefbbec8eb283913eaa5f24be348a3347dc27
|
||||
vendor/golang.org/x/crypto/openpgp/armor/armor_test.go type=file mode=0664 size=3102 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=e261040ae16f64903cde837945ad3a81474a3b72a0f7551f6318830a1044ac70
|
||||
vendor/golang.org/x/crypto/openpgp/armor/encode.go type=file mode=0664 size=3392 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=7266294573e174cfb78e571a00cbb3e8d2f91908b80730eb066b8c2c7d87d9dc
|
||||
vendor/golang.org/x/crypto/openpgp/canonical_text.go type=file mode=0664 size=1143 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=4a3bfa165a78aa099605613e2b520985dbda9500c1c5e4a73a27114ff07e7a25
|
||||
vendor/golang.org/x/crypto/openpgp/canonical_text_test.go type=file mode=0664 size=1202 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=e531fddb89427fdaa50f1f6b56d3651bae5a0317f1253a9d881c8eaa3112f4c3
|
||||
vendor/golang.org/x/crypto/openpgp/clearsign type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957
|
||||
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go type=file mode=0664 size=9457 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=9bbff408119e071e5769be5882fd381cc0c464e3508b09e947a87617abdca76e
|
||||
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go type=file mode=0664 size=6104 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=e381a011f4d710751cefd0f64cde30d8b275e82bf649c37b0bd67442f7f8c628
|
||||
vendor/golang.org/x/crypto/openpgp/elgamal type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957
|
||||
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go type=file mode=0664 size=3543 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=5c619abe82ea4d6b6e7533dabb23edfbf94b22502966883f302a8976aa089039
|
||||
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go type=file mode=0664 size=1589 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.434900957 sha512256digest=9cd4fe1b7d0d992d30a0657f238fcf0633d39df2dda7b80fdcbe5a415f90715f
|
||||
vendor/golang.org/x/crypto/openpgp/errors type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952
|
||||
vendor/golang.org/x/crypto/openpgp/errors/errors.go type=file mode=0664 size=1883 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=da67ae346387c702f5cf9276a898e59c023522a00b6ac0b7d892ed2c78becd2e
|
||||
vendor/golang.org/x/crypto/openpgp/keys.go type=file mode=0664 size=17806 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=1a56374663da077c59b9be83b06cc3f2dce34fc6d622d0a7e3fb028f9266d694
|
||||
vendor/golang.org/x/crypto/openpgp/keys_test.go type=file mode=0664 size=20358 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=2186d10ac7393e1d76ad96d270b79757a8d8653a232da9539218951f3cd827f8
|
||||
vendor/golang.org/x/crypto/openpgp/packet type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941
|
||||
vendor/golang.org/x/crypto/openpgp/packet/compressed.go type=file mode=0664 size=3289 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=adecbe682175746c0b3cc99301427af62feb7ff4d64c1ffc780811635e735a07
|
||||
vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go type=file mode=0664 size=897 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=05b50262a8d4c64c1eaa50c7af7b63f783040e5de10786767ef69964ef7cf3d7
|
||||
vendor/golang.org/x/crypto/openpgp/packet/config.go type=file mode=0664 size=2440 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=00a82226c5f090c6eeb281dc7d403ef738d223e8d524429ea7ae201ae0e06c75
|
||||
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go type=file mode=0664 size=5166 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=8bd50af79b58eb0b211111c59cb0a05723d9e0a08775536931402e55a65bc4ce
|
||||
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go type=file mode=0664 size=3564 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=080566cfe10ab282aefa8ade0388f647e0ef5d5711c531011981d28d0afafbdc
|
||||
vendor/golang.org/x/crypto/openpgp/packet/literal.go type=file mode=0664 size=1924 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=996ba9ab21f2be954d24293920637763ce51b7fbdd9c79bebebf275e8d934add
|
||||
vendor/golang.org/x/crypto/openpgp/packet/ocfb.go type=file mode=0664 size=3707 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=65ba916f7d9281cc8c03c6052c07e31e1843b7462cb37e750e5692d0ab669041
|
||||
vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go type=file mode=0664 size=1269 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=f8dcff932881b568ecc34f6e147b000182704f07b17658c4d1ed28d70cab81d8
|
||||
vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go type=file mode=0664 size=1778 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=9aed3906d54e5efe91f32aa2659de0776a71610411e5bb53d971c4a6cde29451
|
||||
vendor/golang.org/x/crypto/openpgp/packet/opaque.go type=file mode=0664 size=4094 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=64ae0e8f3c05a6a4e1c0fadc7a3dff3f61c0ac9a860d69b61a58dddad5717940
|
||||
vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go type=file mode=0664 size=2501 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=0cfc6c1af52fc37cc846e7e0cf6c010047282e11bd6582f6be5b8d60f9f1a34f
|
||||
vendor/golang.org/x/crypto/openpgp/packet/packet.go type=file mode=0664 size=13568 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.435900952 sha512256digest=148d34e2e129a6b5f5b14cbd1a2111647aef73c0305fe02f1518ba35efe16d6b
|
||||
vendor/golang.org/x/crypto/openpgp/packet/packet_test.go type=file mode=0664 size=6342 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=f5ddc5664c217d6edae5172fa5f6fdb40d8973577a87e00d2b5fc6ec4ebf69c4
|
||||
vendor/golang.org/x/crypto/openpgp/packet/private_key.go type=file mode=0664 size=6917 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=736844634714bbf73107bfd732e1da57111bb3ce218da32d917f1e839f3a73dd
|
||||
vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go type=file mode=0664 size=3102 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=2c0d6b7879839aaeb264bec35d1a82324ea63c8e54575466a715391690d8070f
|
||||
vendor/golang.org/x/crypto/openpgp/packet/public_key.go type=file mode=0664 size=19380 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=22d25c31bbc85b9835e712cb38204579c51f3e5e153f01e917aa7728eac7a469
|
||||
vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go type=file mode=0664 size=8170 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=a03f67f13a9237e6d15bbede91ccb84d06e82b2eb552a17fc6c72124c47be8b8
|
||||
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go type=file mode=0664 size=8001 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=a1e5e33772018db138a971699b329191c6911700bf8eb945f6402bbc09a39a46
|
||||
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go type=file mode=0664 size=2366 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=83569fd6889935de5cebace9ca2c9b7eabf7df08ec88857eb8b1fece963b5a08
|
||||
vendor/golang.org/x/crypto/openpgp/packet/reader.go type=file mode=0664 size=1508 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=381c0747bcda0beca356b8d0334ef78b463c04c8fcf1af17c020b475571174c3
|
||||
vendor/golang.org/x/crypto/openpgp/packet/signature.go type=file mode=0664 size=19847 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=00603958d0cc55177125789ff43f93bc859ae8dff577ae5d8610bcfab24ae2a2
|
||||
vendor/golang.org/x/crypto/openpgp/packet/signature_test.go type=file mode=0664 size=1625 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=50f7af45db15cb6b161743f87403fdbda207642de457eaaebae128c130550039
|
||||
vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go type=file mode=0664 size=3936 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=8b4ff517dc9c1736ea8ff0cfc75c27352cc559f58eb75cea9182d847ecb38b3b
|
||||
vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go type=file mode=0664 size=2768 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=eaa81e4b4060c33f827dfd606a74a66bd0650c72db23ee269d31da958ae454d2
|
||||
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go type=file mode=0664 size=4736 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=591057f74c8e6ddb10cdd376b4643cd9fdc24b6b6c1466319ff66274e1ad1463
|
||||
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go type=file mode=0664 size=2464 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=d3d0f9559db93771161657b268eafa6de1e10b28109735913755ee89d9fe717e
|
||||
vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go type=file mode=0664 size=7244 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.436900946 sha512256digest=1103b66704f3a5de5cddad6ffa2a2ee957e6392b9737676a87549cf1c212525b
|
||||
vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go type=file mode=0664 size=2811 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=c89d1f8b13174327621f0cbf286a71e67c6b31e1e2ac37c66b1c6269eb2d1835
|
||||
vendor/golang.org/x/crypto/openpgp/packet/userattribute.go type=file mode=0664 size=2534 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=1df2601d86a3a7445f056a6d0cefb98c8f3a4a195e359b69703fad3868d94460
|
||||
vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go type=file mode=0664 size=5873 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=9491f937bb41e35da2c67f9e4a3ac1c18b735d85d48494dfb3daebb2b2052b5c
|
||||
vendor/golang.org/x/crypto/openpgp/packet/userid.go type=file mode=0664 size=3518 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=a6a4cdb224eff2e9713b00d5f6d582a5ad0440ed9250a4983511bce2b4f5fc0e
|
||||
vendor/golang.org/x/crypto/openpgp/packet/userid_test.go type=file mode=0664 size=2308 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=3e8f041dc105a2d807bf2634e384ab814a778538f6d82d5af95b8b777ffddf68
|
||||
vendor/golang.org/x/crypto/openpgp/read.go type=file mode=0664 size=13011 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=4b42631372013dccdcf71ba38486d471c34488c38985e44e9abc4ce91a14e1ad
|
||||
vendor/golang.org/x/crypto/openpgp/read_test.go type=file mode=0664 size=35594 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=d28d4c839d61daa75ca7cb21b7875f84e61cadaa0840a088c1407eac8b5bafac
|
||||
vendor/golang.org/x/crypto/openpgp/s2k type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941
|
||||
vendor/golang.org/x/crypto/openpgp/s2k/s2k.go type=file mode=0664 size=7191 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=e605aac7209f947fac16b9dcf88bd439d84664b472976cda5ddcdaf738a83ab5
|
||||
vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go type=file mode=0664 size=3244 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=982e06de36758a70d17db7a1ac412ac30668e469372cc388b0374e537109ad16
|
||||
vendor/golang.org/x/crypto/openpgp/write.go type=file mode=0664 size=11569 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=0053b773963b78dc0202155677dc09906ef6e7bc1f70fc53935fd6e95c1cf1da
|
||||
vendor/golang.org/x/crypto/openpgp/write_test.go type=file mode=0664 size=5769 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=6452bddf4da69773644d31fccdfee40da8d70e35d4439947bd48732a7214a79f
|
||||
vendor/golang.org/x/crypto/otr type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936
|
||||
vendor/golang.org/x/crypto/otr/libotr_test_helper.c type=file mode=0664 size=5538 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.437900941 sha512256digest=4d83e23d963cb62e04f9939e1d4d347ef2bd70cc1fda8e6fa659fe8dee266e8a
|
||||
vendor/golang.org/x/crypto/otr/otr.go type=file mode=0664 size=35866 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=1726c522c18197e8cfa6052b1bfe54038faeca2fdb49a593c6edff446cd3ab2e
|
||||
vendor/golang.org/x/crypto/otr/otr_test.go type=file mode=0664 size=12128 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=8732ddf210b53102f7040b02ee3943215bcb3f69269874d4db5d1c0d86d40a45
|
||||
vendor/golang.org/x/crypto/otr/smp.go type=file mode=0664 size=11982 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=468f2cb9f1bf77631d1eb7c96bbc4a574bda0b38b8db41572db534a8ccf76ee7
|
||||
vendor/golang.org/x/crypto/pbkdf2 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936
|
||||
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go type=file mode=0664 size=2484 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=e4327789933349b342bc7e78ca8819563f51f6676095aacd1ab9e47e2b5b126e
|
||||
vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go type=file mode=0664 size=3261 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=b73297d2911a29e1ba5d8784c9dc17dd6dc6f8289fbe287e6d204a3714676982
|
||||
vendor/golang.org/x/crypto/poly1305 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936
|
||||
vendor/golang.org/x/crypto/poly1305/const_amd64.s type=file mode=0664 size=1585 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=868380bb86c6df5d26d1ac3d2875b093b18b8f88a9def5615d51da76e086c604
|
||||
vendor/golang.org/x/crypto/poly1305/poly1305.go type=file mode=0664 size=1280 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=374d648ea2f6c58d942ba38a88dc060d3aa484364383c36fbcab54e0fab8fd13
|
||||
vendor/golang.org/x/crypto/poly1305/poly1305_amd64.s type=file mode=0664 size=8501 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=d58606faf9490f1de48fa186129b1c6deada09b29807156fede97fa1b4411ad8
|
||||
vendor/golang.org/x/crypto/poly1305/poly1305_test.go type=file mode=0664 size=1548 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=7d5e1af6be7fe92af67f49b67e6677ec9b0f4b1e128e7312a5e101cefc683095
|
||||
vendor/golang.org/x/crypto/poly1305/sum_amd64.go type=file mode=0664 size=690 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=2a77e9768db8741fc9d523e2d35893c09167caca46a18312ad5e9d63dd77e0b9
|
||||
vendor/golang.org/x/crypto/poly1305/sum_ref.go type=file mode=0664 size=20830 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=9d61336ce2b45e30daa00573ffee77a7fb098dc6e195da6266b390dec067d6dd
|
||||
vendor/golang.org/x/crypto/ripemd160 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936
|
||||
vendor/golang.org/x/crypto/ripemd160/ripemd160.go type=file mode=0664 size=2476 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=eb2bffaae443aef72931d6bd212aecd0be13349f675b7e6f4f9800cde40e8bb1
|
||||
vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go type=file mode=0664 size=1791 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=10141ac7e5b05e08e4e1866646f7df2df55e9fe95f1dde32b106987d0b0b0480
|
||||
vendor/golang.org/x/crypto/ripemd160/ripemd160block.go type=file mode=0664 size=4257 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.438900936 sha512256digest=b9f1981e13546cc75bfb1db199fba960388718176950c5857508dc3a9fd8c997
|
||||
vendor/golang.org/x/crypto/salsa20 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931
|
||||
vendor/golang.org/x/crypto/salsa20/salsa type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go type=file mode=0664 size=4098 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=a08dc45427b8ff5b1f3ac216b4b7e21c6739afc2d0ae4d18a70a8f7cc8b6e352
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s type=file mode=0664 size=13929 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=ca7bc54db396ea5222791c76ba9a95572d09e91861aeb48664faa84ea346d53c
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go type=file mode=0664 size=4983 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=9825dfd3b0ccb54e5900e62595ac931ef987e7319aa19217edb7c1a473074ea4
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go type=file mode=0664 size=763 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=f551fd3a1a02b4f47a62fc7e2af30ac1b23dc49d6e8977f6f7bdf2dc1db9627d
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go type=file mode=0664 size=5752 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=d8b188cbf0ba29e6945f334b1103bb8b2e146cd4f82413208633c51006d4aca8
|
||||
vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go type=file mode=0664 size=1149 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=53026559296b4a3776bc81922b0c3fe5ef4e5835a0d62874b566108c2080a6e2
|
||||
vendor/golang.org/x/crypto/salsa20/salsa20.go type=file mode=0664 size=1919 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=2620142a4713ab1a21da3ff76edfe9c115cf2dc2db8307b9f208fa96f5280780
|
||||
vendor/golang.org/x/crypto/salsa20/salsa20_test.go type=file mode=0664 size=3771 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=6ff0e6274b13e84f03e7d96f745f5839b566d02a43b39a232cf430da682b852f
|
||||
vendor/golang.org/x/crypto/scrypt type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931
|
||||
vendor/golang.org/x/crypto/scrypt/scrypt.go type=file mode=0664 size=5866 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=47d016aa178d7e4195a8351dbe9015c26aac1b89a375ae5b98d15ea5f67b8b79
|
||||
vendor/golang.org/x/crypto/scrypt/scrypt_test.go type=file mode=0664 size=4455 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=ee694200743f2fd4bc26f4ae4368cbd307b49399d1e1e2c9bfe195e7ce296b4a
|
||||
vendor/golang.org/x/crypto/sha3 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925
|
||||
vendor/golang.org/x/crypto/sha3/doc.go type=file mode=0664 size=3190 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=af288b26f47e4f23bfd02a0e907315dfa4a60269189c640ef75ddaf2e5c5169f
|
||||
vendor/golang.org/x/crypto/sha3/hashes.go type=file mode=0664 size=1909 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=e292f93708072e3e09bb21049046c8e2edea434f6679eb85137c2835ed406b95
|
||||
vendor/golang.org/x/crypto/sha3/keccakf.go type=file mode=0664 size=9920 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=64ef19e0d0b7504d6123fcd375b7dd33394484ec73b26a7db785740bf79cc053
|
||||
vendor/golang.org/x/crypto/sha3/register.go type=file mode=0664 size=413 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=b73fb07d6b614529c74265aee400e404e973955e3bc979707061d6ebdb7c8b14
|
||||
vendor/golang.org/x/crypto/sha3/sha3.go type=file mode=0664 size=5821 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=5793dbb766e0ae6d54a40098e9cdfab28300525f6365431f7d36f6b32d43b265
|
||||
vendor/golang.org/x/crypto/sha3/sha3_test.go type=file mode=0664 size=8887 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=0d7139bbc4eff00afc1b5bbb940c8f42ce7eb660bbc4da7abb95443c9a5e8a33
|
||||
vendor/golang.org/x/crypto/sha3/shake.go type=file mode=0664 size=1847 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931 sha512256digest=3c48cd175445e52f95bfa9e874564bad0f548eaf57aafab2355f05bfbe535880
|
||||
vendor/golang.org/x/crypto/sha3/testdata type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.439900931
|
||||
vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate type=file mode=0664 size=521342 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=e1c6d2c9f1b72c3cb256ed89d792b5d45d9918b0be9167e18c087a1bea40a1c7
|
||||
vendor/golang.org/x/crypto/sha3/xor.go type=file mode=0664 size=397 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=e9715de8a4cb248f43844a9f7be46f108d63f4cc4b86da447359edec12721dda
|
||||
vendor/golang.org/x/crypto/sha3/xor_generic.go type=file mode=0664 size=680 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=929eb30da60b8fb2b8bad6fcb3576475f25f70fba1a0d6a8130a0fed732c54cc
|
||||
vendor/golang.org/x/crypto/sha3/xor_unaligned.go type=file mode=0664 size=1066 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=08f85fd66c354189243f1dc99c00282fb105b7e2b3d40055cc73a6f1382a66a2
|
||||
vendor/golang.org/x/crypto/ssh type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/ssh/agent type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920
|
||||
vendor/golang.org/x/crypto/ssh/agent/client.go type=file mode=0664 size=13381 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=f0cf9fec51893c03e7e4894c0bdb53e473e2190faf6956ab2d68b68c5c6c01ea
|
||||
vendor/golang.org/x/crypto/ssh/agent/client_test.go type=file mode=0664 size=6902 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.440900925 sha512256digest=a1e796a312222c67871b658d365d7820a0022dcff66a0998f2d2474c9e5ca814
|
||||
vendor/golang.org/x/crypto/ssh/agent/forward.go type=file mode=0664 size=2214 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=e631ebeaf66b3071580abd406bc662fb68d208557c0f95fe2d51529ac60db2ea
|
||||
vendor/golang.org/x/crypto/ssh/agent/keyring.go type=file mode=0664 size=3636 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=2850e7217bfe6a03a7579dbb8f431eb4a01d5bd5ff2bf00e297e730b330547a6
|
||||
vendor/golang.org/x/crypto/ssh/agent/server.go type=file mode=0664 size=4451 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=e02ea70abbb9b3f5ccf8fa80df2e8632611f1a595f51eff438bf78402e7fc0dc
|
||||
vendor/golang.org/x/crypto/ssh/agent/server_test.go type=file mode=0664 size=1646 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=eee9c87cd6b27f9815964bb42c034b60b465da7d2a75b583dcb33bec1e384155
|
||||
vendor/golang.org/x/crypto/ssh/agent/testdata_test.go type=file mode=0664 size=2223 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=ce5d6a9d303ce20d7db0cef98fc4fdf33e28029c10403be48c433eef1da48bfe
|
||||
vendor/golang.org/x/crypto/ssh/benchmark_test.go type=file mode=0664 size=2240 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=cacb493253628206c39e6971ba955347736f6770c13aa8e680f9321dfb165c14
|
||||
vendor/golang.org/x/crypto/ssh/buffer.go type=file mode=0664 size=2198 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=824c0c8e8f221a68a105bb08a3eb1c3d9f3849fe0485b571029e94c79133d7ed
|
||||
vendor/golang.org/x/crypto/ssh/buffer_test.go type=file mode=0664 size=2220 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=5ae9c9646f732ef5ec86e7d9768327e9f5e35e2c4fd1ae78373390de0131267e
|
||||
vendor/golang.org/x/crypto/ssh/certs.go type=file mode=0664 size=12773 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=5dddd8a2d3d212015434995d9d50279771cbcaf549a3531280b9acecc893bcd9
|
||||
vendor/golang.org/x/crypto/ssh/certs_test.go type=file mode=0664 size=4632 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=df67d08e8abee28ef6ec5e6886956559c6d283716b43da2a6d98ad47d64de277
|
||||
vendor/golang.org/x/crypto/ssh/channel.go type=file mode=0664 size=16003 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=5883b21db7cf6bac7544353fa856d4751e5b6ef7f6e6afb55947344cd2b74787
|
||||
vendor/golang.org/x/crypto/ssh/cipher.go type=file mode=0664 size=8992 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=1f9628e738d59032d159b67f2ce49feeec056f095bfe62b08e67c507c3a5ac26
|
||||
vendor/golang.org/x/crypto/ssh/cipher_test.go type=file mode=0664 size=1395 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=0179df5b60e6a8080e4b31a45e6f4345fb8f4dc8f4cee7bc9ae99826afeeb108
|
||||
vendor/golang.org/x/crypto/ssh/client.go type=file mode=0664 size=6054 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.441900920 sha512256digest=d30f0d102026bb78cb7d8013ae974c8fee1281d0f6b7270b18c76175ec7b9244
|
||||
vendor/golang.org/x/crypto/ssh/client_auth.go type=file mode=0664 size=11942 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=6914b2e6396f7ef7072783cbded541cae898eda0758a61e9667e0bfd62fe10ad
|
||||
vendor/golang.org/x/crypto/ssh/client_auth_test.go type=file mode=0664 size=10085 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=d7b67bfec3559ccb5d7a811da5567c44bea404a8dade62e10bca21f047785588
|
||||
vendor/golang.org/x/crypto/ssh/client_test.go type=file mode=0664 size=969 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=8271743ef8df9d930d98e895e3d65ab558d3c6c5203445f7bfb58c81a35ea031
|
||||
vendor/golang.org/x/crypto/ssh/common.go type=file mode=0664 size=9173 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=9a8f921bd96313452816683dc0d1b1974f3130275080df236369feb88e1f84f7
|
||||
vendor/golang.org/x/crypto/ssh/connection.go type=file mode=0664 size=3457 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=811635959bfe6c462844d501b5c9784a100ee99d9742a74989ccb7e88f5b98b1
|
||||
vendor/golang.org/x/crypto/ssh/doc.go type=file mode=0664 size=771 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=5ec367435a18dfdece2fea6f2ee3694bfb9d04724bfa745c9eb0fbc26114225e
|
||||
vendor/golang.org/x/crypto/ssh/example_test.go type=file mode=0664 size=5530 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=f822ecf3a659336d45e16e78ac296ff0e8e785443cd1f7f1d99e9ea1d01c6a9c
|
||||
vendor/golang.org/x/crypto/ssh/handshake.go type=file mode=0664 size=9852 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=fb21b28cab3bbfc6909905318125dd8c1f4107a8c3967d4e71ece7f7fbd47b11
|
||||
vendor/golang.org/x/crypto/ssh/handshake_test.go type=file mode=0664 size=7343 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=5597f84d0eaf571a593a2894a0ea4378d13b6deabf2e173bd351c2a6283500c9
|
||||
vendor/golang.org/x/crypto/ssh/kex.go type=file mode=0664 size=10119 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=54ff5406781208f812ebd48b5abd4830d607b7860b6805535a34f0cd7a12bdde
|
||||
vendor/golang.org/x/crypto/ssh/kex_test.go type=file mode=0664 size=1048 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.442900915 sha512256digest=0f699b3226d66922f91f1f61855e5ae8a13c35a364ef84dd296a8de0ce08ad0c
|
||||
vendor/golang.org/x/crypto/ssh/keys.go type=file mode=0664 size=15079 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=f0ff3e0127bb3dab71fbcd390d80147d3a58c02076d4a19387e04b293a985247
|
||||
vendor/golang.org/x/crypto/ssh/keys_test.go type=file mode=0664 size=8724 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=9c453fc0419b8e7d9e45b42e08958f7816a2671a5be4181a2a89c5391eaa1faa
|
||||
vendor/golang.org/x/crypto/ssh/mac.go type=file mode=0664 size=1088 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=1ec064847ffa0c8559d0fdc2427a7758800b7628721a6a27b5b0ca0fc281aa45
|
||||
vendor/golang.org/x/crypto/ssh/mempipe_test.go type=file mode=0664 size=2020 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=b5531caedc0a29970ab0b8b138b0da7452e8f548eafb86cb531a647e8e758dcc
|
||||
vendor/golang.org/x/crypto/ssh/messages.go type=file mode=0664 size=16798 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=2ca5a71322c6d54b3bce36c1f71b4432b5301ca0d8c264d0e9629437d87d6f27
|
||||
vendor/golang.org/x/crypto/ssh/messages_test.go type=file mode=0664 size=5236 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=54e422acfe5043cbd4e51bd0eaa8ac95a8c9316536d9fc2d3c4389957bfd6ba1
|
||||
vendor/golang.org/x/crypto/ssh/mux.go type=file mode=0664 size=7977 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=20cc881c08d1895a3726903e325f57b0a7a9f05173fef90f283c1bd952915558
|
||||
vendor/golang.org/x/crypto/ssh/mux_test.go type=file mode=0664 size=11321 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=a41bba8d62eee12dd424381fad56b20c7a19d90d027280a31199bdfcb0ad71ca
|
||||
vendor/golang.org/x/crypto/ssh/server.go type=file mode=0664 size=14515 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=510d9f14aa556c282c776ef8208b4bfe587cd3a5382bc8554ae2e9b024f004f2
|
||||
vendor/golang.org/x/crypto/ssh/session.go type=file mode=0664 size=14236 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.443900909 sha512256digest=d25a238f4a7a1c572ff862572dc714cb8e880c88ee5d762a36f2e22d59354d57
|
||||
vendor/golang.org/x/crypto/ssh/session_test.go type=file mode=0664 size=17398 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=2e6dff4f32b5894c0fcac7f1fcf98f99a892189149fab6693d627a3462f088e2
|
||||
vendor/golang.org/x/crypto/ssh/tcpip.go type=file mode=0664 size=10469 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=e254e27950bf25e48b6181acabe242942cb89eac6968b910e5ce8a09a42a7253
|
||||
vendor/golang.org/x/crypto/ssh/tcpip_test.go type=file mode=0664 size=496 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=8d5211a3008ca53f120be7988d5f15071a96a968db72d21a9304e9ddc0b1a9d8
|
||||
vendor/golang.org/x/crypto/ssh/terminal type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904
|
||||
vendor/golang.org/x/crypto/ssh/terminal/terminal.go type=file mode=0664 size=20992 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=9da93725ad97cb0b7984fdec297dc30db5c8172a2b31ccc177cc74299fea822e
|
||||
vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go type=file mode=0664 size=5334 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=c9037e9bb9f3f70177437fcb09679e01916b3b83e33c0251d3cc3432bfecd8ae
|
||||
vendor/golang.org/x/crypto/ssh/terminal/util.go type=file mode=0664 size=4025 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=01d19c877d21a1ff519f6a056b3595a6bcfeb83f5cc03731344cb54aa6304cf2
|
||||
vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go type=file mode=0664 size=332 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=7bce0ed5ed05201c9a7ca18f5073473633730ac2d1bad9a12ff10fc3c7e92fa7
|
||||
vendor/golang.org/x/crypto/ssh/terminal/util_linux.go type=file mode=0664 size=457 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=82819f84cebea56c71d7c24967ebbd2bef70998637cc62ca3f6d5f35e6a762d8
|
||||
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go type=file mode=0664 size=4423 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=2b0d8fdaab4bbae108661eeb457f518bcf80d48cf67fb30cb9bae142c5aff17b
|
||||
vendor/golang.org/x/crypto/ssh/test type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904
|
||||
vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go type=file mode=0664 size=1271 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=bbbcefe888ef99fc65b74f91b65a7b096193333fdac3dcca2a90170b87f52756
|
||||
vendor/golang.org/x/crypto/ssh/test/cert_test.go type=file mode=0664 size=1096 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=8b54dbb9c3bcaec5e60f8cd236022e623dab8331018077779ceab532f43b5c87
|
||||
vendor/golang.org/x/crypto/ssh/test/doc.go type=file mode=0664 size=309 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=f76d97f2da6554ee7f72617707e38419f05b2a5527fcc7993a19b2f6d51939e2
|
||||
vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go type=file mode=0664 size=3297 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=fa6d2a1d93fbefd55d8179b63f22d7a9ab31d1f25fcf8da863e62199c7f6301a
|
||||
vendor/golang.org/x/crypto/ssh/test/session_test.go type=file mode=0664 size=7075 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=922e4fa0837c9c067eef33c6da1f36726bc9a761380e40a44625d6431c380f56
|
||||
vendor/golang.org/x/crypto/ssh/test/tcpip_test.go type=file mode=0664 size=791 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=5cbfc65be04f9191137589879bfc14350cbbfdd504642b08c37522472853a899
|
||||
vendor/golang.org/x/crypto/ssh/test/test_unix_test.go type=file mode=0664 size=5877 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=4e7660d40f097c87d9ab815a7bc2ea6bf2470fbd7a14f19c23244974408e5d16
|
||||
vendor/golang.org/x/crypto/ssh/test/testdata_test.go type=file mode=0664 size=2222 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.444900904 sha512256digest=d586900390d00c0c02cfac0cf2b32a371c7cc36ef6f0dea8023979ab154febec
|
||||
vendor/golang.org/x/crypto/ssh/testdata type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/ssh/testdata/doc.go type=file mode=0664 size=418 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=24b5b64697da8d1742f071127c836efe4a0a4834589b1c5bb376741d51478f10
|
||||
vendor/golang.org/x/crypto/ssh/testdata/keys.go type=file mode=0664 size=1916 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=19a366ead0a070dd9f01411b02b3fd6fdf4bed6b3ed613dd1665d6fe79afb675
|
||||
vendor/golang.org/x/crypto/ssh/testdata_test.go type=file mode=0664 size=2158 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=fac0ad360dd0f1a99bde8cb772ba9b906a66facddc6e18f8146444fc192fccaf
|
||||
vendor/golang.org/x/crypto/ssh/transport.go type=file mode=0664 size=8703 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=3ccccff7d8faf1623e75a548fda6517d0871cce2f82b15a0abb1cf4773684009
|
||||
vendor/golang.org/x/crypto/ssh/transport_test.go type=file mode=0664 size=2581 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=e128680809ae8ced7c8b5bd5e58aa4cc813f67c96b47737aec050376f37ea8e1
|
||||
vendor/golang.org/x/crypto/twofish type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/twofish/twofish.go type=file mode=0664 size=11966 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=36212f712cd64514191deafcb83cc0c03c98352e8a9e8d808318e41d1e6fffb4
|
||||
vendor/golang.org/x/crypto/twofish/twofish_test.go type=file mode=0664 size=4851 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=cacd3e89572a5f5ab2c981dbc3151b6cb7a29567e7de4a9c6a7d3635486f3224
|
||||
vendor/golang.org/x/crypto/xtea type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/xtea/block.go type=file mode=0664 size=1807 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=c34c9ca0e5e39db0ee2ca0b19278176979e8eaef082bd610e5c55bb1befb09bb
|
||||
vendor/golang.org/x/crypto/xtea/cipher.go type=file mode=0664 size=2436 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=77780a45a1a5a3fc72807552bd9ebc5e7d1bf8d34dafbe1c818c439f252c48ce
|
||||
vendor/golang.org/x/crypto/xtea/xtea_test.go type=file mode=0664 size=7417 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=eaf72d92ac9c3bd17af55ce576ab48641af2d4ef138231800f9daddc4ad298b4
|
||||
vendor/golang.org/x/crypto/xts type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899
|
||||
vendor/golang.org/x/crypto/xts/xts.go type=file mode=0664 size=4500 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=b13eeec77e4f1290c5a6819ced5dbc0a90499961fa3738441679450f064c5abf
|
||||
vendor/golang.org/x/crypto/xts/xts_test.go type=file mode=0664 size=8511 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=b03cbba79c93ad20dedd41dc2416634da95dafd4cb1fded45e37c1e72f43357f
|
||||
vendor/golang.org/x/sys type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783
|
||||
vendor/golang.org/x/sys/.gitattributes type=file mode=0664 size=345 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=121f311806f70b4e9278a7a7178bbb73cb8afc0ce20d6134f24cf6a9f637cf85
|
||||
vendor/golang.org/x/sys/.gitignore type=file mode=0664 size=84 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=c1bc3cda1eb014d25dbebe52e50c7231f60762092811d111e2b60b2a847984d5
|
||||
vendor/golang.org/x/sys/AUTHORS type=file mode=0664 size=173 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=2e6b61f243b5f5e42e480c2d4588f1538ff08617ce66c01e99589333d4199a2e
|
||||
vendor/golang.org/x/sys/CONTRIBUTING.md type=file mode=0664 size=1031 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.445900899 sha512256digest=9f99f8daf18ff8de732527ac23231c253c9800139002bf2b03250fce7372fdfb
|
||||
vendor/golang.org/x/sys/CONTRIBUTORS type=file mode=0664 size=170 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=261a74c469ed7777fd933f3cd1544b351d162ad51d5cedb570aab4da0fbc62d7
|
||||
vendor/golang.org/x/sys/LICENSE type=file mode=0664 size=1479 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=ea1cff0ac6655ef2801edc8f18ba083c7fae87b0fb0c542ea1d9628e46992f19
|
||||
vendor/golang.org/x/sys/PATENTS type=file mode=0664 size=1303 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=2ea07f77ca1c22dc417acfa6942f0faf5f545f44bca4c9387dab0e6e5ca442af
|
||||
vendor/golang.org/x/sys/README.md type=file mode=0664 size=628 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=4181c831648424320a2021eabe96ba5dd22b4ea951fe7adce5d5826ce05f005e
|
||||
vendor/golang.org/x/sys/codereview.cfg type=file mode=0664 size=21 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=6c7d6dcbcc4c211ab4c82aa98d2b61bf9c5fcbc72e607e6800eb85d3af3c6b1a
|
||||
vendor/golang.org/x/sys/plan9 type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888
|
||||
vendor/golang.org/x/sys/plan9/asm.s type=file mode=0664 size=215 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=5a3d197e8fabcda93134bcc11c5bdb171a6df3c4b01587cafb92b96cdcb4a8fa
|
||||
vendor/golang.org/x/sys/plan9/asm_plan9_386.s type=file mode=0664 size=702 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=22ba41e4bef8ee9849a1f995db164ffc5fa32e730923ce754017bcb35c4a063d
|
||||
vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s type=file mode=0664 size=704 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=f75d590eab0ea207a360d6d211053d4f4c0f968dc7cc7c11ae06cf82db367022
|
||||
vendor/golang.org/x/sys/plan9/const_plan9.go type=file mode=0664 size=1004 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=4dad6553dd157eedfe97742d095e19b018d9d184e0d9d8422380793a960e9082
|
||||
vendor/golang.org/x/sys/plan9/dir_plan9.go type=file mode=0664 size=5734 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=206de341d6fc697b39175f3a1e5075768c32a48c65e3f60245e006eceba5628d
|
||||
vendor/golang.org/x/sys/plan9/env_plan9.go type=file mode=0664 size=489 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=34cd7e466b514dc08f4d27b2013512251f922bd8f61f5061e5ffd2f5ceacd153
|
||||
vendor/golang.org/x/sys/plan9/env_unset.go type=file mode=0664 size=307 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=13fb763dd3caaa775e66ab434f8da4c08c31331246dee76ee1382682a7fd7f87
|
||||
vendor/golang.org/x/sys/plan9/errors_plan9.go type=file mode=0664 size=1566 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=3c668aec0f76b7f92911f18e86c8f92c4b441f64bdcf9fbefc452f0f6e4cca58
|
||||
vendor/golang.org/x/sys/plan9/mkall.sh type=file mode=0775 size=4168 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=cddd84a6e5b34f35544710f9c04ab57209bd82ff60ec62fed903a3f1864f302c
|
||||
vendor/golang.org/x/sys/plan9/mkerrors.sh type=file mode=0775 size=6072 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=e6e3e69647827ab44983cae89884bf4fea84cc834224f0f794fb305048d02923
|
||||
vendor/golang.org/x/sys/plan9/mksyscall.pl type=file mode=0775 size=8021 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=3b35c22a555900734ba4dde0a3d526429aef479e1b22c17a7da9937a8543d3ce
|
||||
vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh type=file mode=0775 size=459 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=e0d11c3df396de0fe85337441832431bf5d68d225a81663d89c11ac8aff0c1c8
|
||||
vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go type=file mode=0664 size=372 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=83789ed1a05a8a89640f3e2e3a34a5767db34c9cb67cd887d23d85328ba7ae2d
|
||||
vendor/golang.org/x/sys/plan9/pwd_plan9.go type=file mode=0664 size=412 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=21b0d0b25128d2f05ad887b3f2a36980b50c30659b7afb267d50ebdaf247f3e6
|
||||
vendor/golang.org/x/sys/plan9/race.go type=file mode=0664 size=584 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=55e9443d6e17a1fd16548deab237b97309181fc5d8178945c80e7fe31fc773bf
|
||||
vendor/golang.org/x/sys/plan9/race0.go type=file mode=0664 size=447 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=95d252584ca609d6c95dabf4e55f45b82eb1bbf4f8baf08dc101965282d38502
|
||||
vendor/golang.org/x/sys/plan9/str.go type=file mode=0664 size=499 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.446900894 sha512256digest=cb3e9d88c984ca1df8e389478d118fde3daf8bef24b899cd0c514681b775a014
|
||||
vendor/golang.org/x/sys/plan9/syscall.go type=file mode=0664 size=2532 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=29d56098a10fb715a78c7e721d917c997858b0522b7620b1fb715d87d58d99be
|
||||
vendor/golang.org/x/sys/plan9/syscall_plan9.go type=file mode=0664 size=7182 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=1f341831c56d56bc6b551697fd34c141bcc48c986bef9f5d95065fbbd4954d23
|
||||
vendor/golang.org/x/sys/plan9/syscall_test.go type=file mode=0664 size=782 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=801d44414ede88e0edd6d5aadbffb3e1c1bbf0064482362c16be80dbfd762829
|
||||
vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go type=file mode=0664 size=6539 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=754df0ad7ec30111f18c0dd6f25be38db868c018517b418fefbbb93aa8a2d131
|
||||
vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go type=file mode=0664 size=6539 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=754df0ad7ec30111f18c0dd6f25be38db868c018517b418fefbbb93aa8a2d131
|
||||
vendor/golang.org/x/sys/plan9/zsysnum_plan9.go type=file mode=0664 size=1057 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=98b81b36ae64287761f468dd265073d3ef00fbffd959c726cedae03dfc582c0e
|
||||
vendor/golang.org/x/sys/unix type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783
|
||||
vendor/golang.org/x/sys/unix/.gitignore type=file mode=0664 size=6 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=1793186c7cc109798a73b563d7e04d626a832a2de511b47b91adbe2ccac72cc9
|
||||
vendor/golang.org/x/sys/unix/README.md type=file mode=0664 size=8271 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=89d4796bb14f104b6b537db55d1227024b8a497f69c65732a91a603462cb9ad6
|
||||
vendor/golang.org/x/sys/unix/asm_darwin_386.s type=file mode=0664 size=675 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=726d7e55ddedbf9c6cf9bbcadd5aad631e81afd4b87d14a3f1ae0ef86e42d470
|
||||
vendor/golang.org/x/sys/unix/asm_darwin_amd64.s type=file mode=0664 size=678 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=ec946919220894a801322261a56193f02134dceb6f4e2d95e2bcada391802d99
|
||||
vendor/golang.org/x/sys/unix/asm_darwin_arm.s type=file mode=0664 size=686 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=aba41df4736ad5cf04990b4a69e385752b2e471823672fcd981b70bb0b5656a5
|
||||
vendor/golang.org/x/sys/unix/asm_darwin_arm64.s type=file mode=0664 size=691 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=f8e8e3e17de0dee99358680292805ffd69d3183ad00b73f5072c9225ab2b6227
|
||||
vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s type=file mode=0664 size=681 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=dd2e709a396b4b3673456d4b6e9f307b52e96d50c3663e7e0cef6890fd126262
|
||||
vendor/golang.org/x/sys/unix/asm_freebsd_386.s type=file mode=0664 size=676 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=170cf69100db944eb055beb7144c3e4b3a43012b661f5b587044085cb081f471
|
||||
vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s type=file mode=0664 size=679 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=74d959abf910b671bb9d5e96cf8fa1aeaf7ca256d30d33d1c1d2a99e4c2cb7e3
|
||||
vendor/golang.org/x/sys/unix/asm_freebsd_arm.s type=file mode=0664 size=666 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=0d34b34692ea2b2685ff9734874efe562d60eee613863ae1779c977a60b4f6c0
|
||||
vendor/golang.org/x/sys/unix/asm_linux_386.s type=file mode=0664 size=797 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=9428798ab945dacc931a7ae180a024024d09813dd25b504b8b7b4c602fe50f20
|
||||
vendor/golang.org/x/sys/unix/asm_linux_amd64.s type=file mode=0664 size=677 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=f67b38dcda396c7a22e2e8e01e0140dafb50d2cfc5192e024209a9072d9f85e4
|
||||
vendor/golang.org/x/sys/unix/asm_linux_arm.s type=file mode=0664 size=649 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.447900888 sha512256digest=b233d7ccf7cea17a8ac70792ddc90cc44de4c093ece28a24df58a443d01b0247
|
||||
vendor/golang.org/x/sys/unix/asm_linux_arm64.s type=file mode=0664 size=591 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=687a1f04da242234b2da964cff7760b8342a790714cea57ecf3f893eeb463a0d
|
||||
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s type=file mode=0664 size=650 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=24e16b2816b8d2c41175442855da8ecd128be257983c5b272fee02406c6a0645
|
||||
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s type=file mode=0664 size=706 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=eb204c30e3cd4d40bc2575a805f481723cb16d7ad1686bc6af26b45e837066c4
|
||||
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s type=file mode=0664 size=643 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=692e2be4962a6c6ff289b4a02d4060521a2a5a48db8a65be10df4f424b34e8ef
|
||||
vendor/golang.org/x/sys/unix/asm_linux_s390x.s type=file mode=0664 size=635 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=14dbb2e6754cef06aaef3eddc20eaaab03ed351676277dc89481fae30fb0a297
|
||||
vendor/golang.org/x/sys/unix/asm_netbsd_386.s type=file mode=0664 size=675 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=2c8fe2f54ba73c855e63cba8e1504a24e5ce227f8481476875a62e0201b74973
|
||||
vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s type=file mode=0664 size=678 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=28ce95cab4f28b2092414dd84a4585518bbcca9b9463f95f1b085ccfa53f58be
|
||||
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s type=file mode=0664 size=665 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=e8c0f5836faa5fd8f9fb2aa79e003a2b2b2da394005e6f290b813b9ed1dcd069
|
||||
vendor/golang.org/x/sys/unix/asm_openbsd_386.s type=file mode=0664 size=676 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=2941230ba6460c420d518a7e27ccac530b8b0d32ff30fe1ee8ab2a17fbb7f539
|
||||
vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s type=file mode=0664 size=679 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=57b818fcb687ce814d466ad5acd30521b6d7e10d5a911255fafd7653198ce31b
|
||||
vendor/golang.org/x/sys/unix/asm_openbsd_arm.s type=file mode=0664 size=666 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=dbd94d1bd5d04c7649ccf9707768f7d84289acd010d91a843c630865382fcd4a
|
||||
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s type=file mode=0664 size=426 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=3590238b4e35decd6b5711639be9c39f5695d5c9ef80066d5cdd9b381ceae9e0
|
||||
vendor/golang.org/x/sys/unix/bluetooth_linux.go type=file mode=0664 size=655 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=1030f9b73bad872abc822c99c2108640448b1f7c03cb3db7bf4b2f789b889880
|
||||
vendor/golang.org/x/sys/unix/cap_freebsd.go type=file mode=0664 size=5182 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=ae588894492046820482fd5f96d17df2ee54f4d8017d35288fa738c09312c17c
|
||||
vendor/golang.org/x/sys/unix/constants.go type=file mode=0664 size=285 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=226650163c679eb604fefed06d54064935afa764d1c71b176d357410137538de
|
||||
vendor/golang.org/x/sys/unix/creds_test.go type=file mode=0664 size=3321 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=a3a20f89c28e87d8177d8d36e5d90f81bfd74a5e4e8478a2428d69c41f911fe5
|
||||
vendor/golang.org/x/sys/unix/dev_darwin.go type=file mode=0664 size=747 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=cdfe857262a7bd5392c46560ca6053aa5ec3598a48bc23fac45b157a743ea1a2
|
||||
vendor/golang.org/x/sys/unix/dev_darwin_test.go type=file mode=0664 size=1314 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=b9960e3cd2a6250876c8085444bfd614ccd0c8b7685ad119613ffd59c58df9e4
|
||||
vendor/golang.org/x/sys/unix/dev_dragonfly.go type=file mode=0664 size=1030 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=d22f6b9fb00bba13993cb6a509063a08bfe1a50dbb87d7ae9a0e176c0e5d85a8
|
||||
vendor/golang.org/x/sys/unix/dev_dragonfly_test.go type=file mode=0664 size=1302 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=6aaa03562474c04427fbd3e2f4100c8a7a8407d98315331bea0b4c4111f6826d
|
||||
vendor/golang.org/x/sys/unix/dev_freebsd.go type=file mode=0664 size=1013 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=6cc8187f528496d2b80427f63870b4815411c93d38032b8234b5d0f14f44e9c1
|
||||
vendor/golang.org/x/sys/unix/dev_linux.go type=file mode=0664 size=1579 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=a494207bd423324ebc0da5715705ed36316826f1b438a373895e7238965b6af0
|
||||
vendor/golang.org/x/sys/unix/dev_linux_test.go type=file mode=0664 size=1381 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=6d237daeea888bacd345b866e8fec3a01681917c9939b2627039bbd1512a3a20
|
||||
vendor/golang.org/x/sys/unix/dev_netbsd.go type=file mode=0664 size=913 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=31f2d12ec605526c215bb1e4ef33493edce83d85465e4f8eb124180e9aaa62b1
|
||||
vendor/golang.org/x/sys/unix/dev_netbsd_test.go type=file mode=0664 size=1303 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=7d0f5c5a0ccec8fca4db6c881d8a2bce2e9d6b9946622dff603fa31ccd4350bd
|
||||
vendor/golang.org/x/sys/unix/dev_openbsd.go type=file mode=0664 size=918 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=a7105d3970f060444f792032fa6abb1b665eaf16affe402f7104638924bf4586
|
||||
vendor/golang.org/x/sys/unix/dev_openbsd_test.go type=file mode=0664 size=1358 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=1550df1cd7ab5733ce3518c28543653cf038240a1d194496e96d5d11aaeab5ad
|
||||
vendor/golang.org/x/sys/unix/dev_solaris_test.go type=file mode=0664 size=1291 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.448900883 sha512256digest=5a4430134bbd0ac48b5be8b9e26b6e1c33af7f6945420269f0804f648bde78a8
|
||||
vendor/golang.org/x/sys/unix/dirent.go type=file mode=0664 size=3057 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=8d5d612436e8689fe1ef6ca7765dc222ed34fffba91695d297c1eefaba57e8c0
|
||||
vendor/golang.org/x/sys/unix/endian_big.go type=file mode=0664 size=236 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=98f588e96ba180389c63564ce258a1b28c994254efc8e9f0bcb4fc38e0b766ae
|
||||
vendor/golang.org/x/sys/unix/endian_little.go type=file mode=0664 size=266 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=44e5449191c33c3c060922c3b22bf4acb42e3f69cf2e69b1636d75cf7176e2a8
|
||||
vendor/golang.org/x/sys/unix/env_unix.go type=file mode=0664 size=546 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=661bcc5bd8869a15493c501d7ec418c1ac284104b88bff972791a46dee7da169
|
||||
vendor/golang.org/x/sys/unix/env_unset.go type=file mode=0664 size=306 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=9226f64ef3bfd65d64b7429cee4e005217b7394986f9437e835215a61d75b0d3
|
||||
vendor/golang.org/x/sys/unix/errors_freebsd_386.go type=file mode=0664 size=9407 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.449900878 sha512256digest=6fc461195892bfb1d33962525df409b3146510bfb15c08dcf3b0d80fe092f866
|
||||
vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go type=file mode=0664 size=9407 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.450900873 sha512256digest=f692cb9906d464200afc73286693be255103c3d678c95b5c56e8053392aa310f
|
||||
vendor/golang.org/x/sys/unix/errors_freebsd_arm.go type=file mode=0664 size=9037 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=54ce31d5caa959c92c18969837a4f7a3367022dc2737a252ca40e03cc69b8e96
|
||||
vendor/golang.org/x/sys/unix/export_test.go type=file mode=0664 size=256 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=2d27fd7d03cb3f04853298cbb97c38c7f091e13d66ab125a06bf9a1af04d501c
|
||||
vendor/golang.org/x/sys/unix/file_unix.go type=file mode=0664 size=614 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=09f51f620292bf32fc719e0b5dfba865bb21fdfe616ecfa1f657deb4b89b01d5
|
||||
vendor/golang.org/x/sys/unix/flock.go type=file mode=0664 size=695 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=6f8716b07a762d2fec17e039d151c696f79a2ff785b869876225e49dd4f7fecd
|
||||
vendor/golang.org/x/sys/unix/flock_linux_32bit.go type=file mode=0664 size=388 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=b70a7ed1969b483abd3092542c733e49cfa438f5812355d46a1e79638cbf2ff0
|
||||
vendor/golang.org/x/sys/unix/gccgo.go type=file mode=0664 size=1541 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=5c4a055bb1739f79743979bcb1434756c8f88c999105d08efcabe721c09ae92d
|
||||
vendor/golang.org/x/sys/unix/gccgo_c.c type=file mode=0664 size=1014 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=d0cf40675ee3a585699e7b87b2f5226014a05b0ecafa0eafc118b76ed94460e4
|
||||
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go type=file mode=0664 size=430 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=4f17fad3cf09feab7b51390bc0d5658279e52eaf364c2f09d2a3cdf3d972bd93
|
||||
vendor/golang.org/x/sys/unix/linux type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867
|
||||
vendor/golang.org/x/sys/unix/linux/Dockerfile type=file mode=0664 size=2088 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=b1cdee4ca2e3c4ea900d74a214ccf9933459dadb8e77ea4dae2e1d9c989fccf5
|
||||
vendor/golang.org/x/sys/unix/linux/mkall.go type=file mode=0664 size=10396 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=f07d3398f2737c77d3eafabd67e123fbd67bd9f169aad1c510b768b1db56cddb
|
||||
vendor/golang.org/x/sys/unix/linux/mksysnum.pl type=file mode=0775 size=1988 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=7dc0702eb661cd3b34ff193a268efd1e5303874e27dbe98591b55003da9beae6
|
||||
vendor/golang.org/x/sys/unix/linux/types.go type=file mode=0664 size=15985 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=9e4e427155e5dc58c6befaa68306ccc5362d7ea4df2111b02695e784f4c62ebc
|
||||
vendor/golang.org/x/sys/unix/mkall.sh type=file mode=0775 size=6474 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=63dd2f0784095b4c8e034b4f77a0ebe2626402760fcddb56708aa4adbe669764
|
||||
vendor/golang.org/x/sys/unix/mkerrors.sh type=file mode=0775 size=13831 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=85fb5a9f405d302ae8bfb6b860216d2dde9f8ad1fccf7be90a27c54fe6fb28ac
|
||||
vendor/golang.org/x/sys/unix/mkpost.go type=file mode=0664 size=2631 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=f7503cd4d657be68ad4b27f072199a4922abcabd388bf913cf89fe372f55d0e9
|
||||
vendor/golang.org/x/sys/unix/mksyscall.pl type=file mode=0775 size=8238 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=615490be180ba5c249d5a058450f41ef2e313f9dc65101500300e42d5558ad11
|
||||
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl type=file mode=0775 size=7108 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=9c9819f91d9a011e9153f73da3f3274a3f9b0f3c6b39cc6e7eb4f6af198ec429
|
||||
vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl type=file mode=0775 size=5320 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=d4b831d026acb1140a375f8f372523f0c2e253e3cc90b31a78f3ab7830eadede
|
||||
vendor/golang.org/x/sys/unix/mksysnum_darwin.pl type=file mode=0775 size=751 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=914efb2614e12d6e0a4c84f90965acb3c95ab0cfd288ca1c5970c934f93837e7
|
||||
vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl type=file mode=0775 size=1039 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.451900867 sha512256digest=78d7f62dcb67c3cea6737b60f785320da2172ca5a9b991f65549e9d5492dfe50
|
||||
vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl type=file mode=0775 size=1041 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=e5b9363a3a8a7ae6226791d186ef18d7fd97f1688ec6cec6a2af999c8526bc75
|
||||
vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl type=file mode=0775 size=1227 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=94956e55a1dd70e86770e79d7f4d5b9d7f4f5b736d20985a1c2fa56d56ae987e
|
||||
vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl type=file mode=0775 size=1044 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=965e4c689cb205ff7751d8725876c27b5e28093e54df670fe3618b48de498fad
|
||||
vendor/golang.org/x/sys/unix/mmap_unix_test.go type=file mode=0664 size=844 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=be10e286da104abc70f545f80f2bdf0d55b813961e7e26dcbf1859a15fcef5f5
|
||||
vendor/golang.org/x/sys/unix/openbsd_pledge.go type=file mode=0664 size=889 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=80567386299b0a684ae97d442f0f6ad8bfc857278a789bd180d6227d0996519a
|
||||
vendor/golang.org/x/sys/unix/openbsd_test.go type=file mode=0664 size=2504 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=8068ce28ec3caa3b3fa253e3a189cd6606f3783c58b37ce64868dd3a7d1b2f41
|
||||
vendor/golang.org/x/sys/unix/pagesize_unix.go type=file mode=0664 size=364 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=4e6f8f46f385e2042e25990999224cdba1cc244ec3015a3e776f6e1c9d73875f
|
||||
vendor/golang.org/x/sys/unix/race.go type=file mode=0664 size=608 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=8dc91f6210f0e238fcaf7f86b553e934510ac6c75ce91bdd203d7676b328ebab
|
||||
vendor/golang.org/x/sys/unix/race0.go type=file mode=0664 size=506 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=96dd85162b94b9f524d30d2eff3bd2e54d4ed10d91f995aa1284c6f885646bb2
|
||||
vendor/golang.org/x/sys/unix/sockcmsg_linux.go type=file mode=0664 size=1072 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=bf0d5db8b7493fc034c430fcfb4766417e8e1a7508c5c61bf7328fd38d78319f
|
||||
vendor/golang.org/x/sys/unix/sockcmsg_unix.go type=file mode=0664 size=3004 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=7447109f9cbbb656603d308640c10ea9dc9a6624ac15505061bce0de01493237
|
||||
vendor/golang.org/x/sys/unix/str.go type=file mode=0664 size=611 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=e866bc1a11f3c577f6aabd7938872dbf41b1397616ce5bfb8909f638a0f71000
|
||||
vendor/golang.org/x/sys/unix/syscall.go type=file mode=0664 size=2473 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=105fcb77117a424f60f49b34dc5704af19cfea69c30a2028e5eae6694b91668e
|
||||
vendor/golang.org/x/sys/unix/syscall_bsd.go type=file mode=0664 size=16412 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=0e4d9ee5c5f6eb0439c12adf6f10acdca195b7cf98414142cac45ac3c182c22e
|
||||
vendor/golang.org/x/sys/unix/syscall_bsd_test.go type=file mode=0664 size=1303 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=19be54172834153be6b2c4f34e52b3d3f01ca4e61ab5c26da468b298e7f63aee
|
||||
vendor/golang.org/x/sys/unix/syscall_darwin.go type=file mode=0664 size=14402 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=ea6c694a516dc46df716e4766b8ae289007316201f95c4a3af14153b0c1d3068
|
||||
vendor/golang.org/x/sys/unix/syscall_darwin_386.go type=file mode=0664 size=1894 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=129cf0ea8786a9565e45c6fd26a8c3b403cdd35c3727c2549794c3570f8939b3
|
||||
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go type=file mode=0664 size=1842 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=9caa8d9d1f56fd7608ebf5f7155ab4627e8d39280e7a05a534ab83e1e34c7c4e
|
||||
vendor/golang.org/x/sys/unix/syscall_darwin_arm.go type=file mode=0664 size=1700 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=fbe3117680c808a16306792195dcd2c8800ec83f95abeef305e57e001f47a551
|
||||
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go type=file mode=0664 size=1849 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.452900862 sha512256digest=2ca5636a82e97bcae9513a7f8b22407347bff8db57ddb0c4fa62b9200d6901f6
|
||||
vendor/golang.org/x/sys/unix/syscall_dragonfly.go type=file mode=0664 size=10661 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=9fa9eb3d3bffd845f80e382fe2f7ae12cb6cb6335f15968b0264ed78ac87f59b
|
||||
vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go type=file mode=0664 size=1362 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=9b98e533283c20fdf289d378ed094a25d5d920177f4249be0e285b8790edf169
|
||||
vendor/golang.org/x/sys/unix/syscall_freebsd.go type=file mode=0664 size=18984 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=fa308081980b38bcae99d9336d68a57a5e405717a3fc3bf287e3d47466bf0eb7
|
||||
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go type=file mode=0664 size=1400 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=63e7a69c785d52d9971b56301bbd643ae25f15fe2714af0bba63d228f38ee2ec
|
||||
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go type=file mode=0664 size=1360 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=53165dacd7642909b00fac1562322f1f9c6dddfc4893d14d20202a4d0ea6c4ff
|
||||
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go type=file mode=0664 size=1379 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=7392bee062164a2c1c7a58c6e234e069b621e34e9526a75c375d52dd8061b581
|
||||
vendor/golang.org/x/sys/unix/syscall_freebsd_test.go type=file mode=0664 size=7071 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=83beba3058fbfcc62ee365664098affbd4026f62a9633995f43e1b319748507f
|
||||
vendor/golang.org/x/sys/unix/syscall_linux.go type=file mode=0664 size=42337 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=4a669a12101a434a4827c7beab6ff6dd69870dd02b51ed835401d1191e946a83
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_386.go type=file mode=0664 size=11026 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=f9292452892c5c9b530799d150410896293b71c5daaea8b9f730e596169e6626
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go type=file mode=0664 size=5238 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=eff154f2580f743e1deb3c5e772d990e588a112b77dcb2bf5e7cac6362570cb6
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go type=file mode=0664 size=297 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=2de31b70481346aa26eabefedd55c255d897057031f117dc67283126b1ca86f7
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_arm.go type=file mode=0664 size=7748 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=d4e69a5cdc3862c3b359cb7ae760f7bd1c040c7263e2c4923cbf19576aa83efc
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_arm64.go type=file mode=0664 size=6022 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=6b65045f06e4cd07588e93bf6192eefee02836a6df663ac607fa470c81b2f444
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go type=file mode=0664 size=6287 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.453900857 sha512256digest=af605829a33d9c4641f38da8eedf83bf470b81819a0ce7389da8f98fe76df2bd
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go type=file mode=0664 size=7022 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=67221ce149fa75aba755dca6b05c1e1851970bedc2a735a1e0ababf538781618
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go type=file mode=0664 size=4996 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=b237b58fd9d190e6dfb9bc3a1ef4146a01152953a419d0e25969f6a2098b0d51
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go type=file mode=0664 size=9951 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=f7435ad0eef255574c86faf1457d38d6c25cb6cf5b81c4d5d785666c473404ac
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go type=file mode=0664 size=5115 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=c85ef216ba3f9d8ed038f50d0be1ce5df683b940faa9bb042f2eee4c92abb75b
|
||||
vendor/golang.org/x/sys/unix/syscall_linux_test.go type=file mode=0664 size=4802 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=b2d63724d8ea6361a1dd883b846e088e812e7f6fb8bfb9fe8de85f549ac1306d
|
||||
vendor/golang.org/x/sys/unix/syscall_netbsd.go type=file mode=0664 size=11241 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=ac46c9fe0fbf79ac20f3efbe3c577a7b60f061b3606e99691dd2dc5d7720848a
|
||||
vendor/golang.org/x/sys/unix/syscall_netbsd_386.go type=file mode=0664 size=912 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=9da2c69933b98eb81fd581694d6588826320e336e140e4dd2c893abb8729c008
|
||||
vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go type=file mode=0664 size=914 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=3de21a18511954cacfe1ed2df2c8c5ef23c00c54cbd07a6d38c4ed4fdb92359c
|
||||
vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go type=file mode=0664 size=912 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=3b01b576d4646af34ecb3dcd731d8ce4f622770c9529292bc610a4a7d56898b0
|
||||
vendor/golang.org/x/sys/unix/syscall_no_getwd.go type=file mode=0664 size=301 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=9b650a395b572244827e9fb8f5f4b247b1ec8ac99aeb3168c88714daf0ee4263
|
||||
vendor/golang.org/x/sys/unix/syscall_openbsd.go type=file mode=0664 size=7605 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=c32af07cf02dac38ffda73c11e9bc700ad25f3fc5938c1dbda8edc5ec5d0b081
|
||||
vendor/golang.org/x/sys/unix/syscall_openbsd_386.go type=file mode=0664 size=912 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=c18a20eded970b5ade02f631d6ce778981d7813841227b952ea451b1aab7acff
|
||||
vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go type=file mode=0664 size=886 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=3aa8446604313927f241cd5bf15f3ba1976a2228f60c7d127eae1e31f61c78e2
|
||||
vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go type=file mode=0664 size=912 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=eabf9ae74565592ebcea748db2645a91ec5954fb9c002e59a83b1b985d35771e
|
||||
vendor/golang.org/x/sys/unix/syscall_solaris.go type=file mode=0664 size=20369 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=53d6595ad46ace1758496fe3de4a8fa9ae49567dd56735e6c34b664b504d355b
|
||||
vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go type=file mode=0664 size=842 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=dd5eebc32ff0c38d41738cdf9c968698370335d652d955f2e047a67fbbe8bdbb
|
||||
vendor/golang.org/x/sys/unix/syscall_solaris_test.go type=file mode=0664 size=692 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=47fc7b857f1b6cad4f89c30c2b9221bddeb588ed69562b5200484ccbd0f533ae
|
||||
vendor/golang.org/x/sys/unix/syscall_test.go type=file mode=0664 size=1085 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=e7f53a051857dc28a36968e80916fd51f3f7a5ec68128d73677de215823f835b
|
||||
vendor/golang.org/x/sys/unix/syscall_unix.go type=file mode=0664 size=6739 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=af6e0879d0339ccc0a682dddd82ba2d9a2723a4f7eef85c0d5db7ca365a91551
|
||||
vendor/golang.org/x/sys/unix/syscall_unix_gc.go type=file mode=0664 size=606 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=e26eb2003583c1b39b4bbf2cce40efd46186717cb76a1baefd7afb5cd1193e3b
|
||||
vendor/golang.org/x/sys/unix/syscall_unix_test.go type=file mode=0664 size=8586 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.454900852 sha512256digest=122d71e217d0bfe6d9902e6da38cb5f1cf883e92be9c6031d785f2739dcf61e4
|
||||
vendor/golang.org/x/sys/unix/types_darwin.go type=file mode=0664 size=5260 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=7db87818277ea2692e348fab5d2947c0024f641a0f4fabfc5e3d1f7e5f9110e4
|
||||
vendor/golang.org/x/sys/unix/types_dragonfly.go type=file mode=0664 size=5117 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=c458d5be72f8c2fab144ede0d57e32fde2d47784684e670a86216f93688ee8b1
|
||||
vendor/golang.org/x/sys/unix/types_freebsd.go type=file mode=0664 size=8237 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=519ceed197f54aaf2be3fec476cdb3368d49829b98edbdee499ee50a09a9713e
|
||||
vendor/golang.org/x/sys/unix/types_netbsd.go type=file mode=0664 size=4840 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=b8f297577459faccf04bfc7d6eefc2e194e7f7a9533df36d94bb3f0619f0b81e
|
||||
vendor/golang.org/x/sys/unix/types_openbsd.go type=file mode=0664 size=5110 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=7e50488eeeeef3677d374ee767a44d397092c8e08c22ef29b0d8584084524ec3
|
||||
vendor/golang.org/x/sys/unix/types_solaris.go type=file mode=0664 size=5518 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=f0247afd6cb889629d0911a0b723cff193f8a903975304a58a7d68430538d748
|
||||
vendor/golang.org/x/sys/unix/zerrors_darwin_386.go type=file mode=0664 size=68231 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=a33eab019d5ccca084ac0b47a2017b4c0afe182f95a73b1876af95d8a95a24fe
|
||||
vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go type=file mode=0664 size=68233 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=0b33099abaf9c17a4b503726242048d2ae0f9fead8c8a9e72a04433bfb517b20
|
||||
vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go type=file mode=0664 size=68221 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.455900846 sha512256digest=f3d204933352bb8b93397aa24b122b2295a6c630e81abe4c5c80eebf25ca3874
|
||||
vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go type=file mode=0664 size=68233 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.456900841 sha512256digest=632cab198b9b4221cd7f019baeeb51d669498c20459ce8f7c218fad29ee1431e
|
||||
vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go type=file mode=0664 size=63577 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.456900841 sha512256digest=274f5185e212d88c23c92211cdc1e6d21d33749cb66a6b11caf5247d0bba5146
|
||||
vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go type=file mode=0664 size=68239 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.456900841 sha512256digest=6370d1cbdbd2822263643ab854a6d778e535efe70b70eb7377daedaaf13dc17e
|
||||
vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go type=file mode=0664 size=68291 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.456900841 sha512256digest=688c406dcf94d3ef10362fdeaa70c2aba4173874608daa2f826e25a5494a59a3
|
||||
vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go type=file mode=0664 size=68597 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=4b0c8e80f9d02f5624f0d923d1ad736473e10a6253dd63300938c25c9a21a915
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_386.go type=file mode=0664 size=97027 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=a7644f0d89abe85929d9b559077b6e5195551cfe04fc4cac2bec5ee3608aebf9
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go type=file mode=0664 size=97065 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=c8cbc2603231f3031c1b088be5fd8d1f8a3053294b3fed96ff1d5270c41b64a8
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go type=file mode=0664 size=97251 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=f1df67cf7e1f51b6611c46c15cd2d5f0ccf52469845b949a6baac6074987d0c3
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go type=file mode=0664 size=96646 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=1e771c581c2bc2fbed8bd31ab565279316d1aff64e263f44f53e876f1335bc97
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go type=file mode=0664 size=97708 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.457900836 sha512256digest=e84e872372021ae4f68cad00bd733439277c2a0138cc52b72c7716295e94bedc
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go type=file mode=0664 size=97695 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=139793b02799b4dec2e8092dfdac401a811d2a584346d7609aa96b1b40c2c7b9
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go type=file mode=0664 size=97697 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=b761cc77d4df5ba0eeb09ad814eea95e60527384026fed2853c0ee8502863502
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go type=file mode=0664 size=97710 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=d103223fd93b4adbfec0112410433f152104a141e08af6a935db9b51be4a548b
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go type=file mode=0664 size=99998 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=56ed15af23a0dab5293d80829146e4ba4fe4e59bb03e51c62870e4830b07cbbb
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go type=file mode=0664 size=100000 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=bdcb442e3b0e2e10d775f68b1193440005ad6df5f72915167e32039f830b7c44
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go type=file mode=0664 size=99869 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=f45253fe17e10e54a854489b6f9639efd8bf6bf8bc3216518365ea55cfe637db
|
||||
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go type=file mode=0664 size=85936 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.458900830 sha512256digest=a828bcbef60831441c9cd00adf9eb3cc394215b1a3f54c662858f99a96ff595e
|
||||
vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go type=file mode=0664 size=70116 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=297a3d8d5122e49d512edac795448344a864fe7f37fa08173a7d582432ae5d46
|
||||
vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go type=file mode=0664 size=69698 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=89306c2c8bd2c274f8c8340ab22ca11a2a1fa287437ad2fc9de95948ca80757d
|
||||
vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go type=file mode=0664 size=69229 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=b39f894f1fa33682ce96ea3e6c2914761d08c7860a140e99174cbc7802b55eb4
|
||||
vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go type=file mode=0664 size=64910 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=74a535ae53c0705d19df8a24417d538779c7850692057fa19b7fe9565af6f6a1
|
||||
vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go type=file mode=0664 size=64866 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=7f688c7b98a03330fcdb9edb862f015debaaf1ac306daa0804c91fc81f8d2c45
|
||||
vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go type=file mode=0664 size=64986 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.459900825 sha512256digest=90f59fe6b5039b204ddf528a716edb62692fdf5ec14cee26e97907792e24c74e
|
||||
vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go type=file mode=0664 size=55962 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=7bc25fa518a08c9714731f10c67d5a5e27bc2eeb92cf558cd076f5210ed9e6db
|
||||
vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go type=file mode=0664 size=38195 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=443808e7c6eb58eba34b01052820d465a522c7b7d097f043617def471f1147fc
|
||||
vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go type=file mode=0664 size=38048 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=f1ecaa7daed979f46aaeaf6a1f28fd3eaf26cd4324996ef0373a7609b3cd26dd
|
||||
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go type=file mode=0664 size=38188 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=57153855d62f86ccf8a6d6db363331c6029eeabf464f09e7309e4664cf208b60
|
||||
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go type=file mode=0664 size=38048 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=853d6cda427e1498cfa5f78384f6b981aa6cfab2fe6de56182a304441986b063
|
||||
vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go type=file mode=0664 size=34135 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=f842c5256c4ff8b23f31ed27be09bc5dab493c2ecf6f7635f8afe760c4019ef7
|
||||
vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go type=file mode=0664 size=45674 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=435e7c5c2697ebd765574e0a23928170771f3d41f98ec8ce51da1b7483d84dfb
|
||||
vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go type=file mode=0664 size=45491 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=88b1a5d562da338b7cf49fc9e049732a4d908b20beb8e537c2b23c1aac3fb8f2
|
||||
vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go type=file mode=0664 size=45708 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.460900820 sha512256digest=a1ab37154ae91e251ec89abf2fa962a5e968dd6fbabc73df147362b264c23a9c
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go type=file mode=0664 size=47539 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=1d6cdaddbfbfff8cf0b91199d3279dd4fcc00ea02c567bb61d6644c874765ae8
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go type=file mode=0664 size=52740 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=0286f20cdd76406e013fd105e108ff24c5face6760b234dba6a16493f6c22e7a
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go type=file mode=0664 size=50716 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=7dcd28210157bce72c6d7a7d1714c01e0f56d3a295ee1d0b3df98cea3c30ff97
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go type=file mode=0664 size=49734 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=2fa70856a5f0e76b3f156e96396398d4369f5b9348622e24f69554460a1029af
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go type=file mode=0664 size=52082 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=d8dcbbadbb2520889bf68fb67090977f8ab5f7cc7043357411b58cdf2398933e
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go type=file mode=0664 size=51395 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=b199f9b6172da6b70229faa4b1a9fc7b6356f5fc5765263738c7cb05f6499198
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go type=file mode=0664 size=51399 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=f78c0195de90b72579c5d3465637111a74367eb75cd73c7a2a7514c45fa6c2eb
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go type=file mode=0664 size=52086 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=5ad282683095915c99a9e33447e18d07693a728f844f006d931c145e533b6bae
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go type=file mode=0664 size=52934 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=bc14c21964f5fd05c75bf0e9ebb0279a3fba9d66a37f41e3a5138e4437bf3d93
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go type=file mode=0664 size=52938 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=0f75dcb00c83a30131cb57e37e58b6a1f542c00a3fe6ea1e0b2b241f48fe61e8
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go type=file mode=0664 size=46874 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=b743a983a377d31a24a9ba7ef5d31354fc3527d4dce84e54cdedd03aadabefb4
|
||||
vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go type=file mode=0664 size=44728 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=f26dc211f14c4f8035b73612982dfd90834e1c09aa989de65154962758dd6ffe
|
||||
vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go type=file mode=0664 size=31891 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=af9cdf91fe2c36164de4fa3ed038f14038bec076fc54af956fa25ea77457f9bd
|
||||
vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go type=file mode=0664 size=31743 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=e8b00003195ca4250a18778ec1f0ae164656b837d962d994325f3677f7f4b9dc
|
||||
vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go type=file mode=0664 size=31896 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=fdd1119582f350c753b2e6e7540190ac30a8b54ebe10d622f25bd18ca80bbe1f
|
||||
vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go type=file mode=0664 size=33300 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.461900815 sha512256digest=af635b3c4882ea5048da47441941aa0b3242d0476d810125ec467697eff2f97b
|
||||
vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go type=file mode=0664 size=33152 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=3d9a34af2dd1e304e24a37ffa2488241c8afd94e5ca3f4e79622b87c56cd59f0
|
||||
vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go type=file mode=0664 size=33305 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=0faea38dd503903cad40a920c758c98f59f2ee4e4bb6a6beba6b1e801b454523
|
||||
vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go type=file mode=0664 size=44500 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=3be412f7aa291690f4e12b92d23d7cbfa6ef6fe5bfb036f005a084af067a9f83
|
||||
vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go type=file mode=0664 size=11986 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=a0c871c1d9e2b175b93338b07b244b2bb654e9cdb0aa387994718f254db61ff1
|
||||
vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go type=file mode=0664 size=11986 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=a0c871c1d9e2b175b93338b07b244b2bb654e9cdb0aa387994718f254db61ff1
|
||||
vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go type=file mode=0664 size=11986 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=a0c871c1d9e2b175b93338b07b244b2bb654e9cdb0aa387994718f254db61ff1
|
||||
vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go type=file mode=0664 size=16506 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=8bb84085428dfac3401a645f60f1aca81a630e1bd6522f3c53f71fd431f2f829
|
||||
vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go type=file mode=0664 size=16508 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=d9e8603cbdebe2f35133bb0fb2768d0ff5ce0f1f1d178990c2057fb320f0c49c
|
||||
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go type=file mode=0664 size=17697 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=983db0f2fe7a6f5922d2b4dd42f0cbc00a8a464e3b5ac8129d2b6089441a62e9
|
||||
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go type=file mode=0664 size=17699 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=72b479827976db9d5aebf663b48839db56fd41a94ffacf70376ee40059eae328
|
||||
vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go type=file mode=0664 size=24161 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.462900809 sha512256digest=c4db2065890efb27ea9db44a0ceab42791790c2e9e5bb4bdd74248f3943ff1c8
|
||||
vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go type=file mode=0664 size=25623 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=5befa2680b15e9981e291beee40a6c56011837762a178ccd2b84eab0cc2ac449
|
||||
vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go type=file mode=0664 size=25625 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=3bdaa06622d436e79530094aa65b7462bcbef6897aca55776c7c18a25bd6ba07
|
||||
vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go type=file mode=0664 size=25623 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=d04d1424746505e05e78a5155505691350370aed2ed6acab41b2b434f3709966
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_386.go type=file mode=0664 size=13047 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=384144a3c9d1c9f6dd219b109de7ccde43923991861e11021daf64bb27270aeb
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go type=file mode=0664 size=11417 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=4bdb0e2b3c39c24b57c48aee35723a44b46342e6c2a193b11642f831fcdbbb3c
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go type=file mode=0664 size=12117 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=ab9ab2be4786115536692e1431f393151dd3da1c846f555843feec037365132f
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go type=file mode=0664 size=9522 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.463900804 sha512256digest=696ef2e52734bce58c25268c45067ed77e483f66f7397cdfc340847af3d8556e
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go type=file mode=0664 size=13009 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=fb453ef4ada8f4892c1db1f43bf01cd5406f062ad86d9aa8aa54fb92f830a47d
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go type=file mode=0664 size=11611 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=5204b369474c7ba523004c70e5724e4c197e7eb3f727362fc20bd2aa93555fea
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go type=file mode=0664 size=11613 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=32a81f707bfc9d0a53455a1725777c513e375546750e856a999a4a0271194a94
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go type=file mode=0664 size=13011 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=336125faeb15c94f43be6da4e9fedcf2d7137e033a82673caf3323d134f8842e
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go type=file mode=0664 size=12364 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=9f9fe29f18a395d5da8074653f10edc4afe5765cc481ff7a156dee4de34340b0
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go type=file mode=0664 size=12366 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=e2c59480adfee1d1721f2da613118404f90db1fdcc7f80866c4e092ac90f7b35
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go type=file mode=0664 size=11153 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=3077e58a29f985f51fe6626aa80ee9b07183cbfd253ccd26d5555aeb50bb1dc8
|
||||
vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go type=file mode=0664 size=11627 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=8e3d19f3484b31cb0b74ce3065dc8a9b764bc1236dc107be1b0b1a746868d597
|
||||
vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go type=file mode=0664 size=26249 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.464900799 sha512256digest=84a1d3577ad9efbe15b119880e06e523ef4e5c165b7b3aa8ae04c466e40f95a2
|
||||
vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go type=file mode=0664 size=26251 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=e7605c55181ca00e586d289d1b9da3bbc33d91020ed62409daee31cd471b50fd
|
||||
vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go type=file mode=0664 size=26249 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=0f2f8b61509acb907b7cc465aea6f6e08a9929977f124ff438db5b4fabb1081e
|
||||
vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go type=file mode=0664 size=14343 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=d026eadf38e09541256531e745cd1a967315820ca65a65ecb16626f4603f2279
|
||||
vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go type=file mode=0664 size=14345 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=f11c85cbaff35c6e1b159e4ad8bbce97b11bbfe074ca7dceab0cf83f7eabefa2
|
||||
vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go type=file mode=0664 size=14801 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=b898bdbeb639b162a12137983f468c9d206799ae149d3dae992e641aeaca8de4
|
||||
vendor/golang.org/x/sys/unix/zsysnum_solaris_amd64.go type=file mode=0664 size=286 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=4b85545ec2b0afb73065697d583003bf81e69ea63a33bd7740c8e0511f046e53
|
||||
vendor/golang.org/x/sys/unix/ztypes_darwin_386.go type=file mode=0664 size=7088 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=69965aa975a8e17796805a7fbea4480658e444c273c7cc857023384a810518fe
|
||||
vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go type=file mode=0664 size=7303 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=5a735e0dc5d072c148be8660cd0f35511437e52f410bc708bb66f57993a1c3a3
|
||||
vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go type=file mode=0664 size=7106 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=04a311a5a756f9cbce2e5d33df4dc40ad1c8da5679ae31fb1ae3ba2a777cdfc2
|
||||
vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go type=file mode=0664 size=7255 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=d1c31d0c1156152e53536386e5d2edd89f0677dcfc9229a863203224cd1a8795
|
||||
vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go type=file mode=0664 size=6879 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=a17ace91aac6fde3b41b7926a0dbc2d01c4cff28bdc9d5bfa15259040d0aa8cd
|
||||
vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go type=file mode=0664 size=8383 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=8850b6f1b199085dcc3de01d287bacb6d3bdf5894a14ddbb0e6bed8745034ef7
|
||||
vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go type=file mode=0664 size=8468 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=d713c13a0c3e7d19262650e11d861acd2622a391b675060e192b229f110482d8
|
||||
vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go type=file mode=0664 size=8493 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.465900794 sha512256digest=322972bda83d28989ceeead12e68e8e4836cdaac34e6e86d3129877a497d5240
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_386.go type=file mode=0664 size=14896 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=94965019a6ce7f0b46f1296ec4098097ca3f1a7aee8f1ad4ef3aad3b32854949
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go type=file mode=0664 size=15241 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=d09df8d55f52d9eba83a7c567ac43e1193c262779d148b418494a78759925972
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go type=file mode=0664 size=14779 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=6815aa38db25fd7c3a1fed293155c5c4e366a846819acd66821ee93bc14dfe15
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go type=file mode=0664 size=14885 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=0934597c25d70bd1ce3a8e9e6d4106010ead862f02961b36ea2d7a2846cbeb50
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go type=file mode=0664 size=14824 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=aeff3c297f6dcc31b56500b2fa0f4d8cfce5b21c97fd0eb6e2bde5686b2c6a05
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go type=file mode=0664 size=14923 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=d25acc07a832ce49268a62b80d72cdf2d09b52443ff2146889d28b88f8972645
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go type=file mode=0664 size=14925 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=f5b23e69e3ef24e24f91cb3fafcac3352dbfe2f60c62d1ec9775b89a6ea7dae1
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go type=file mode=0664 size=14826 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=10e4781078ff4926592c06821be99cf8eacb59de85c56171912d4c3264b31d59
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go type=file mode=0664 size=15076 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=6fd0a0437c2332a23cfcd58d06cee89eb2ec66e66bf615897b1c6b249e393dfb
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go type=file mode=0664 size=15078 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=a75abe109b487b24cc01e9f1982c5671cfd3462a4875e8720bb7601a1cea1da6
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go type=file mode=0664 size=15353 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=a6d2c1f7c8ff1b70f58ba7a17c17eae4e44fc259eafab56102f8b0240d423360
|
||||
vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go type=file mode=0664 size=11442 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=9409f66d6e47bf33d1e8ddaf86f7f931f8dea3f091ab19540ab3c73dd28155e5
|
||||
vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go type=file mode=0664 size=6093 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=03965e5a6240c60f14cf6ecf63d7b1a34673ca7323aa6f0c90a0d2b2a9dccc66
|
||||
vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go type=file mode=0664 size=6279 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.466900789 sha512256digest=e5ed42e7b340581a58b038218a2bbe4c46d6ed672849205fb1bdb2116c8e1aca
|
||||
vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go type=file mode=0664 size=6238 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=ac531f076071cfe8cfa7d515fdb3bfef55358a24816a4c52021c9fcd6463fe3a
|
||||
vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go type=file mode=0664 size=6861 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=72ba3a6f0d9a00a37bb1ab4163b193d200bcc45943fdb783eeff98b6a54bd0b3
|
||||
vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go type=file mode=0664 size=7022 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=5766a6597832c64b111be726303f6a3a3261948b9d8cf67aae806a4c03c905fb
|
||||
vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go type=file mode=0664 size=6770 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=7d5aaa31bf85ff3eb5bd5d71c4ea8b31edfc361ef8d31c70d228aef328b1ece7
|
||||
vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go type=file mode=0664 size=6722 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=ffb709cf263ae56f2c67637b85c4a7c5b63d2acfc3fcfa007f98846a296835bd
|
||||
vendor/golang.org/x/sys/windows type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767
|
||||
vendor/golang.org/x/sys/windows/asm_windows_386.s type=file mode=0664 size=378 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=58d393e4c02842ed863c42538a6a2b8149b4957a0f7933e7dc0d50d98803c001
|
||||
vendor/golang.org/x/sys/windows/asm_windows_amd64.s type=file mode=0664 size=381 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=ba022694d8c21b99c77b61b21a2c25f36eed4180681d51c152e05c8fa200f852
|
||||
vendor/golang.org/x/sys/windows/dll_windows.go type=file mode=0664 size=11128 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=3520d5dad0515ac5d4a345a78fc64c24862f711c56265228046e25b5b4d455a9
|
||||
vendor/golang.org/x/sys/windows/env_unset.go type=file mode=0664 size=327 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=2973b09180689676b7ded3c4c8574fb88a3e35812f4cd1d115ec6551c690e5bb
|
||||
vendor/golang.org/x/sys/windows/env_windows.go type=file mode=0664 size=487 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=dd755498ee242619fcaa30f27afd53aa41245eddfbcc1df6c6b93c50f8f157c3
|
||||
vendor/golang.org/x/sys/windows/eventlog.go type=file mode=0664 size=824 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=a2f8a51099e77875823323aa622d46d972efc715c5652256488a5b31d6a646ac
|
||||
vendor/golang.org/x/sys/windows/exec_windows.go type=file mode=0664 size=1949 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=ed4923e4c075c4201ed62d12a915e7cad454ed431cac75d48d99daf75acbaa78
|
||||
vendor/golang.org/x/sys/windows/memory_windows.go type=file mode=0664 size=706 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=76cd0d0ffdd3978293f5fc1292ae25af7330e6ec2411c395ebe6541b66ea53cf
|
||||
vendor/golang.org/x/sys/windows/mksyscall.go type=file mode=0664 size=330 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=5c16a267d957527960bddf522ea5f5094ed02f04f3d0b3e6758f549857e59e16
|
||||
vendor/golang.org/x/sys/windows/race.go type=file mode=0664 size=588 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=f1320e01be7935bd2dd971edc95e8be8eda5fc34fdedb0719c3f9a4ed76d95b8
|
||||
vendor/golang.org/x/sys/windows/race0.go type=file mode=0664 size=451 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=809559ba2984e20400dab18202bf0405a5bc8806bb835e81af6625ad9c4fb1fc
|
||||
vendor/golang.org/x/sys/windows/registry type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778
|
||||
vendor/golang.org/x/sys/windows/registry/export_test.go type=file mode=0664 size=311 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=3ce47dd70187cde02063100515b4b23382a95cc3ba23ab925838c7c5e2bfb108
|
||||
vendor/golang.org/x/sys/windows/registry/key.go type=file mode=0664 size=6149 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=cf61d3cd1c5be251a0ff761e282b6b12582b8fcd119f3c76c56fbe43c9ea2bda
|
||||
vendor/golang.org/x/sys/windows/registry/mksyscall.go type=file mode=0664 size=279 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=fc241ec3bd3c3226e2b57b990c103c747bea998281d1150d8cb659ede8a53d43
|
||||
vendor/golang.org/x/sys/windows/registry/registry_test.go type=file mode=0664 size=21613 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.467900783 sha512256digest=ce43c79f6978a97c7e518a0b01da47077500bd82bc49ba8db93effd306476708
|
||||
vendor/golang.org/x/sys/windows/registry/syscall.go type=file mode=0664 size=1672 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=696b9d5331bb99d6bcd07a9d7901575cd7551ff17c22281b635dd7b5db764de0
|
||||
vendor/golang.org/x/sys/windows/registry/value.go type=file mode=0664 size=11659 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=cc3f5ec0613f4b19142d45df90ae671f76f37103d25b81a2e619179e992b9d9d
|
||||
vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go type=file mode=0664 size=4497 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=d83b6e21f7d505089d8dc0203f7a67e46f7b480253b0948abacafc066bfcb41c
|
||||
vendor/golang.org/x/sys/windows/security_windows.go type=file mode=0664 size=12717 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=5dbd8c3c6b49a23bcbc5c6cb9e178b8838817c89b1b2d55eee481a6636481748
|
||||
vendor/golang.org/x/sys/windows/service.go type=file mode=0664 size=6760 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=9f548a44ae665f1e2be6798cd0c08004705d9c24511d60579082725c762c4c75
|
||||
vendor/golang.org/x/sys/windows/str.go type=file mode=0664 size=503 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=6a1dd05563d1850a61182fc8abb2985a7139423cdc07bd3bb417925af804d8c1
|
||||
vendor/golang.org/x/sys/windows/svc type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773
|
||||
vendor/golang.org/x/sys/windows/svc/debug type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778
|
||||
vendor/golang.org/x/sys/windows/svc/debug/log.go type=file mode=0664 size=1434 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=36f6b32913126cce77be4bfe994f606c14aaf45aff421fe4fb8b0f5fe3e5d2dd
|
||||
vendor/golang.org/x/sys/windows/svc/debug/service.go type=file mode=0664 size=1013 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=d76bb6933e48c64b9573721547d7129e656b89221f80e07a2ef3748420bd6d3b
|
||||
vendor/golang.org/x/sys/windows/svc/event.go type=file mode=0664 size=979 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=94c5b43479f0a3201bf5ae95e326e1b96593dc0edf92f9e1100839e66f84d588
|
||||
vendor/golang.org/x/sys/windows/svc/eventlog type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778
|
||||
vendor/golang.org/x/sys/windows/svc/eventlog/install.go type=file mode=0664 size=2341 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=5cf5daa0e431195eb4350cfece36376a962b135f6ef1bae422517dc8ed6115c7
|
||||
vendor/golang.org/x/sys/windows/svc/eventlog/log.go type=file mode=0664 size=2041 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=8a504aca519496a4f5b79c5fa60fa8aac7fecf299c63716fdabd83ba213da53f
|
||||
vendor/golang.org/x/sys/windows/svc/eventlog/log_test.go type=file mode=0664 size=1061 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=c393876238b289f5d349ab32c307ba716ffc30f3e423eed5b6a15db3aa375c6d
|
||||
vendor/golang.org/x/sys/windows/svc/example type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773
|
||||
vendor/golang.org/x/sys/windows/svc/example/beep.go type=file mode=0664 size=477 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=b943a452e5d817683380ea39c7b8845d04928334ae8990ee80d2cf1d0980d5da
|
||||
vendor/golang.org/x/sys/windows/svc/example/install.go type=file mode=0664 size=1835 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=ae2446a0cfe3ac3ebcc68c7b3455f16fb4df626a98ceeae643f8102d59d16347
|
||||
vendor/golang.org/x/sys/windows/svc/example/main.go type=file mode=0664 size=1769 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.468900778 sha512256digest=3ce3c4e311f0dc882cdb1686fa88ce26263b3822379db527bd04ba058a23ddb1
|
||||
vendor/golang.org/x/sys/windows/svc/example/manage.go type=file mode=0664 size=1396 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=64659105feeb84f1ff677e29552b6bcf16e8dc1bddb30888b3cb106ce8e5042c
|
||||
vendor/golang.org/x/sys/windows/svc/example/service.go type=file mode=0664 size=2027 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=f84055875f8674a647cb8edf49f1cdc35cd0e88544fe6f7856a4a347d897c7d9
|
||||
vendor/golang.org/x/sys/windows/svc/go12.c type=file mode=0664 size=497 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=b6cd9fe0b0cb80022aeb239ef013e8ac37e9fa5330d2451b4b92c565529365cf
|
||||
vendor/golang.org/x/sys/windows/svc/go12.go type=file mode=0664 size=257 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=7ed60f81776941804a4235d3328e3c1f05ff25f535d194dd2eb3d149f4774ffb
|
||||
vendor/golang.org/x/sys/windows/svc/go13.go type=file mode=0664 size=863 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=9e4c8e9803004e778509b7a4728313b1a789f02bf8906171af2fd80d752f6626
|
||||
vendor/golang.org/x/sys/windows/svc/mgr type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773
|
||||
vendor/golang.org/x/sys/windows/svc/mgr/config.go type=file mode=0664 size=3939 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=69bf2a714f7d6f62db674c9e18ad00214b90c0ffb13116149ee9f0d43ec4b261
|
||||
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go type=file mode=0664 size=4455 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=83687c4dd83faa67ef8db09a153c56845c4010a4dd05401f0a3fdc0f681c3c24
|
||||
vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go type=file mode=0664 size=3908 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=825a2145e522294fddf0d37ae4175df3b1bbb1acfa61de94cd1c9522cb54ff98
|
||||
vendor/golang.org/x/sys/windows/svc/mgr/service.go type=file mode=0664 size=1791 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=1b0977a1347a7989286d32f6358debe8c6517e5e38d11cdaf388ef3f92fb6b9b
|
||||
vendor/golang.org/x/sys/windows/svc/security.go type=file mode=0664 size=1553 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=05774567b99190dcfaa1198fc818d3a9f0586bcf40527c14c7d4019f8800e3c0
|
||||
vendor/golang.org/x/sys/windows/svc/service.go type=file mode=0664 size=10848 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=91aa0a8eec292418bb2e45609fd9536370fb31d413119663779a29a7c0fa5369
|
||||
vendor/golang.org/x/sys/windows/svc/svc_test.go type=file mode=0664 size=2638 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=cda7e9488d951a5d278c51a45d595ae597167c240aadfcc997f2c564be94c955
|
||||
vendor/golang.org/x/sys/windows/svc/sys_386.s type=file mode=0664 size=1241 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=44892d02d381297466df500895f6ba5991202947c45bb736d8e566f144912e25
|
||||
vendor/golang.org/x/sys/windows/svc/sys_amd64.s type=file mode=0664 size=1031 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=1530d9d362cf67b5abcbbae7b7e244843b0089b50ae376d86070d31ce17c4d36
|
||||
vendor/golang.org/x/sys/windows/syscall.go type=file mode=0664 size=2407 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=129c8714171a4cce55aa92caba4a590881062aa00646e048abd78f97c4e88f4c
|
||||
vendor/golang.org/x/sys/windows/syscall_test.go type=file mode=0664 size=1433 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=8efdb25b14f6699769f13f16a3703f166b2a18a6d8dbe836d1188e259674b48a
|
||||
vendor/golang.org/x/sys/windows/syscall_windows.go type=file mode=0664 size=38971 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=9f24c38c3d96ac08f3a3e6acc64fe165a544305a8acd26ead6d4a71ad45a1bdf
|
||||
vendor/golang.org/x/sys/windows/syscall_windows_test.go type=file mode=0664 size=2857 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.469900773 sha512256digest=94530256b93cfadc7561335221b443298fe5780a6c4e83386986d0cf04b6e577
|
||||
vendor/golang.org/x/sys/windows/types_windows.go type=file mode=0664 size=31549 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=3f82ee167ab35b67c63619c544e47a05e2d26af92761d799ad5d1d6d99e73294
|
||||
vendor/golang.org/x/sys/windows/types_windows_386.go type=file mode=0664 size=478 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=8bb43554de9c8339edfac4c58130193448c774660c9659cb1ae49c2710e6d547
|
||||
vendor/golang.org/x/sys/windows/types_windows_amd64.go type=file mode=0664 size=478 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=25469d12b697e94aa4eb902b8643f5fec03108885e1521d470623237962ec497
|
||||
vendor/golang.org/x/sys/windows/zsyscall_windows.go type=file mode=0664 size=81066 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=f6c866585ffde0cc4ebedd64b2ea42ef6af9624880c353409ada4d868b895db0
|
||||
version.go type=file mode=0664 size=624 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=8653b2bc3523c290f6bd998bb29865c0165ad4e85aaccd0816a34287dc0e04d1
|
||||
walk.go type=file mode=0664 size=10410 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=d398fe4bb1bb9af39442dd6f695fa2fc66302ebbcb5bc1adb6418b2f3d5f9ed3
|
||||
walk_test.go type=file mode=0664 size=1156 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1513088893.904788061 sha512256digest=227e25157b95da02017dab4d2dcff4199f356219cfc622228a6fe0535a41ab1c
|
||||
xattr type=dir mode=0775 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767
|
||||
xattr/xattr.go type=file mode=0664 size=984 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=a2700b603df30c3b0a91bdcf9045e64aea42f62647b0128ea154f51a0c48991e
|
||||
xattr/xattr_test.go type=file mode=0664 size=859 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=91294ea554801b75f6a9e33c268807c9620b531eb813ea24512dd4eeaf0592e4
|
||||
xattr/xattr_unsupported.go type=file mode=0664 size=509 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=81ced06a1cdf88c4936d10bbf8d46edc2d42dc26efeed3691ddbeeb469865f8a
|
||||
xattr/xattr_unsupported_test.go type=file mode=0664 size=877 uid=1000 gid=1000 uname=vbatts gname=vbatts time=1512774394.470900767 sha512256digest=46605a03a985c7a3a4ab1a488f81382db4865f77b90b6a2b32693af39a8e1fba
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DefaultUpdateKeywords is the default set of keywords that can take updates to the files on disk
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbatts/go-mtree/pkg/govis"
|
||||
)
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@ package mtree
|
|||
import (
|
||||
"encoding/base64"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/vbatts/go-mtree/xattr"
|
||||
)
|
||||
|
@ -22,37 +19,3 @@ func xattrUpdateKeywordFunc(path string, kv KeyVal) (os.FileInfo, error) {
|
|||
}
|
||||
return os.Lstat(path)
|
||||
}
|
||||
|
||||
func lchtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
var utimes [2]syscall.Timespec
|
||||
utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
|
||||
utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
|
||||
if e := utimensat(atFdCwd, name, (*[2]syscall.Timespec)(unsafe.Pointer(&utimes[0])), atSymlinkNofollow); e != nil {
|
||||
return &os.PathError{Op: "chtimes", Path: name, Err: e}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// from uapi/linux/fcntl.h
|
||||
// don't follow symlinks
|
||||
const atSymlinkNofollow = 0x100
|
||||
|
||||
// special value for utimes as the FD for the current working directory
|
||||
const atFdCwd = -0x64
|
||||
|
||||
func utimensat(dirfd int, path string, times *[2]syscall.Timespec, flags int) (err error) {
|
||||
if len(times) != 2 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
var _p0 *byte
|
||||
_p0, err = syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,13 +4,8 @@ package mtree
|
|||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func xattrUpdateKeywordFunc(path string, kv KeyVal) (os.FileInfo, error) {
|
||||
return os.Lstat(path)
|
||||
}
|
||||
|
||||
func lchtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
logrus
|
|
@ -1,13 +0,0 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- tip
|
||||
env:
|
||||
- GOMAXPROCS=4 GORACE=halt_on_error=1
|
||||
install:
|
||||
- go get github.com/stretchr/testify/assert
|
||||
script:
|
||||
- go test -race -v .
|
||||
- cd hooks/null && go test -race -v .
|
|
@ -1,100 +0,0 @@
|
|||
# 1.0.0
|
||||
|
||||
* Officially changed name to lower-case
|
||||
* bug: colors on Windows 10 (#541)
|
||||
* bug: fix race in accessing level (#512)
|
||||
|
||||
# 0.11.5
|
||||
|
||||
* feature: add writer and writerlevel to entry (#372)
|
||||
|
||||
# 0.11.4
|
||||
|
||||
* bug: fix undefined variable on solaris (#493)
|
||||
|
||||
# 0.11.3
|
||||
|
||||
* formatter: configure quoting of empty values (#484)
|
||||
* formatter: configure quoting character (default is `"`) (#484)
|
||||
* bug: fix not importing io correctly in non-linux environments (#481)
|
||||
|
||||
# 0.11.2
|
||||
|
||||
* bug: fix windows terminal detection (#476)
|
||||
|
||||
# 0.11.1
|
||||
|
||||
* bug: fix tty detection with custom out (#471)
|
||||
|
||||
# 0.11.0
|
||||
|
||||
* performance: Use bufferpool to allocate (#370)
|
||||
* terminal: terminal detection for app-engine (#343)
|
||||
* feature: exit handler (#375)
|
||||
|
||||
# 0.10.0
|
||||
|
||||
* feature: Add a test hook (#180)
|
||||
* feature: `ParseLevel` is now case-insensitive (#326)
|
||||
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
|
||||
* performance: avoid re-allocations on `WithFields` (#335)
|
||||
|
||||
# 0.9.0
|
||||
|
||||
* logrus/text_formatter: don't emit empty msg
|
||||
* logrus/hooks/airbrake: move out of main repository
|
||||
* logrus/hooks/sentry: move out of main repository
|
||||
* logrus/hooks/papertrail: move out of main repository
|
||||
* logrus/hooks/bugsnag: move out of main repository
|
||||
* logrus/core: run tests with `-race`
|
||||
* logrus/core: detect TTY based on `stderr`
|
||||
* logrus/core: support `WithError` on logger
|
||||
* logrus/core: Solaris support
|
||||
|
||||
# 0.8.7
|
||||
|
||||
* logrus/core: fix possible race (#216)
|
||||
* logrus/doc: small typo fixes and doc improvements
|
||||
|
||||
|
||||
# 0.8.6
|
||||
|
||||
* hooks/raven: allow passing an initialized client
|
||||
|
||||
# 0.8.5
|
||||
|
||||
* logrus/core: revert #208
|
||||
|
||||
# 0.8.4
|
||||
|
||||
* formatter/text: fix data race (#218)
|
||||
|
||||
# 0.8.3
|
||||
|
||||
* logrus/core: fix entry log level (#208)
|
||||
* logrus/core: improve performance of text formatter by 40%
|
||||
* logrus/core: expose `LevelHooks` type
|
||||
* logrus/core: add support for DragonflyBSD and NetBSD
|
||||
* formatter/text: print structs more verbosely
|
||||
|
||||
# 0.8.2
|
||||
|
||||
* logrus: fix more Fatal family functions
|
||||
|
||||
# 0.8.1
|
||||
|
||||
* logrus: fix not exiting on `Fatalf` and `Fatalln`
|
||||
|
||||
# 0.8.0
|
||||
|
||||
* logrus: defaults to stderr instead of stdout
|
||||
* hooks/sentry: add special field for `*http.Request`
|
||||
* formatter/text: ignore Windows for colors
|
||||
|
||||
# 0.7.3
|
||||
|
||||
* formatter/\*: allow configuration of timestamp layout
|
||||
|
||||
# 0.7.2
|
||||
|
||||
* formatter/text: Add configuration option for time format (#158)
|
|
@ -1,74 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
current := len(handlers)
|
||||
RegisterExitHandler(func() {})
|
||||
if len(handlers) != current+1 {
|
||||
t.Fatalf("can't add handler")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler(t *testing.T) {
|
||||
gofile := "/tmp/testprog.go"
|
||||
if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
|
||||
t.Fatalf("can't create go file")
|
||||
}
|
||||
|
||||
outfile := "/tmp/testprog.out"
|
||||
arg := time.Now().UTC().String()
|
||||
err := exec.Command("go", "run", gofile, outfile, arg).Run()
|
||||
if err == nil {
|
||||
t.Fatalf("completed normally, should have failed")
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(outfile)
|
||||
if err != nil {
|
||||
t.Fatalf("can't read output file %s", outfile)
|
||||
}
|
||||
|
||||
if string(data) != arg {
|
||||
t.Fatalf("bad data")
|
||||
}
|
||||
}
|
||||
|
||||
var testprog = []byte(`
|
||||
// Test program for atexit, gets output file and data as arguments and writes
|
||||
// data to output file in atexit handler.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var outfile = ""
|
||||
var data = ""
|
||||
|
||||
func handler() {
|
||||
ioutil.WriteFile(outfile, []byte(data), 0666)
|
||||
}
|
||||
|
||||
func badHandler() {
|
||||
n := 0
|
||||
fmt.Println(1/n)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
outfile = flag.Arg(0)
|
||||
data = flag.Arg(1)
|
||||
|
||||
logrus.RegisterExitHandler(handler)
|
||||
logrus.RegisterExitHandler(badHandler)
|
||||
logrus.Fatal("Bye bye")
|
||||
}
|
||||
`)
|
|
@ -1,275 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var bufferPool *sync.Pool
|
||||
|
||||
func init() {
|
||||
bufferPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Defines the key when adding errors using WithError.
|
||||
var ErrorKey = "error"
|
||||
|
||||
// An entry is the final or intermediate Logrus logging entry. It contains all
|
||||
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
|
||||
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
|
||||
// passed around as much as you wish to avoid field duplication.
|
||||
type Entry struct {
|
||||
Logger *Logger
|
||||
|
||||
// Contains all the fields set by the user.
|
||||
Data Fields
|
||||
|
||||
// Time at which the log entry was created
|
||||
Time time.Time
|
||||
|
||||
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
|
||||
Level Level
|
||||
|
||||
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
|
||||
Message string
|
||||
|
||||
// When formatter is called in entry.log(), an Buffer may be set to entry
|
||||
Buffer *bytes.Buffer
|
||||
}
|
||||
|
||||
func NewEntry(logger *Logger) *Entry {
|
||||
return &Entry{
|
||||
Logger: logger,
|
||||
// Default is three fields, give a little extra room
|
||||
Data: make(Fields, 5),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the string representation from the reader and ultimately the
|
||||
// formatter.
|
||||
func (entry *Entry) String() (string, error) {
|
||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
str := string(serialized)
|
||||
return str, nil
|
||||
}
|
||||
|
||||
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
|
||||
func (entry *Entry) WithError(err error) *Entry {
|
||||
return entry.WithField(ErrorKey, err)
|
||||
}
|
||||
|
||||
// Add a single field to the Entry.
|
||||
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
||||
return entry.WithFields(Fields{key: value})
|
||||
}
|
||||
|
||||
// Add a map of fields to the Entry.
|
||||
func (entry *Entry) WithFields(fields Fields) *Entry {
|
||||
data := make(Fields, len(entry.Data)+len(fields))
|
||||
for k, v := range entry.Data {
|
||||
data[k] = v
|
||||
}
|
||||
for k, v := range fields {
|
||||
data[k] = v
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: data}
|
||||
}
|
||||
|
||||
// This function is not declared with a pointer value because otherwise
|
||||
// race conditions will occur when using multiple goroutines
|
||||
func (entry Entry) log(level Level, msg string) {
|
||||
var buffer *bytes.Buffer
|
||||
entry.Time = time.Now()
|
||||
entry.Level = level
|
||||
entry.Message = msg
|
||||
|
||||
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
|
||||
entry.Logger.mu.Lock()
|
||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||
entry.Logger.mu.Unlock()
|
||||
}
|
||||
buffer = bufferPool.Get().(*bytes.Buffer)
|
||||
buffer.Reset()
|
||||
defer bufferPool.Put(buffer)
|
||||
entry.Buffer = buffer
|
||||
serialized, err := entry.Logger.Formatter.Format(&entry)
|
||||
entry.Buffer = nil
|
||||
if err != nil {
|
||||
entry.Logger.mu.Lock()
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
||||
entry.Logger.mu.Unlock()
|
||||
} else {
|
||||
entry.Logger.mu.Lock()
|
||||
_, err = entry.Logger.Out.Write(serialized)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
||||
}
|
||||
entry.Logger.mu.Unlock()
|
||||
}
|
||||
|
||||
// To avoid Entry#log() returning a value that only would make sense for
|
||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
||||
// directly here.
|
||||
if level <= PanicLevel {
|
||||
panic(&entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Debug(args ...interface{}) {
|
||||
if entry.Logger.level() >= DebugLevel {
|
||||
entry.log(DebugLevel, fmt.Sprint(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Print(args ...interface{}) {
|
||||
entry.Info(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Info(args ...interface{}) {
|
||||
if entry.Logger.level() >= InfoLevel {
|
||||
entry.log(InfoLevel, fmt.Sprint(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Warn(args ...interface{}) {
|
||||
if entry.Logger.level() >= WarnLevel {
|
||||
entry.log(WarnLevel, fmt.Sprint(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Warning(args ...interface{}) {
|
||||
entry.Warn(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Error(args ...interface{}) {
|
||||
if entry.Logger.level() >= ErrorLevel {
|
||||
entry.log(ErrorLevel, fmt.Sprint(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatal(args ...interface{}) {
|
||||
if entry.Logger.level() >= FatalLevel {
|
||||
entry.log(FatalLevel, fmt.Sprint(args...))
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panic(args ...interface{}) {
|
||||
if entry.Logger.level() >= PanicLevel {
|
||||
entry.log(PanicLevel, fmt.Sprint(args...))
|
||||
}
|
||||
panic(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Entry Printf family functions
|
||||
|
||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= DebugLevel {
|
||||
entry.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Infof(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= InfoLevel {
|
||||
entry.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Printf(format string, args ...interface{}) {
|
||||
entry.Infof(format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= WarnLevel {
|
||||
entry.Warn(fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
||||
entry.Warnf(format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= ErrorLevel {
|
||||
entry.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= FatalLevel {
|
||||
entry.Fatal(fmt.Sprintf(format, args...))
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
||||
if entry.Logger.level() >= PanicLevel {
|
||||
entry.Panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Entry Println family functions
|
||||
|
||||
func (entry *Entry) Debugln(args ...interface{}) {
|
||||
if entry.Logger.level() >= DebugLevel {
|
||||
entry.Debug(entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Infoln(args ...interface{}) {
|
||||
if entry.Logger.level() >= InfoLevel {
|
||||
entry.Info(entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Println(args ...interface{}) {
|
||||
entry.Infoln(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warnln(args ...interface{}) {
|
||||
if entry.Logger.level() >= WarnLevel {
|
||||
entry.Warn(entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Warningln(args ...interface{}) {
|
||||
entry.Warnln(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Errorln(args ...interface{}) {
|
||||
if entry.Logger.level() >= ErrorLevel {
|
||||
entry.Error(entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatalln(args ...interface{}) {
|
||||
if entry.Logger.level() >= FatalLevel {
|
||||
entry.Fatal(entry.sprintlnn(args...))
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panicln(args ...interface{}) {
|
||||
if entry.Logger.level() >= PanicLevel {
|
||||
entry.Panic(entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
||||
// fmt.Sprintln where spaces are always added between operands, regardless of
|
||||
// their type. Instead of vendoring the Sprintln implementation to spare a
|
||||
// string allocation, we do the simplest thing.
|
||||
func (entry *Entry) sprintlnn(args ...interface{}) string {
|
||||
msg := fmt.Sprintln(args...)
|
||||
return msg[:len(msg)-1]
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEntryWithError(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
defer func() {
|
||||
ErrorKey = "error"
|
||||
}()
|
||||
|
||||
err := fmt.Errorf("kaboom at layer %d", 4711)
|
||||
|
||||
assert.Equal(err, WithError(err).Data["error"])
|
||||
|
||||
logger := New()
|
||||
logger.Out = &bytes.Buffer{}
|
||||
entry := NewEntry(logger)
|
||||
|
||||
assert.Equal(err, entry.WithError(err).Data["error"])
|
||||
|
||||
ErrorKey = "err"
|
||||
|
||||
assert.Equal(err, entry.WithError(err).Data["err"])
|
||||
|
||||
}
|
||||
|
||||
func TestEntryPanicln(t *testing.T) {
|
||||
errBoom := fmt.Errorf("boom time")
|
||||
|
||||
defer func() {
|
||||
p := recover()
|
||||
assert.NotNil(t, p)
|
||||
|
||||
switch pVal := p.(type) {
|
||||
case *Entry:
|
||||
assert.Equal(t, "kaboom", pVal.Message)
|
||||
assert.Equal(t, errBoom, pVal.Data["err"])
|
||||
default:
|
||||
t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
|
||||
}
|
||||
}()
|
||||
|
||||
logger := New()
|
||||
logger.Out = &bytes.Buffer{}
|
||||
entry := NewEntry(logger)
|
||||
entry.WithField("err", errBoom).Panicln("kaboom")
|
||||
}
|
||||
|
||||
func TestEntryPanicf(t *testing.T) {
|
||||
errBoom := fmt.Errorf("boom again")
|
||||
|
||||
defer func() {
|
||||
p := recover()
|
||||
assert.NotNil(t, p)
|
||||
|
||||
switch pVal := p.(type) {
|
||||
case *Entry:
|
||||
assert.Equal(t, "kaboom true", pVal.Message)
|
||||
assert.Equal(t, errBoom, pVal.Data["err"])
|
||||
default:
|
||||
t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
|
||||
}
|
||||
}()
|
||||
|
||||
logger := New()
|
||||
logger.Out = &bytes.Buffer{}
|
||||
entry := NewEntry(logger)
|
||||
entry.WithField("err", errBoom).Panicf("kaboom %v", true)
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
// "os"
|
||||
)
|
||||
|
||||
var log = logrus.New()
|
||||
|
||||
func init() {
|
||||
log.Formatter = new(logrus.JSONFormatter)
|
||||
log.Formatter = new(logrus.TextFormatter) // default
|
||||
|
||||
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
|
||||
// if err == nil {
|
||||
// log.Out = file
|
||||
// } else {
|
||||
// log.Info("Failed to log to file, using default stderr")
|
||||
// }
|
||||
|
||||
log.Level = logrus.DebugLevel
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"omg": true,
|
||||
"err": err,
|
||||
"number": 100,
|
||||
}).Fatal("The ice breaks!")
|
||||
}
|
||||
}()
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"animal": "walrus",
|
||||
"number": 8,
|
||||
}).Debug("Started observing beach")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"animal": "walrus",
|
||||
"size": 10,
|
||||
}).Info("A group of walrus emerges from the ocean")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"omg": true,
|
||||
"number": 122,
|
||||
}).Warn("The group's number increased tremendously!")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"temperature": -4,
|
||||
}).Debug("Temperature changes")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"animal": "orca",
|
||||
"size": 9009,
|
||||
}).Panic("It's over 9000!")
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2"
|
||||
)
|
||||
|
||||
var log = logrus.New()
|
||||
|
||||
func init() {
|
||||
log.Formatter = new(logrus.TextFormatter) // default
|
||||
log.Hooks.Add(airbrake.NewHook(123, "xyz", "development"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.WithFields(logrus.Fields{
|
||||
"animal": "walrus",
|
||||
"size": 10,
|
||||
}).Info("A group of walrus emerges from the ocean")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"omg": true,
|
||||
"number": 122,
|
||||
}).Warn("The group's number increased tremendously!")
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"omg": true,
|
||||
"number": 100,
|
||||
}).Fatal("The ice breaks!")
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import "time"
|
||||
|
||||
const DefaultTimestampFormat = time.RFC3339
|
||||
|
||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||
// `Entry`. It exposes all the fields, including the default ones:
|
||||
//
|
||||
// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
|
||||
// * `entry.Data["time"]`. The timestamp.
|
||||
// * `entry.Data["level"]. The level the entry was logged at.
|
||||
//
|
||||
// Any additional fields added with `WithField` or `WithFields` are also in
|
||||
// `entry.Data`. Format is expected to return an array of bytes which are then
|
||||
// logged to `logger.Out`.
|
||||
type Formatter interface {
|
||||
Format(*Entry) ([]byte, error)
|
||||
}
|
||||
|
||||
// This is to not silently overwrite `time`, `msg` and `level` fields when
|
||||
// dumping it. If this code wasn't there doing:
|
||||
//
|
||||
// logrus.WithField("level", 1).Info("hello")
|
||||
//
|
||||
// Would just silently drop the user provided level. Instead with this code
|
||||
// it'll logged as:
|
||||
//
|
||||
// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
|
||||
//
|
||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
||||
// avoid code duplication between the two default formatters.
|
||||
func prefixFieldClashes(data Fields) {
|
||||
if t, ok := data["time"]; ok {
|
||||
data["fields.time"] = t
|
||||
}
|
||||
|
||||
if m, ok := data["msg"]; ok {
|
||||
data["fields.msg"] = m
|
||||
}
|
||||
|
||||
if l, ok := data["level"]; ok {
|
||||
data["fields.level"] = l
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// smallFields is a small size data set for benchmarking
|
||||
var smallFields = Fields{
|
||||
"foo": "bar",
|
||||
"baz": "qux",
|
||||
"one": "two",
|
||||
"three": "four",
|
||||
}
|
||||
|
||||
// largeFields is a large size data set for benchmarking
|
||||
var largeFields = Fields{
|
||||
"foo": "bar",
|
||||
"baz": "qux",
|
||||
"one": "two",
|
||||
"three": "four",
|
||||
"five": "six",
|
||||
"seven": "eight",
|
||||
"nine": "ten",
|
||||
"eleven": "twelve",
|
||||
"thirteen": "fourteen",
|
||||
"fifteen": "sixteen",
|
||||
"seventeen": "eighteen",
|
||||
"nineteen": "twenty",
|
||||
"a": "b",
|
||||
"c": "d",
|
||||
"e": "f",
|
||||
"g": "h",
|
||||
"i": "j",
|
||||
"k": "l",
|
||||
"m": "n",
|
||||
"o": "p",
|
||||
"q": "r",
|
||||
"s": "t",
|
||||
"u": "v",
|
||||
"w": "x",
|
||||
"y": "z",
|
||||
"this": "will",
|
||||
"make": "thirty",
|
||||
"entries": "yeah",
|
||||
}
|
||||
|
||||
var errorFields = Fields{
|
||||
"foo": fmt.Errorf("bar"),
|
||||
"baz": fmt.Errorf("qux"),
|
||||
}
|
||||
|
||||
func BenchmarkErrorTextFormatter(b *testing.B) {
|
||||
doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields)
|
||||
}
|
||||
|
||||
func BenchmarkSmallTextFormatter(b *testing.B) {
|
||||
doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
|
||||
}
|
||||
|
||||
func BenchmarkLargeTextFormatter(b *testing.B) {
|
||||
doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
|
||||
}
|
||||
|
||||
func BenchmarkSmallColoredTextFormatter(b *testing.B) {
|
||||
doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
|
||||
}
|
||||
|
||||
func BenchmarkLargeColoredTextFormatter(b *testing.B) {
|
||||
doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
|
||||
}
|
||||
|
||||
func BenchmarkSmallJSONFormatter(b *testing.B) {
|
||||
doBenchmark(b, &JSONFormatter{}, smallFields)
|
||||
}
|
||||
|
||||
func BenchmarkLargeJSONFormatter(b *testing.B) {
|
||||
doBenchmark(b, &JSONFormatter{}, largeFields)
|
||||
}
|
||||
|
||||
func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
|
||||
logger := New()
|
||||
|
||||
entry := &Entry{
|
||||
Time: time.Time{},
|
||||
Level: InfoLevel,
|
||||
Message: "message",
|
||||
Data: fields,
|
||||
Logger: logger,
|
||||
}
|
||||
var d []byte
|
||||
var err error
|
||||
for i := 0; i < b.N; i++ {
|
||||
d, err = formatter.Format(entry)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.SetBytes(int64(len(d)))
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type TestHook struct {
|
||||
Fired bool
|
||||
}
|
||||
|
||||
func (hook *TestHook) Fire(entry *Entry) error {
|
||||
hook.Fired = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hook *TestHook) Levels() []Level {
|
||||
return []Level{
|
||||
DebugLevel,
|
||||
InfoLevel,
|
||||
WarnLevel,
|
||||
ErrorLevel,
|
||||
FatalLevel,
|
||||
PanicLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func TestHookFires(t *testing.T) {
|
||||
hook := new(TestHook)
|
||||
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Hooks.Add(hook)
|
||||
assert.Equal(t, hook.Fired, false)
|
||||
|
||||
log.Print("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, hook.Fired, true)
|
||||
})
|
||||
}
|
||||
|
||||
type ModifyHook struct {
|
||||
}
|
||||
|
||||
func (hook *ModifyHook) Fire(entry *Entry) error {
|
||||
entry.Data["wow"] = "whale"
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hook *ModifyHook) Levels() []Level {
|
||||
return []Level{
|
||||
DebugLevel,
|
||||
InfoLevel,
|
||||
WarnLevel,
|
||||
ErrorLevel,
|
||||
FatalLevel,
|
||||
PanicLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func TestHookCanModifyEntry(t *testing.T) {
|
||||
hook := new(ModifyHook)
|
||||
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Hooks.Add(hook)
|
||||
log.WithField("wow", "elephant").Print("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["wow"], "whale")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCanFireMultipleHooks(t *testing.T) {
|
||||
hook1 := new(ModifyHook)
|
||||
hook2 := new(TestHook)
|
||||
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Hooks.Add(hook1)
|
||||
log.Hooks.Add(hook2)
|
||||
|
||||
log.WithField("wow", "elephant").Print("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["wow"], "whale")
|
||||
assert.Equal(t, hook2.Fired, true)
|
||||
})
|
||||
}
|
||||
|
||||
type ErrorHook struct {
|
||||
Fired bool
|
||||
}
|
||||
|
||||
func (hook *ErrorHook) Fire(entry *Entry) error {
|
||||
hook.Fired = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hook *ErrorHook) Levels() []Level {
|
||||
return []Level{
|
||||
ErrorLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorHookShouldntFireOnInfo(t *testing.T) {
|
||||
hook := new(ErrorHook)
|
||||
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Hooks.Add(hook)
|
||||
log.Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, hook.Fired, false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestErrorHookShouldFireOnError(t *testing.T) {
|
||||
hook := new(ErrorHook)
|
||||
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Hooks.Add(hook)
|
||||
log.Error("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, hook.Fired, true)
|
||||
})
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"log/syslog"
|
||||
"github.com/sirupsen/logrus"
|
||||
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log := logrus.New()
|
||||
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
||||
|
||||
if err == nil {
|
||||
log.Hooks.Add(hook)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following.
|
||||
|
||||
```go
|
||||
import (
|
||||
"log/syslog"
|
||||
"github.com/sirupsen/logrus"
|
||||
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log := logrus.New()
|
||||
hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
|
||||
|
||||
if err == nil {
|
||||
log.Hooks.Add(hook)
|
||||
}
|
||||
}
|
||||
```
|
|
@ -1,54 +0,0 @@
|
|||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package logrus_syslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"log/syslog"
|
||||
"os"
|
||||
)
|
||||
|
||||
// SyslogHook to send logs via syslog.
|
||||
type SyslogHook struct {
|
||||
Writer *syslog.Writer
|
||||
SyslogNetwork string
|
||||
SyslogRaddr string
|
||||
}
|
||||
|
||||
// Creates a hook to be added to an instance of logger. This is called with
|
||||
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
|
||||
// `if err == nil { log.Hooks.Add(hook) }`
|
||||
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
|
||||
w, err := syslog.Dial(network, raddr, priority, tag)
|
||||
return &SyslogHook{w, network, raddr}, err
|
||||
}
|
||||
|
||||
func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
|
||||
line, err := entry.String()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
switch entry.Level {
|
||||
case logrus.PanicLevel:
|
||||
return hook.Writer.Crit(line)
|
||||
case logrus.FatalLevel:
|
||||
return hook.Writer.Crit(line)
|
||||
case logrus.ErrorLevel:
|
||||
return hook.Writer.Err(line)
|
||||
case logrus.WarnLevel:
|
||||
return hook.Writer.Warning(line)
|
||||
case logrus.InfoLevel:
|
||||
return hook.Writer.Info(line)
|
||||
case logrus.DebugLevel:
|
||||
return hook.Writer.Debug(line)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (hook *SyslogHook) Levels() []logrus.Level {
|
||||
return logrus.AllLevels
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package logrus_syslog
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"log/syslog"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLocalhostAddAndPrint(t *testing.T) {
|
||||
log := logrus.New()
|
||||
hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unable to connect to local syslog.")
|
||||
}
|
||||
|
||||
log.Hooks.Add(hook)
|
||||
|
||||
for _, level := range hook.Levels() {
|
||||
if len(log.Hooks[level]) != 1 {
|
||||
t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Congratulations!")
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
// The Test package is used for testing logrus. It is here for backwards
|
||||
// compatibility from when logrus' organization was upper-case. Please use
|
||||
// lower-case logrus and the `null` package instead of this one.
|
||||
package test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Hook is a hook designed for dealing with logs in test scenarios.
|
||||
type Hook struct {
|
||||
// Entries is an array of all entries that have been received by this hook.
|
||||
// For safe access, use the AllEntries() method, rather than reading this
|
||||
// value directly.
|
||||
Entries []*logrus.Entry
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewGlobal installs a test hook for the global logger.
|
||||
func NewGlobal() *Hook {
|
||||
|
||||
hook := new(Hook)
|
||||
logrus.AddHook(hook)
|
||||
|
||||
return hook
|
||||
|
||||
}
|
||||
|
||||
// NewLocal installs a test hook for a given local logger.
|
||||
func NewLocal(logger *logrus.Logger) *Hook {
|
||||
|
||||
hook := new(Hook)
|
||||
logger.Hooks.Add(hook)
|
||||
|
||||
return hook
|
||||
|
||||
}
|
||||
|
||||
// NewNullLogger creates a discarding logger and installs the test hook.
|
||||
func NewNullLogger() (*logrus.Logger, *Hook) {
|
||||
|
||||
logger := logrus.New()
|
||||
logger.Out = ioutil.Discard
|
||||
|
||||
return logger, NewLocal(logger)
|
||||
|
||||
}
|
||||
|
||||
func (t *Hook) Fire(e *logrus.Entry) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.Entries = append(t.Entries, e)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Hook) Levels() []logrus.Level {
|
||||
return logrus.AllLevels
|
||||
}
|
||||
|
||||
// LastEntry returns the last entry that was logged or nil.
|
||||
func (t *Hook) LastEntry() *logrus.Entry {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
i := len(t.Entries) - 1
|
||||
if i < 0 {
|
||||
return nil
|
||||
}
|
||||
// Make a copy, for safety
|
||||
e := *t.Entries[i]
|
||||
return &e
|
||||
}
|
||||
|
||||
// AllEntries returns all entries that were logged.
|
||||
func (t *Hook) AllEntries() []*logrus.Entry {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
// Make a copy so the returned value won't race with future log requests
|
||||
entries := make([]*logrus.Entry, len(t.Entries))
|
||||
for i, entry := range t.Entries {
|
||||
// Make a copy, for safety
|
||||
e := *entry
|
||||
entries[i] = &e
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
// Reset removes all Entries from this test hook.
|
||||
func (t *Hook) Reset() {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.Entries = make([]*logrus.Entry, 0)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAllHooks(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
logger, hook := NewNullLogger()
|
||||
assert.Nil(hook.LastEntry())
|
||||
assert.Equal(0, len(hook.Entries))
|
||||
|
||||
logger.Error("Hello error")
|
||||
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
||||
assert.Equal("Hello error", hook.LastEntry().Message)
|
||||
assert.Equal(1, len(hook.Entries))
|
||||
|
||||
logger.Warn("Hello warning")
|
||||
assert.Equal(logrus.WarnLevel, hook.LastEntry().Level)
|
||||
assert.Equal("Hello warning", hook.LastEntry().Message)
|
||||
assert.Equal(2, len(hook.Entries))
|
||||
|
||||
hook.Reset()
|
||||
assert.Nil(hook.LastEntry())
|
||||
assert.Equal(0, len(hook.Entries))
|
||||
|
||||
hook = NewGlobal()
|
||||
|
||||
logrus.Error("Hello error")
|
||||
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
||||
assert.Equal("Hello error", hook.LastEntry().Message)
|
||||
assert.Equal(1, len(hook.Entries))
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type fieldKey string
|
||||
type FieldMap map[fieldKey]string
|
||||
|
||||
const (
|
||||
FieldKeyMsg = "msg"
|
||||
FieldKeyLevel = "level"
|
||||
FieldKeyTime = "time"
|
||||
)
|
||||
|
||||
func (f FieldMap) resolve(key fieldKey) string {
|
||||
if k, ok := f[key]; ok {
|
||||
return k
|
||||
}
|
||||
|
||||
return string(key)
|
||||
}
|
||||
|
||||
type JSONFormatter struct {
|
||||
// TimestampFormat sets the format used for marshaling timestamps.
|
||||
TimestampFormat string
|
||||
|
||||
// DisableTimestamp allows disabling automatic timestamps in output
|
||||
DisableTimestamp bool
|
||||
|
||||
// FieldMap allows users to customize the names of keys for various fields.
|
||||
// As an example:
|
||||
// formatter := &JSONFormatter{
|
||||
// FieldMap: FieldMap{
|
||||
// FieldKeyTime: "@timestamp",
|
||||
// FieldKeyLevel: "@level",
|
||||
// FieldKeyMsg: "@message",
|
||||
// },
|
||||
// }
|
||||
FieldMap FieldMap
|
||||
}
|
||||
|
||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
data := make(Fields, len(entry.Data)+3)
|
||||
for k, v := range entry.Data {
|
||||
switch v := v.(type) {
|
||||
case error:
|
||||
// Otherwise errors are ignored by `encoding/json`
|
||||
// https://github.com/sirupsen/logrus/issues/137
|
||||
data[k] = v.Error()
|
||||
default:
|
||||
data[k] = v
|
||||
}
|
||||
}
|
||||
prefixFieldClashes(data)
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
timestampFormat = DefaultTimestampFormat
|
||||
}
|
||||
|
||||
if !f.DisableTimestamp {
|
||||
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
|
||||
}
|
||||
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
|
||||
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
|
||||
|
||||
serialized, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
||||
}
|
||||
return append(serialized, '\n'), nil
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrorNotLost(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
if entry["error"] != "wild walrus" {
|
||||
t.Fatal("Error field not set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
if entry["omg"] != "wild walrus" {
|
||||
t.Fatal("Error field not set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldClashWithTime(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("time", "right now!"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
if entry["fields.time"] != "right now!" {
|
||||
t.Fatal("fields.time not set to original time field")
|
||||
}
|
||||
|
||||
if entry["time"] != "0001-01-01T00:00:00Z" {
|
||||
t.Fatal("time field not set to current time, was: ", entry["time"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldClashWithMsg(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("msg", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
if entry["fields.msg"] != "something" {
|
||||
t.Fatal("fields.msg not set to original msg field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldClashWithLevel(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
entry := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &entry)
|
||||
if err != nil {
|
||||
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
||||
}
|
||||
|
||||
if entry["fields.level"] != "something" {
|
||||
t.Fatal("fields.level not set to original level field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONEntryEndsWithNewline(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
|
||||
if b[len(b)-1] != '\n' {
|
||||
t.Fatal("Expected JSON log entry to end with a newline")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONMessageKey(t *testing.T) {
|
||||
formatter := &JSONFormatter{
|
||||
FieldMap: FieldMap{
|
||||
FieldKeyMsg: "message",
|
||||
},
|
||||
}
|
||||
|
||||
b, err := formatter.Format(&Entry{Message: "oh hai"})
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
s := string(b)
|
||||
if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
|
||||
t.Fatal("Expected JSON to format message key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONLevelKey(t *testing.T) {
|
||||
formatter := &JSONFormatter{
|
||||
FieldMap: FieldMap{
|
||||
FieldKeyLevel: "somelevel",
|
||||
},
|
||||
}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
s := string(b)
|
||||
if !strings.Contains(s, "somelevel") {
|
||||
t.Fatal("Expected JSON to format level key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONTimeKey(t *testing.T) {
|
||||
formatter := &JSONFormatter{
|
||||
FieldMap: FieldMap{
|
||||
FieldKeyTime: "timeywimey",
|
||||
},
|
||||
}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
s := string(b)
|
||||
if !strings.Contains(s, "timeywimey") {
|
||||
t.Fatal("Expected JSON to format time key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONDisableTimestamp(t *testing.T) {
|
||||
formatter := &JSONFormatter{
|
||||
DisableTimestamp: true,
|
||||
}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
s := string(b)
|
||||
if strings.Contains(s, FieldKeyTime) {
|
||||
t.Error("Did not prevent timestamp", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONEnableTimestamp(t *testing.T) {
|
||||
formatter := &JSONFormatter{}
|
||||
|
||||
b, err := formatter.Format(WithField("level", "something"))
|
||||
if err != nil {
|
||||
t.Fatal("Unable to format entry: ", err)
|
||||
}
|
||||
s := string(b)
|
||||
if !strings.Contains(s, FieldKeyTime) {
|
||||
t.Error("Timestamp not present", s)
|
||||
}
|
||||
}
|
|
@ -1,317 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
||||
// file, or leave it default which is `os.Stderr`. You can also set this to
|
||||
// something more adventorous, such as logging to Kafka.
|
||||
Out io.Writer
|
||||
// Hooks for the logger instance. These allow firing events based on logging
|
||||
// levels and log entries. For example, to send errors to an error tracking
|
||||
// service, log to StatsD or dump the core on fatal errors.
|
||||
Hooks LevelHooks
|
||||
// All log entries pass through the formatter before logged to Out. The
|
||||
// included formatters are `TextFormatter` and `JSONFormatter` for which
|
||||
// TextFormatter is the default. In development (when a TTY is attached) it
|
||||
// logs with colors, but to a file it wouldn't. You can easily implement your
|
||||
// own that implements the `Formatter` interface, see the `README` or included
|
||||
// formatters for examples.
|
||||
Formatter Formatter
|
||||
// The logging level the logger should log at. This is typically (and defaults
|
||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
||||
// logged. `logrus.Debug` is useful in
|
||||
Level Level
|
||||
// Used to sync writing to the log. Locking is enabled by Default
|
||||
mu MutexWrap
|
||||
// Reusable empty entry
|
||||
entryPool sync.Pool
|
||||
}
|
||||
|
||||
type MutexWrap struct {
|
||||
lock sync.Mutex
|
||||
disabled bool
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Lock() {
|
||||
if !mw.disabled {
|
||||
mw.lock.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Unlock() {
|
||||
if !mw.disabled {
|
||||
mw.lock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Disable() {
|
||||
mw.disabled = true
|
||||
}
|
||||
|
||||
// Creates a new logger. Configuration should be set by changing `Formatter`,
|
||||
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
||||
// instantiate your own:
|
||||
//
|
||||
// var log = &Logger{
|
||||
// Out: os.Stderr,
|
||||
// Formatter: new(JSONFormatter),
|
||||
// Hooks: make(LevelHooks),
|
||||
// Level: logrus.DebugLevel,
|
||||
// }
|
||||
//
|
||||
// It's recommended to make this a global instance called `log`.
|
||||
func New() *Logger {
|
||||
return &Logger{
|
||||
Out: os.Stderr,
|
||||
Formatter: new(TextFormatter),
|
||||
Hooks: make(LevelHooks),
|
||||
Level: InfoLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) newEntry() *Entry {
|
||||
entry, ok := logger.entryPool.Get().(*Entry)
|
||||
if ok {
|
||||
return entry
|
||||
}
|
||||
return NewEntry(logger)
|
||||
}
|
||||
|
||||
func (logger *Logger) releaseEntry(entry *Entry) {
|
||||
logger.entryPool.Put(entry)
|
||||
}
|
||||
|
||||
// Adds a field to the log entry, note that it doesn't log until you call
|
||||
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
|
||||
// If you want multiple fields, use `WithFields`.
|
||||
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithField(key, value)
|
||||
}
|
||||
|
||||
// Adds a struct of fields to the log entry. All it does is call `WithField` for
|
||||
// each `Field`.
|
||||
func (logger *Logger) WithFields(fields Fields) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithFields(fields)
|
||||
}
|
||||
|
||||
// Add an error as single field to the log entry. All it does is call
|
||||
// `WithError` for the given `error`.
|
||||
func (logger *Logger) WithError(err error) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithError(err)
|
||||
}
|
||||
|
||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
||||
if logger.level() >= DebugLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Debugf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Infof(format string, args ...interface{}) {
|
||||
if logger.level() >= InfoLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Infof(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Printf(format string, args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Printf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warnf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warnf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
||||
if logger.level() >= ErrorLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Errorf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
||||
if logger.level() >= FatalLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Fatalf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
||||
if logger.level() >= PanicLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Panicf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Debug(args ...interface{}) {
|
||||
if logger.level() >= DebugLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Debug(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Info(args ...interface{}) {
|
||||
if logger.level() >= InfoLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Info(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Print(args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Info(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warn(args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warn(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Warning(args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warn(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Error(args ...interface{}) {
|
||||
if logger.level() >= ErrorLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Error(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatal(args ...interface{}) {
|
||||
if logger.level() >= FatalLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Fatal(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panic(args ...interface{}) {
|
||||
if logger.level() >= PanicLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Panic(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Debugln(args ...interface{}) {
|
||||
if logger.level() >= DebugLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Debugln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Infoln(args ...interface{}) {
|
||||
if logger.level() >= InfoLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Infoln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Println(args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Println(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warnln(args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warnln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Warningln(args ...interface{}) {
|
||||
if logger.level() >= WarnLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Warnln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Errorln(args ...interface{}) {
|
||||
if logger.level() >= ErrorLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Errorln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatalln(args ...interface{}) {
|
||||
if logger.level() >= FatalLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Fatalln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panicln(args ...interface{}) {
|
||||
if logger.level() >= PanicLevel {
|
||||
entry := logger.newEntry()
|
||||
entry.Panicln(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
//When file is opened with appending mode, it's safe to
|
||||
//write concurrently to a file (within 4k message on Linux).
|
||||
//In these cases user can choose to disable the lock.
|
||||
func (logger *Logger) SetNoLock() {
|
||||
logger.mu.Disable()
|
||||
}
|
||||
|
||||
func (logger *Logger) level() Level {
|
||||
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
|
||||
}
|
||||
|
||||
func (logger *Logger) setLevel(level Level) {
|
||||
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// smallFields is a small size data set for benchmarking
|
||||
var loggerFields = Fields{
|
||||
"foo": "bar",
|
||||
"baz": "qux",
|
||||
"one": "two",
|
||||
"three": "four",
|
||||
}
|
||||
|
||||
func BenchmarkDummyLogger(b *testing.B) {
|
||||
nullf, err := os.OpenFile("/dev/null", os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
b.Fatalf("%v", err)
|
||||
}
|
||||
defer nullf.Close()
|
||||
doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
|
||||
}
|
||||
|
||||
func BenchmarkDummyLoggerNoLock(b *testing.B) {
|
||||
nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
b.Fatalf("%v", err)
|
||||
}
|
||||
defer nullf.Close()
|
||||
doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields)
|
||||
}
|
||||
|
||||
func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
|
||||
logger := Logger{
|
||||
Out: out,
|
||||
Level: InfoLevel,
|
||||
Formatter: formatter,
|
||||
}
|
||||
entry := logger.WithFields(fields)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
entry.Info("aaa")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) {
|
||||
logger := Logger{
|
||||
Out: out,
|
||||
Level: InfoLevel,
|
||||
Formatter: formatter,
|
||||
}
|
||||
logger.SetNoLock()
|
||||
entry := logger.WithFields(fields)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
entry.Info("aaa")
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,386 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
|
||||
var buffer bytes.Buffer
|
||||
var fields Fields
|
||||
|
||||
logger := New()
|
||||
logger.Out = &buffer
|
||||
logger.Formatter = new(JSONFormatter)
|
||||
|
||||
log(logger)
|
||||
|
||||
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assertions(fields)
|
||||
}
|
||||
|
||||
func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
logger := New()
|
||||
logger.Out = &buffer
|
||||
logger.Formatter = &TextFormatter{
|
||||
DisableColors: true,
|
||||
}
|
||||
|
||||
log(logger)
|
||||
|
||||
fields := make(map[string]string)
|
||||
for _, kv := range strings.Split(buffer.String(), " ") {
|
||||
if !strings.Contains(kv, "=") {
|
||||
continue
|
||||
}
|
||||
kvArr := strings.Split(kv, "=")
|
||||
key := strings.TrimSpace(kvArr[0])
|
||||
val := kvArr[1]
|
||||
if kvArr[1][0] == '"' {
|
||||
var err error
|
||||
val, err = strconv.Unquote(val)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
fields[key] = val
|
||||
}
|
||||
assertions(fields)
|
||||
}
|
||||
|
||||
func TestPrint(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Print("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test")
|
||||
assert.Equal(t, fields["level"], "info")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test")
|
||||
assert.Equal(t, fields["level"], "info")
|
||||
})
|
||||
}
|
||||
|
||||
func TestWarn(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Warn("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test")
|
||||
assert.Equal(t, fields["level"], "warning")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Infoln("test", "test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test test")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Infoln("test", 10)
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test 10")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Infoln(10, 10)
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "10 10")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Infoln(10, 10)
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "10 10")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Info("test", 10)
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test10")
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.Info("test", "test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "testtest")
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithFieldsShouldAllowAssignments(t *testing.T) {
|
||||
var buffer bytes.Buffer
|
||||
var fields Fields
|
||||
|
||||
logger := New()
|
||||
logger.Out = &buffer
|
||||
logger.Formatter = new(JSONFormatter)
|
||||
|
||||
localLog := logger.WithFields(Fields{
|
||||
"key1": "value1",
|
||||
})
|
||||
|
||||
localLog.WithField("key2", "value2").Info("test")
|
||||
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "value2", fields["key2"])
|
||||
assert.Equal(t, "value1", fields["key1"])
|
||||
|
||||
buffer = bytes.Buffer{}
|
||||
fields = Fields{}
|
||||
localLog.Info("test")
|
||||
err = json.Unmarshal(buffer.Bytes(), &fields)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, ok := fields["key2"]
|
||||
assert.Equal(t, false, ok)
|
||||
assert.Equal(t, "value1", fields["key1"])
|
||||
}
|
||||
|
||||
func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.WithField("msg", "hello").Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.WithField("msg", "hello").Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["msg"], "test")
|
||||
assert.Equal(t, fields["fields.msg"], "hello")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.WithField("time", "hello").Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["fields.time"], "hello")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
|
||||
LogAndAssertJSON(t, func(log *Logger) {
|
||||
log.WithField("level", 1).Info("test")
|
||||
}, func(fields Fields) {
|
||||
assert.Equal(t, fields["level"], "info")
|
||||
assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
|
||||
})
|
||||
}
|
||||
|
||||
func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
|
||||
LogAndAssertText(t, func(log *Logger) {
|
||||
ll := log.WithField("herp", "derp")
|
||||
ll.Info("hello")
|
||||
ll.Info("bye")
|
||||
}, func(fields map[string]string) {
|
||||
for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
|
||||
if _, ok := fields[fieldName]; ok {
|
||||
t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
|
||||
|
||||
var buffer bytes.Buffer
|
||||
var fields Fields
|
||||
|
||||
logger := New()
|
||||
logger.Out = &buffer
|
||||
logger.Formatter = new(JSONFormatter)
|
||||
|
||||
llog := logger.WithField("context", "eating raw fish")
|
||||
|
||||
llog.Info("looks delicious")
|
||||
|
||||
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||
assert.NoError(t, err, "should have decoded first message")
|
||||
assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
|
||||
assert.Equal(t, fields["msg"], "looks delicious")
|
||||
assert.Equal(t, fields["context"], "eating raw fish")
|
||||
|
||||
buffer.Reset()
|
||||
|
||||
llog.Warn("omg it is!")
|
||||
|
||||
err = json.Unmarshal(buffer.Bytes(), &fields)
|
||||
assert.NoError(t, err, "should have decoded second message")
|
||||
assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
|
||||
assert.Equal(t, fields["msg"], "omg it is!")
|
||||
assert.Equal(t, fields["context"], "eating raw fish")
|
||||
assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
|
||||
|
||||
}
|
||||
|
||||
func TestConvertLevelToString(t *testing.T) {
|
||||
assert.Equal(t, "debug", DebugLevel.String())
|
||||
assert.Equal(t, "info", InfoLevel.String())
|
||||
assert.Equal(t, "warning", WarnLevel.String())
|
||||
assert.Equal(t, "error", ErrorLevel.String())
|
||||
assert.Equal(t, "fatal", FatalLevel.String())
|
||||
assert.Equal(t, "panic", PanicLevel.String())
|
||||
}
|
||||
|
||||
func TestParseLevel(t *testing.T) {
|
||||
l, err := ParseLevel("panic")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, PanicLevel, l)
|
||||
|
||||
l, err = ParseLevel("PANIC")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, PanicLevel, l)
|
||||
|
||||
l, err = ParseLevel("fatal")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, FatalLevel, l)
|
||||
|
||||
l, err = ParseLevel("FATAL")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, FatalLevel, l)
|
||||
|
||||
l, err = ParseLevel("error")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, ErrorLevel, l)
|
||||
|
||||
l, err = ParseLevel("ERROR")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, ErrorLevel, l)
|
||||
|
||||
l, err = ParseLevel("warn")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, WarnLevel, l)
|
||||
|
||||
l, err = ParseLevel("WARN")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, WarnLevel, l)
|
||||
|
||||
l, err = ParseLevel("warning")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, WarnLevel, l)
|
||||
|
||||
l, err = ParseLevel("WARNING")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, WarnLevel, l)
|
||||
|
||||
l, err = ParseLevel("info")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, InfoLevel, l)
|
||||
|
||||
l, err = ParseLevel("INFO")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, InfoLevel, l)
|
||||
|
||||
l, err = ParseLevel("debug")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, DebugLevel, l)
|
||||
|
||||
l, err = ParseLevel("DEBUG")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, DebugLevel, l)
|
||||
|
||||
l, err = ParseLevel("invalid")
|
||||
assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
|
||||
}
|
||||
|
||||
func TestGetSetLevelRace(t *testing.T) {
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < 100; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
if i%2 == 0 {
|
||||
SetLevel(InfoLevel)
|
||||
} else {
|
||||
GetLevel()
|
||||
}
|
||||
}(i)
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestLoggingRace(t *testing.T) {
|
||||
logger := New()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(100)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
go func() {
|
||||
logger.Info("info")
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// Compile test
|
||||
func TestLogrusInterface(t *testing.T) {
|
||||
var buffer bytes.Buffer
|
||||
fn := func(l FieldLogger) {
|
||||
b := l.WithField("key", "value")
|
||||
b.Debug("Test")
|
||||
}
|
||||
// test logger
|
||||
logger := New()
|
||||
logger.Out = &buffer
|
||||
fn(logger)
|
||||
|
||||
// test Entry
|
||||
e := logger.WithField("another", "value")
|
||||
fn(e)
|
||||
}
|
||||
|
||||
// Implements io.Writer using channels for synchronization, so we can wait on
|
||||
// the Entry.Writer goroutine to write in a non-racey way. This does assume that
|
||||
// there is a single call to Logger.Out for each message.
|
||||
type channelWriter chan []byte
|
||||
|
||||
func (cw channelWriter) Write(p []byte) (int, error) {
|
||||
cw <- p
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func TestEntryWriter(t *testing.T) {
|
||||
cw := channelWriter(make(chan []byte, 1))
|
||||
log := New()
|
||||
log.Out = cw
|
||||
log.Formatter = new(JSONFormatter)
|
||||
log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
|
||||
|
||||
bs := <-cw
|
||||
var fields Fields
|
||||
err := json.Unmarshal(bs, &fields)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, fields["foo"], "bar")
|
||||
assert.Equal(t, fields["level"], "warning")
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
// +build appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import "io"
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
return true
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
type Termios syscall.Termios
|
|
@ -1,14 +0,0 @@
|
|||
// Based on ssh/terminal:
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
type Termios syscall.Termios
|
|
@ -1,28 +0,0 @@
|
|||
// Based on ssh/terminal:
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
var termios Termios
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// +build solaris,!appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
_, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA)
|
||||
return err == nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// Based on ssh/terminal:
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,!appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
var (
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||
)
|
||||
|
||||
const (
|
||||
enableProcessedOutput = 0x0001
|
||||
enableWrapAtEolOutput = 0x0002
|
||||
enableVirtualTerminalProcessing = 0x0004
|
||||
)
|
||||
|
||||
func getVersion() (float64, error) {
|
||||
stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
|
||||
cmd := exec.Command("cmd", "ver")
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// The output should be like "Microsoft Windows [Version XX.X.XXXXXX]"
|
||||
version := strings.Replace(stdout.String(), "\n", "", -1)
|
||||
version = strings.Replace(version, "\r\n", "", -1)
|
||||
|
||||
x1 := strings.Index(version, "[Version")
|
||||
|
||||
if x1 == -1 || strings.Index(version, "]") == -1 {
|
||||
return -1, errors.New("Can't determine Windows version")
|
||||
}
|
||||
|
||||
return strconv.ParseFloat(version[x1+9:x1+13], 64)
|
||||
}
|
||||
|
||||
func init() {
|
||||
ver, err := getVersion()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Activate Virtual Processing for Windows CMD
|
||||
// Info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
if ver >= 10 {
|
||||
handle := syscall.Handle(os.Stderr.Fd())
|
||||
procSetConsoleMode.Call(uintptr(handle), enableProcessedOutput|enableWrapAtEolOutput|enableVirtualTerminalProcessing)
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
nocolor = 0
|
||||
red = 31
|
||||
green = 32
|
||||
yellow = 33
|
||||
blue = 34
|
||||
gray = 37
|
||||
)
|
||||
|
||||
var (
|
||||
baseTimestamp time.Time
|
||||
)
|
||||
|
||||
func init() {
|
||||
baseTimestamp = time.Now()
|
||||
}
|
||||
|
||||
type TextFormatter struct {
|
||||
// Set to true to bypass checking for a TTY before outputting colors.
|
||||
ForceColors bool
|
||||
|
||||
// Force disabling colors.
|
||||
DisableColors bool
|
||||
|
||||
// Disable timestamp logging. useful when output is redirected to logging
|
||||
// system that already adds timestamps.
|
||||
DisableTimestamp bool
|
||||
|
||||
// Enable logging the full timestamp when a TTY is attached instead of just
|
||||
// the time passed since beginning of execution.
|
||||
FullTimestamp bool
|
||||
|
||||
// TimestampFormat to use for display when a full timestamp is printed
|
||||
TimestampFormat string
|
||||
|
||||
// The fields are sorted by default for a consistent output. For applications
|
||||
// that log extremely frequently and don't use the JSON formatter this may not
|
||||
// be desired.
|
||||
DisableSorting bool
|
||||
|
||||
// QuoteEmptyFields will wrap empty fields in quotes if true
|
||||
QuoteEmptyFields bool
|
||||
|
||||
// QuoteCharacter can be set to the override the default quoting character "
|
||||
// with something else. For example: ', or `.
|
||||
QuoteCharacter string
|
||||
|
||||
// Whether the logger's out is to a terminal
|
||||
isTerminal bool
|
||||
|
||||
sync.Once
|
||||
}
|
||||
|
||||
func (f *TextFormatter) init(entry *Entry) {
|
||||
if len(f.QuoteCharacter) == 0 {
|
||||
f.QuoteCharacter = "\""
|
||||
}
|
||||
if entry.Logger != nil {
|
||||
f.isTerminal = IsTerminal(entry.Logger.Out)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
keys := make([]string, 0, len(entry.Data))
|
||||
for k := range entry.Data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
if !f.DisableSorting {
|
||||
sort.Strings(keys)
|
||||
}
|
||||
if entry.Buffer != nil {
|
||||
b = entry.Buffer
|
||||
} else {
|
||||
b = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
prefixFieldClashes(entry.Data)
|
||||
|
||||
f.Do(func() { f.init(entry) })
|
||||
|
||||
isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
timestampFormat = DefaultTimestampFormat
|
||||
}
|
||||
if isColored {
|
||||
f.printColored(b, entry, keys, timestampFormat)
|
||||
} else {
|
||||
if !f.DisableTimestamp {
|
||||
f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
|
||||
}
|
||||
f.appendKeyValue(b, "level", entry.Level.String())
|
||||
if entry.Message != "" {
|
||||
f.appendKeyValue(b, "msg", entry.Message)
|
||||
}
|
||||
for _, key := range keys {
|
||||
f.appendKeyValue(b, key, entry.Data[key])
|
||||
}
|
||||
}
|
||||
|
||||
b.WriteByte('\n')
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
|
||||
var levelColor int
|
||||
switch entry.Level {
|
||||
case DebugLevel:
|
||||
levelColor = gray
|
||||
case WarnLevel:
|
||||
levelColor = yellow
|
||||
case ErrorLevel, FatalLevel, PanicLevel:
|
||||
levelColor = red
|
||||
default:
|
||||
levelColor = blue
|
||||
}
|
||||
|
||||
levelText := strings.ToUpper(entry.Level.String())[0:4]
|
||||
|
||||
if f.DisableTimestamp {
|
||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
|
||||
} else if !f.FullTimestamp {
|
||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message)
|
||||
} else {
|
||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
|
||||
}
|
||||
for _, k := range keys {
|
||||
v := entry.Data[k]
|
||||
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
|
||||
f.appendValue(b, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *TextFormatter) needsQuoting(text string) bool {
|
||||
if f.QuoteEmptyFields && len(text) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, ch := range text {
|
||||
if !((ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') ||
|
||||
ch == '-' || ch == '.') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
|
||||
|
||||
b.WriteString(key)
|
||||
b.WriteByte('=')
|
||||
f.appendValue(b, value)
|
||||
b.WriteByte(' ')
|
||||
}
|
||||
|
||||
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if !f.needsQuoting(value) {
|
||||
b.WriteString(value)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter)
|
||||
}
|
||||
case error:
|
||||
errmsg := value.Error()
|
||||
if !f.needsQuoting(errmsg) {
|
||||
b.WriteString(errmsg)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter)
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(b, value)
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestQuoting(t *testing.T) {
|
||||
tf := &TextFormatter{DisableColors: true}
|
||||
|
||||
checkQuoting := func(q bool, value interface{}) {
|
||||
b, _ := tf.Format(WithField("test", value))
|
||||
idx := bytes.Index(b, ([]byte)("test="))
|
||||
cont := bytes.Contains(b[idx+5:], []byte(tf.QuoteCharacter))
|
||||
if cont != q {
|
||||
if q {
|
||||
t.Errorf("quoting expected for: %#v", value)
|
||||
} else {
|
||||
t.Errorf("quoting not expected for: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkQuoting(false, "")
|
||||
checkQuoting(false, "abcd")
|
||||
checkQuoting(false, "v1.0")
|
||||
checkQuoting(false, "1234567890")
|
||||
checkQuoting(true, "/foobar")
|
||||
checkQuoting(true, "x y")
|
||||
checkQuoting(true, "x,y")
|
||||
checkQuoting(false, errors.New("invalid"))
|
||||
checkQuoting(true, errors.New("invalid argument"))
|
||||
|
||||
// Test for custom quote character.
|
||||
tf.QuoteCharacter = "`"
|
||||
checkQuoting(false, "")
|
||||
checkQuoting(false, "abcd")
|
||||
checkQuoting(true, "/foobar")
|
||||
checkQuoting(true, errors.New("invalid argument"))
|
||||
|
||||
// Test for multi-character quotes.
|
||||
tf.QuoteCharacter = "§~±"
|
||||
checkQuoting(false, "abcd")
|
||||
checkQuoting(true, errors.New("invalid argument"))
|
||||
|
||||
// Test for quoting empty fields.
|
||||
tf.QuoteEmptyFields = true
|
||||
checkQuoting(true, "")
|
||||
checkQuoting(false, "abcd")
|
||||
checkQuoting(true, errors.New("invalid argument"))
|
||||
}
|
||||
|
||||
func TestTimestampFormat(t *testing.T) {
|
||||
checkTimeStr := func(format string) {
|
||||
customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format}
|
||||
customStr, _ := customFormatter.Format(WithField("test", "test"))
|
||||
timeStart := bytes.Index(customStr, ([]byte)("time="))
|
||||
timeEnd := bytes.Index(customStr, ([]byte)("level="))
|
||||
timeStr := customStr[timeStart+5+len(customFormatter.QuoteCharacter) : timeEnd-1-len(customFormatter.QuoteCharacter)]
|
||||
if format == "" {
|
||||
format = time.RFC3339
|
||||
}
|
||||
_, e := time.Parse(format, (string)(timeStr))
|
||||
if e != nil {
|
||||
t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e)
|
||||
}
|
||||
}
|
||||
|
||||
checkTimeStr("2006-01-02T15:04:05.000000000Z07:00")
|
||||
checkTimeStr("Mon Jan _2 15:04:05 2006")
|
||||
checkTimeStr("")
|
||||
}
|
||||
|
||||
func TestDisableTimestampWithColoredOutput(t *testing.T) {
|
||||
tf := &TextFormatter{DisableTimestamp: true, ForceColors: true}
|
||||
|
||||
b, _ := tf.Format(WithField("test", "test"))
|
||||
if strings.Contains(string(b), "[0000]") {
|
||||
t.Error("timestamp not expected when DisableTimestamp is true")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add tests for sorting etc., this requires a parser for the text
|
||||
// formatter output.
|
|
@ -0,0 +1,15 @@
|
|||
ISC License
|
||||
|
||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -0,0 +1,145 @@
|
|||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// Go versions prior to 1.4 are disabled because they use a different layout
|
||||
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
||||
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||
// not access to the unsafe package is available.
|
||||
UnsafeDisabled = false
|
||||
|
||||
// ptrSize is the size of a pointer on the current arch.
|
||||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||
)
|
||||
|
||||
type flag uintptr
|
||||
|
||||
var (
|
||||
// flagRO indicates whether the value field of a reflect.Value
|
||||
// is read-only.
|
||||
flagRO flag
|
||||
|
||||
// flagAddr indicates whether the address of the reflect.Value's
|
||||
// value may be taken.
|
||||
flagAddr flag
|
||||
)
|
||||
|
||||
// flagKindMask holds the bits that make up the kind
|
||||
// part of the flags field. In all the supported versions,
|
||||
// it is in the lower 5 bits.
|
||||
const flagKindMask = flag(0x1f)
|
||||
|
||||
// Different versions of Go have used different
|
||||
// bit layouts for the flags type. This table
|
||||
// records the known combinations.
|
||||
var okFlags = []struct {
|
||||
ro, addr flag
|
||||
}{{
|
||||
// From Go 1.4 to 1.5
|
||||
ro: 1 << 5,
|
||||
addr: 1 << 7,
|
||||
}, {
|
||||
// Up to Go tip.
|
||||
ro: 1<<5 | 1<<6,
|
||||
addr: 1 << 8,
|
||||
}}
|
||||
|
||||
var flagValOffset = func() uintptr {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
return field.Offset
|
||||
}()
|
||||
|
||||
// flagField returns a pointer to the flag field of a reflect.Value.
|
||||
func flagField(v *reflect.Value) *flag {
|
||||
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
||||
}
|
||||
|
||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||
// the typical safety restrictions preventing access to unaddressable and
|
||||
// unexported data. It works by digging the raw pointer to the underlying
|
||||
// value out of the protected value and generating a new unprotected (unsafe)
|
||||
// reflect.Value to it.
|
||||
//
|
||||
// This allows us to check for implementations of the Stringer and error
|
||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||
// inaccessible values such as unexported struct fields.
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
||||
return v
|
||||
}
|
||||
flagFieldPtr := flagField(&v)
|
||||
*flagFieldPtr &^= flagRO
|
||||
*flagFieldPtr |= flagAddr
|
||||
return v
|
||||
}
|
||||
|
||||
// Sanity checks against future reflect package changes
|
||||
// to the type or semantics of the Value.flag field.
|
||||
func init() {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
||||
panic("reflect.Value flag field has changed kind")
|
||||
}
|
||||
type t0 int
|
||||
var t struct {
|
||||
A t0
|
||||
// t0 will have flagEmbedRO set.
|
||||
t0
|
||||
// a will have flagStickyRO set
|
||||
a t0
|
||||
}
|
||||
vA := reflect.ValueOf(t).FieldByName("A")
|
||||
va := reflect.ValueOf(t).FieldByName("a")
|
||||
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
||||
|
||||
// Infer flagRO from the difference between the flags
|
||||
// for the (otherwise identical) fields in t.
|
||||
flagPublic := *flagField(&vA)
|
||||
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
||||
flagRO = flagPublic ^ flagWithRO
|
||||
|
||||
// Infer flagAddr from the difference between a value
|
||||
// taken from a pointer and not.
|
||||
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
||||
flagNoPtr := *flagField(&vA)
|
||||
flagPtr := *flagField(&vPtrA)
|
||||
flagAddr = flagNoPtr ^ flagPtr
|
||||
|
||||
// Check that the inferred flags tally with one of the known versions.
|
||||
for _, f := range okFlags {
|
||||
if flagRO == f.ro && flagAddr == f.addr {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic("reflect.Value read-only flag has changed semantics")
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build js appengine safe disableunsafe !go1.4
|
||||
|
||||
package spew
|
||||
|
||||
import "reflect"
|
||||
|
||||
const (
|
||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||
// not access to the unsafe package is available.
|
||||
UnsafeDisabled = true
|
||||
)
|
||||
|
||||
// unsafeReflectValue typically converts the passed reflect.Value into a one
|
||||
// that bypasses the typical safety restrictions preventing access to
|
||||
// unaddressable and unexported data. However, doing this relies on access to
|
||||
// the unsafe package. This is a stub version which simply returns the passed
|
||||
// reflect.Value when the unsafe package is not available.
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
return v
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Some constants in the form of bytes to avoid string overhead. This mirrors
|
||||
// the technique used in the fmt package.
|
||||
var (
|
||||
panicBytes = []byte("(PANIC=")
|
||||
plusBytes = []byte("+")
|
||||
iBytes = []byte("i")
|
||||
trueBytes = []byte("true")
|
||||
falseBytes = []byte("false")
|
||||
interfaceBytes = []byte("(interface {})")
|
||||
commaNewlineBytes = []byte(",\n")
|
||||
newlineBytes = []byte("\n")
|
||||
openBraceBytes = []byte("{")
|
||||
openBraceNewlineBytes = []byte("{\n")
|
||||
closeBraceBytes = []byte("}")
|
||||
asteriskBytes = []byte("*")
|
||||
colonBytes = []byte(":")
|
||||
colonSpaceBytes = []byte(": ")
|
||||
openParenBytes = []byte("(")
|
||||
closeParenBytes = []byte(")")
|
||||
spaceBytes = []byte(" ")
|
||||
pointerChainBytes = []byte("->")
|
||||
nilAngleBytes = []byte("<nil>")
|
||||
maxNewlineBytes = []byte("<max depth reached>\n")
|
||||
maxShortBytes = []byte("<max>")
|
||||
circularBytes = []byte("<already shown>")
|
||||
circularShortBytes = []byte("<shown>")
|
||||
invalidAngleBytes = []byte("<invalid>")
|
||||
openBracketBytes = []byte("[")
|
||||
closeBracketBytes = []byte("]")
|
||||
percentBytes = []byte("%")
|
||||
precisionBytes = []byte(".")
|
||||
openAngleBytes = []byte("<")
|
||||
closeAngleBytes = []byte(">")
|
||||
openMapBytes = []byte("map[")
|
||||
closeMapBytes = []byte("]")
|
||||
lenEqualsBytes = []byte("len=")
|
||||
capEqualsBytes = []byte("cap=")
|
||||
)
|
||||
|
||||
// hexDigits is used to map a decimal value to a hex digit.
|
||||
var hexDigits = "0123456789abcdef"
|
||||
|
||||
// catchPanic handles any panics that might occur during the handleMethods
|
||||
// calls.
|
||||
func catchPanic(w io.Writer, v reflect.Value) {
|
||||
if err := recover(); err != nil {
|
||||
w.Write(panicBytes)
|
||||
fmt.Fprintf(w, "%v", err)
|
||||
w.Write(closeParenBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// handleMethods attempts to call the Error and String methods on the underlying
|
||||
// type the passed reflect.Value represents and outputes the result to Writer w.
|
||||
//
|
||||
// It handles panics in any called methods by catching and displaying the error
|
||||
// as the formatted value.
|
||||
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
|
||||
// We need an interface to check if the type implements the error or
|
||||
// Stringer interface. However, the reflect package won't give us an
|
||||
// interface on certain things like unexported struct fields in order
|
||||
// to enforce visibility rules. We use unsafe, when it's available,
|
||||
// to bypass these restrictions since this package does not mutate the
|
||||
// values.
|
||||
if !v.CanInterface() {
|
||||
if UnsafeDisabled {
|
||||
return false
|
||||
}
|
||||
|
||||
v = unsafeReflectValue(v)
|
||||
}
|
||||
|
||||
// Choose whether or not to do error and Stringer interface lookups against
|
||||
// the base type or a pointer to the base type depending on settings.
|
||||
// Technically calling one of these methods with a pointer receiver can
|
||||
// mutate the value, however, types which choose to satisify an error or
|
||||
// Stringer interface with a pointer receiver should not be mutating their
|
||||
// state inside these interface methods.
|
||||
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
|
||||
v = unsafeReflectValue(v)
|
||||
}
|
||||
if v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
// Is it an error or Stringer?
|
||||
switch iface := v.Interface().(type) {
|
||||
case error:
|
||||
defer catchPanic(w, v)
|
||||
if cs.ContinueOnMethod {
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(iface.Error()))
|
||||
w.Write(closeParenBytes)
|
||||
w.Write(spaceBytes)
|
||||
return false
|
||||
}
|
||||
|
||||
w.Write([]byte(iface.Error()))
|
||||
return true
|
||||
|
||||
case fmt.Stringer:
|
||||
defer catchPanic(w, v)
|
||||
if cs.ContinueOnMethod {
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(iface.String()))
|
||||
w.Write(closeParenBytes)
|
||||
w.Write(spaceBytes)
|
||||
return false
|
||||
}
|
||||
w.Write([]byte(iface.String()))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// printBool outputs a boolean value as true or false to Writer w.
|
||||
func printBool(w io.Writer, val bool) {
|
||||
if val {
|
||||
w.Write(trueBytes)
|
||||
} else {
|
||||
w.Write(falseBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// printInt outputs a signed integer value to Writer w.
|
||||
func printInt(w io.Writer, val int64, base int) {
|
||||
w.Write([]byte(strconv.FormatInt(val, base)))
|
||||
}
|
||||
|
||||
// printUint outputs an unsigned integer value to Writer w.
|
||||
func printUint(w io.Writer, val uint64, base int) {
|
||||
w.Write([]byte(strconv.FormatUint(val, base)))
|
||||
}
|
||||
|
||||
// printFloat outputs a floating point value using the specified precision,
|
||||
// which is expected to be 32 or 64bit, to Writer w.
|
||||
func printFloat(w io.Writer, val float64, precision int) {
|
||||
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
|
||||
}
|
||||
|
||||
// printComplex outputs a complex value using the specified float precision
|
||||
// for the real and imaginary parts to Writer w.
|
||||
func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||
r := real(c)
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
||||
i := imag(c)
|
||||
if i >= 0 {
|
||||
w.Write(plusBytes)
|
||||
}
|
||||
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
||||
w.Write(iBytes)
|
||||
w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||
// prefix to Writer w.
|
||||
func printHexPtr(w io.Writer, p uintptr) {
|
||||
// Null pointer.
|
||||
num := uint64(p)
|
||||
if num == 0 {
|
||||
w.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
|
||||
buf := make([]byte, 18)
|
||||
|
||||
// It's simpler to construct the hex string right to left.
|
||||
base := uint64(16)
|
||||
i := len(buf) - 1
|
||||
for num >= base {
|
||||
buf[i] = hexDigits[num%base]
|
||||
num /= base
|
||||
i--
|
||||
}
|
||||
buf[i] = hexDigits[num]
|
||||
|
||||
// Add '0x' prefix.
|
||||
i--
|
||||
buf[i] = 'x'
|
||||
i--
|
||||
buf[i] = '0'
|
||||
|
||||
// Strip unused leading bytes.
|
||||
buf = buf[i:]
|
||||
w.Write(buf)
|
||||
}
|
||||
|
||||
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
|
||||
// elements to be sorted.
|
||||
type valuesSorter struct {
|
||||
values []reflect.Value
|
||||
strings []string // either nil or same len and values
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// newValuesSorter initializes a valuesSorter instance, which holds a set of
|
||||
// surrogate keys on which the data should be sorted. It uses flags in
|
||||
// ConfigState to decide if and how to populate those surrogate keys.
|
||||
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
|
||||
vs := &valuesSorter{values: values, cs: cs}
|
||||
if canSortSimply(vs.values[0].Kind()) {
|
||||
return vs
|
||||
}
|
||||
if !cs.DisableMethods {
|
||||
vs.strings = make([]string, len(values))
|
||||
for i := range vs.values {
|
||||
b := bytes.Buffer{}
|
||||
if !handleMethods(cs, &b, vs.values[i]) {
|
||||
vs.strings = nil
|
||||
break
|
||||
}
|
||||
vs.strings[i] = b.String()
|
||||
}
|
||||
}
|
||||
if vs.strings == nil && cs.SpewKeys {
|
||||
vs.strings = make([]string, len(values))
|
||||
for i := range vs.values {
|
||||
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
|
||||
}
|
||||
}
|
||||
return vs
|
||||
}
|
||||
|
||||
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
|
||||
// directly, or whether it should be considered for sorting by surrogate keys
|
||||
// (if the ConfigState allows it).
|
||||
func canSortSimply(kind reflect.Kind) bool {
|
||||
// This switch parallels valueSortLess, except for the default case.
|
||||
switch kind {
|
||||
case reflect.Bool:
|
||||
return true
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
return true
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
return true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
case reflect.String:
|
||||
return true
|
||||
case reflect.Uintptr:
|
||||
return true
|
||||
case reflect.Array:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Len returns the number of values in the slice. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s *valuesSorter) Len() int {
|
||||
return len(s.values)
|
||||
}
|
||||
|
||||
// Swap swaps the values at the passed indices. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s *valuesSorter) Swap(i, j int) {
|
||||
s.values[i], s.values[j] = s.values[j], s.values[i]
|
||||
if s.strings != nil {
|
||||
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
|
||||
}
|
||||
}
|
||||
|
||||
// valueSortLess returns whether the first value should sort before the second
|
||||
// value. It is used by valueSorter.Less as part of the sort.Interface
|
||||
// implementation.
|
||||
func valueSortLess(a, b reflect.Value) bool {
|
||||
switch a.Kind() {
|
||||
case reflect.Bool:
|
||||
return !a.Bool() && b.Bool()
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
return a.Int() < b.Int()
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return a.Float() < b.Float()
|
||||
case reflect.String:
|
||||
return a.String() < b.String()
|
||||
case reflect.Uintptr:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Array:
|
||||
// Compare the contents of both arrays.
|
||||
l := a.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
av := a.Index(i)
|
||||
bv := b.Index(i)
|
||||
if av.Interface() == bv.Interface() {
|
||||
continue
|
||||
}
|
||||
return valueSortLess(av, bv)
|
||||
}
|
||||
}
|
||||
return a.String() < b.String()
|
||||
}
|
||||
|
||||
// Less returns whether the value at index i should sort before the
|
||||
// value at index j. It is part of the sort.Interface implementation.
|
||||
func (s *valuesSorter) Less(i, j int) bool {
|
||||
if s.strings == nil {
|
||||
return valueSortLess(s.values[i], s.values[j])
|
||||
}
|
||||
return s.strings[i] < s.strings[j]
|
||||
}
|
||||
|
||||
// sortValues is a sort function that handles both native types and any type that
|
||||
// can be converted to error or Stringer. Other inputs are sorted according to
|
||||
// their Value.String() value to ensure display stability.
|
||||
func sortValues(values []reflect.Value, cs *ConfigState) {
|
||||
if len(values) == 0 {
|
||||
return
|
||||
}
|
||||
sort.Sort(newValuesSorter(values, cs))
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ConfigState houses the configuration options used by spew to format and
|
||||
// display values. There is a global instance, Config, that is used to control
|
||||
// all top-level Formatter and Dump functionality. Each ConfigState instance
|
||||
// provides methods equivalent to the top-level functions.
|
||||
//
|
||||
// The zero value for ConfigState provides no indentation. You would typically
|
||||
// want to set it to a space or a tab.
|
||||
//
|
||||
// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
|
||||
// with default settings. See the documentation of NewDefaultConfig for default
|
||||
// values.
|
||||
type ConfigState struct {
|
||||
// Indent specifies the string to use for each indentation level. The
|
||||
// global config instance that all top-level functions use set this to a
|
||||
// single space by default. If you would like more indentation, you might
|
||||
// set this to a tab with "\t" or perhaps two spaces with " ".
|
||||
Indent string
|
||||
|
||||
// MaxDepth controls the maximum number of levels to descend into nested
|
||||
// data structures. The default, 0, means there is no limit.
|
||||
//
|
||||
// NOTE: Circular data structures are properly detected, so it is not
|
||||
// necessary to set this value unless you specifically want to limit deeply
|
||||
// nested data structures.
|
||||
MaxDepth int
|
||||
|
||||
// DisableMethods specifies whether or not error and Stringer interfaces are
|
||||
// invoked for types that implement them.
|
||||
DisableMethods bool
|
||||
|
||||
// DisablePointerMethods specifies whether or not to check for and invoke
|
||||
// error and Stringer interfaces on types which only accept a pointer
|
||||
// receiver when the current type is not a pointer.
|
||||
//
|
||||
// NOTE: This might be an unsafe action since calling one of these methods
|
||||
// with a pointer receiver could technically mutate the value, however,
|
||||
// in practice, types which choose to satisify an error or Stringer
|
||||
// interface with a pointer receiver should not be mutating their state
|
||||
// inside these interface methods. As a result, this option relies on
|
||||
// access to the unsafe package, so it will not have any effect when
|
||||
// running in environments without access to the unsafe package such as
|
||||
// Google App Engine or with the "safe" build tag specified.
|
||||
DisablePointerMethods bool
|
||||
|
||||
// DisablePointerAddresses specifies whether to disable the printing of
|
||||
// pointer addresses. This is useful when diffing data structures in tests.
|
||||
DisablePointerAddresses bool
|
||||
|
||||
// DisableCapacities specifies whether to disable the printing of capacities
|
||||
// for arrays, slices, maps and channels. This is useful when diffing
|
||||
// data structures in tests.
|
||||
DisableCapacities bool
|
||||
|
||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||
// a custom error or Stringer interface is invoked. The default, false,
|
||||
// means it will print the results of invoking the custom error or Stringer
|
||||
// interface and return immediately instead of continuing to recurse into
|
||||
// the internals of the data type.
|
||||
//
|
||||
// NOTE: This flag does not have any effect if method invocation is disabled
|
||||
// via the DisableMethods or DisablePointerMethods options.
|
||||
ContinueOnMethod bool
|
||||
|
||||
// SortKeys specifies map keys should be sorted before being printed. Use
|
||||
// this to have a more deterministic, diffable output. Note that only
|
||||
// native types (bool, int, uint, floats, uintptr and string) and types
|
||||
// that support the error or Stringer interfaces (if methods are
|
||||
// enabled) are supported, with other types sorted according to the
|
||||
// reflect.Value.String() output which guarantees display stability.
|
||||
SortKeys bool
|
||||
|
||||
// SpewKeys specifies that, as a last resort attempt, map keys should
|
||||
// be spewed to strings and sorted by those strings. This is only
|
||||
// considered if SortKeys is true.
|
||||
SpewKeys bool
|
||||
}
|
||||
|
||||
// Config is the active configuration of the top-level functions.
|
||||
// The configuration can be changed by modifying the contents of spew.Config.
|
||||
var Config = ConfigState{Indent: " "}
|
||||
|
||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the formatted string as a value that satisfies error. See NewFormatter
|
||||
// for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
|
||||
return fmt.Errorf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprint(w, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintf(w, format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||
// passed with a Formatter interface returned by c.NewFormatter. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintln(w, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
|
||||
return fmt.Print(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Printf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
|
||||
return fmt.Println(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprint(a ...interface{}) string {
|
||||
return fmt.Sprint(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
|
||||
return fmt.Sprintf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||
// were passed with a Formatter interface returned by c.NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprintln(a ...interface{}) string {
|
||||
return fmt.Sprintln(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
/*
|
||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||
interface. As a result, it integrates cleanly with standard fmt package
|
||||
printing functions. The formatter is useful for inline printing of smaller data
|
||||
types similar to the standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Typically this function shouldn't be called directly. It is much easier to make
|
||||
use of the custom formatter by calling one of the convenience functions such as
|
||||
c.Printf, c.Println, or c.Printf.
|
||||
*/
|
||||
func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
|
||||
return newFormatter(c, v)
|
||||
}
|
||||
|
||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||
// exactly the same as Dump.
|
||||
func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
|
||||
fdump(c, w, a...)
|
||||
}
|
||||
|
||||
/*
|
||||
Dump displays the passed parameters to standard out with newlines, customizable
|
||||
indentation, and additional debug information such as complete types and all
|
||||
pointer addresses used to indirect to the final value. It provides the
|
||||
following features over the built-in printing facilities provided by the fmt
|
||||
package:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output
|
||||
|
||||
The configuration options are controlled by modifying the public members
|
||||
of c. See ConfigState for options documentation.
|
||||
|
||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||
get the formatted result as a string.
|
||||
*/
|
||||
func (c *ConfigState) Dump(a ...interface{}) {
|
||||
fdump(c, os.Stdout, a...)
|
||||
}
|
||||
|
||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||
// as Dump.
|
||||
func (c *ConfigState) Sdump(a ...interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
fdump(c, &buf, a...)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||
// length with each argument converted to a spew Formatter interface using
|
||||
// the ConfigState associated with s.
|
||||
func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
|
||||
formatters = make([]interface{}, len(args))
|
||||
for index, arg := range args {
|
||||
formatters[index] = newFormatter(c, arg)
|
||||
}
|
||||
return formatters
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a ConfigState with the following default settings.
|
||||
//
|
||||
// Indent: " "
|
||||
// MaxDepth: 0
|
||||
// DisableMethods: false
|
||||
// DisablePointerMethods: false
|
||||
// ContinueOnMethod: false
|
||||
// SortKeys: false
|
||||
func NewDefaultConfig() *ConfigState {
|
||||
return &ConfigState{Indent: " "}
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package spew implements a deep pretty printer for Go data structures to aid in
|
||||
debugging.
|
||||
|
||||
A quick overview of the additional features spew provides over the built-in
|
||||
printing facilities for Go data types are as follows:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output (only when using
|
||||
Dump style)
|
||||
|
||||
There are two different approaches spew allows for dumping Go data structures:
|
||||
|
||||
* Dump style which prints with newlines, customizable indentation,
|
||||
and additional debug information such as types and all pointer addresses
|
||||
used to indirect to the final value
|
||||
* A custom Formatter interface that integrates cleanly with the standard fmt
|
||||
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
|
||||
similar to the default %v while providing the additional functionality
|
||||
outlined above and passing unsupported format verbs such as %x and %q
|
||||
along to fmt
|
||||
|
||||
Quick Start
|
||||
|
||||
This section demonstrates how to quickly get started with spew. See the
|
||||
sections below for further details on formatting and configuration options.
|
||||
|
||||
To dump a variable with full newlines, indentation, type, and pointer
|
||||
information use Dump, Fdump, or Sdump:
|
||||
spew.Dump(myVar1, myVar2, ...)
|
||||
spew.Fdump(someWriter, myVar1, myVar2, ...)
|
||||
str := spew.Sdump(myVar1, myVar2, ...)
|
||||
|
||||
Alternatively, if you would prefer to use format strings with a compacted inline
|
||||
printing style, use the convenience wrappers Printf, Fprintf, etc with
|
||||
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
|
||||
%#+v (adds types and pointer addresses):
|
||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
|
||||
Configuration Options
|
||||
|
||||
Configuration of spew is handled by fields in the ConfigState type. For
|
||||
convenience, all of the top-level functions use a global state available
|
||||
via the spew.Config global.
|
||||
|
||||
It is also possible to create a ConfigState instance that provides methods
|
||||
equivalent to the top-level functions. This allows concurrent configuration
|
||||
options. See the ConfigState documentation for more details.
|
||||
|
||||
The following configuration options are available:
|
||||
* Indent
|
||||
String to use for each indentation level for Dump functions.
|
||||
It is a single space by default. A popular alternative is "\t".
|
||||
|
||||
* MaxDepth
|
||||
Maximum number of levels to descend into nested data structures.
|
||||
There is no limit by default.
|
||||
|
||||
* DisableMethods
|
||||
Disables invocation of error and Stringer interface methods.
|
||||
Method invocation is enabled by default.
|
||||
|
||||
* DisablePointerMethods
|
||||
Disables invocation of error and Stringer interface methods on types
|
||||
which only accept pointer receivers from non-pointer variables.
|
||||
Pointer method invocation is enabled by default.
|
||||
|
||||
* DisablePointerAddresses
|
||||
DisablePointerAddresses specifies whether to disable the printing of
|
||||
pointer addresses. This is useful when diffing data structures in tests.
|
||||
|
||||
* DisableCapacities
|
||||
DisableCapacities specifies whether to disable the printing of
|
||||
capacities for arrays, slices, maps and channels. This is useful when
|
||||
diffing data structures in tests.
|
||||
|
||||
* ContinueOnMethod
|
||||
Enables recursion into types after invoking error and Stringer interface
|
||||
methods. Recursion after method invocation is disabled by default.
|
||||
|
||||
* SortKeys
|
||||
Specifies map keys should be sorted before being printed. Use
|
||||
this to have a more deterministic, diffable output. Note that
|
||||
only native types (bool, int, uint, floats, uintptr and string)
|
||||
and types which implement error or Stringer interfaces are
|
||||
supported with other types sorted according to the
|
||||
reflect.Value.String() output which guarantees display
|
||||
stability. Natural map order is used by default.
|
||||
|
||||
* SpewKeys
|
||||
Specifies that, as a last resort attempt, map keys should be
|
||||
spewed to strings and sorted by those strings. This is only
|
||||
considered if SortKeys is true.
|
||||
|
||||
Dump Usage
|
||||
|
||||
Simply call spew.Dump with a list of variables you want to dump:
|
||||
|
||||
spew.Dump(myVar1, myVar2, ...)
|
||||
|
||||
You may also call spew.Fdump if you would prefer to output to an arbitrary
|
||||
io.Writer. For example, to dump to standard error:
|
||||
|
||||
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
|
||||
|
||||
A third option is to call spew.Sdump to get the formatted output as a string:
|
||||
|
||||
str := spew.Sdump(myVar1, myVar2, ...)
|
||||
|
||||
Sample Dump Output
|
||||
|
||||
See the Dump example for details on the setup of the types and variables being
|
||||
shown here.
|
||||
|
||||
(main.Foo) {
|
||||
unexportedField: (*main.Bar)(0xf84002e210)({
|
||||
flag: (main.Flag) flagTwo,
|
||||
data: (uintptr) <nil>
|
||||
}),
|
||||
ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||
(string) (len=3) "one": (bool) true
|
||||
}
|
||||
}
|
||||
|
||||
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
|
||||
command as shown.
|
||||
([]uint8) (len=32 cap=32) {
|
||||
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
|
||||
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
|
||||
00000020 31 32 |12|
|
||||
}
|
||||
|
||||
Custom Formatter
|
||||
|
||||
Spew provides a custom formatter that implements the fmt.Formatter interface
|
||||
so that it integrates cleanly with standard fmt package printing functions. The
|
||||
formatter is useful for inline printing of smaller data types similar to the
|
||||
standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Custom Formatter Usage
|
||||
|
||||
The simplest way to make use of the spew custom formatter is to call one of the
|
||||
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
|
||||
functions have syntax you are most likely already familiar with:
|
||||
|
||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
spew.Println(myVar, myVar2)
|
||||
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
|
||||
See the Index for the full list convenience functions.
|
||||
|
||||
Sample Formatter Output
|
||||
|
||||
Double pointer to a uint8:
|
||||
%v: <**>5
|
||||
%+v: <**>(0xf8400420d0->0xf8400420c8)5
|
||||
%#v: (**uint8)5
|
||||
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
|
||||
|
||||
Pointer to circular struct with a uint8 field and a pointer to itself:
|
||||
%v: <*>{1 <*><shown>}
|
||||
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
|
||||
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
|
||||
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
|
||||
|
||||
See the Printf example for details on the setup of variables being shown
|
||||
here.
|
||||
|
||||
Errors
|
||||
|
||||
Since it is possible for custom Stringer/error interfaces to panic, spew
|
||||
detects them and handles them internally by printing the panic information
|
||||
inline with the output. Since spew is intended to provide deep pretty printing
|
||||
capabilities on structures, it intentionally does not return any errors.
|
||||
*/
|
||||
package spew
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// uint8Type is a reflect.Type representing a uint8. It is used to
|
||||
// convert cgo types to uint8 slices for hexdumping.
|
||||
uint8Type = reflect.TypeOf(uint8(0))
|
||||
|
||||
// cCharRE is a regular expression that matches a cgo char.
|
||||
// It is used to detect character arrays to hexdump them.
|
||||
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
||||
|
||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||
// char. It is used to detect unsigned character arrays to hexdump
|
||||
// them.
|
||||
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
||||
|
||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||
// It is used to detect uint8_t arrays to hexdump them.
|
||||
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
||||
)
|
||||
|
||||
// dumpState contains information about the state of a dump operation.
|
||||
type dumpState struct {
|
||||
w io.Writer
|
||||
depth int
|
||||
pointers map[uintptr]int
|
||||
ignoreNextType bool
|
||||
ignoreNextIndent bool
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// indent performs indentation according to the depth level and cs.Indent
|
||||
// option.
|
||||
func (d *dumpState) indent() {
|
||||
if d.ignoreNextIndent {
|
||||
d.ignoreNextIndent = false
|
||||
return
|
||||
}
|
||||
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
|
||||
}
|
||||
|
||||
// unpackValue returns values inside of non-nil interfaces when possible.
|
||||
// This is useful for data types like structs, arrays, slices, and maps which
|
||||
// can contain varying types packed inside an interface.
|
||||
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// dumpPtr handles formatting of pointers by indirecting them as necessary.
|
||||
func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||
// Remove pointers at or below the current depth from map used to detect
|
||||
// circular refs.
|
||||
for k, depth := range d.pointers {
|
||||
if depth >= d.depth {
|
||||
delete(d.pointers, k)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep list of all dereferenced pointers to show later.
|
||||
pointerChain := make([]uintptr, 0)
|
||||
|
||||
// Figure out how many levels of indirection there are by dereferencing
|
||||
// pointers and unpacking interfaces down the chain while detecting circular
|
||||
// references.
|
||||
nilFound := false
|
||||
cycleFound := false
|
||||
indirects := 0
|
||||
ve := v
|
||||
for ve.Kind() == reflect.Ptr {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
indirects++
|
||||
addr := ve.Pointer()
|
||||
pointerChain = append(pointerChain, addr)
|
||||
if pd, ok := d.pointers[addr]; ok && pd < d.depth {
|
||||
cycleFound = true
|
||||
indirects--
|
||||
break
|
||||
}
|
||||
d.pointers[addr] = d.depth
|
||||
|
||||
ve = ve.Elem()
|
||||
if ve.Kind() == reflect.Interface {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
ve = ve.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
// Display type information.
|
||||
d.w.Write(openParenBytes)
|
||||
d.w.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||
d.w.Write([]byte(ve.Type().String()))
|
||||
d.w.Write(closeParenBytes)
|
||||
|
||||
// Display pointer information.
|
||||
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
for i, addr := range pointerChain {
|
||||
if i > 0 {
|
||||
d.w.Write(pointerChainBytes)
|
||||
}
|
||||
printHexPtr(d.w, addr)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// Display dereferenced value.
|
||||
d.w.Write(openParenBytes)
|
||||
switch {
|
||||
case nilFound:
|
||||
d.w.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound:
|
||||
d.w.Write(circularBytes)
|
||||
|
||||
default:
|
||||
d.ignoreNextType = true
|
||||
d.dump(ve)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
|
||||
// reflection) arrays and slices are dumped in hexdump -C fashion.
|
||||
func (d *dumpState) dumpSlice(v reflect.Value) {
|
||||
// Determine whether this type should be hex dumped or not. Also,
|
||||
// for types which should be hexdumped, try to use the underlying data
|
||||
// first, then fall back to trying to convert them to a uint8 slice.
|
||||
var buf []uint8
|
||||
doConvert := false
|
||||
doHexDump := false
|
||||
numEntries := v.Len()
|
||||
if numEntries > 0 {
|
||||
vt := v.Index(0).Type()
|
||||
vts := vt.String()
|
||||
switch {
|
||||
// C types that need to be converted.
|
||||
case cCharRE.MatchString(vts):
|
||||
fallthrough
|
||||
case cUnsignedCharRE.MatchString(vts):
|
||||
fallthrough
|
||||
case cUint8tCharRE.MatchString(vts):
|
||||
doConvert = true
|
||||
|
||||
// Try to use existing uint8 slices and fall back to converting
|
||||
// and copying if that fails.
|
||||
case vt.Kind() == reflect.Uint8:
|
||||
// We need an addressable interface to convert the type
|
||||
// to a byte slice. However, the reflect package won't
|
||||
// give us an interface on certain things like
|
||||
// unexported struct fields in order to enforce
|
||||
// visibility rules. We use unsafe, when available, to
|
||||
// bypass these restrictions since this package does not
|
||||
// mutate the values.
|
||||
vs := v
|
||||
if !vs.CanInterface() || !vs.CanAddr() {
|
||||
vs = unsafeReflectValue(vs)
|
||||
}
|
||||
if !UnsafeDisabled {
|
||||
vs = vs.Slice(0, numEntries)
|
||||
|
||||
// Use the existing uint8 slice if it can be
|
||||
// type asserted.
|
||||
iface := vs.Interface()
|
||||
if slice, ok := iface.([]uint8); ok {
|
||||
buf = slice
|
||||
doHexDump = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// The underlying data needs to be converted if it can't
|
||||
// be type asserted to a uint8 slice.
|
||||
doConvert = true
|
||||
}
|
||||
|
||||
// Copy and convert the underlying type if needed.
|
||||
if doConvert && vt.ConvertibleTo(uint8Type) {
|
||||
// Convert and copy each element into a uint8 byte
|
||||
// slice.
|
||||
buf = make([]uint8, numEntries)
|
||||
for i := 0; i < numEntries; i++ {
|
||||
vv := v.Index(i)
|
||||
buf[i] = uint8(vv.Convert(uint8Type).Uint())
|
||||
}
|
||||
doHexDump = true
|
||||
}
|
||||
}
|
||||
|
||||
// Hexdump the entire slice as needed.
|
||||
if doHexDump {
|
||||
indent := strings.Repeat(d.cs.Indent, d.depth)
|
||||
str := indent + hex.Dump(buf)
|
||||
str = strings.Replace(str, "\n", "\n"+indent, -1)
|
||||
str = strings.TrimRight(str, d.cs.Indent)
|
||||
d.w.Write([]byte(str))
|
||||
return
|
||||
}
|
||||
|
||||
// Recursively call dump for each item.
|
||||
for i := 0; i < numEntries; i++ {
|
||||
d.dump(d.unpackValue(v.Index(i)))
|
||||
if i < (numEntries - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dump is the main workhorse for dumping a value. It uses the passed reflect
|
||||
// value to figure out what kind of object we are dealing with and formats it
|
||||
// appropriately. It is a recursive function, however circular data structures
|
||||
// are detected and handled properly.
|
||||
func (d *dumpState) dump(v reflect.Value) {
|
||||
// Handle invalid reflect values immediately.
|
||||
kind := v.Kind()
|
||||
if kind == reflect.Invalid {
|
||||
d.w.Write(invalidAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle pointers specially.
|
||||
if kind == reflect.Ptr {
|
||||
d.indent()
|
||||
d.dumpPtr(v)
|
||||
return
|
||||
}
|
||||
|
||||
// Print type information unless already handled elsewhere.
|
||||
if !d.ignoreNextType {
|
||||
d.indent()
|
||||
d.w.Write(openParenBytes)
|
||||
d.w.Write([]byte(v.Type().String()))
|
||||
d.w.Write(closeParenBytes)
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
d.ignoreNextType = false
|
||||
|
||||
// Display length and capacity if the built-in len and cap functions
|
||||
// work with the value's kind and the len/cap itself is non-zero.
|
||||
valueLen, valueCap := 0, 0
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Chan:
|
||||
valueLen, valueCap = v.Len(), v.Cap()
|
||||
case reflect.Map, reflect.String:
|
||||
valueLen = v.Len()
|
||||
}
|
||||
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
if valueLen != 0 {
|
||||
d.w.Write(lenEqualsBytes)
|
||||
printInt(d.w, int64(valueLen), 10)
|
||||
}
|
||||
if !d.cs.DisableCapacities && valueCap != 0 {
|
||||
if valueLen != 0 {
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
d.w.Write(capEqualsBytes)
|
||||
printInt(d.w, int64(valueCap), 10)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
|
||||
// Call Stringer/error interfaces if they exist and the handle methods flag
|
||||
// is enabled
|
||||
if !d.cs.DisableMethods {
|
||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||
if handled := handleMethods(d.cs, d.w, v); handled {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Bool:
|
||||
printBool(d.w, v.Bool())
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
printInt(d.w, v.Int(), 10)
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
printUint(d.w, v.Uint(), 10)
|
||||
|
||||
case reflect.Float32:
|
||||
printFloat(d.w, v.Float(), 32)
|
||||
|
||||
case reflect.Float64:
|
||||
printFloat(d.w, v.Float(), 64)
|
||||
|
||||
case reflect.Complex64:
|
||||
printComplex(d.w, v.Complex(), 32)
|
||||
|
||||
case reflect.Complex128:
|
||||
printComplex(d.w, v.Complex(), 64)
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case reflect.Array:
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
d.dumpSlice(v)
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.String:
|
||||
d.w.Write([]byte(strconv.Quote(v.String())))
|
||||
|
||||
case reflect.Interface:
|
||||
// The only time we should get here is for nil interfaces due to
|
||||
// unpackValue calls.
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
// Do nothing. We should never get here since pointers have already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Map:
|
||||
// nil maps should be indicated as different than empty maps
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
numEntries := v.Len()
|
||||
keys := v.MapKeys()
|
||||
if d.cs.SortKeys {
|
||||
sortValues(keys, d.cs)
|
||||
}
|
||||
for i, key := range keys {
|
||||
d.dump(d.unpackValue(key))
|
||||
d.w.Write(colonSpaceBytes)
|
||||
d.ignoreNextIndent = true
|
||||
d.dump(d.unpackValue(v.MapIndex(key)))
|
||||
if i < (numEntries - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Struct:
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
vt := v.Type()
|
||||
numFields := v.NumField()
|
||||
for i := 0; i < numFields; i++ {
|
||||
d.indent()
|
||||
vtf := vt.Field(i)
|
||||
d.w.Write([]byte(vtf.Name))
|
||||
d.w.Write(colonSpaceBytes)
|
||||
d.ignoreNextIndent = true
|
||||
d.dump(d.unpackValue(v.Field(i)))
|
||||
if i < (numFields - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Uintptr:
|
||||
printHexPtr(d.w, uintptr(v.Uint()))
|
||||
|
||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||
printHexPtr(d.w, v.Pointer())
|
||||
|
||||
// There were not any other types at the time this code was written, but
|
||||
// fall back to letting the default fmt package handle it in case any new
|
||||
// types are added.
|
||||
default:
|
||||
if v.CanInterface() {
|
||||
fmt.Fprintf(d.w, "%v", v.Interface())
|
||||
} else {
|
||||
fmt.Fprintf(d.w, "%v", v.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fdump is a helper function to consolidate the logic from the various public
|
||||
// methods which take varying writers and config states.
|
||||
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
|
||||
for _, arg := range a {
|
||||
if arg == nil {
|
||||
w.Write(interfaceBytes)
|
||||
w.Write(spaceBytes)
|
||||
w.Write(nilAngleBytes)
|
||||
w.Write(newlineBytes)
|
||||
continue
|
||||
}
|
||||
|
||||
d := dumpState{w: w, cs: cs}
|
||||
d.pointers = make(map[uintptr]int)
|
||||
d.dump(reflect.ValueOf(arg))
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||
// exactly the same as Dump.
|
||||
func Fdump(w io.Writer, a ...interface{}) {
|
||||
fdump(&Config, w, a...)
|
||||
}
|
||||
|
||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||
// as Dump.
|
||||
func Sdump(a ...interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
fdump(&Config, &buf, a...)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
/*
|
||||
Dump displays the passed parameters to standard out with newlines, customizable
|
||||
indentation, and additional debug information such as complete types and all
|
||||
pointer addresses used to indirect to the final value. It provides the
|
||||
following features over the built-in printing facilities provided by the fmt
|
||||
package:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output
|
||||
|
||||
The configuration options are controlled by an exported package global,
|
||||
spew.Config. See ConfigState for options documentation.
|
||||
|
||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||
get the formatted result as a string.
|
||||
*/
|
||||
func Dump(a ...interface{}) {
|
||||
fdump(&Config, os.Stdout, a...)
|
||||
}
|
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// supportedFlags is a list of all the character flags supported by fmt package.
|
||||
const supportedFlags = "0-+# "
|
||||
|
||||
// formatState implements the fmt.Formatter interface and contains information
|
||||
// about the state of a formatting operation. The NewFormatter function can
|
||||
// be used to get a new Formatter which can be used directly as arguments
|
||||
// in standard fmt package printing calls.
|
||||
type formatState struct {
|
||||
value interface{}
|
||||
fs fmt.State
|
||||
depth int
|
||||
pointers map[uintptr]int
|
||||
ignoreNextType bool
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// buildDefaultFormat recreates the original format string without precision
|
||||
// and width information to pass in to fmt.Sprintf in the case of an
|
||||
// unrecognized type. Unless new types are added to the language, this
|
||||
// function won't ever be called.
|
||||
func (f *formatState) buildDefaultFormat() (format string) {
|
||||
buf := bytes.NewBuffer(percentBytes)
|
||||
|
||||
for _, flag := range supportedFlags {
|
||||
if f.fs.Flag(int(flag)) {
|
||||
buf.WriteRune(flag)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteRune('v')
|
||||
|
||||
format = buf.String()
|
||||
return format
|
||||
}
|
||||
|
||||
// constructOrigFormat recreates the original format string including precision
|
||||
// and width information to pass along to the standard fmt package. This allows
|
||||
// automatic deferral of all format strings this package doesn't support.
|
||||
func (f *formatState) constructOrigFormat(verb rune) (format string) {
|
||||
buf := bytes.NewBuffer(percentBytes)
|
||||
|
||||
for _, flag := range supportedFlags {
|
||||
if f.fs.Flag(int(flag)) {
|
||||
buf.WriteRune(flag)
|
||||
}
|
||||
}
|
||||
|
||||
if width, ok := f.fs.Width(); ok {
|
||||
buf.WriteString(strconv.Itoa(width))
|
||||
}
|
||||
|
||||
if precision, ok := f.fs.Precision(); ok {
|
||||
buf.Write(precisionBytes)
|
||||
buf.WriteString(strconv.Itoa(precision))
|
||||
}
|
||||
|
||||
buf.WriteRune(verb)
|
||||
|
||||
format = buf.String()
|
||||
return format
|
||||
}
|
||||
|
||||
// unpackValue returns values inside of non-nil interfaces when possible and
|
||||
// ensures that types for values which have been unpacked from an interface
|
||||
// are displayed when the show types flag is also set.
|
||||
// This is useful for data types like structs, arrays, slices, and maps which
|
||||
// can contain varying types packed inside an interface.
|
||||
func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
|
||||
if v.Kind() == reflect.Interface {
|
||||
f.ignoreNextType = false
|
||||
if !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// formatPtr handles formatting of pointers by indirecting them as necessary.
|
||||
func (f *formatState) formatPtr(v reflect.Value) {
|
||||
// Display nil if top level pointer is nil.
|
||||
showTypes := f.fs.Flag('#')
|
||||
if v.IsNil() && (!showTypes || f.ignoreNextType) {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Remove pointers at or below the current depth from map used to detect
|
||||
// circular refs.
|
||||
for k, depth := range f.pointers {
|
||||
if depth >= f.depth {
|
||||
delete(f.pointers, k)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep list of all dereferenced pointers to possibly show later.
|
||||
pointerChain := make([]uintptr, 0)
|
||||
|
||||
// Figure out how many levels of indirection there are by derferencing
|
||||
// pointers and unpacking interfaces down the chain while detecting circular
|
||||
// references.
|
||||
nilFound := false
|
||||
cycleFound := false
|
||||
indirects := 0
|
||||
ve := v
|
||||
for ve.Kind() == reflect.Ptr {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
indirects++
|
||||
addr := ve.Pointer()
|
||||
pointerChain = append(pointerChain, addr)
|
||||
if pd, ok := f.pointers[addr]; ok && pd < f.depth {
|
||||
cycleFound = true
|
||||
indirects--
|
||||
break
|
||||
}
|
||||
f.pointers[addr] = f.depth
|
||||
|
||||
ve = ve.Elem()
|
||||
if ve.Kind() == reflect.Interface {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
ve = ve.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
// Display type or indirection level depending on flags.
|
||||
if showTypes && !f.ignoreNextType {
|
||||
f.fs.Write(openParenBytes)
|
||||
f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||
f.fs.Write([]byte(ve.Type().String()))
|
||||
f.fs.Write(closeParenBytes)
|
||||
} else {
|
||||
if nilFound || cycleFound {
|
||||
indirects += strings.Count(ve.Type().String(), "*")
|
||||
}
|
||||
f.fs.Write(openAngleBytes)
|
||||
f.fs.Write([]byte(strings.Repeat("*", indirects)))
|
||||
f.fs.Write(closeAngleBytes)
|
||||
}
|
||||
|
||||
// Display pointer information depending on flags.
|
||||
if f.fs.Flag('+') && (len(pointerChain) > 0) {
|
||||
f.fs.Write(openParenBytes)
|
||||
for i, addr := range pointerChain {
|
||||
if i > 0 {
|
||||
f.fs.Write(pointerChainBytes)
|
||||
}
|
||||
printHexPtr(f.fs, addr)
|
||||
}
|
||||
f.fs.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// Display dereferenced value.
|
||||
switch {
|
||||
case nilFound:
|
||||
f.fs.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound:
|
||||
f.fs.Write(circularShortBytes)
|
||||
|
||||
default:
|
||||
f.ignoreNextType = true
|
||||
f.format(ve)
|
||||
}
|
||||
}
|
||||
|
||||
// format is the main workhorse for providing the Formatter interface. It
|
||||
// uses the passed reflect value to figure out what kind of object we are
|
||||
// dealing with and formats it appropriately. It is a recursive function,
|
||||
// however circular data structures are detected and handled properly.
|
||||
func (f *formatState) format(v reflect.Value) {
|
||||
// Handle invalid reflect values immediately.
|
||||
kind := v.Kind()
|
||||
if kind == reflect.Invalid {
|
||||
f.fs.Write(invalidAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle pointers specially.
|
||||
if kind == reflect.Ptr {
|
||||
f.formatPtr(v)
|
||||
return
|
||||
}
|
||||
|
||||
// Print type information unless already handled elsewhere.
|
||||
if !f.ignoreNextType && f.fs.Flag('#') {
|
||||
f.fs.Write(openParenBytes)
|
||||
f.fs.Write([]byte(v.Type().String()))
|
||||
f.fs.Write(closeParenBytes)
|
||||
}
|
||||
f.ignoreNextType = false
|
||||
|
||||
// Call Stringer/error interfaces if they exist and the handle methods
|
||||
// flag is enabled.
|
||||
if !f.cs.DisableMethods {
|
||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||
if handled := handleMethods(f.cs, f.fs, v); handled {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Bool:
|
||||
printBool(f.fs, v.Bool())
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
printInt(f.fs, v.Int(), 10)
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
printUint(f.fs, v.Uint(), 10)
|
||||
|
||||
case reflect.Float32:
|
||||
printFloat(f.fs, v.Float(), 32)
|
||||
|
||||
case reflect.Float64:
|
||||
printFloat(f.fs, v.Float(), 64)
|
||||
|
||||
case reflect.Complex64:
|
||||
printComplex(f.fs, v.Complex(), 32)
|
||||
|
||||
case reflect.Complex128:
|
||||
printComplex(f.fs, v.Complex(), 64)
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case reflect.Array:
|
||||
f.fs.Write(openBracketBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
numEntries := v.Len()
|
||||
for i := 0; i < numEntries; i++ {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(v.Index(i)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeBracketBytes)
|
||||
|
||||
case reflect.String:
|
||||
f.fs.Write([]byte(v.String()))
|
||||
|
||||
case reflect.Interface:
|
||||
// The only time we should get here is for nil interfaces due to
|
||||
// unpackValue calls.
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
// Do nothing. We should never get here since pointers have already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Map:
|
||||
// nil maps should be indicated as different than empty maps
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
|
||||
f.fs.Write(openMapBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
keys := v.MapKeys()
|
||||
if f.cs.SortKeys {
|
||||
sortValues(keys, f.cs)
|
||||
}
|
||||
for i, key := range keys {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(key))
|
||||
f.fs.Write(colonBytes)
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(v.MapIndex(key)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeMapBytes)
|
||||
|
||||
case reflect.Struct:
|
||||
numFields := v.NumField()
|
||||
f.fs.Write(openBraceBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
vt := v.Type()
|
||||
for i := 0; i < numFields; i++ {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
vtf := vt.Field(i)
|
||||
if f.fs.Flag('+') || f.fs.Flag('#') {
|
||||
f.fs.Write([]byte(vtf.Name))
|
||||
f.fs.Write(colonBytes)
|
||||
}
|
||||
f.format(f.unpackValue(v.Field(i)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Uintptr:
|
||||
printHexPtr(f.fs, uintptr(v.Uint()))
|
||||
|
||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||
printHexPtr(f.fs, v.Pointer())
|
||||
|
||||
// There were not any other types at the time this code was written, but
|
||||
// fall back to letting the default fmt package handle it if any get added.
|
||||
default:
|
||||
format := f.buildDefaultFormat()
|
||||
if v.CanInterface() {
|
||||
fmt.Fprintf(f.fs, format, v.Interface())
|
||||
} else {
|
||||
fmt.Fprintf(f.fs, format, v.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
|
||||
// details.
|
||||
func (f *formatState) Format(fs fmt.State, verb rune) {
|
||||
f.fs = fs
|
||||
|
||||
// Use standard formatting for verbs that are not v.
|
||||
if verb != 'v' {
|
||||
format := f.constructOrigFormat(verb)
|
||||
fmt.Fprintf(fs, format, f.value)
|
||||
return
|
||||
}
|
||||
|
||||
if f.value == nil {
|
||||
if fs.Flag('#') {
|
||||
fs.Write(interfaceBytes)
|
||||
}
|
||||
fs.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
f.format(reflect.ValueOf(f.value))
|
||||
}
|
||||
|
||||
// newFormatter is a helper function to consolidate the logic from the various
|
||||
// public methods which take varying config states.
|
||||
func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
|
||||
fs := &formatState{value: v, cs: cs}
|
||||
fs.pointers = make(map[uintptr]int)
|
||||
return fs
|
||||
}
|
||||
|
||||
/*
|
||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||
interface. As a result, it integrates cleanly with standard fmt package
|
||||
printing functions. The formatter is useful for inline printing of smaller data
|
||||
types similar to the standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Typically this function shouldn't be called directly. It is much easier to make
|
||||
use of the custom formatter by calling one of the convenience functions such as
|
||||
Printf, Println, or Fprintf.
|
||||
*/
|
||||
func NewFormatter(v interface{}) fmt.Formatter {
|
||||
return newFormatter(&Config, v)
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the formatted string as a value that satisfies error. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Errorf(format string, a ...interface{}) (err error) {
|
||||
return fmt.Errorf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprint(w, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintf(w, format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||
// passed with a default Formatter interface returned by NewFormatter. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintln(w, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Print(a ...interface{}) (n int, err error) {
|
||||
return fmt.Print(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Printf(format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Printf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Println(a ...interface{}) (n int, err error) {
|
||||
return fmt.Println(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprint(a ...interface{}) string {
|
||||
return fmt.Sprint(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprintf(format string, a ...interface{}) string {
|
||||
return fmt.Sprintf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||
// were passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprintln(a ...interface{}) string {
|
||||
return fmt.Sprintln(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||
// length with each argument converted to a default spew Formatter interface.
|
||||
func convertArgs(args []interface{}) (formatters []interface{}) {
|
||||
formatters = make([]interface{}, len(args))
|
||||
for index, arg := range args {
|
||||
formatters[index] = NewFormatter(arg)
|
||||
}
|
||||
return formatters
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
logrus
|
||||
vendor
|
||||
|
||||
.idea/
|
|
@ -0,0 +1,40 @@
|
|||
run:
|
||||
# do not run on test files yet
|
||||
tests: false
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
|
||||
lll:
|
||||
line-length: 100
|
||||
tab-width: 4
|
||||
|
||||
prealloc:
|
||||
simple: false
|
||||
range-loops: false
|
||||
for-loops: false
|
||||
|
||||
whitespace:
|
||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- megacheck
|
||||
- govet
|
||||
disable:
|
||||
- maligned
|
||||
- prealloc
|
||||
disable-all: false
|
||||
presets:
|
||||
- bugs
|
||||
- unused
|
||||
fast: false
|
|
@ -0,0 +1,17 @@
|
|||
language: go
|
||||
go_import_path: github.com/sirupsen/logrus
|
||||
git:
|
||||
depth: 1
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
go: [1.13.x, 1.14.x]
|
||||
os: [linux, osx]
|
||||
install:
|
||||
- ./travis/install.sh
|
||||
script:
|
||||
- ./travis/cross_build.sh
|
||||
- ./travis/lint.sh
|
||||
- export GOMAXPROCS=4
|
||||
- export GORACE=halt_on_error=1
|
||||
- go test -race -v ./...
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi
|
|
@ -0,0 +1,223 @@
|
|||
# 1.6.0
|
||||
Fixes:
|
||||
* end of line cleanup
|
||||
* revert the entry concurrency bug fix whic leads to deadlock under some circumstances
|
||||
* update dependency on go-windows-terminal-sequences to fix a crash with go 1.14
|
||||
|
||||
Features:
|
||||
* add an option to the `TextFormatter` to completely disable fields quoting
|
||||
|
||||
# 1.5.0
|
||||
Code quality:
|
||||
* add golangci linter run on travis
|
||||
|
||||
Fixes:
|
||||
* add mutex for hooks concurrent access on `Entry` data
|
||||
* caller function field for go1.14
|
||||
* fix build issue for gopherjs target
|
||||
|
||||
Feature:
|
||||
* add an hooks/writer sub-package whose goal is to split output on different stream depending on the trace level
|
||||
* add a `DisableHTMLEscape` option in the `JSONFormatter`
|
||||
* add `ForceQuote` and `PadLevelText` options in the `TextFormatter`
|
||||
|
||||
# 1.4.2
|
||||
* Fixes build break for plan9, nacl, solaris
|
||||
# 1.4.1
|
||||
This new release introduces:
|
||||
* Enhance TextFormatter to not print caller information when they are empty (#944)
|
||||
* Remove dependency on golang.org/x/crypto (#932, #943)
|
||||
|
||||
Fixes:
|
||||
* Fix Entry.WithContext method to return a copy of the initial entry (#941)
|
||||
|
||||
# 1.4.0
|
||||
This new release introduces:
|
||||
* Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
|
||||
* Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter` (#909, #911)
|
||||
* Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
|
||||
|
||||
Fixes:
|
||||
* Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893).
|
||||
* Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903)
|
||||
* Fix infinite recursion on unknown `Level.String()` (#907)
|
||||
* Fix race condition in `getCaller` (#916).
|
||||
|
||||
|
||||
# 1.3.0
|
||||
This new release introduces:
|
||||
* Log, Logf, Logln functions for Logger and Entry that take a Level
|
||||
|
||||
Fixes:
|
||||
* Building prometheus node_exporter on AIX (#840)
|
||||
* Race condition in TextFormatter (#468)
|
||||
* Travis CI import path (#868)
|
||||
* Remove coloured output on Windows (#862)
|
||||
* Pointer to func as field in JSONFormatter (#870)
|
||||
* Properly marshal Levels (#873)
|
||||
|
||||
# 1.2.0
|
||||
This new release introduces:
|
||||
* A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued
|
||||
* A new trace level named `Trace` whose level is below `Debug`
|
||||
* A configurable exit function to be called upon a Fatal trace
|
||||
* The `Level` object now implements `encoding.TextUnmarshaler` interface
|
||||
|
||||
# 1.1.1
|
||||
This is a bug fix release.
|
||||
* fix the build break on Solaris
|
||||
* don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized
|
||||
|
||||
# 1.1.0
|
||||
This new release introduces:
|
||||
* several fixes:
|
||||
* a fix for a race condition on entry formatting
|
||||
* proper cleanup of previously used entries before putting them back in the pool
|
||||
* the extra new line at the end of message in text formatter has been removed
|
||||
* a new global public API to check if a level is activated: IsLevelEnabled
|
||||
* the following methods have been added to the Logger object
|
||||
* IsLevelEnabled
|
||||
* SetFormatter
|
||||
* SetOutput
|
||||
* ReplaceHooks
|
||||
* introduction of go module
|
||||
* an indent configuration for the json formatter
|
||||
* output colour support for windows
|
||||
* the field sort function is now configurable for text formatter
|
||||
* the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater
|
||||
|
||||
# 1.0.6
|
||||
|
||||
This new release introduces:
|
||||
* a new api WithTime which allows to easily force the time of the log entry
|
||||
which is mostly useful for logger wrapper
|
||||
* a fix reverting the immutability of the entry given as parameter to the hooks
|
||||
a new configuration field of the json formatter in order to put all the fields
|
||||
in a nested dictionnary
|
||||
* a new SetOutput method in the Logger
|
||||
* a new configuration of the textformatter to configure the name of the default keys
|
||||
* a new configuration of the text formatter to disable the level truncation
|
||||
|
||||
# 1.0.5
|
||||
|
||||
* Fix hooks race (#707)
|
||||
* Fix panic deadlock (#695)
|
||||
|
||||
# 1.0.4
|
||||
|
||||
* Fix race when adding hooks (#612)
|
||||
* Fix terminal check in AppEngine (#635)
|
||||
|
||||
# 1.0.3
|
||||
|
||||
* Replace example files with testable examples
|
||||
|
||||
# 1.0.2
|
||||
|
||||
* bug: quote non-string values in text formatter (#583)
|
||||
* Make (*Logger) SetLevel a public method
|
||||
|
||||
# 1.0.1
|
||||
|
||||
* bug: fix escaping in text formatter (#575)
|
||||
|
||||
# 1.0.0
|
||||
|
||||
* Officially changed name to lower-case
|
||||
* bug: colors on Windows 10 (#541)
|
||||
* bug: fix race in accessing level (#512)
|
||||
|
||||
# 0.11.5
|
||||
|
||||
* feature: add writer and writerlevel to entry (#372)
|
||||
|
||||
# 0.11.4
|
||||
|
||||
* bug: fix undefined variable on solaris (#493)
|
||||
|
||||
# 0.11.3
|
||||
|
||||
* formatter: configure quoting of empty values (#484)
|
||||
* formatter: configure quoting character (default is `"`) (#484)
|
||||
* bug: fix not importing io correctly in non-linux environments (#481)
|
||||
|
||||
# 0.11.2
|
||||
|
||||
* bug: fix windows terminal detection (#476)
|
||||
|
||||
# 0.11.1
|
||||
|
||||
* bug: fix tty detection with custom out (#471)
|
||||
|
||||
# 0.11.0
|
||||
|
||||
* performance: Use bufferpool to allocate (#370)
|
||||
* terminal: terminal detection for app-engine (#343)
|
||||
* feature: exit handler (#375)
|
||||
|
||||
# 0.10.0
|
||||
|
||||
* feature: Add a test hook (#180)
|
||||
* feature: `ParseLevel` is now case-insensitive (#326)
|
||||
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
|
||||
* performance: avoid re-allocations on `WithFields` (#335)
|
||||
|
||||
# 0.9.0
|
||||
|
||||
* logrus/text_formatter: don't emit empty msg
|
||||
* logrus/hooks/airbrake: move out of main repository
|
||||
* logrus/hooks/sentry: move out of main repository
|
||||
* logrus/hooks/papertrail: move out of main repository
|
||||
* logrus/hooks/bugsnag: move out of main repository
|
||||
* logrus/core: run tests with `-race`
|
||||
* logrus/core: detect TTY based on `stderr`
|
||||
* logrus/core: support `WithError` on logger
|
||||
* logrus/core: Solaris support
|
||||
|
||||
# 0.8.7
|
||||
|
||||
* logrus/core: fix possible race (#216)
|
||||
* logrus/doc: small typo fixes and doc improvements
|
||||
|
||||
|
||||
# 0.8.6
|
||||
|
||||
* hooks/raven: allow passing an initialized client
|
||||
|
||||
# 0.8.5
|
||||
|
||||
* logrus/core: revert #208
|
||||
|
||||
# 0.8.4
|
||||
|
||||
* formatter/text: fix data race (#218)
|
||||
|
||||
# 0.8.3
|
||||
|
||||
* logrus/core: fix entry log level (#208)
|
||||
* logrus/core: improve performance of text formatter by 40%
|
||||
* logrus/core: expose `LevelHooks` type
|
||||
* logrus/core: add support for DragonflyBSD and NetBSD
|
||||
* formatter/text: print structs more verbosely
|
||||
|
||||
# 0.8.2
|
||||
|
||||
* logrus: fix more Fatal family functions
|
||||
|
||||
# 0.8.1
|
||||
|
||||
* logrus: fix not exiting on `Fatalf` and `Fatalln`
|
||||
|
||||
# 0.8.0
|
||||
|
||||
* logrus: defaults to stderr instead of stdout
|
||||
* hooks/sentry: add special field for `*http.Request`
|
||||
* formatter/text: ignore Windows for colors
|
||||
|
||||
# 0.7.3
|
||||
|
||||
* formatter/\*: allow configuration of timestamp layout
|
||||
|
||||
# 0.7.2
|
||||
|
||||
* formatter/text: Add configuration option for time format (#158)
|
154
vendor/github.com/Sirupsen/logrus/README.md → vendor/github.com/sirupsen/logrus/README.md
generated
vendored
154
vendor/github.com/Sirupsen/logrus/README.md → vendor/github.com/sirupsen/logrus/README.md
generated
vendored
|
@ -1,22 +1,39 @@
|
|||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
|
||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
|
||||
|
||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
||||
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
|
||||
yet stable (pre 1.0). Logrus itself is completely stable and has been used in
|
||||
many large deployments. The core API is unlikely to change much but please
|
||||
version control your Logrus to make sure you aren't fetching latest `master` on
|
||||
every build.**
|
||||
the standard library logger.
|
||||
|
||||
**Seeing weird case-sensitive problems?** Unfortunately, the author failed to
|
||||
realize the consequences of renaming to lower-case. Due to the Go package
|
||||
environment, this caused issues. Regretfully, there's no turning back now.
|
||||
**Logrus is in maintenance-mode.** We will not be introducing new features. It's
|
||||
simply too hard to do in a way that won't break many people's projects, which is
|
||||
the last thing you want from your Logging library (again...).
|
||||
|
||||
This does not mean Logrus is dead. Logrus will continue to be maintained for
|
||||
security, (backwards compatible) bug fixes, and performance (where we are
|
||||
limited by the interface).
|
||||
|
||||
I believe Logrus' biggest contribution is to have played a part in today's
|
||||
widespread use of structured logging in Golang. There doesn't seem to be a
|
||||
reason to do a major, breaking iteration into Logrus V2, since the fantastic Go
|
||||
community has built those independently. Many fantastic alternatives have sprung
|
||||
up. Logrus would look like those, had it been re-designed with what we know
|
||||
about structured logging in Go today. Check out, for example,
|
||||
[Zerolog][zerolog], [Zap][zap], and [Apex][apex].
|
||||
|
||||
[zerolog]: https://github.com/rs/zerolog
|
||||
[zap]: https://github.com/uber-go/zap
|
||||
[apex]: https://github.com/apex/log
|
||||
|
||||
**Seeing weird case-sensitive problems?** It's in the past been possible to
|
||||
import Logrus as both upper- and lower-case. Due to the Go package environment,
|
||||
this caused issues in the community and we needed a standard. Some environments
|
||||
experienced problems with the upper-case variant, so the lower-case was decided.
|
||||
Everything using `logrus` will need to use the lower-case:
|
||||
`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
|
||||
|
||||
I am terribly sorry for this inconvenience. Logrus strives hard for backwards
|
||||
compatibility, and the author failed to realize the cascading consequences of
|
||||
such a name-change. To fix Glide, see [these
|
||||
To fix Glide, see [these
|
||||
comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
|
||||
For an in-depth explanation of the casing issue, see [this
|
||||
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
|
||||
|
||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
||||
plain text):
|
||||
|
@ -54,8 +71,39 @@ time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased
|
|||
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
|
||||
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
|
||||
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
|
||||
exit status 1
|
||||
```
|
||||
To ensure this behaviour even if a TTY is attached, set your formatter as follows:
|
||||
|
||||
```go
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
DisableColors: true,
|
||||
FullTimestamp: true,
|
||||
})
|
||||
```
|
||||
|
||||
#### Logging Method Name
|
||||
|
||||
If you wish to add the calling method as a field, instruct the logger via:
|
||||
```go
|
||||
log.SetReportCaller(true)
|
||||
```
|
||||
This adds the caller as 'method' like so:
|
||||
|
||||
```json
|
||||
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
|
||||
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
|
||||
```
|
||||
|
||||
```text
|
||||
time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
|
||||
```
|
||||
Note that this does add measurable overhead - the cost will depend on the version of Go, but is
|
||||
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
|
||||
environment via benchmarks:
|
||||
```
|
||||
go test -bench=.*CallerTracing
|
||||
```
|
||||
|
||||
|
||||
#### Case-sensitivity
|
||||
|
||||
|
@ -154,7 +202,7 @@ func main() {
|
|||
log.Out = os.Stdout
|
||||
|
||||
// You could set this to any `io.Writer` such as a file
|
||||
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
|
||||
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
// if err == nil {
|
||||
// log.Out = file
|
||||
// } else {
|
||||
|
@ -218,7 +266,7 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
|
|||
```go
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
|
||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
|
||||
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||
"log/syslog"
|
||||
)
|
||||
|
@ -239,59 +287,15 @@ func init() {
|
|||
```
|
||||
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
||||
|
||||
| Hook | Description |
|
||||
| ----- | ----------- |
|
||||
| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
|
||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
||||
| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
|
||||
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
||||
| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
|
||||
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
|
||||
| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/)
|
||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
|
||||
| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) |
|
||||
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
|
||||
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
|
||||
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
|
||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
||||
| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
|
||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
||||
| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||
| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
|
||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
|
||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
|
||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
||||
| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
|
||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
||||
| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
|
||||
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
|
||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
||||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
|
||||
| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
|
||||
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
|
||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
|
||||
| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
|
||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
||||
| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
||||
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
|
||||
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
|
||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
||||
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
|
||||
| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) |
|
||||
A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
|
||||
|
||||
|
||||
#### Level logging
|
||||
|
||||
Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
|
||||
Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.
|
||||
|
||||
```go
|
||||
log.Trace("Something very low level.")
|
||||
log.Debug("Useful debugging information.")
|
||||
log.Info("Something noteworthy happened!")
|
||||
log.Warn("You should probably take a look at this.")
|
||||
|
@ -363,15 +367,23 @@ The built-in logging formatters are:
|
|||
field to `true`. To force no colored output even if there is a TTY set the
|
||||
`DisableColors` field to `true`. For Windows, see
|
||||
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
|
||||
* When colors are enabled, levels are truncated to 4 characters by default. To disable
|
||||
truncation set the `DisableLevelTruncation` field to `true`.
|
||||
* When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
|
||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
|
||||
* `logrus.JSONFormatter`. Logs fields as JSON.
|
||||
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
|
||||
|
||||
Third party logging formatters:
|
||||
|
||||
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
|
||||
* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html).
|
||||
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the Power of Zalgo.
|
||||
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
|
||||
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Sava log to files.
|
||||
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added.
|
||||
|
||||
You can define your formatter by implementing the `Formatter` interface,
|
||||
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
|
||||
|
@ -436,26 +448,26 @@ entries. It should not be a feature of the application-level logger.
|
|||
|
||||
| Tool | Description |
|
||||
| ---- | ----------- |
|
||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|
||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments.|
|
||||
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
|
||||
|
||||
#### Testing
|
||||
|
||||
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
|
||||
|
||||
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
|
||||
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just adds the `test` hook
|
||||
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
|
||||
|
||||
```go
|
||||
import(
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/null"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSomething(t*testing.T){
|
||||
logger, hook := null.NewNullLogger()
|
||||
logger, hook := test.NewNullLogger()
|
||||
logger.Error("Helloerror")
|
||||
|
||||
assert.Equal(t, 1, len(hook.Entries))
|
||||
|
@ -471,7 +483,7 @@ func TestSomething(t*testing.T){
|
|||
|
||||
Logrus can register one or more functions that will be called when any `fatal`
|
||||
level message is logged. The registered handlers will be executed before
|
||||
logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
|
||||
logrus performs an `os.Exit(1)`. This behavior may be helpful if callers need
|
||||
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
|
||||
|
||||
```
|
||||
|
@ -485,7 +497,7 @@ logrus.RegisterExitHandler(handler)
|
|||
|
||||
#### Thread safety
|
||||
|
||||
By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
|
||||
By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
|
||||
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
|
||||
|
||||
Situation when locking is not needed includes:
|
||||
|
@ -496,6 +508,6 @@ Situation when locking is not needed includes:
|
|||
|
||||
1) logger.Out is protected by locks.
|
||||
|
||||
2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
|
||||
2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing)
|
||||
|
||||
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)
|
|
@ -51,9 +51,9 @@ func Exit(code int) {
|
|||
os.Exit(code)
|
||||
}
|
||||
|
||||
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
|
||||
// all handlers. The handlers will also be invoked when any Fatal log entry is
|
||||
// made.
|
||||
// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
|
||||
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
|
||||
// any Fatal log entry is made.
|
||||
//
|
||||
// This method is useful when a caller wishes to use logrus to log a fatal
|
||||
// message but also needs to gracefully shutdown. An example usecase could be
|
||||
|
@ -62,3 +62,15 @@ func Exit(code int) {
|
|||
func RegisterExitHandler(handler func()) {
|
||||
handlers = append(handlers, handler)
|
||||
}
|
||||
|
||||
// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
|
||||
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
|
||||
// any Fatal log entry is made.
|
||||
//
|
||||
// This method is useful when a caller wishes to use logrus to log a fatal
|
||||
// message but also needs to gracefully shutdown. An example usecase could be
|
||||
// closing database connections, or sending a alert that the application is
|
||||
// closing.
|
||||
func DeferExitHandler(handler func()) {
|
||||
handlers = append([]func(){handler}, handlers...)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
version: "{build}"
|
||||
platform: x64
|
||||
clone_folder: c:\gopath\src\github.com\sirupsen\logrus
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
install:
|
||||
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
|
||||
- go version
|
||||
build_script:
|
||||
- go get -t
|
||||
- go test
|
|
@ -0,0 +1,52 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool BufferPool
|
||||
)
|
||||
|
||||
type BufferPool interface {
|
||||
Put(*bytes.Buffer)
|
||||
Get() *bytes.Buffer
|
||||
}
|
||||
|
||||
type defaultPool struct {
|
||||
pool *sync.Pool
|
||||
}
|
||||
|
||||
func (p *defaultPool) Put(buf *bytes.Buffer) {
|
||||
p.pool.Put(buf)
|
||||
}
|
||||
|
||||
func (p *defaultPool) Get() *bytes.Buffer {
|
||||
return p.pool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
func getBuffer() *bytes.Buffer {
|
||||
return bufferPool.Get()
|
||||
}
|
||||
|
||||
func putBuffer(buf *bytes.Buffer) {
|
||||
buf.Reset()
|
||||
bufferPool.Put(buf)
|
||||
}
|
||||
|
||||
// SetBufferPool allows to replace the default logrus buffer pool
|
||||
// to better meets the specific needs of an application.
|
||||
func SetBufferPool(bp BufferPool) {
|
||||
bufferPool = bp
|
||||
}
|
||||
|
||||
func init() {
|
||||
SetBufferPool(&defaultPool{
|
||||
pool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
0
vendor/github.com/Sirupsen/logrus/doc.go → vendor/github.com/sirupsen/logrus/doc.go
generated
vendored
0
vendor/github.com/Sirupsen/logrus/doc.go → vendor/github.com/sirupsen/logrus/doc.go
generated
vendored
|
@ -0,0 +1,422 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
// qualified package name, cached at first use
|
||||
logrusPackage string
|
||||
|
||||
// Positions in the call stack when tracing to report the calling method
|
||||
minimumCallerDepth int
|
||||
|
||||
// Used for caller information initialisation
|
||||
callerInitOnce sync.Once
|
||||
)
|
||||
|
||||
const (
|
||||
maximumCallerDepth int = 25
|
||||
knownLogrusFrames int = 4
|
||||
)
|
||||
|
||||
func init() {
|
||||
// start at the bottom of the stack before the package-name cache is primed
|
||||
minimumCallerDepth = 1
|
||||
}
|
||||
|
||||
// Defines the key when adding errors using WithError.
|
||||
var ErrorKey = "error"
|
||||
|
||||
// An entry is the final or intermediate Logrus logging entry. It contains all
|
||||
// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
|
||||
// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
|
||||
// reused and passed around as much as you wish to avoid field duplication.
|
||||
type Entry struct {
|
||||
Logger *Logger
|
||||
|
||||
// Contains all the fields set by the user.
|
||||
Data Fields
|
||||
|
||||
// Time at which the log entry was created
|
||||
Time time.Time
|
||||
|
||||
// Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
|
||||
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
|
||||
Level Level
|
||||
|
||||
// Calling method, with package name
|
||||
Caller *runtime.Frame
|
||||
|
||||
// Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
|
||||
Message string
|
||||
|
||||
// When formatter is called in entry.log(), a Buffer may be set to entry
|
||||
Buffer *bytes.Buffer
|
||||
|
||||
// Contains the context set by the user. Useful for hook processing etc.
|
||||
Context context.Context
|
||||
|
||||
// err may contain a field formatting error
|
||||
err string
|
||||
}
|
||||
|
||||
func NewEntry(logger *Logger) *Entry {
|
||||
return &Entry{
|
||||
Logger: logger,
|
||||
// Default is three fields, plus one optional. Give a little extra room.
|
||||
Data: make(Fields, 6),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the bytes representation of this entry from the formatter.
|
||||
func (entry *Entry) Bytes() ([]byte, error) {
|
||||
return entry.Logger.Formatter.Format(entry)
|
||||
}
|
||||
|
||||
// Returns the string representation from the reader and ultimately the
|
||||
// formatter.
|
||||
func (entry *Entry) String() (string, error) {
|
||||
serialized, err := entry.Bytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
str := string(serialized)
|
||||
return str, nil
|
||||
}
|
||||
|
||||
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
|
||||
func (entry *Entry) WithError(err error) *Entry {
|
||||
return entry.WithField(ErrorKey, err)
|
||||
}
|
||||
|
||||
// Add a context to the Entry.
|
||||
func (entry *Entry) WithContext(ctx context.Context) *Entry {
|
||||
dataCopy := make(Fields, len(entry.Data))
|
||||
for k, v := range entry.Data {
|
||||
dataCopy[k] = v
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx}
|
||||
}
|
||||
|
||||
// Add a single field to the Entry.
|
||||
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
||||
return entry.WithFields(Fields{key: value})
|
||||
}
|
||||
|
||||
// Add a map of fields to the Entry.
|
||||
func (entry *Entry) WithFields(fields Fields) *Entry {
|
||||
data := make(Fields, len(entry.Data)+len(fields))
|
||||
for k, v := range entry.Data {
|
||||
data[k] = v
|
||||
}
|
||||
fieldErr := entry.err
|
||||
for k, v := range fields {
|
||||
isErrField := false
|
||||
if t := reflect.TypeOf(v); t != nil {
|
||||
switch t.Kind() {
|
||||
case reflect.Func:
|
||||
isErrField = true
|
||||
case reflect.Ptr:
|
||||
isErrField = t.Elem().Kind() == reflect.Func
|
||||
}
|
||||
}
|
||||
if isErrField {
|
||||
tmp := fmt.Sprintf("can not add field %q", k)
|
||||
if fieldErr != "" {
|
||||
fieldErr = entry.err + ", " + tmp
|
||||
} else {
|
||||
fieldErr = tmp
|
||||
}
|
||||
} else {
|
||||
data[k] = v
|
||||
}
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
|
||||
}
|
||||
|
||||
// Overrides the time of the Entry.
|
||||
func (entry *Entry) WithTime(t time.Time) *Entry {
|
||||
dataCopy := make(Fields, len(entry.Data))
|
||||
for k, v := range entry.Data {
|
||||
dataCopy[k] = v
|
||||
}
|
||||
return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context}
|
||||
}
|
||||
|
||||
// getPackageName reduces a fully qualified function name to the package name
|
||||
// There really ought to be to be a better way...
|
||||
func getPackageName(f string) string {
|
||||
for {
|
||||
lastPeriod := strings.LastIndex(f, ".")
|
||||
lastSlash := strings.LastIndex(f, "/")
|
||||
if lastPeriod > lastSlash {
|
||||
f = f[:lastPeriod]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// getCaller retrieves the name of the first non-logrus calling function
|
||||
func getCaller() *runtime.Frame {
|
||||
// cache this package's fully-qualified name
|
||||
callerInitOnce.Do(func() {
|
||||
pcs := make([]uintptr, maximumCallerDepth)
|
||||
_ = runtime.Callers(0, pcs)
|
||||
|
||||
// dynamic get the package name and the minimum caller depth
|
||||
for i := 0; i < maximumCallerDepth; i++ {
|
||||
funcName := runtime.FuncForPC(pcs[i]).Name()
|
||||
if strings.Contains(funcName, "getCaller") {
|
||||
logrusPackage = getPackageName(funcName)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
minimumCallerDepth = knownLogrusFrames
|
||||
})
|
||||
|
||||
// Restrict the lookback frames to avoid runaway lookups
|
||||
pcs := make([]uintptr, maximumCallerDepth)
|
||||
depth := runtime.Callers(minimumCallerDepth, pcs)
|
||||
frames := runtime.CallersFrames(pcs[:depth])
|
||||
|
||||
for f, again := frames.Next(); again; f, again = frames.Next() {
|
||||
pkg := getPackageName(f.Function)
|
||||
|
||||
// If the caller isn't part of this package, we're done
|
||||
if pkg != logrusPackage {
|
||||
return &f //nolint:scopelint
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here, we failed to find the caller's context
|
||||
return nil
|
||||
}
|
||||
|
||||
func (entry Entry) HasCaller() (has bool) {
|
||||
return entry.Logger != nil &&
|
||||
entry.Logger.ReportCaller &&
|
||||
entry.Caller != nil
|
||||
}
|
||||
|
||||
// This function is not declared with a pointer value because otherwise
|
||||
// race conditions will occur when using multiple goroutines
|
||||
func (entry Entry) log(level Level, msg string) {
|
||||
var buffer *bytes.Buffer
|
||||
|
||||
// Default to now, but allow users to override if they want.
|
||||
//
|
||||
// We don't have to worry about polluting future calls to Entry#log()
|
||||
// with this assignment because this function is declared with a
|
||||
// non-pointer receiver.
|
||||
if entry.Time.IsZero() {
|
||||
entry.Time = time.Now()
|
||||
}
|
||||
|
||||
entry.Level = level
|
||||
entry.Message = msg
|
||||
entry.Logger.mu.Lock()
|
||||
if entry.Logger.ReportCaller {
|
||||
entry.Caller = getCaller()
|
||||
}
|
||||
entry.Logger.mu.Unlock()
|
||||
|
||||
entry.fireHooks()
|
||||
|
||||
buffer = getBuffer()
|
||||
defer func() {
|
||||
entry.Buffer = nil
|
||||
putBuffer(buffer)
|
||||
}()
|
||||
buffer.Reset()
|
||||
entry.Buffer = buffer
|
||||
|
||||
entry.write()
|
||||
|
||||
entry.Buffer = nil
|
||||
|
||||
// To avoid Entry#log() returning a value that only would make sense for
|
||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
||||
// directly here.
|
||||
if level <= PanicLevel {
|
||||
panic(&entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) fireHooks() {
|
||||
entry.Logger.mu.Lock()
|
||||
defer entry.Logger.mu.Unlock()
|
||||
err := entry.Logger.Hooks.Fire(entry.Level, entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) write() {
|
||||
entry.Logger.mu.Lock()
|
||||
defer entry.Logger.mu.Unlock()
|
||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
||||
return
|
||||
}
|
||||
if _, err = entry.Logger.Out.Write(serialized); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Log(level Level, args ...interface{}) {
|
||||
if entry.Logger.IsLevelEnabled(level) {
|
||||
entry.log(level, fmt.Sprint(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Trace(args ...interface{}) {
|
||||
entry.Log(TraceLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Debug(args ...interface{}) {
|
||||
entry.Log(DebugLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Print(args ...interface{}) {
|
||||
entry.Info(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Info(args ...interface{}) {
|
||||
entry.Log(InfoLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warn(args ...interface{}) {
|
||||
entry.Log(WarnLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warning(args ...interface{}) {
|
||||
entry.Warn(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Error(args ...interface{}) {
|
||||
entry.Log(ErrorLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatal(args ...interface{}) {
|
||||
entry.Log(FatalLevel, args...)
|
||||
entry.Logger.Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panic(args ...interface{}) {
|
||||
entry.Log(PanicLevel, args...)
|
||||
panic(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Entry Printf family functions
|
||||
|
||||
func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
|
||||
if entry.Logger.IsLevelEnabled(level) {
|
||||
entry.Log(level, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Tracef(format string, args ...interface{}) {
|
||||
entry.Logf(TraceLevel, format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
||||
entry.Logf(DebugLevel, format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Infof(format string, args ...interface{}) {
|
||||
entry.Logf(InfoLevel, format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Printf(format string, args ...interface{}) {
|
||||
entry.Infof(format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
||||
entry.Logf(WarnLevel, format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
||||
entry.Warnf(format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
||||
entry.Logf(ErrorLevel, format, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
||||
entry.Logf(FatalLevel, format, args...)
|
||||
entry.Logger.Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
||||
entry.Logf(PanicLevel, format, args...)
|
||||
}
|
||||
|
||||
// Entry Println family functions
|
||||
|
||||
func (entry *Entry) Logln(level Level, args ...interface{}) {
|
||||
if entry.Logger.IsLevelEnabled(level) {
|
||||
entry.Log(level, entry.sprintlnn(args...))
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Traceln(args ...interface{}) {
|
||||
entry.Logln(TraceLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Debugln(args ...interface{}) {
|
||||
entry.Logln(DebugLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Infoln(args ...interface{}) {
|
||||
entry.Logln(InfoLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Println(args ...interface{}) {
|
||||
entry.Infoln(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warnln(args ...interface{}) {
|
||||
entry.Logln(WarnLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Warningln(args ...interface{}) {
|
||||
entry.Warnln(args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Errorln(args ...interface{}) {
|
||||
entry.Logln(ErrorLevel, args...)
|
||||
}
|
||||
|
||||
func (entry *Entry) Fatalln(args ...interface{}) {
|
||||
entry.Logln(FatalLevel, args...)
|
||||
entry.Logger.Exit(1)
|
||||
}
|
||||
|
||||
func (entry *Entry) Panicln(args ...interface{}) {
|
||||
entry.Logln(PanicLevel, args...)
|
||||
}
|
||||
|
||||
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
||||
// fmt.Sprintln where spaces are always added between operands, regardless of
|
||||
// their type. Instead of vendoring the Sprintln implementation to spare a
|
||||
// string allocation, we do the simplest thing.
|
||||
func (entry *Entry) sprintlnn(args ...interface{}) string {
|
||||
msg := fmt.Sprintln(args...)
|
||||
return msg[:len(msg)-1]
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -15,37 +17,38 @@ func StandardLogger() *Logger {
|
|||
|
||||
// SetOutput sets the standard logger output.
|
||||
func SetOutput(out io.Writer) {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
std.Out = out
|
||||
std.SetOutput(out)
|
||||
}
|
||||
|
||||
// SetFormatter sets the standard logger formatter.
|
||||
func SetFormatter(formatter Formatter) {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
std.Formatter = formatter
|
||||
std.SetFormatter(formatter)
|
||||
}
|
||||
|
||||
// SetReportCaller sets whether the standard logger will include the calling
|
||||
// method as a field.
|
||||
func SetReportCaller(include bool) {
|
||||
std.SetReportCaller(include)
|
||||
}
|
||||
|
||||
// SetLevel sets the standard logger level.
|
||||
func SetLevel(level Level) {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
std.setLevel(level)
|
||||
std.SetLevel(level)
|
||||
}
|
||||
|
||||
// GetLevel returns the standard logger level.
|
||||
func GetLevel() Level {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
return std.level()
|
||||
return std.GetLevel()
|
||||
}
|
||||
|
||||
// IsLevelEnabled checks if the log level of the standard logger is greater than the level param
|
||||
func IsLevelEnabled(level Level) bool {
|
||||
return std.IsLevelEnabled(level)
|
||||
}
|
||||
|
||||
// AddHook adds a hook to the standard logger hooks.
|
||||
func AddHook(hook Hook) {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
std.Hooks.Add(hook)
|
||||
std.AddHook(hook)
|
||||
}
|
||||
|
||||
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
|
||||
|
@ -53,6 +56,11 @@ func WithError(err error) *Entry {
|
|||
return std.WithField(ErrorKey, err)
|
||||
}
|
||||
|
||||
// WithContext creates an entry from the standard logger and adds a context to it.
|
||||
func WithContext(ctx context.Context) *Entry {
|
||||
return std.WithContext(ctx)
|
||||
}
|
||||
|
||||
// WithField creates an entry from the standard logger and adds a field to
|
||||
// it. If you want multiple fields, use `WithFields`.
|
||||
//
|
||||
|
@ -72,6 +80,20 @@ func WithFields(fields Fields) *Entry {
|
|||
return std.WithFields(fields)
|
||||
}
|
||||
|
||||
// WithTime creates an entry from the standard logger and overrides the time of
|
||||
// logs generated with it.
|
||||
//
|
||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
||||
// or Panic on the Entry it returns.
|
||||
func WithTime(t time.Time) *Entry {
|
||||
return std.WithTime(t)
|
||||
}
|
||||
|
||||
// Trace logs a message at level Trace on the standard logger.
|
||||
func Trace(args ...interface{}) {
|
||||
std.Trace(args...)
|
||||
}
|
||||
|
||||
// Debug logs a message at level Debug on the standard logger.
|
||||
func Debug(args ...interface{}) {
|
||||
std.Debug(args...)
|
||||
|
@ -107,11 +129,61 @@ func Panic(args ...interface{}) {
|
|||
std.Panic(args...)
|
||||
}
|
||||
|
||||
// Fatal logs a message at level Fatal on the standard logger.
|
||||
// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
||||
func Fatal(args ...interface{}) {
|
||||
std.Fatal(args...)
|
||||
}
|
||||
|
||||
// TraceFn logs a message from a func at level Trace on the standard logger.
|
||||
func TraceFn(fn LogFunction) {
|
||||
std.TraceFn(fn)
|
||||
}
|
||||
|
||||
// DebugFn logs a message from a func at level Debug on the standard logger.
|
||||
func DebugFn(fn LogFunction) {
|
||||
std.DebugFn(fn)
|
||||
}
|
||||
|
||||
// PrintFn logs a message from a func at level Info on the standard logger.
|
||||
func PrintFn(fn LogFunction) {
|
||||
std.PrintFn(fn)
|
||||
}
|
||||
|
||||
// InfoFn logs a message from a func at level Info on the standard logger.
|
||||
func InfoFn(fn LogFunction) {
|
||||
std.InfoFn(fn)
|
||||
}
|
||||
|
||||
// WarnFn logs a message from a func at level Warn on the standard logger.
|
||||
func WarnFn(fn LogFunction) {
|
||||
std.WarnFn(fn)
|
||||
}
|
||||
|
||||
// WarningFn logs a message from a func at level Warn on the standard logger.
|
||||
func WarningFn(fn LogFunction) {
|
||||
std.WarningFn(fn)
|
||||
}
|
||||
|
||||
// ErrorFn logs a message from a func at level Error on the standard logger.
|
||||
func ErrorFn(fn LogFunction) {
|
||||
std.ErrorFn(fn)
|
||||
}
|
||||
|
||||
// PanicFn logs a message from a func at level Panic on the standard logger.
|
||||
func PanicFn(fn LogFunction) {
|
||||
std.PanicFn(fn)
|
||||
}
|
||||
|
||||
// FatalFn logs a message from a func at level Fatal on the standard logger then the process will exit with status set to 1.
|
||||
func FatalFn(fn LogFunction) {
|
||||
std.FatalFn(fn)
|
||||
}
|
||||
|
||||
// Tracef logs a message at level Trace on the standard logger.
|
||||
func Tracef(format string, args ...interface{}) {
|
||||
std.Tracef(format, args...)
|
||||
}
|
||||
|
||||
// Debugf logs a message at level Debug on the standard logger.
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
std.Debugf(format, args...)
|
||||
|
@ -147,11 +219,16 @@ func Panicf(format string, args ...interface{}) {
|
|||
std.Panicf(format, args...)
|
||||
}
|
||||
|
||||
// Fatalf logs a message at level Fatal on the standard logger.
|
||||
// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
std.Fatalf(format, args...)
|
||||
}
|
||||
|
||||
// Traceln logs a message at level Trace on the standard logger.
|
||||
func Traceln(args ...interface{}) {
|
||||
std.Traceln(args...)
|
||||
}
|
||||
|
||||
// Debugln logs a message at level Debug on the standard logger.
|
||||
func Debugln(args ...interface{}) {
|
||||
std.Debugln(args...)
|
||||
|
@ -187,7 +264,7 @@ func Panicln(args ...interface{}) {
|
|||
std.Panicln(args...)
|
||||
}
|
||||
|
||||
// Fatalln logs a message at level Fatal on the standard logger.
|
||||
// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
|
||||
func Fatalln(args ...interface{}) {
|
||||
std.Fatalln(args...)
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package logrus
|
||||
|
||||
import "time"
|
||||
|
||||
// Default key names for the default fields
|
||||
const (
|
||||
defaultTimestampFormat = time.RFC3339
|
||||
FieldKeyMsg = "msg"
|
||||
FieldKeyLevel = "level"
|
||||
FieldKeyTime = "time"
|
||||
FieldKeyLogrusError = "logrus_error"
|
||||
FieldKeyFunc = "func"
|
||||
FieldKeyFile = "file"
|
||||
)
|
||||
|
||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||
// `Entry`. It exposes all the fields, including the default ones:
|
||||
//
|
||||
// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
|
||||
// * `entry.Data["time"]`. The timestamp.
|
||||
// * `entry.Data["level"]. The level the entry was logged at.
|
||||
//
|
||||
// Any additional fields added with `WithField` or `WithFields` are also in
|
||||
// `entry.Data`. Format is expected to return an array of bytes which are then
|
||||
// logged to `logger.Out`.
|
||||
type Formatter interface {
|
||||
Format(*Entry) ([]byte, error)
|
||||
}
|
||||
|
||||
// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
|
||||
// dumping it. If this code wasn't there doing:
|
||||
//
|
||||
// logrus.WithField("level", 1).Info("hello")
|
||||
//
|
||||
// Would just silently drop the user provided level. Instead with this code
|
||||
// it'll logged as:
|
||||
//
|
||||
// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
|
||||
//
|
||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
||||
// avoid code duplication between the two default formatters.
|
||||
func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) {
|
||||
timeKey := fieldMap.resolve(FieldKeyTime)
|
||||
if t, ok := data[timeKey]; ok {
|
||||
data["fields."+timeKey] = t
|
||||
delete(data, timeKey)
|
||||
}
|
||||
|
||||
msgKey := fieldMap.resolve(FieldKeyMsg)
|
||||
if m, ok := data[msgKey]; ok {
|
||||
data["fields."+msgKey] = m
|
||||
delete(data, msgKey)
|
||||
}
|
||||
|
||||
levelKey := fieldMap.resolve(FieldKeyLevel)
|
||||
if l, ok := data[levelKey]; ok {
|
||||
data["fields."+levelKey] = l
|
||||
delete(data, levelKey)
|
||||
}
|
||||
|
||||
logrusErrKey := fieldMap.resolve(FieldKeyLogrusError)
|
||||
if l, ok := data[logrusErrKey]; ok {
|
||||
data["fields."+logrusErrKey] = l
|
||||
delete(data, logrusErrKey)
|
||||
}
|
||||
|
||||
// If reportCaller is not set, 'func' will not conflict.
|
||||
if reportCaller {
|
||||
funcKey := fieldMap.resolve(FieldKeyFunc)
|
||||
if l, ok := data[funcKey]; ok {
|
||||
data["fields."+funcKey] = l
|
||||
}
|
||||
fileKey := fieldMap.resolve(FieldKeyFile)
|
||||
if l, ok := data[fileKey]; ok {
|
||||
data["fields."+fileKey] = l
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
module github.com/sirupsen/logrus
|
||||
|
||||
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
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
|
||||
)
|
||||
|
||||
go 1.13
|
|
@ -0,0 +1,10 @@
|
|||
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=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
@ -0,0 +1,125 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type fieldKey string
|
||||
|
||||
// FieldMap allows customization of the key names for default fields.
|
||||
type FieldMap map[fieldKey]string
|
||||
|
||||
func (f FieldMap) resolve(key fieldKey) string {
|
||||
if k, ok := f[key]; ok {
|
||||
return k
|
||||
}
|
||||
|
||||
return string(key)
|
||||
}
|
||||
|
||||
// JSONFormatter formats logs into parsable json
|
||||
type JSONFormatter struct {
|
||||
// TimestampFormat sets the format used for marshaling timestamps.
|
||||
TimestampFormat string
|
||||
|
||||
// DisableTimestamp allows disabling automatic timestamps in output
|
||||
DisableTimestamp bool
|
||||
|
||||
// DisableHTMLEscape allows disabling html escaping in output
|
||||
DisableHTMLEscape bool
|
||||
|
||||
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
|
||||
DataKey string
|
||||
|
||||
// FieldMap allows users to customize the names of keys for default fields.
|
||||
// As an example:
|
||||
// formatter := &JSONFormatter{
|
||||
// FieldMap: FieldMap{
|
||||
// FieldKeyTime: "@timestamp",
|
||||
// FieldKeyLevel: "@level",
|
||||
// FieldKeyMsg: "@message",
|
||||
// FieldKeyFunc: "@caller",
|
||||
// },
|
||||
// }
|
||||
FieldMap FieldMap
|
||||
|
||||
// CallerPrettyfier can be set by the user to modify the content
|
||||
// of the function and file keys in the json data when ReportCaller is
|
||||
// activated. If any of the returned value is the empty string the
|
||||
// corresponding key will be removed from json fields.
|
||||
CallerPrettyfier func(*runtime.Frame) (function string, file string)
|
||||
|
||||
// PrettyPrint will indent all json logs
|
||||
PrettyPrint bool
|
||||
}
|
||||
|
||||
// Format renders a single log entry
|
||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
data := make(Fields, len(entry.Data)+4)
|
||||
for k, v := range entry.Data {
|
||||
switch v := v.(type) {
|
||||
case error:
|
||||
// Otherwise errors are ignored by `encoding/json`
|
||||
// https://github.com/sirupsen/logrus/issues/137
|
||||
data[k] = v.Error()
|
||||
default:
|
||||
data[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if f.DataKey != "" {
|
||||
newData := make(Fields, 4)
|
||||
newData[f.DataKey] = data
|
||||
data = newData
|
||||
}
|
||||
|
||||
prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
timestampFormat = defaultTimestampFormat
|
||||
}
|
||||
|
||||
if entry.err != "" {
|
||||
data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
|
||||
}
|
||||
if !f.DisableTimestamp {
|
||||
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
|
||||
}
|
||||
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
|
||||
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
|
||||
if entry.HasCaller() {
|
||||
funcVal := entry.Caller.Function
|
||||
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
|
||||
if f.CallerPrettyfier != nil {
|
||||
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
|
||||
}
|
||||
if funcVal != "" {
|
||||
data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
|
||||
}
|
||||
if fileVal != "" {
|
||||
data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
|
||||
}
|
||||
}
|
||||
|
||||
var b *bytes.Buffer
|
||||
if entry.Buffer != nil {
|
||||
b = entry.Buffer
|
||||
} else {
|
||||
b = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(b)
|
||||
encoder.SetEscapeHTML(!f.DisableHTMLEscape)
|
||||
if f.PrettyPrint {
|
||||
encoder.SetIndent("", " ")
|
||||
}
|
||||
if err := encoder.Encode(data); err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
|
@ -0,0 +1,404 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogFunction For big messages, it can be more efficient to pass a function
|
||||
// and only call it if the log level is actually enables rather than
|
||||
// generating the log message and then checking if the level is enabled
|
||||
type LogFunction func()[]interface{}
|
||||
|
||||
type Logger struct {
|
||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
||||
// file, or leave it default which is `os.Stderr`. You can also set this to
|
||||
// something more adventurous, such as logging to Kafka.
|
||||
Out io.Writer
|
||||
// Hooks for the logger instance. These allow firing events based on logging
|
||||
// levels and log entries. For example, to send errors to an error tracking
|
||||
// service, log to StatsD or dump the core on fatal errors.
|
||||
Hooks LevelHooks
|
||||
// All log entries pass through the formatter before logged to Out. The
|
||||
// included formatters are `TextFormatter` and `JSONFormatter` for which
|
||||
// TextFormatter is the default. In development (when a TTY is attached) it
|
||||
// logs with colors, but to a file it wouldn't. You can easily implement your
|
||||
// own that implements the `Formatter` interface, see the `README` or included
|
||||
// formatters for examples.
|
||||
Formatter Formatter
|
||||
|
||||
// Flag for whether to log caller info (off by default)
|
||||
ReportCaller bool
|
||||
|
||||
// The logging level the logger should log at. This is typically (and defaults
|
||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
||||
// logged.
|
||||
Level Level
|
||||
// Used to sync writing to the log. Locking is enabled by Default
|
||||
mu MutexWrap
|
||||
// Reusable empty entry
|
||||
entryPool sync.Pool
|
||||
// Function to exit the application, defaults to `os.Exit()`
|
||||
ExitFunc exitFunc
|
||||
}
|
||||
|
||||
type exitFunc func(int)
|
||||
|
||||
type MutexWrap struct {
|
||||
lock sync.Mutex
|
||||
disabled bool
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Lock() {
|
||||
if !mw.disabled {
|
||||
mw.lock.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Unlock() {
|
||||
if !mw.disabled {
|
||||
mw.lock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (mw *MutexWrap) Disable() {
|
||||
mw.disabled = true
|
||||
}
|
||||
|
||||
// Creates a new logger. Configuration should be set by changing `Formatter`,
|
||||
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
||||
// instantiate your own:
|
||||
//
|
||||
// var log = &logrus.Logger{
|
||||
// Out: os.Stderr,
|
||||
// Formatter: new(logrus.TextFormatter),
|
||||
// Hooks: make(logrus.LevelHooks),
|
||||
// Level: logrus.DebugLevel,
|
||||
// }
|
||||
//
|
||||
// It's recommended to make this a global instance called `log`.
|
||||
func New() *Logger {
|
||||
return &Logger{
|
||||
Out: os.Stderr,
|
||||
Formatter: new(TextFormatter),
|
||||
Hooks: make(LevelHooks),
|
||||
Level: InfoLevel,
|
||||
ExitFunc: os.Exit,
|
||||
ReportCaller: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) newEntry() *Entry {
|
||||
entry, ok := logger.entryPool.Get().(*Entry)
|
||||
if ok {
|
||||
return entry
|
||||
}
|
||||
return NewEntry(logger)
|
||||
}
|
||||
|
||||
func (logger *Logger) releaseEntry(entry *Entry) {
|
||||
entry.Data = map[string]interface{}{}
|
||||
logger.entryPool.Put(entry)
|
||||
}
|
||||
|
||||
// WithField allocates a new entry and adds a field to it.
|
||||
// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
|
||||
// this new returned entry.
|
||||
// If you want multiple fields, use `WithFields`.
|
||||
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithField(key, value)
|
||||
}
|
||||
|
||||
// Adds a struct of fields to the log entry. All it does is call `WithField` for
|
||||
// each `Field`.
|
||||
func (logger *Logger) WithFields(fields Fields) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithFields(fields)
|
||||
}
|
||||
|
||||
// Add an error as single field to the log entry. All it does is call
|
||||
// `WithError` for the given `error`.
|
||||
func (logger *Logger) WithError(err error) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithError(err)
|
||||
}
|
||||
|
||||
// Add a context to the log entry.
|
||||
func (logger *Logger) WithContext(ctx context.Context) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithContext(ctx)
|
||||
}
|
||||
|
||||
// Overrides the time of the log entry.
|
||||
func (logger *Logger) WithTime(t time.Time) *Entry {
|
||||
entry := logger.newEntry()
|
||||
defer logger.releaseEntry(entry)
|
||||
return entry.WithTime(t)
|
||||
}
|
||||
|
||||
func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
|
||||
if logger.IsLevelEnabled(level) {
|
||||
entry := logger.newEntry()
|
||||
entry.Logf(level, format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Tracef(format string, args ...interface{}) {
|
||||
logger.Logf(TraceLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
||||
logger.Logf(DebugLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Infof(format string, args ...interface{}) {
|
||||
logger.Logf(InfoLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Printf(format string, args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Printf(format, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
||||
logger.Logf(WarnLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
||||
logger.Warnf(format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
||||
logger.Logf(ErrorLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
||||
logger.Logf(FatalLevel, format, args...)
|
||||
logger.Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
||||
logger.Logf(PanicLevel, format, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Log(level Level, args ...interface{}) {
|
||||
if logger.IsLevelEnabled(level) {
|
||||
entry := logger.newEntry()
|
||||
entry.Log(level, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) LogFn(level Level, fn LogFunction) {
|
||||
if logger.IsLevelEnabled(level) {
|
||||
entry := logger.newEntry()
|
||||
entry.Log(level, fn()...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Trace(args ...interface{}) {
|
||||
logger.Log(TraceLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Debug(args ...interface{}) {
|
||||
logger.Log(DebugLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Info(args ...interface{}) {
|
||||
logger.Log(InfoLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Print(args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Print(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warn(args ...interface{}) {
|
||||
logger.Log(WarnLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warning(args ...interface{}) {
|
||||
logger.Warn(args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Error(args ...interface{}) {
|
||||
logger.Log(ErrorLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatal(args ...interface{}) {
|
||||
logger.Log(FatalLevel, args...)
|
||||
logger.Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panic(args ...interface{}) {
|
||||
logger.Log(PanicLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) TraceFn(fn LogFunction) {
|
||||
logger.LogFn(TraceLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) DebugFn(fn LogFunction) {
|
||||
logger.LogFn(DebugLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) InfoFn(fn LogFunction) {
|
||||
logger.LogFn(InfoLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) PrintFn(fn LogFunction) {
|
||||
entry := logger.newEntry()
|
||||
entry.Print(fn()...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) WarnFn(fn LogFunction) {
|
||||
logger.LogFn(WarnLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) WarningFn(fn LogFunction) {
|
||||
logger.WarnFn(fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) ErrorFn(fn LogFunction) {
|
||||
logger.LogFn(ErrorLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) FatalFn(fn LogFunction) {
|
||||
logger.LogFn(FatalLevel, fn)
|
||||
logger.Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) PanicFn(fn LogFunction) {
|
||||
logger.LogFn(PanicLevel, fn)
|
||||
}
|
||||
|
||||
func (logger *Logger) Logln(level Level, args ...interface{}) {
|
||||
if logger.IsLevelEnabled(level) {
|
||||
entry := logger.newEntry()
|
||||
entry.Logln(level, args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func (logger *Logger) Traceln(args ...interface{}) {
|
||||
logger.Logln(TraceLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Debugln(args ...interface{}) {
|
||||
logger.Logln(DebugLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Infoln(args ...interface{}) {
|
||||
logger.Logln(InfoLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Println(args ...interface{}) {
|
||||
entry := logger.newEntry()
|
||||
entry.Println(args...)
|
||||
logger.releaseEntry(entry)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warnln(args ...interface{}) {
|
||||
logger.Logln(WarnLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Warningln(args ...interface{}) {
|
||||
logger.Warnln(args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Errorln(args ...interface{}) {
|
||||
logger.Logln(ErrorLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Fatalln(args ...interface{}) {
|
||||
logger.Logln(FatalLevel, args...)
|
||||
logger.Exit(1)
|
||||
}
|
||||
|
||||
func (logger *Logger) Panicln(args ...interface{}) {
|
||||
logger.Logln(PanicLevel, args...)
|
||||
}
|
||||
|
||||
func (logger *Logger) Exit(code int) {
|
||||
runHandlers()
|
||||
if logger.ExitFunc == nil {
|
||||
logger.ExitFunc = os.Exit
|
||||
}
|
||||
logger.ExitFunc(code)
|
||||
}
|
||||
|
||||
//When file is opened with appending mode, it's safe to
|
||||
//write concurrently to a file (within 4k message on Linux).
|
||||
//In these cases user can choose to disable the lock.
|
||||
func (logger *Logger) SetNoLock() {
|
||||
logger.mu.Disable()
|
||||
}
|
||||
|
||||
func (logger *Logger) level() Level {
|
||||
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
|
||||
}
|
||||
|
||||
// SetLevel sets the logger level.
|
||||
func (logger *Logger) SetLevel(level Level) {
|
||||
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
||||
}
|
||||
|
||||
// GetLevel returns the logger level.
|
||||
func (logger *Logger) GetLevel() Level {
|
||||
return logger.level()
|
||||
}
|
||||
|
||||
// AddHook adds a hook to the logger hooks.
|
||||
func (logger *Logger) AddHook(hook Hook) {
|
||||
logger.mu.Lock()
|
||||
defer logger.mu.Unlock()
|
||||
logger.Hooks.Add(hook)
|
||||
}
|
||||
|
||||
// IsLevelEnabled checks if the log level of the logger is greater than the level param
|
||||
func (logger *Logger) IsLevelEnabled(level Level) bool {
|
||||
return logger.level() >= level
|
||||
}
|
||||
|
||||
// SetFormatter sets the logger formatter.
|
||||
func (logger *Logger) SetFormatter(formatter Formatter) {
|
||||
logger.mu.Lock()
|
||||
defer logger.mu.Unlock()
|
||||
logger.Formatter = formatter
|
||||
}
|
||||
|
||||
// SetOutput sets the logger output.
|
||||
func (logger *Logger) SetOutput(output io.Writer) {
|
||||
logger.mu.Lock()
|
||||
defer logger.mu.Unlock()
|
||||
logger.Out = output
|
||||
}
|
||||
|
||||
func (logger *Logger) SetReportCaller(reportCaller bool) {
|
||||
logger.mu.Lock()
|
||||
defer logger.mu.Unlock()
|
||||
logger.ReportCaller = reportCaller
|
||||
}
|
||||
|
||||
// ReplaceHooks replaces the logger hooks and returns the old ones
|
||||
func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
|
||||
logger.mu.Lock()
|
||||
oldHooks := logger.Hooks
|
||||
logger.Hooks = hooks
|
||||
logger.mu.Unlock()
|
||||
return oldHooks
|
||||
}
|
|
@ -14,22 +14,11 @@ type Level uint32
|
|||
|
||||
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
|
||||
func (level Level) String() string {
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
return "debug"
|
||||
case InfoLevel:
|
||||
return "info"
|
||||
case WarnLevel:
|
||||
return "warning"
|
||||
case ErrorLevel:
|
||||
return "error"
|
||||
case FatalLevel:
|
||||
return "fatal"
|
||||
case PanicLevel:
|
||||
return "panic"
|
||||
if b, err := level.MarshalText(); err == nil {
|
||||
return string(b)
|
||||
} else {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// ParseLevel takes a string level and returns the Logrus log level constant.
|
||||
|
@ -47,12 +36,47 @@ func ParseLevel(lvl string) (Level, error) {
|
|||
return InfoLevel, nil
|
||||
case "debug":
|
||||
return DebugLevel, nil
|
||||
case "trace":
|
||||
return TraceLevel, nil
|
||||
}
|
||||
|
||||
var l Level
|
||||
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (level *Level) UnmarshalText(text []byte) error {
|
||||
l, err := ParseLevel(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*level = l
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (level Level) MarshalText() ([]byte, error) {
|
||||
switch level {
|
||||
case TraceLevel:
|
||||
return []byte("trace"), nil
|
||||
case DebugLevel:
|
||||
return []byte("debug"), nil
|
||||
case InfoLevel:
|
||||
return []byte("info"), nil
|
||||
case WarnLevel:
|
||||
return []byte("warning"), nil
|
||||
case ErrorLevel:
|
||||
return []byte("error"), nil
|
||||
case FatalLevel:
|
||||
return []byte("fatal"), nil
|
||||
case PanicLevel:
|
||||
return []byte("panic"), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("not a valid logrus level %d", level)
|
||||
}
|
||||
|
||||
// A constant exposing all logging levels
|
||||
var AllLevels = []Level{
|
||||
PanicLevel,
|
||||
|
@ -61,6 +85,7 @@ var AllLevels = []Level{
|
|||
WarnLevel,
|
||||
InfoLevel,
|
||||
DebugLevel,
|
||||
TraceLevel,
|
||||
}
|
||||
|
||||
// These are the different logging levels. You can set the logging level to log
|
||||
|
@ -69,7 +94,7 @@ const (
|
|||
// PanicLevel level, highest level of severity. Logs and then calls panic with the
|
||||
// message passed to Debug, Info, ...
|
||||
PanicLevel Level = iota
|
||||
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
|
||||
// FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the
|
||||
// logging level is set to Panic.
|
||||
FatalLevel
|
||||
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
||||
|
@ -82,6 +107,8 @@ const (
|
|||
InfoLevel
|
||||
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
||||
DebugLevel
|
||||
// TraceLevel level. Designates finer-grained informational events than the Debug.
|
||||
TraceLevel
|
||||
)
|
||||
|
||||
// Won't compile if StdLogger can't be realized by a log.Logger
|
||||
|
@ -140,4 +167,20 @@ type FieldLogger interface {
|
|||
Errorln(args ...interface{})
|
||||
Fatalln(args ...interface{})
|
||||
Panicln(args ...interface{})
|
||||
|
||||
// IsDebugEnabled() bool
|
||||
// IsInfoEnabled() bool
|
||||
// IsWarnEnabled() bool
|
||||
// IsErrorEnabled() bool
|
||||
// IsFatalEnabled() bool
|
||||
// IsPanicEnabled() bool
|
||||
}
|
||||
|
||||
// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is
|
||||
// here for consistancy. Do not use. Use Logger or Entry instead.
|
||||
type Ext1FieldLogger interface {
|
||||
FieldLogger
|
||||
Tracef(format string, args ...interface{})
|
||||
Trace(args ...interface{})
|
||||
Traceln(args ...interface{})
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// +build appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func checkIfTerminal(w io.Writer) bool {
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
// +build !js
|
||||
|
||||
package logrus
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const ioctlReadTermios = unix.TIOCGETA
|
||||
|
||||
func isTerminal(fd int) bool {
|
||||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// +build js
|
||||
|
||||
package logrus
|
||||
|
||||
func isTerminal(fd int) bool {
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// +build js nacl plan9
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func checkIfTerminal(w io.Writer) bool {
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// +build !appengine,!js,!windows,!nacl,!plan9
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func checkIfTerminal(w io.Writer) bool {
|
||||
switch v := w.(type) {
|
||||
case *os.File:
|
||||
return isTerminal(int(v.Fd()))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package logrus
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func isTerminal(fd int) bool {
|
||||
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
|
||||
return err == nil
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// +build linux aix
|
||||
// +build !js
|
||||
|
||||
package logrus
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const ioctlReadTermios = unix.TCGETS
|
||||
|
||||
func isTerminal(fd int) bool {
|
||||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue