This commit is contained in:
commit
2ff4b8dfbb
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
dist/
|
50
.goreleaser.yaml
Normal file
50
.goreleaser.yaml
Normal file
@ -0,0 +1,50 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
before:
|
||||
hooks:
|
||||
# You may remove this if you don't use go modules.
|
||||
- go mod tidy
|
||||
# you may remove this if you don't need go generate
|
||||
- go generate ./...
|
||||
builds:
|
||||
- id: "gpaste-client"
|
||||
binary: "gpaste"
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
main: ./cmd/client/client.go
|
||||
|
||||
- id: "gpaste-server"
|
||||
binary: "gpaste-server"
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
main: ./cmd/server/server.go
|
||||
archives:
|
||||
- format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
gitea_urls:
|
||||
api: https://git.t-juice.club/api/v1/
|
||||
download: https://git.t-juice.club
|
||||
env_files:
|
||||
gitea_token: gitea_token
|
49
.woodpecker.yml
Normal file
49
.woodpecker.yml
Normal file
@ -0,0 +1,49 @@
|
||||
pipeline:
|
||||
test:
|
||||
image: golang:latest
|
||||
commands:
|
||||
- go build ./cmd/client/client.go
|
||||
- go build ./cmd/server/server.go
|
||||
- go test -v ./...
|
||||
- go vet ./...
|
||||
when:
|
||||
branch: master
|
||||
event: [push, pull_request, tag, deployment]
|
||||
|
||||
image-latest:
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: registry.t-juice.club/gpaste
|
||||
registry: registry.t-juice.club
|
||||
username: woodpecker
|
||||
password:
|
||||
from_secret: registry_password
|
||||
tags:
|
||||
- latest
|
||||
- "${CI_COMMIT_SHA:0:8}"
|
||||
when:
|
||||
branch: master
|
||||
event: push
|
||||
|
||||
image-tagged:
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: registry.t-juice.club/gpaste
|
||||
registry: registry.t-juice.club
|
||||
username: woodpecker
|
||||
password:
|
||||
from_secret: registry_password
|
||||
tags:
|
||||
- "${CI_COMMIT_TAG}"
|
||||
when:
|
||||
event: [tag]
|
||||
|
||||
goreleaser-tagged:
|
||||
image: goreleaser/goreleaser
|
||||
commands:
|
||||
- git fetch --tags
|
||||
- echo "$GITEA_TOKEN" > gitea_token
|
||||
- goreleaser release
|
||||
when:
|
||||
event: [tag]
|
||||
secrets: [gitea_token]
|
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM golang:alpine AS builder
|
||||
WORKDIR /src
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN go build -o gpaste ./cmd/client/client.go
|
||||
RUN go build -o gpaste-server ./cmd/server/server.go
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=builder /src/gpaste /bin/gpaste
|
||||
COPY --from=builder /src/gpaste-server /bin/gpaste-server
|
||||
CMD ["/bin/gpaste-server"]
|
7
cmd/client/client.go
Normal file
7
cmd/client/client.go
Normal file
@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Starting gpaste client")
|
||||
}
|
7
cmd/server/server.go
Normal file
7
cmd/server/server.go
Normal file
@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Starting gpaste server")
|
||||
}
|
21
file.go
Normal file
21
file.go
Normal file
@ -0,0 +1,21 @@
|
||||
package gpaste
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
ID string
|
||||
Body io.ReadCloser
|
||||
|
||||
MaxViews uint
|
||||
ExpiresOn time.Time
|
||||
}
|
||||
|
||||
type FileStore interface {
|
||||
Store(f *File) error
|
||||
Get(id string) (*File, error)
|
||||
Delete(id string) error
|
||||
List() ([]string, error)
|
||||
}
|
82
filestore_memory.go
Normal file
82
filestore_memory.go
Normal file
@ -0,0 +1,82 @@
|
||||
package gpaste
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type fileData struct {
|
||||
ID string
|
||||
Body bytes.Buffer
|
||||
|
||||
MaxViews uint
|
||||
ExpiresOn time.Time
|
||||
}
|
||||
|
||||
type MemoryFileStore struct {
|
||||
lock sync.RWMutex
|
||||
data map[string]*fileData
|
||||
}
|
||||
|
||||
func NewMemoryFileStore() *MemoryFileStore {
|
||||
return &MemoryFileStore{
|
||||
data: make(map[string]*fileData),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MemoryFileStore) Store(f *File) error {
|
||||
|
||||
data := &fileData{
|
||||
ID: f.ID,
|
||||
MaxViews: f.MaxViews,
|
||||
ExpiresOn: f.ExpiresOn,
|
||||
}
|
||||
|
||||
_, err := io.Copy(&data.Body, f.Body)
|
||||
_ = f.Body.Close()
|
||||
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[f.ID] = data
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *MemoryFileStore) Get(id string) (*File, error) {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
fd, ok := s.data[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no such item")
|
||||
}
|
||||
f := &File{
|
||||
ID: fd.ID,
|
||||
MaxViews: fd.MaxViews,
|
||||
ExpiresOn: fd.ExpiresOn,
|
||||
Body: io.NopCloser(&fd.Body),
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (s *MemoryFileStore) Delete(id string) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.RUnlock()
|
||||
delete(s.data, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MemoryFileStore) List() ([]string, error) {
|
||||
var ids []string
|
||||
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
for id := range s.data {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
13
filestore_memory_test.go
Normal file
13
filestore_memory_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package gpaste_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.t-juice.club/torjus/gpaste"
|
||||
)
|
||||
|
||||
func TestMemoryFileStore(t *testing.T) {
|
||||
s := gpaste.NewMemoryFileStore()
|
||||
|
||||
RunFilestoreTest(s, t)
|
||||
}
|
63
filestore_test.go
Normal file
63
filestore_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package gpaste_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"git.t-juice.club/torjus/gpaste"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func RunFilestoreTest(s gpaste.FileStore, t *testing.T) {
|
||||
t.Run("Basic", func(t *testing.T) {
|
||||
// Create
|
||||
dataString := "TEST_LOL_OMG"
|
||||
id := uuid.Must(uuid.NewRandom()).String()
|
||||
bodyBuf := &bytes.Buffer{}
|
||||
bodyBuf.Write([]byte(dataString))
|
||||
body := io.NopCloser(bodyBuf)
|
||||
f := &gpaste.File{
|
||||
ID: id,
|
||||
MaxViews: 0,
|
||||
Body: body,
|
||||
}
|
||||
|
||||
err := s.Store(f)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to store file: %s", err)
|
||||
}
|
||||
|
||||
// Retrieve
|
||||
retrieved, err := s.Get(id)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to retrieve file: %s", err)
|
||||
}
|
||||
|
||||
retrievedBuf := &bytes.Buffer{}
|
||||
_, err = retrievedBuf.ReadFrom(retrieved.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read retrieved body: %s", err)
|
||||
}
|
||||
_ = retrieved.Body.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("Error reading from retrieved file: %s", err)
|
||||
}
|
||||
|
||||
if retrievedBuf.String() != dataString {
|
||||
t.Fatalf("Data from retrieved body mismatch. Got %s want %s", retrievedBuf.String(), dataString)
|
||||
}
|
||||
|
||||
// List
|
||||
ids, err := s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Error doing list: %s", err)
|
||||
}
|
||||
if len(ids) != 1 {
|
||||
t.Fatalf("List has wrong length: %d", len(ids))
|
||||
}
|
||||
if ids[0] != id {
|
||||
t.Fatalf("ID is wrong. Got %s want %s", ids[0], id)
|
||||
}
|
||||
})
|
||||
}
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module git.t-juice.club/torjus/gpaste
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/google/uuid v1.3.0
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
Loading…
Reference in New Issue
Block a user