Refactor for ff, zerolog, and re-integrate SDK #14

Merged
jolheiser merged 1 commits from ff into main 2022-03-20 04:15:25 +00:00
37 changed files with 524 additions and 698 deletions

View File

@ -1,43 +0,0 @@
---
kind: pipeline
name: compliance
trigger:
event:
- pull_request
steps:
- name: build
pull: always
image: golang:1.16
commands:
- make test
- make build
- name: check
pull: always
image: golang:1.16
commands:
- make vet
---
kind: pipeline
name: release
trigger:
event:
- push
branch:
- main
steps:
- name: build
pull: always
image: golang:1.16
commands:
- make build
- name: gitea-release
pull: always
image: jolheiser/drone-gitea-main:latest
settings:
token:
from_secret: gitea_token
base: https://git.jojodev.com
files:
- "vanity"

6
.gitignore vendored
View File

@ -1,7 +1,5 @@
# GoLand # GoLand
.idea .idea/
# Vanity # Vanity
/vanity /vanity*
/vanity.exe
/vanity.db

37
.woodpecker.yml 100644
View File

@ -0,0 +1,37 @@
clone:
git:
image: woodpeckerci/plugin-git:next
pipeline:
compliance:
image: golang:1.17
commands:
- go test -race ./...
- go run github.com/rs/zerolog/cmd/lint ./cmd/vanity-cli
- go run github.com/rs/zerolog/cmd/lint ./cmd/vanity-server
- go vet ./...
when:
event: pull_request
build:
image: golang:1.17
commands:
- GOOS="linux" go build ./cmd/vanity-cli
- GOOS="windows" go build ./cmd/vanity-cli
- GOOS="linux" go build ./cmd/vanity-server
- GOOS="windows" go build ./cmd/vanity-server
release-main:
image: jolheiser/drone-gitea-main:latest
settings:
base: https://git.jojodev.com
token:
from_secret: gitea_token
files:
- "vanity-cli"
- "vanity-cli.exe"
- "vanity-server"
- "vanity-server.exe"
when:
event: push
branch: main

View File

@ -1,41 +0,0 @@
GO ?= go
VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
.PHONY: build
build:
$(GO) build -ldflags '-s -w -X "go.jolheiser.com/vanity/router.Version=$(VERSION)"'
.PHONY: fmt
fmt: fmt-cli fmt-lib
.PHONY: test
test: test-cli test-lib
.PHONY: fmt-cli
fmt-cli:
$(GO) fmt ./...
.PHONY: test-cli
test-cli:
$(GO) test -race ./...
.PHONY: fmt-lib
fmt-lib:
@cd go-vanity && $(GO) fmt ./...
.PHONY: test-lib
test-lib:
@cd go-vanity && $(GO) test -race ./...
.PHONY: vet
vet:
$(GO) vet ./...
.PHONY: docker-build
docker-build:
docker build -f docker/Dockerfile -t jolheiser/vanity .
.PHONY: docker-push
docker-push:
docker push jolheiser/vanity

View File

@ -1,69 +0,0 @@
package cmd
import (
"context"
"net/url"
"go.jolheiser.com/vanity/cmd/flags"
"go.jolheiser.com/vanity/database"
"go.jolheiser.com/vanity/go-vanity"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver"
)
var Add = cli.Command{
Name: "add",
Aliases: []string{"a"},
Usage: "Add a package",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
Aliases: []string{"f"},
Usage: "Overwrite existing package without prompt",
Destination: &flags.Force,
},
&cli.BoolFlag{
Name: "local",
Aliases: []string{"l"},
Usage: "local mode",
Destination: &flags.Local,
},
},
Before: localOrToken,
Action: doAdd,
}
func doAdd(_ *cli.Context) error {
pkg, err := pkgPrompt(vanity.Package{})
if err != nil {
return err
}
if flags.Local {
db, err := database.Load(flags.Database)
if err != nil {
return err
}
if err := db.PutPackage(pkg); err != nil {
return err
}
} else {
client := vanity.New(flags.Token, vanity.WithServer(flags.Server))
if err := client.Add(context.Background(), pkg); err != nil {
return err
}
}
beaver.Infof("Added %s", yellow.Format(pkg.Name))
return nil
}
func validURL(ans interface{}) error {
if err := survey.Required(ans); err != nil {
return err
}
_, err := url.Parse(ans.(string))
return err
}

View File

