Skip to content

Commit b32fdbc

Browse files
authored
Use multireader (#2)
use multireader
1 parent 9a896b8 commit b32fdbc

4 files changed

Lines changed: 115 additions & 105 deletions

File tree

.circleci/config.yml

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,77 +9,40 @@ jobs:
99
executor: base
1010
steps:
1111
- checkout
12-
- run: go get -d ./...
13-
- run: go get github.com/inconshreveable/mousetrap # for windows CLI builds
12+
- run: make deps_go
1413
- run: sudo chown -R circleci /go/src
1514
- save_cache:
1615
key: v1-go-src-{{ .Branch }}-{{ .Revision }}
1716
paths:
1817
- /go/src
19-
test:
20-
executor: base
21-
steps:
22-
- run: sudo chown -R circleci /go/src
23-
- restore_cache:
24-
keys:
25-
- v1-go-src-{{ .Branch }}-{{ .Revision }}
26-
- run:
27-
name: Get shadow
28-
command: go get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
29-
- run:
30-
name: Install shadow
31-
command: go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
32-
- run:
33-
name: Download and install errcheck
34-
command: go get -u github.com/kisielk/errcheck
35-
- run:
36-
name: Download and install misspell
37-
command: go get -u github.com/client9/misspell/cmd/misspell
38-
- run:
39-
name: Download and install ineffassign
40-
command: go get -u github.com/gordonklaus/ineffassign
41-
- run:
42-
name: Download and install staticheck
43-
command: go get -u honnef.co/go/tools/cmd/staticcheck
44-
- run: bash scripts/test.sh
45-
validate:
18+
test_go:
4619
executor: base
4720
steps:
4821
- run: sudo chown -R circleci /go/src
4922
- restore_cache:
5023
keys:
5124
- v1-go-src-{{ .Branch }}-{{ .Revision }}
52-
- run:
53-
name: Install Dig
54-
command: sudo apt update && sudo apt install dnsutils
55-
- run:
56-
name: "Update ~/.ssh/known_hosts"
57-
command: |
58-
mkdir ~/.ssh/
59-
touch ~/.ssh/known_hosts
60-
for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan github.com,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts
61-
- run: go get github.com/spatialcurrent/go-header/...
62-
- run: go install github.com/spatialcurrent/go-header/cmd/goheader
63-
- run: goheader fix --fix-year 2019 --exit-code-on-changes 1 --verbose
25+
- run: make deps_go_test
26+
- run: make test_go
27+
- run: make imports
28+
- run: git diff --exit-code
6429
build_cli:
6530
executor: base
6631
steps:
6732
- run: sudo chown -R circleci /go/src
6833
- restore_cache:
6934
keys:
7035
- v1-go-src-{{ .Branch }}-{{ .Revision }}
71-
- run: make build
36+
- run: go get github.com/inconshreveable/mousetrap # for windows CLI builds
37+
- run: make build_cli
7238
- store_artifacts:
7339
path: bin
7440
destination: /
7541
workflows:
7642
main:
7743
jobs:
7844
- pre_deps_golang
79-
- test:
80-
requires:
81-
- pre_deps_golang
82-
- validate:
45+
- test_go:
8346
requires:
8447
- pre_deps_golang
8548
- build_cli:

Makefile

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,88 @@
44
# Released as open source under the MIT License. See LICENSE file.
55
#
66
# =================================================================
7-
bin/gocat_darwin_amd64:
8-
GOOS=darwin GOARCH=amd64 go build -o bin/gocat_darwin_amd64 $$(go list ./...)
97

10-
bin/gocat_linux_amd64:
11-
GOOS=linux GOARCH=amd64 go build -o bin/gocat_linux_amd64 $$(go list ./...)
8+
ifdef GOPATH
9+
GCFLAGS=-trimpath=$(shell printenv GOPATH)/src
10+
else
11+
GCFLAGS=-trimpath=$(shell go env GOPATH)/src
12+
endif
1213

13-
bin/gocat_windows_amd64.exe:
14-
GOOS=windows GOARCH=amd64 go build -o bin/gocat_windows_amd64.exe $$(go list ./...)
14+
LDFLAGS=-X main.gitBranch=$(shell git branch | grep \* | cut -d ' ' -f2) -X main.gitCommit=$(shell git rev-list -1 HEAD)
1515

16-
bin/gocat_linux_arm64:
17-
GOOS=linux GOARCH=arm64 go build -o bin/gocat_linux_arm64 $$(go list ./...)
16+
ifndef DEST
17+
DEST=bin
18+
endif
1819

19-
build: \
20-
bin/gocat_darwin_amd64 \
21-
bin/gocat_linux_amd64 \
22-
bin/gocat_windows_amd64.exe \
23-
bin/gocat_linux_arm64
20+
.PHONY: help
2421

25-
fmt:
22+
help: ## Print the help documentation
23+
@grep -E '^[a-zA-Z0-9_-\]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
24+
25+
#
26+
# Dependencies
27+
#
28+
29+
deps_go: ## Install Go dependencies
30+
go get -d -t ./...
31+
32+
.PHONY: deps_go_test
33+
deps_go_test: ## Download Go dependencies for tests
34+
go get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow # download shadow
35+
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow # install shadow
36+
go get -u github.com/kisielk/errcheck # download and install errcheck
37+
go get -u github.com/client9/misspell/cmd/misspell # download and install misspell
38+
go get -u github.com/gordonklaus/ineffassign # download and install ineffassign
39+
go get -u honnef.co/go/tools/cmd/staticcheck # download and instal staticcheck
40+
go get -u golang.org/x/tools/cmd/goimports # download and install goimports
41+
42+
deps_arm: ## Install dependencies to cross-compile to ARM
43+
# ARMv7
44+
apt-get install -y libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
45+
# ARMv8
46+
apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
47+
48+
#
49+
# Go building, formatting, testing, and installing
50+
#
51+
52+
fmt: ## Format Go source code
2653
go fmt $$(go list ./... )
2754

28-
install:
29-
go install $$(go list ./...)
55+
imports: ## Update imports in Go source code
56+
# If missing, install goimports with: go get golang.org/x/tools/cmd/goimports
57+
goimports -w $$(find . -iname '*.go')
58+
59+
vet: ## Vet Go source code
60+
go vet $$(go list ./...)
3061

31-
test:
62+
test_go: ## Run Go tests
3263
bash scripts/test.sh
3364

34-
clean:
65+
build: build_cli build_javascript build_so build_android ## Build CLI, Shared Objects (.so), JavaScript, and Android
66+
67+
install: ## Install gocat CLI on current platform
68+
go install -gcflags="$(GCFLAGS)" -ldflags="$(LDFLAGS)" github.com/spatialcurrent/gocat
69+
70+
#
71+
# Command line Programs
72+
#
73+
74+
bin/gocat_darwin_amd64: ## Build gocat CLI for Darwin / amd64
75+
GOOS=darwin GOARCH=amd64 go build -o $(DEST)/gocat_darwin_amd64 -gcflags="$(GCFLAGS)" -ldflags="$(LDFLAGS)" github.com/spatialcurrent/gocat
76+
77+
bin/gocat_linux_amd64: ## Build gocat CLI for Linux / amd64
78+
GOOS=linux GOARCH=amd64 go build -o $(DEST)/gocat_linux_amd64 -gcflags="$(GCFLAGS)" -ldflags="$(LDFLAGS)" github.com/spatialcurrent/gocat
79+
80+
bin/gocat_windows_amd64.exe: ## Build gocat CLI for Windows / amd64
81+
GOOS=windows GOARCH=amd64 go build -o $(DEST)/gocat_windows_amd64.exe -gcflags="$(GCFLAGS)" -ldflags="$(LDFLAGS)" github.com/spatialcurrent/gocat
82+
83+
bin/gocat_linux_arm64: ## Build gocat CLI for Linux / arm64
84+
GOOS=linux GOARCH=arm64 go build -o $(DEST)/gocat_linux_arm64 -gcflags="$(GCFLAGS)" -ldflags="$(LDFLAGS)" github.com/spatialcurrent/gocat
85+
86+
build_cli: bin/gocat_darwin_amd64 bin/gocat_linux_amd64 bin/gocat_windows_amd64.exe bin/gocat_linux_arm64 ## Build command line programs
87+
88+
## Clean
89+
90+
clean: ## Clean artifacts
3591
rm -fr bin

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ If you do have go already installed, you can just run using `go run main.go` or
2323

2424
See the usage below or the following examples.
2525

26-
```
26+
```shell
2727
gocat is a super simple utility to concatenate files (local, remote, or on AWS S3) provided as positional arguments. Supports stdin (aka "-"), local files (path/to/file or file://path/to/file), remote files (http://path/to/file), or files on AWS S3 (s3://path/to/file).
2828

2929
Usage:

main.go

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
package main
99

1010
import (
11+
"bytes"
1112
"fmt"
13+
"io"
14+
"io/ioutil"
1215
"os"
1316
"strings"
1417
)
@@ -22,7 +25,6 @@ import (
2225

2326
import (
2427
"github.com/aws/aws-sdk-go/aws"
25-
//"github.com/aws/aws-sdk-go/aws/awserr"
2628
"github.com/aws/aws-sdk-go/aws/credentials"
2729
awssession "github.com/aws/aws-sdk-go/aws/session"
2830
"github.com/aws/aws-sdk-go/service/s3"
@@ -52,7 +54,7 @@ func initFlags(flag *pflag.FlagSet) {
5254
flag.StringP(flagAWSSecretAccessKey, "", "", "AWS Secret Access Key")
5355
flag.StringP(flagAWSSessionToken, "", "", "AWS Session Token")
5456
flag.IntP(flagBufferSize, "b", 4096, "buffer size for file reader")
55-
flag.BoolP(flagAppendNewlines, "a", false, "append new lines to files that do not end in new lines characters")
57+
flag.BoolP(flagAppendNewlines, "a", false, "append new lines to files")
5658
}
5759

5860
func initViper(cmd *cobra.Command) (*viper.Viper, error) {
@@ -76,9 +78,10 @@ func checkConfig(v *viper.Viper) error {
7678

7779
func main() {
7880
cmd := &cobra.Command{
79-
Use: "gocat [-|stdin|FILE|URI]...",
80-
Short: "gocat",
81-
Long: `gocat is a super simple utility to concatenate files (local, remote, or on AWS S3) provided as positional arguments. Supports stdin (aka "-"), local files (path/to/file or file://path/to/file), remote files (http://path/to/file), or files on AWS S3 (s3://path/to/file).`,
81+
Use: "gocat [flags] [-|stdin|FILE|URI]...",
82+
Short: "gocat",
83+
DisableFlagsInUseLine: true,
84+
Long: `gocat is a super simple utility to concatenate files (local, remote, or on AWS S3) provided as positional arguments. Supports stdin (aka "-"), local files (path/to/file or file://path/to/file), remote files (http://path/to/file), or files on AWS S3 (s3://path/to/file).`,
8285
RunE: func(cmd *cobra.Command, args []string) error {
8386
v, err := initViper(cmd)
8487
if err != nil {
@@ -94,13 +97,15 @@ func main() {
9497
}
9598

9699
bufferSize := v.GetInt(flagBufferSize)
100+
appendNewlines := v.GetBool(flagAppendNewlines)
97101

98102
stdinBytes := make([]byte, 0)
99103

100104
var session *awssession.Session
101105

102106
var s3Client *s3.S3
103107

108+
inputReaders := make([]io.Reader, 0)
104109
for _, uri := range args {
105110

106111
if uri == "-" {
@@ -141,49 +146,35 @@ func main() {
141146
}
142147
}
143148

144-
inputBytes := make([]byte, 0)
145-
146-
// if not reading from stdin or stdin hasn't been read yet.
147-
if uri != "stdin" || len(stdinBytes) == 0 {
148-
inputReader, _, inputError := grw.ReadFromResource(uri, "none", bufferSize, false, s3Client)
149-
if inputError != nil {
150-
return errors.Wrap(inputError, fmt.Sprintf("error reading from uri %q", uri))
149+
if uri == "stdin" {
150+
if len(stdinBytes) == 0 {
151+
b, err := ioutil.ReadAll(os.Stdin)
152+
if err != nil {
153+
return errors.Wrap(err, "error reading from stdin")
154+
}
155+
stdinBytes = b
151156
}
152-
b, inputError := inputReader.ReadAllAndClose()
153-
if inputError != nil {
154-
return errors.Wrap(inputError, fmt.Sprintf("error reading from uri %q", uri))
157+
if len(stdinBytes) > 0 {
158+
inputReaders = append(inputReaders, bytes.NewReader(stdinBytes))
155159
}
156-
inputBytes = b
157-
}
158-
159-
// if reading from stdin and stdin bytes are already cached
160-
if uri == "stdin" && len(inputBytes) == 0 && len(stdinBytes) > 0 {
161-
inputBytes = stdinBytes
162-
}
163-
164-
if len(inputBytes) > 0 {
165-
166-
_, err = os.Stdout.Write(inputBytes)
160+
} else {
161+
inputReader, _, err := grw.ReadFromResource(uri, "none", bufferSize, false, s3Client)
167162
if err != nil {
168-
return errors.Wrap(err, fmt.Sprintf("error writing bytes from uri %q", uri))
169-
}
170-
171-
if v.GetBool(flagAppendNewlines) {
172-
if inputBytes[len(inputBytes)-1] != '\n' {
173-
_, err := os.Stdout.Write([]byte("\n"))
174-
if err != nil {
175-
return errors.Wrap(err, fmt.Sprintf("error writing new line from uri %q", uri))
176-
}
177-
}
178-
}
179-
180-
if uri == "stdin" {
181-
stdinBytes = inputBytes
163+
return errors.Wrap(err, fmt.Sprintf("error reading from uri %q", uri))
182164
}
165+
inputReaders = append(inputReaders, inputReader)
166+
}
183167

168+
if appendNewlines {
169+
inputReaders = append(inputReaders, bytes.NewReader([]byte("\n")))
184170
}
185171

186172
}
173+
174+
if _, err := io.Copy(os.Stdout, io.MultiReader(inputReaders...)); err != nil {
175+
return errors.Wrap(err, "error copying input")
176+
}
177+
187178
return nil
188179
},
189180
}

0 commit comments

Comments
 (0)