@ -1,181 +0,0 @@
package cmd
import (
"context"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"go.jolheiser.com/vanity/cmd/flags"
"go.jolheiser.com/vanity/contrib"
"go.jolheiser.com/vanity/database"
"go.jolheiser.com/vanity/go-vanity"
"go.jolheiser.com/vanity/router"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver/color"
)
var yellow = color.FgYellow
func New() *cli.App {
app := cli.NewApp()
app.Name = "vanity"
app.Usage = "Vanity Import URLs"
app.Version = router.Version
app.Commands = []*cli.Command{
&Add,
&Remove,
&Server,
&Update,
}
app.Flags = []cli.Flag{
&cli.StringFlag{
Name: "server",
Aliases: []string{"s"},
Usage: "vanity server to use",
Value: vanity.DefaultServer,
EnvVars: []string{"VANITY_SERVER"},
Destination: &flags.Server,
},
&cli.StringFlag{
Name: "token",
Aliases: []string{"t"},
Usage: "vanity auth token to use",
DefaultText: "${VANITY_TOKEN}",
EnvVars: []string{"VANITY_TOKEN"},
Destination: &flags.Token,
},
&cli.StringFlag{
Name: "database",
Aliases: []string{"d"},
Usage: "path to vanity database for server",
Value: dbPath(),
DefaultText: "`${HOME}/vanity.db` or `${BINPATH}/vanity.db`",
EnvVars: []string{"VANITY_DATABASE"},
Destination: &flags.Database,
},
&cli.BoolFlag{
Name: "systemd-service",
Usage: "Output example systemd service",
Destination: &flags.SystemdService,
Hidden: true,
},
}
app.Action = action
return app
}
func action(ctx *cli.Context) error {
if flags.SystemdService {
fmt.Println(contrib.SystemdService)
return nil
}
return cli.ShowAppHelp(ctx)
}
func dbPath() string {
fn := "vanity.db"
home, err := os.UserHomeDir()
if err != nil {
bin, err := os.Executable()
if err != nil {
return fn
}
return filepath.Join(filepath.Dir(bin), fn)
}
return filepath.Join(home, fn)
}
func localOrToken(_ *cli.Context) error {
if flags.Local && flags.Token == "" {
return errors.New("server interaction requires --token")
}
return nil
}
func listPackages() ([]vanity.Package, error) {
var pkgs []vanity.Package
if flags.Local {
db, err := database.Load(flags.Database)
if err != nil {
return pkgs, err
}
pkgs, err = db.Packages()
if err != nil {
return pkgs, err
}
} else {
client := vanity.New(flags.Token, vanity.WithServer(flags.Server))
info, err := client.Info(context.Background())
if err != nil {
return pkgs, err
}
pkgs = info.Packages
}
return pkgs, nil
}
func pkgPrompt(def vanity.Package) (vanity.Package, error) {
if def.Branch == "" {
def.Branch = "main"
}
var pkg vanity.Package
questions := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "Name", Default: def.Name},
Validate: survey.Required,
},
{
Name: "description",
Prompt: &survey.Multiline{Message: "Description", Default: def.Description},
Validate: survey.Required,
},
{
Name: "branch",
Prompt: &survey.Input{Message: "Branch", Default: def.Branch},
Validate: survey.Required,
},
{
Name: "weburl",
Prompt: &survey.Input{Message: "Web URL", Default: def.WebURL},
Validate: validURL,
},
}
if err := survey.Ask(questions, &pkg); err != nil {
return pkg, err
}
defHTTP, defSSH := def.CloneHTTP, def.CloneSSH
if def.WebURL != pkg.WebURL {
u, err := url.Parse(pkg.WebURL)
if err != nil {
return pkg, err
}
defHTTP = pkg.WebURL + ".git"
defSSH = fmt.Sprintf("git@%s:%s.git", u.Host, strings.TrimPrefix(u.Path, "/"))
}
questions = []*survey.Question{
{
Name: "clonehttp",
Prompt: &survey.Input{Message: "HTTP(S) CLone URL", Default: defHTTP},
Validate: validURL,
},
{
Name: "clonessh",
Prompt: &survey.Input{Message: "SSH CLone URL", Default: defSSH},
Validate: survey.Required,
},
}
if err := survey.Ask(questions, &pkg); err != nil {
return pkg, err
}
return pkg, nil
}

View File

@ -1,14 +0,0 @@
package flags
var (
Server string
Domain string
Token string
Database string
Local bool
Force bool
Port int
SystemdService bool
)

View File

@ -1,67 +0,0 @@
package cmd
import (
"context"
"go.jolheiser.com/vanity/cmd/flags"
"go.jolheiser.com/vanity/database"
"go.jolheiser.com/vanity/go-vanity"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver"
)
var Remove = cli.Command{
Name: "remove",
Aliases: []string{"rm"},
Usage: "Remove package(s)",
Before: localOrToken,
Action: doRemove,
}
func doRemove(_ *cli.Context) error {
pkgs, err := listPackages()
if err != nil {
return err
}
pkgSlice := make([]string, len(pkgs))
pkgMap := make(map[string]vanity.Package)
for idx, pkg := range pkgs {
pkgSlice[idx] = pkg.Name
pkgMap[pkg.Name] = pkg
}
pkgQuestion := &survey.Select{
Message: "Select package to remove",
Options: pkgSlice,
}
var pkgName string
if err := survey.AskOne(pkgQuestion, &pkgName); err != nil {
return err
}
pkg := vanity.Package{
Name: pkgName,
}
if flags.Local {
db, err := database.Load(flags.Database)
if err != nil {
return err
}
if err := db.RemovePackage(pkg.Name); err != nil {
return err
}
} else {
client := vanity.New(flags.Token, vanity.WithServer(flags.Server))
if err := client.Remove(context.Background(), pkg); err != nil {
return err
}
}
beaver.Infof("Removed %s", yellow.Format(pkgName))
return nil
}

View File

@ -1,55 +0,0 @@
package cmd
import (
"errors"
"fmt"
"net/http"
"go.jolheiser.com/vanity/cmd/flags"
"go.jolheiser.com/vanity/database"
"go.jolheiser.com/vanity/router"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver"
)
var Server = cli.Command{
Name: "server",
Aliases: []string{"web"},
Usage: "Start the vanity server",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "port",
Aliases: []string{"p"},
Usage: "Port to run the vanity server on",
Value: 3333,
EnvVars: []string{"VANITY_PORT"},
Destination: &flags.Port,
},
&cli.StringFlag{
Name: "domain",
Aliases: []string{"d"},
Usage: "The Go module domain (e.g. go.jolheiser.com)",
EnvVars: []string{"VANITY_DOMAIN"},
Destination: &flags.Domain,
},
},
Action: doServer,
}
func doServer(_ *cli.Context) error {
if flags.Token == "" || flags.Domain == "" {
return errors.New("vanity server requires --token and --domain")
}
db, err := database.Load(flags.Database)
if err != nil {
beaver.Fatalf("could not load database at %s: %v", flags.Database, err)
}
beaver.Infof("Running vanity server at http://localhost:%d", flags.Port)
if err := http.ListenAndServe(fmt.Sprintf(":%d", flags.Port), router.New(flags.Token, db)); err != nil {
return err
}
return nil
}

View File

@ -1,76 +0,0 @@
package cmd
import (
"context"
"go.jolheiser.com/vanity/cmd/flags"
"go.jolheiser.com/vanity/database"
"go.jolheiser.com/vanity/go-vanity"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
"go.jolheiser.com/beaver"
)
var Update = cli.Command{
Name: "update",
Aliases: []string{"u"},
Usage: "Update a package",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "local",
Aliases: []string{"l"},
Usage: "local mode",
Destination: &flags.Local,
},
},
Before: localOrToken,
Action: doUpdate,
}
func doUpdate(_ *cli.Context) error {
pkgs, err := listPackages()
if err != nil {
return err
}
pkgSlice := make([]string, len(pkgs))
pkgMap := make(map[string]vanity.Package)
for idx, pkg := range pkgs {
pkgSlice[idx] = pkg.Name
pkgMap[pkg.Name] = pkg
}
pkgQuestion := &survey.Select{
Message: "Select package to update",
Options: pkgSlice,
}
var pkgName string
if err := survey.AskOne(pkgQuestion, &pkgName); err != nil {
return err
}
pkg, err := pkgPrompt(pkgMap[pkgName])
if err != nil {
return err
}
if flags.Local {
db, err := database.Load(flags.Database)
if err != nil {
return err
}
if err := db.PutPackage(pkg); err != nil {
return err
}
} else {
client := vanity.New(flags.Token, vanity.WithServer(flags.Server))
if err := client.Update(context.Background(), pkg); err != nil {
return err
}
}
beaver.Infof("Updated %s", yellow.Format(pkgName))
return nil
}

View File

@ -0,0 +1,36 @@
package main
import (
"context"
"net/url"
"go.jolheiser.com/vanity/sdk"
"github.com/AlecAivazis/survey/v2"
"github.com/rs/zerolog/log"
)
func add(token, server *string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
pkg, err := pkgPrompt(sdk.Package{})
if err != nil {
return err
}
client := sdk.New(*token, sdk.WithServer(*server))
if err := client.Add(context.Background(), pkg); err != nil {
return err
}
log.Info().Msgf("Added %q", pkg.Name)
return nil
}
}
func validURL(ans interface{}) error {
if err := survey.Required(ans); err != nil {
return err
}
_, err := url.Parse(ans.(string))
return err
}

View File

@ -0,0 +1,127 @@
package main
import (
"context"
"flag"
"fmt"
"net/url"
"strings"
"go.jolheiser.com/vanity/sdk"
"github.com/AlecAivazis/survey/v2"
"github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/ffcli"
"github.com/peterbourgon/ff/v3/fftoml"
)
func New() *ffcli.Command {
fs := flag.NewFlagSet("vanity", flag.ExitOnError)
serverFlag := fs.String("server", sdk.DefaultServer, "vanity server to use")
tokenFlag := fs.String("token", "", "vanity auth token to use")
cmd := &ffcli.Command{
Name: "vanity",
ShortUsage: "vanity [add|update|remove]",
ShortHelp: "Vanity CLI",
LongHelp: "Vanity CLI to work with a remote Vanity server",
FlagSet: fs,
Options: []ff.Option{
ff.WithEnvVarPrefix("VANITY"),
ff.WithAllowMissingConfigFile(true),
ff.WithConfigFileFlag("config"),
ff.WithConfigFileParser(fftoml.New().Parse),
},
Subcommands: []*ffcli.Command{
{
Name: "add",
ShortHelp: "add package",
LongHelp: "add a package to the vanity server",
Exec: add(tokenFlag, serverFlag),
},
{
Name: "remove",
ShortHelp: "remove package",
LongHelp: "remove a package from the vanity server",
Exec: remove(tokenFlag, serverFlag),
},
{
Name: "update",
ShortHelp: "update package",
LongHelp: "update a package on the vanity server",
Exec: update(tokenFlag, serverFlag),
},
},
}
return cmd
}
func listPackages(token, server string) ([]sdk.Package, error) {
client := sdk.New(token, sdk.WithServer(server))
info, err := client.Info(context.Background())
if err != nil {
return nil, err
}
return info.Packages, nil
}
func pkgPrompt(def sdk.Package) (sdk.Package, error) {
if def.Branch == "" {
def.Branch = "main"
}
var pkg sdk.Package
questions := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "Name", Default: def.Name},
Validate: survey.Required,
},
{
Name: "description",
Prompt: &survey.Multiline{Message: "Description", Default: def.Description},
Validate: survey.Required,
},
{
Name: "branch",
Prompt: &survey.Input{Message: "Branch", Default: def.Branch},
Validate: survey.Required,
},
{
Name: "weburl",
Prompt: &survey.Input{Message: "Web URL", Default: def.WebURL},
Validate: validURL,
},
}
if err := survey.Ask(questions, &pkg); err != nil {
return pkg, err
}
defHTTP, defSSH := def.CloneHTTP, def.CloneSSH
if def.WebURL != pkg.WebURL {
u, err := url.Parse(pkg.WebURL)
if err != nil {
return pkg, err
}
defHTTP = pkg.WebURL + ".git"
defSSH = fmt.Sprintf("git@%s:%s.git", u.Host, strings.TrimPrefix(u.Path, "/"))
}
questions = []*survey.Question{
{
Name: "clonehttp",
Prompt: &survey.Input{Message: "HTTP(S) CLone URL", Default: defHTTP},
Validate: validURL,
},
{
Name: "clonessh",
Prompt: &survey.Input{Message: "SSH CLone URL", Default: defSSH},
Validate: survey.Required,
},
}
if err := survey.Ask(questions, &pkg); err != nil {
return pkg, err
}
return pkg, nil
}

View File

@ -0,0 +1,18 @@
package main
import (
"context"
"os"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
cmd := New()
if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil {
log.Fatal().Err(err).Msg("")
}
}

View File

@ -0,0 +1,48 @@
package main
import (
"context"
"go.jolheiser.com/vanity/sdk"
"github.com/AlecAivazis/survey/v2"
"github.com/rs/zerolog/log"
)
func remove(token, server *string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
pkgs, err := listPackages(*token, *server)
if err != nil {
return err
}
pkgSlice := make([]string, len(pkgs))
pkgMap := make(map[string]sdk.Package)
for idx, pkg := range pkgs {
pkgSlice[idx] = pkg.Name
pkgMap[pkg.Name] = pkg
}
pkgQuestion := &survey.Select{
Message: "Select package to remove",
Options: pkgSlice,
}
var pkgName string
if err := survey.AskOne(pkgQuestion, &pkgName); err != nil {
return err
}
pkg := sdk.Package{
Name: pkgName,
}
client := sdk.New(*token, sdk.WithServer(*server))
if err := client.Remove(context.Background(), pkg); err != nil {
return err
}
log.Info().Msgf("Removed %q", pkgName)
return nil
}
}

View File

@ -0,0 +1,49 @@
package main
import (
"context"
"go.jolheiser.com/vanity/sdk"
"github.com/AlecAivazis/survey/v2"
"github.com/rs/zerolog/log"
)
func update(token, server *string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
pkgs, err := listPackages(*token, *server)
if err != nil {
return err
}
pkgSlice := make([]string, len(pkgs))
pkgMap := make(map[string]sdk.Package)
for idx, pkg := range pkgs {
pkgSlice[idx] = pkg.Name
pkgMap[pkg.Name] = pkg
}
pkgQuestion := &survey.Select{
Message: "Select package to update",
Options: pkgSlice,
}
var pkgName string
if err := survey.AskOne(pkgQuestion, &pkgName); err != nil {
return err
}
pkg, err := pkgPrompt(pkgMap[pkgName])
if err != nil {
return err
}
client := sdk.New(*token, sdk.WithServer(*server))
if err := client.Update(context.Background(), pkg); err != nil {
return err
}
log.Info().Msgf("Updated %q", pkgName)
return nil
}
}

View File

@ -0,0 +1,18 @@
package main
import (
"context"
"os"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
cmd := New()
if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil {
log.Fatal().Err(err).Msg("")
}
}

View File

@ -0,0 +1,75 @@
package main
import (
"context"
"errors"
"flag"
"fmt"
"net/http"
"os"
"path/filepath"
"go.jolheiser.com/vanity/server/database"
"go.jolheiser.com/vanity/server/router"
"github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/ffcli"
"github.com/peterbourgon/ff/v3/fftoml"
"github.com/rs/zerolog/log"
)
func New() *ffcli.Command {
fs := flag.NewFlagSet("vanity", flag.ExitOnError)
portFlag := fs.Int("port", 3333, "Port to run the vanity server on")
domainFlag := fs.String("domain", "", "The Go module domain (e.g. go.jolheiser.com)")
tokenFlag := fs.String("token", "", "vanity auth token to use")
dbFlag := fs.String("database", dbPath(), "The path to the database")
cmd := &ffcli.Command{
Name: "vanity",
ShortUsage: "vanity",
ShortHelp: "Vanity Server",
LongHelp: "Vanity Server to serve the Go module vanity domain",
FlagSet: fs,
Options: []ff.Option{
ff.WithEnvVarPrefix("VANITY"),
ff.WithAllowMissingConfigFile(true),
ff.WithConfigFileFlag("config"),
ff.WithConfigFileParser(fftoml.New().Parse),
},
Exec: server(portFlag, domainFlag, tokenFlag, dbFlag),
}
return cmd
}
func server(port *int, domain, token, dbPath *string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
if *token == "" || *domain == "" {
return errors.New("vanity server requires --token and --domain")
}
db, err := database.Load(*dbPath)
if err != nil {
log.Fatal().Msgf("could not load database at %s: %v", *dbPath, err)
}
log.Info().Msgf("Running vanity server at http://localhost:%d", *port)
if err := http.ListenAndServe(fmt.Sprintf(":%d", *port), router.New(*token, *domain, db)); err != nil {
return err
}
return nil
}
}
func dbPath() string {
fn := "vanity.db"
home, err := os.UserHomeDir()
if err != nil {
bin, err := os.Executable()
if err != nil {
return fn
}
return filepath.Join(filepath.Dir(bin), fn)
}
return filepath.Join(home, fn)
}

View File

@ -1,28 +0,0 @@
package contrib
import (
_ "embed"
"os"
"strings"
)
//go:embed vanity.service
var SystemdService string
func init() {
bin, err := os.Executable()
if err != nil {
return
}
SystemdService = os.Expand(SystemdService, func(s string) string {
switch strings.ToUpper(s) {
case "BIN":
return bin
case "VANITY_TOKEN":
return os.Getenv("VANITY_TOKEN")
case "VANITY_DOMAIN":
return os.Getenv("VANITY_DOMAIN")
}
return ""
})
}

View File

@ -1,3 +0,0 @@
module go.jolheiser.com/vanity/go-vanity
go 1.16

11
go.mod
View File

@ -2,18 +2,11 @@ module go.jolheiser.com/vanity
go 1.16 go 1.16
replace go.jolheiser.com/vanity/go-vanity => ./go-vanity
require ( require (
github.com/AlecAivazis/survey/v2 v2.2.8 github.com/AlecAivazis/survey/v2 v2.2.8
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/go-chi/chi/v5 v5.0.3 github.com/go-chi/chi/v5 v5.0.3
github.com/urfave/cli/v2 v2.2.0 github.com/peterbourgon/ff/v3 v3.1.2
github.com/rs/zerolog v1.26.1
go.etcd.io/bbolt v1.3.5 go.etcd.io/bbolt v1.3.5
go.jolheiser.com/beaver v1.0.2
go.jolheiser.com/overlay v0.0.3 go.jolheiser.com/overlay v0.0.3
go.jolheiser.com/vanity/go-vanity v0.0.0-00010101000000-000000000000
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
golang.org/x/text v0.3.3 // indirect
) )

57
go.sum
View File

@ -1,15 +1,15 @@
github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0= github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0=
github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4=
github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
@ -22,38 +22,59 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM=
github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk=
go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g=
go.jolheiser.com/overlay v0.0.3 h1:5WoXtnRi1w5KkU9xq+si/wV0GINOMJphfSOvgG2l53I= go.jolheiser.com/overlay v0.0.3 h1:5WoXtnRi1w5KkU9xq+si/wV0GINOMJphfSOvgG2l53I=
go.jolheiser.com/overlay v0.0.3/go.mod h1:xNbssakJ3HjK4RnjuP38q9yQNS4wxXKsyprYIWWr2bg= go.jolheiser.com/overlay v0.0.3/go.mod h1:xNbssakJ3HjK4RnjuP38q9yQNS4wxXKsyprYIWWr2bg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e h1:1SzTfNOXwIS2oWiMF+6qu0OUDKb0dauo6MoDUQyu+yU=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

24
main.go
View File

@ -1,24 +0,0 @@
package main
import (
"os"
"go.jolheiser.com/vanity/cmd"
"go.jolheiser.com/beaver"
)
func main() {
beaver.Console.Format = beaver.FormatOptions{
TimePrefix: true,
StackPrefix: true,
StackLimit: 15,
LevelPrefix: true,
LevelColor: true,
}
if err := cmd.New().Run(os.Args); err != nil {
beaver.Fatal(err)
}
}

View File

@ -1,4 +1,4 @@
package vanity package sdk
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package vanity package sdk
import ( import (
"bytes" "bytes"

View File

@ -1,4 +1,4 @@
package vanity package sdk
import ( import (
"errors" "errors"

View File

@ -1,4 +1,4 @@
package vanity package sdk
import ( import (
"context" "context"

View File

@ -6,7 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"go.jolheiser.com/vanity/go-vanity" "go.jolheiser.com/vanity/sdk"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
) )
@ -33,8 +33,8 @@ func Load(dbPath string) (*Database, error) {
}) })
} }
func (d *Database) Package(name string) (vanity.Package, error) { func (d *Database) Package(name string) (sdk.Package, error) {
var pkg vanity.Package var pkg sdk.Package
data, err := d.PackageJSON(name) data, err := d.PackageJSON(name)
if err != nil { if err != nil {
return pkg, err return pkg, err
@ -54,10 +54,10 @@ func (d *Database) PackageJSON(name string) (pkg []byte, err error) {
}) })
} }
func (d *Database) Packages() (pkgs []vanity.Package, err error) { func (d *Database) Packages() (pkgs []sdk.Package, err error) {
return pkgs, d.db.View(func(tx *bbolt.Tx) error { return pkgs, d.db.View(func(tx *bbolt.Tx) error {
return tx.Bucket(packageBucket).ForEach(func(key, val []byte) error { return tx.Bucket(packageBucket).ForEach(func(key, val []byte) error {
var pkg vanity.Package var pkg sdk.Package
if err := json.NewDecoder(bytes.NewReader(val)).Decode(&pkg); err != nil { if err := json.NewDecoder(bytes.NewReader(val)).Decode(&pkg); err != nil {
return err return err
} }
@ -67,7 +67,7 @@ func (d *Database) Packages() (pkgs []vanity.Package, err error) {
}) })
} }
func (d *Database) PutPackage(pkg vanity.Package) error { func (d *Database) PutPackage(pkg sdk.Package) error {
return d.db.Update(func(tx *bbolt.Tx) error { return d.db.Update(func(tx *bbolt.Tx) error {
data, err := json.Marshal(pkg) data, err := json.Marshal(pkg)
if err != nil { if err != nil {

View File

@ -8,56 +8,55 @@ import (
"strings" "strings"
"time" "time"
"go.jolheiser.com/vanity/cmd/flags" "go.jolheiser.com/vanity/sdk"
"go.jolheiser.com/vanity/database" "go.jolheiser.com/vanity/server/database"
"go.jolheiser.com/vanity/go-vanity"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"go.jolheiser.com/beaver" "github.com/rs/zerolog/log"
) )
func New(token string, db *database.Database) *chi.Mux { func New(token, domain string, db *database.Database) *chi.Mux {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Recoverer) r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second)) r.Use(middleware.Timeout(60 * time.Second))
r.Mount("/_/", http.StripPrefix("/_/", static())) r.Mount("/_/", http.StripPrefix("/_/", static()))
r.Get("/", indexGET(db)) r.Get("/", indexGET(domain, db))
r.Options("/", infoPackages(db)) r.Options("/", infoPackages(db))
r.Post("/", addUpdatePackage(db, token)) r.Post("/", addUpdatePackage(db, token))
r.Patch("/", addUpdatePackage(db, token)) r.Patch("/", addUpdatePackage(db, token))
r.Delete("/", removePackage(db, token)) r.Delete("/", removePackage(db, token))
r.Get("/*", vanityGET(db)) r.Get("/*", vanityGET(domain, db))
return r return r
} }
func indexGET(db *database.Database) http.HandlerFunc { func indexGET(domain string, db *database.Database) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
packages, err := db.Packages() packages, err := db.Packages()
if err != nil { if err != nil {
beaver.Errorf("could not load packages: %v", err) log.Error().Msgf("could not load packages: %v", err)
http.Error(res, "could not load packages", http.StatusInternalServerError) http.Error(res, "could not load packages", http.StatusInternalServerError)
return return
} }
tpl, err := tmpl("index.tmpl") tpl, err := tmpl(domain, "index.tmpl")
if err != nil { if err != nil {
beaver.Warnf("could not load index template: %v", err) log.Warn().Msgf("could not load index template: %v", err)
} }
if err := tpl.Execute(res, map[string]interface{}{ if err := tpl.Execute(res, map[string]interface{}{
"Packages": packages, "Packages": packages,
"Index": true, "Index": true,
}); err != nil { }); err != nil {
beaver.Errorf("could not write response: %v", err) log.Error().Msgf("could not write response: %v", err)
} }
} }
} }
func vanityGET(db *database.Database) http.HandlerFunc { func vanityGET(domain string, db *database.Database) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
key := chi.URLParam(req, "*") key := chi.URLParam(req, "*")
key = strings.Split(key, "/")[0] key = strings.Split(key, "/")[0]
@ -72,36 +71,36 @@ func vanityGET(db *database.Database) http.HandlerFunc {
return return
} }
sdf, err := vanity.AnalyzeSDF(pkg) sdf, err := sdk.AnalyzeSDF(pkg)
if err != nil { if err != nil {
beaver.Warnf("could not get SDF for %s: %v", key, err) log.Warn().Msgf("could not get SDF for %s: %v", key, err)
} }
ctx := map[string]interface{}{ ctx := map[string]interface{}{
"Package": pkg, "Package": pkg,
"Module": pkg.Module(flags.Domain), "Module": pkg.Module(domain),
"GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(flags.Domain), pkg.CloneHTTP, sdf.Dir, sdf.File), "GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(domain), pkg.CloneHTTP, sdf.Dir, sdf.File),
"Index": false, "Index": false,
} }
q := req.URL.Query() q := req.URL.Query()
if q.Get("go-get") != "" || q.Get("git-import") != "" { if q.Get("go-get") != "" || q.Get("git-import") != "" {
tpl, err := tmpl("import.tmpl") tpl, err := tmpl(domain, "import.tmpl")
if err != nil { if err != nil {
beaver.Warnf("could not load import template: %v", err) log.Warn().Msgf("could not load import template: %v", err)
} }
if err := tpl.Execute(res, ctx); err != nil { if err := tpl.Execute(res, ctx); err != nil {
beaver.Errorf("could not write response: %v", err) log.Error().Msgf("could not write response: %v", err)
} }
return return
} }
tpl, err := tmpl("vanity.tmpl") tpl, err := tmpl(domain, "vanity.tmpl")
if err != nil { if err != nil {
beaver.Warnf("could not load vanity template: %v", err) log.Warn().Msgf("could not load vanity template: %v", err)
} }
if err := tpl.Execute(res, ctx); err != nil { if err := tpl.Execute(res, ctx); err != nil {
beaver.Errorf("could not write response: %v", err) log.Error().Msgf("could not write response: %v", err)
} }
} }
} }
@ -114,7 +113,7 @@ func infoPackages(db *database.Database) func(http.ResponseWriter, *http.Request
return return
} }
info := vanity.Info{ info := sdk.Info{
Version: Version, Version: Version,
NumPackages: len(packages), NumPackages: len(packages),
Packages: packages, Packages: packages,
@ -128,7 +127,7 @@ func infoPackages(db *database.Database) func(http.ResponseWriter, *http.Request
func addUpdatePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { func addUpdatePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
if req.Header.Get(vanity.TokenHeader) != token { if req.Header.Get(sdk.TokenHeader) != token {
res.WriteHeader(http.StatusUnauthorized) res.WriteHeader(http.StatusUnauthorized)
return return
} }
@ -140,7 +139,7 @@ func addUpdatePackage(db *database.Database, token string) func(http.ResponseWri
} }
defer req.Body.Close() defer req.Body.Close()
var pkg vanity.Package var pkg sdk.Package
if err := json.Unmarshal(data, &pkg); err != nil { if err := json.Unmarshal(data, &pkg); err != nil {
res.WriteHeader(http.StatusBadRequest) res.WriteHeader(http.StatusBadRequest)
return return
@ -181,7 +180,7 @@ func addUpdatePackage(db *database.Database, token string) func(http.ResponseWri
func removePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { func removePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
if req.Header.Get(vanity.TokenHeader) != token { if req.Header.Get(sdk.TokenHeader) != token {
res.WriteHeader(http.StatusUnauthorized) res.WriteHeader(http.StatusUnauthorized)
return return
} }
@ -193,7 +192,7 @@ func removePackage(db *database.Database, token string) func(http.ResponseWriter
} }
defer req.Body.Close() defer req.Body.Close()
var pkg vanity.Package var pkg sdk.Package
if err := json.Unmarshal(data, &pkg); err != nil { if err := json.Unmarshal(data, &pkg); err != nil {
res.WriteHeader(http.StatusBadRequest) res.WriteHeader(http.StatusBadRequest)
return return

View File

@ -9,10 +9,10 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"go.jolheiser.com/vanity/database" "go.jolheiser.com/vanity/sdk"
"go.jolheiser.com/vanity/go-vanity" "go.jolheiser.com/vanity/server/database"
"go.jolheiser.com/beaver" "github.com/rs/zerolog/log"
) )
var ( var (
@ -31,10 +31,10 @@ func TestMain(m *testing.M) {
db, err := database.Load(dbPath) db, err := database.Load(dbPath)
if err != nil { if err != nil {
beaver.Fatalf("could not load database at %s: %v", dbPath, err) log.Fatal().Msgf("could not load database at %s: %v", dbPath, err)
} }
server = httptest.NewServer(New(token, db)) server = httptest.NewServer(New(token, "", db))
code := m.Run() code := m.Run()
@ -48,12 +48,12 @@ func TestMain(m *testing.M) {
func TestRouter(t *testing.T) { func TestRouter(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := vanity.New("", vanity.WithServer(server.URL)) client := sdk.New("", sdk.WithServer(server.URL))
// Info // Info
checkInfo(t, client, 0) checkInfo(t, client, 0)
pkg1 := vanity.Package{ pkg1 := sdk.Package{
Name: "test1", Name: "test1",
Description: "test1", Description: "test1",
Branch: "main", Branch: "main",
@ -61,7 +61,7 @@ func TestRouter(t *testing.T) {
CloneHTTP: "https://gitea.com/jolheiser/test1.git", CloneHTTP: "https://gitea.com/jolheiser/test1.git",
CloneSSH: "https://gitea.com/jolheiser/test1", CloneSSH: "https://gitea.com/jolheiser/test1",
} }
pkg2 := vanity.Package{ pkg2 := sdk.Package{
Name: "test2", Name: "test2",
Description: "test2", Description: "test2",
Branch: "main", Branch: "main",
@ -77,7 +77,7 @@ func TestRouter(t *testing.T) {
} }
// Add (with token) // Add (with token)
client = vanity.New(token, vanity.WithServer(server.URL)) client = sdk.New(token, sdk.WithServer(server.URL))
checkAdd(t, client, pkg1, pkg2) checkAdd(t, client, pkg1, pkg2)
// Info (after second package) // Info (after second package)
@ -102,7 +102,7 @@ func TestRouter(t *testing.T) {
checkInfo(t, client, 1) checkInfo(t, client, 1)
} }
func checkInfo(t *testing.T, client *vanity.Client, numPackages int) { func checkInfo(t *testing.T, client *sdk.Client, numPackages int) {
info, err := client.Info(context.Background()) info, err := client.Info(context.Background())
if err != nil { if err != nil {
t.Logf("info should not return error: %v\n", err) t.Logf("info should not return error: %v\n", err)
@ -114,7 +114,7 @@ func checkInfo(t *testing.T, client *vanity.Client, numPackages int) {
} }
} }
func checkAdd(t *testing.T, client *vanity.Client, pkg1, pkg2 vanity.Package) { func checkAdd(t *testing.T, client *sdk.Client, pkg1, pkg2 sdk.Package) {
ctx := context.Background() ctx := context.Background()
if err := client.Add(ctx, pkg1); err != nil { if err := client.Add(ctx, pkg1); err != nil {
t.Logf("pkg1 should be added: %v\n", err) t.Logf("pkg1 should be added: %v\n", err)
@ -131,10 +131,10 @@ func checkAdd(t *testing.T, client *vanity.Client, pkg1, pkg2 vanity.Package) {
} }
} }
func checkUpdate(t *testing.T, client *vanity.Client, pkg vanity.Package) { func checkUpdate(t *testing.T, client *sdk.Client, pkg sdk.Package) {
ctx := context.Background() ctx := context.Background()
// Update invalid package // Update invalid package
if err := client.Update(ctx, vanity.Package{Name: "test4"}); err == nil { if err := client.Update(ctx, sdk.Package{Name: "test4"}); err == nil {
t.Log("should not be able to update invalid package") t.Log("should not be able to update invalid package")
t.Fail() t.Fail()
} }
@ -146,7 +146,7 @@ func checkUpdate(t *testing.T, client *vanity.Client, pkg vanity.Package) {
} }
} }
func checkRemove(t *testing.T, client *vanity.Client, pkg vanity.Package) { func checkRemove(t *testing.T, client *sdk.Client, pkg sdk.Package) {
ctx := context.Background() ctx := context.Background()
if err := client.Remove(ctx, pkg); err != nil { if err := client.Remove(ctx, pkg); err != nil {
t.Logf("should be able to remove package: %v\n", err) t.Logf("should be able to remove package: %v\n", err)

View File

@ -11,8 +11,6 @@ import (
"strings" "strings"
"go.jolheiser.com/overlay" "go.jolheiser.com/overlay"
"go.jolheiser.com/vanity/cmd/flags"
) )
var ( var (
@ -34,8 +32,8 @@ func customRoot() string {
return customPath return customPath
} }
func tmpl(name string) (*template.Template, error) { func tmpl(domain, name string) (*template.Template, error) {
return template.New(name).Funcs(funcMap).ParseFS(ofs, "templates/base.tmpl", "templates/"+name) return template.New(name).Funcs(funcMap(domain)).ParseFS(ofs, "templates/base.tmpl", "templates/"+name)
} }
func static() http.Handler { func static() http.Handler {
@ -46,7 +44,8 @@ func static() http.Handler {
return http.FileServer(http.FS(sub)) return http.FileServer(http.FS(sub))
} }
var funcMap = template.FuncMap{ func funcMap(domain string) template.FuncMap {
return template.FuncMap{
"AppVer": func() string { "AppVer": func() string {
return Version return Version
}, },
@ -54,6 +53,7 @@ var funcMap = template.FuncMap{
return runtime.Version() return runtime.Version()
}, },
"Domain": func() string { "Domain": func() string {
return strings.TrimSuffix(flags.Domain, "/") return strings.TrimSuffix(domain, "/")
}, },
}
} }

8
tools.go 100644
View File

@ -0,0 +1,8 @@
//go:build tools
// +build tools
package main
import (
_ "github.com/rs/zerolog/cmd/lint"
)