Shiny things (#8)
Resolves #4 Resolves #5 Resolves #6 Change list: * Adds topics format * Groups projects by their topics/tags, any without topics are tossed in `other` * Adds minimal page for `go-get` or `git-import` URL query parameters * Changes the version information to explicitly mention Vanity and Go. * Adds manual update mode as an alternative to the automatic intervals. * Moved templates to `.tmpl` files and using `//go:embed` to add to binary. Co-authored-by: jolheiser <john.olheiser@gmail.com> Reviewed-on: https://gitea.com/jolheiser/vanity/pulls/8 Co-authored-by: John Olheiser <john.olheiser@gmail.com> Co-committed-by: John Olheiser <john.olheiser@gmail.com>pull/9/head v0.3.0
parent
e7c3ac2d0f
commit
c3e03c1408
19
README.md
19
README.md
|
@ -70,6 +70,25 @@ Overrides are available via config or by setting an environment variable `VANITY
|
||||||
|
|
||||||
To run Vanity in config-only mode for packages, set `--service` to `off`.
|
To run Vanity in config-only mode for packages, set `--service` to `off`.
|
||||||
|
|
||||||
|
## Manual Mode
|
||||||
|
|
||||||
|
To run Vanity without automatic updating, use `--manual`.
|
||||||
|
|
||||||
|
When running with manual-mode, the provided button or `/_/update` endpoint can be used once every `--interval`.
|
||||||
|
|
||||||
|
## Topic Lists
|
||||||
|
|
||||||
|
By setting `--topics`, anyone visiting the index page will see packages grouped by their topics.
|
||||||
|
|
||||||
|
Regardless of the setting, you can switch beteween list-view and topic-view with the provided button
|
||||||
|
or changing the URL between `?format=list` and `?format=topics`.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
In order to preserve namespaces for packages, Vanity's API uses the URL `/_/{endpoint}`
|
||||||
|
|
||||||
|
Vanity currently supports `/_/status` and `/_/update`, to get some status information and update the package cache respectively.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
|
@ -12,6 +12,7 @@ type Package struct {
|
||||||
WebURL string `toml:"web_url"`
|
WebURL string `toml:"web_url"`
|
||||||
CloneHTTP string `toml:"clone_http"`
|
CloneHTTP string `toml:"clone_http"`
|
||||||
CloneSSH string `toml:"clone_ssh"`
|
CloneSSH string `toml:"clone_ssh"`
|
||||||
|
Topics []string `toml:"topics"`
|
||||||
|
|
||||||
Private bool `toml:"-"`
|
Private bool `toml:"-"`
|
||||||
Fork bool `toml:"-"`
|
Fork bool `toml:"-"`
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"go.jolheiser.com/vanity/api"
|
"go.jolheiser.com/vanity/api"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/pelletier/go-toml"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"go.jolheiser.com/beaver"
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
@ -44,11 +44,15 @@ func setConfig(ctx *cli.Context) {
|
||||||
var cfg tomlConfig
|
var cfg tomlConfig
|
||||||
if configPath != "" {
|
if configPath != "" {
|
||||||
beaver.Infof("Loading configuration from %s", configPath)
|
beaver.Infof("Loading configuration from %s", configPath)
|
||||||
_, err := toml.DecodeFile(configPath, &cfg)
|
tree, err := toml.LoadFile(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beaver.Errorf("Could not load configuration from %s: %v", configPath, err)
|
beaver.Errorf("Could not load configuration from %s: %v", configPath, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err = tree.Unmarshal(&cfg); err != nil {
|
||||||
|
beaver.Errorf("Could not unmarshal configuration from %s: %v", configPath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.IsSet("port") && cfg.Port > 0 {
|
if !ctx.IsSet("port") && cfg.Port > 0 {
|
||||||
|
|
|
@ -35,6 +35,8 @@ var (
|
||||||
Archive bool
|
Archive bool
|
||||||
Override = make(map[string]string)
|
Override = make(map[string]string)
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
|
Manual bool
|
||||||
|
Topics bool
|
||||||
Debug bool
|
Debug bool
|
||||||
|
|
||||||
ConfigPackages []*api.Package
|
ConfigPackages []*api.Package
|
||||||
|
@ -135,6 +137,18 @@ var Flags = []cli.Flag{
|
||||||
EnvVars: []string{"VANITY_INTERVAL"},
|
EnvVars: []string{"VANITY_INTERVAL"},
|
||||||
Destination: &Interval,
|
Destination: &Interval,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "manual",
|
||||||
|
Usage: "Disable cron and only update with endpoint",
|
||||||
|
EnvVars: []string{"VANITY_MANUAL"},
|
||||||
|
Destination: &Manual,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "topics",
|
||||||
|
Usage: "Group projects by topic by default",
|
||||||
|
EnvVars: []string{"VANITY_TOPICS"},
|
||||||
|
Destination: &Topics,
|
||||||
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "Debug logging",
|
Usage: "Debug logging",
|
||||||
|
@ -196,6 +210,10 @@ func Before(ctx *cli.Context) error {
|
||||||
Exclude[idx] = regexp.MustCompile(e)
|
Exclude[idx] = regexp.MustCompile(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if Manual {
|
||||||
|
beaver.Info("Running in manual mode")
|
||||||
|
}
|
||||||
|
|
||||||
if Debug {
|
if Debug {
|
||||||
beaver.Console.Level = beaver.DEBUG
|
beaver.Console.Level = beaver.DEBUG
|
||||||
}
|
}
|
||||||
|
@ -213,5 +231,6 @@ func Before(ctx *cli.Context) error {
|
||||||
beaver.Debugf("Archive: %t", Archive)
|
beaver.Debugf("Archive: %t", Archive)
|
||||||
beaver.Debugf("Override: %s", override.Value())
|
beaver.Debugf("Override: %s", override.Value())
|
||||||
beaver.Debugf("Interval: %s", Interval)
|
beaver.Debugf("Interval: %s", Interval)
|
||||||
|
beaver.Debugf("Manual: %t", Manual)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -1,16 +1,18 @@
|
||||||
module go.jolheiser.com/vanity
|
module go.jolheiser.com/vanity
|
||||||
|
|
||||||
go 1.12
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.12.2
|
code.gitea.io/sdk/gitea v0.13.2
|
||||||
github.com/BurntSushi/toml v0.3.1
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||||
github.com/go-chi/chi v4.1.2+incompatible
|
github.com/go-chi/chi v4.1.2+incompatible
|
||||||
|
github.com/go-chi/cors v1.1.1 // indirect
|
||||||
github.com/google/go-github/v32 v32.1.0
|
github.com/google/go-github/v32 v32.1.0
|
||||||
|
github.com/pelletier/go-toml v1.8.1
|
||||||
github.com/urfave/cli/v2 v2.2.0
|
github.com/urfave/cli/v2 v2.2.0
|
||||||
github.com/xanzy/go-gitlab v0.37.0
|
github.com/xanzy/go-gitlab v0.37.0
|
||||||
go.jolheiser.com/beaver v1.0.2
|
go.jolheiser.com/beaver v1.0.2
|
||||||
|
go.jolheiser.com/overlay v0.0.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
|
||||||
|
|
24
go.sum
24
go.sum
|
@ -30,10 +30,9 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
code.gitea.io/sdk/gitea v0.12.2 h1:NQI8b/CT9AEQjsxbVIZ6gsPUXv38moT5y1ocN7n1YcQ=
|
code.gitea.io/sdk/gitea v0.13.2 h1:wAnT/J7Z62q3fJXbgnecoaOBh8CM1Qq0/DakWxiv4yA=
|
||||||
code.gitea.io/sdk/gitea v0.12.2/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
|
code.gitea.io/sdk/gitea v0.13.2/go.mod h1:lee2y8LeV3kQb2iK+hHlMqoadL4bp27QOkOV/hawLKg=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
@ -42,7 +41,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
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/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
@ -55,6 +53,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
|
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
|
||||||
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
|
github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw=
|
||||||
|
github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
@ -115,19 +115,19 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC
|
||||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY=
|
github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY=
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||||
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
@ -149,12 +149,13 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk=
|
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/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g=
|
||||||
|
go.jolheiser.com/overlay v0.0.2 h1:cwEHLbWqdH7lEOG87WUwgUGVqfOWBsWe03FiHHmuTWE=
|
||||||
|
go.jolheiser.com/overlay v0.0.2/go.mod h1:xNbssakJ3HjK4RnjuP38q9yQNS4wxXKsyprYIWWr2bg=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
|
||||||
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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
@ -198,7 +199,6 @@ golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
|
||||||
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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
@ -238,7 +238,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
|
||||||
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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
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=
|
||||||
|
@ -247,7 +246,6 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -268,7 +266,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
|
||||||
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -400,7 +397,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
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/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
|
6
main.go
6
main.go
|
@ -36,7 +36,11 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func doAction(ctx *cli.Context) error {
|
func doAction(ctx *cli.Context) error {
|
||||||
if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.Init()); err != nil {
|
mux, err := router.Init()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), mux); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
"github.com/go-chi/cors"
|
||||||
|
"go.jolheiser.com/beaver"
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
"net/http"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func apiRoutes() *chi.Mux {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
r.Use(cors.AllowAll().Handler)
|
||||||
|
|
||||||
|
r.Get("/status", doAPIStatus)
|
||||||
|
r.Get("/update", doAPIUpdate)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func doAPIStatus(res http.ResponseWriter, _ *http.Request) {
|
||||||
|
res.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var nextUpdate *string
|
||||||
|
if !lastUpdate.IsZero() {
|
||||||
|
nu := lastUpdate.Add(flags.Interval).Format(time.RFC3339)
|
||||||
|
nextUpdate = &nu
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := map[string]interface{}{
|
||||||
|
"vanity_version": api.Version,
|
||||||
|
"go_version": runtime.Version(),
|
||||||
|
"num_packages": len(cache.Packages),
|
||||||
|
"next_update": nextUpdate,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(&resp)
|
||||||
|
if err != nil {
|
||||||
|
beaver.Errorf("could not marshal API status: %v", err)
|
||||||
|
data = []byte("{}")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = res.Write(data); err != nil {
|
||||||
|
beaver.Errorf("could not write response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doAPIUpdate(res http.ResponseWriter, _ *http.Request) {
|
||||||
|
res.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp := map[string]bool{
|
||||||
|
"updated": false,
|
||||||
|
}
|
||||||
|
if canUpdate {
|
||||||
|
updateCache()
|
||||||
|
resp["updated"] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
beaver.Errorf("could not marshal payload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = res.Write(payload); err != nil {
|
||||||
|
beaver.Errorf("could not write response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
106
router/cache.go
106
router/cache.go
|
@ -1,32 +1,110 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go.jolheiser.com/beaver"
|
||||||
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
"go.jolheiser.com/vanity/service"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"go.jolheiser.com/vanity/api"
|
"go.jolheiser.com/vanity/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cache = &packageCache{
|
var cache = &packageCache{
|
||||||
packages: make(map[string]*api.Package),
|
Packages: make(map[string]*api.Package),
|
||||||
}
|
}
|
||||||
|
|
||||||
type packageCache struct {
|
type packageList map[string]*api.Package
|
||||||
packages map[string]*api.Package
|
|
||||||
sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packageCache) Update(packages map[string]*api.Package) {
|
func (p packageList) Names() []string {
|
||||||
c.Lock()
|
names := make([]string, len(p))
|
||||||
c.packages = packages
|
|
||||||
c.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packageCache) Names() []string {
|
|
||||||
names := make([]string, len(c.packages))
|
|
||||||
idx := 0
|
idx := 0
|
||||||
for name := range c.packages {
|
for name := range p {
|
||||||
names[idx] = name
|
names[idx] = name
|
||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p packageList) Topics() map[string][]*api.Package {
|
||||||
|
topics := make(map[string][]*api.Package, 0)
|
||||||
|
for _, pkg := range p {
|
||||||
|
if len(pkg.Topics) == 0 {
|
||||||
|
if tt, ok := topics["other"]; ok {
|
||||||
|
topics["other"] = append(tt, pkg)
|
||||||
|
} else {
|
||||||
|
topics["other"] = []*api.Package{pkg}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, t := range pkg.Topics {
|
||||||
|
if tt, ok := topics[t]; ok {
|
||||||
|
topics[t] = append(tt, pkg)
|
||||||
|
} else {
|
||||||
|
topics[t] = []*api.Package{pkg}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topics
|
||||||
|
}
|
||||||
|
|
||||||
|
type packageCache struct {
|
||||||
|
Packages packageList
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *packageCache) Update(packages map[string]*api.Package) {
|
||||||
|
c.Lock()
|
||||||
|
c.Packages = packages
|
||||||
|
c.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCache() {
|
||||||
|
packages, err := svc.Packages()
|
||||||
|
if err != nil {
|
||||||
|
beaver.Errorf("could not update packages: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
for name, pkg := range packages {
|
||||||
|
if err := service.Check(pkg); err != nil {
|
||||||
|
beaver.Debug(err)
|
||||||
|
delete(packages, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
goMod, err := svc.GoMod(pkg)
|
||||||
|
if err != nil {
|
||||||
|
beaver.Debugf("No go.mod could be found in the root directory of %s", pkg.Name)
|
||||||
|
delete(packages, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines := strings.Split(goMod, "\n")
|
||||||
|
line := strings.Fields(lines[0])
|
||||||
|
if !strings.HasPrefix(line[1], flags.Domain) {
|
||||||
|
beaver.Debugf("%s is a Go project, however its module does not include this domain", pkg.Name)
|
||||||
|
delete(packages, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
beaver.Debugf("Including %s", pkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overrides
|
||||||
|
for name, pkg := range packages {
|
||||||
|
for key, override := range flags.Override {
|
||||||
|
if strings.EqualFold(name, key) {
|
||||||
|
beaver.Debugf("Overriding %s -> %s", name, override)
|
||||||
|
delete(packages, key)
|
||||||
|
pkg.Name = override
|
||||||
|
packages[override] = pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add packages manually added to config
|
||||||
|
for _, pkg := range flags.ConfigPackages {
|
||||||
|
packages[pkg.Name] = pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.Update(packages)
|
||||||
|
canUpdate = false
|
||||||
|
}
|
||||||
|
|
|
@ -1,73 +1,30 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"go.jolheiser.com/beaver"
|
||||||
|
"go.jolheiser.com/vanity/service"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
"go.jolheiser.com/vanity/service"
|
|
||||||
|
|
||||||
"go.jolheiser.com/beaver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var svc service.Service
|
var (
|
||||||
|
svc service.Service
|
||||||
|
lastUpdate time.Time
|
||||||
|
canUpdate bool
|
||||||
|
)
|
||||||
|
|
||||||
func cronStart() {
|
func cronStart() {
|
||||||
|
canUpdate = true
|
||||||
ticker := time.NewTicker(flags.Interval)
|
ticker := time.NewTicker(flags.Interval)
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
<-ticker.C
|
||||||
|
if !flags.Manual && canUpdate {
|
||||||
beaver.Debug("Running package update...")
|
beaver.Debug("Running package update...")
|
||||||
cronUpdate()
|
updateCache()
|
||||||
beaver.Debugf("Finished package update: %s", cache.Names())
|
beaver.Debugf("Finished package update: %s", cache.Packages.Names())
|
||||||
|
lastUpdate = time.Now()
|
||||||
|
}
|
||||||
|
canUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cronUpdate() {
|
|
||||||
packages, err := svc.Packages()
|
|
||||||
if err != nil {
|
|
||||||
beaver.Errorf("could not update packages: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
for name, pkg := range packages {
|
|
||||||
if err := service.Check(pkg); err != nil {
|
|
||||||
beaver.Debug(err)
|
|
||||||
delete(packages, name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
goMod, err := svc.GoMod(pkg)
|
|
||||||
if err != nil {
|
|
||||||
beaver.Debugf("No go.mod could be found in the root directory of %s", pkg.Name)
|
|
||||||
delete(packages, name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lines := strings.Split(goMod, "\n")
|
|
||||||
line := strings.Fields(lines[0])
|
|
||||||
if !strings.HasPrefix(line[1], flags.Domain) {
|
|
||||||
beaver.Debugf("%s is a Go project, however its module does not include this domain", pkg.Name)
|
|
||||||
delete(packages, name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
beaver.Debugf("Including %s", pkg.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overrides
|
|
||||||
for name, pkg := range packages {
|
|
||||||
for key, override := range flags.Override {
|
|
||||||
if strings.EqualFold(name, key) {
|
|
||||||
beaver.Debugf("Overriding %s -> %s", name, override)
|
|
||||||
delete(packages, key)
|
|
||||||
pkg.Name = override
|
|
||||||
packages[override] = pkg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add packages manually added to config
|
|
||||||
for _, pkg := range flags.ConfigPackages {
|
|
||||||
packages[pkg.Name] = pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.Update(packages)
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,13 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.jolheiser.com/vanity/api"
|
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
"go.jolheiser.com/vanity/router/templates"
|
|
||||||
"go.jolheiser.com/vanity/service"
|
"go.jolheiser.com/vanity/service"
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
|
@ -18,56 +15,78 @@ import (
|
||||||
"go.jolheiser.com/beaver"
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var tmpl *template.Template
|
||||||
index = template.Must(template.New("index").Parse(templates.Head + templates.Index + templates.Foot))
|
|
||||||
vanity = template.Must(template.New("vanity").Parse(templates.Head + templates.Vanity + templates.Foot))
|
func Init() (*chi.Mux, error) {
|
||||||
)
|
var err error
|
||||||
|
tmpl, err = Templates()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
func Init() *chi.Mux {
|
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Use(middleware.RedirectSlashes)
|
r.Use(middleware.RedirectSlashes)
|
||||||
r.Use(middleware.Recoverer)
|
r.Use(middleware.Recoverer)
|
||||||
r.Use(middleware.Timeout(30 * time.Second))
|
r.Use(middleware.Timeout(60 * time.Second))
|
||||||
|
|
||||||
r.Get("/", doIndex)
|
r.Get("/", doIndex)
|
||||||
r.Get("/*", doVanity)
|
r.Get("/*", doVanity)
|
||||||
|
r.Mount("/_", apiRoutes())
|
||||||
|
|
||||||
svc = service.New()
|
svc = service.New()
|
||||||
|
|
||||||
beaver.Info("Warming up cache...")
|
beaver.Info("Warming up cache...")
|
||||||
cronUpdate()
|
updateCache()
|
||||||
beaver.Infof("Finished warming up cache: %s", cache.Names())
|
beaver.Infof("Finished warming up cache: %s", cache.Packages.Names())
|
||||||
go cronStart()
|
go cronStart()
|
||||||
|
|
||||||
beaver.Infof("Running vanity server at http://localhost:%d", flags.Port)
|
beaver.Infof("Running vanity server at http://localhost:%d", flags.Port)
|
||||||
return r
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func doIndex(res http.ResponseWriter, _ *http.Request) {
|
func doIndex(res http.ResponseWriter, req *http.Request) {
|
||||||
if err := index.Execute(res, map[string]interface{}{
|
format := "list"
|
||||||
"Packages": cache.packages,
|
if flags.Topics {
|
||||||
"AppVer": api.Version,
|
format = "topics"
|
||||||
"GoVer": runtime.Version(),
|
}
|
||||||
|
q := req.URL.Query().Get("format")
|
||||||
|
if q != "" {
|
||||||
|
format = q
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmpl.Lookup("index.tmpl").Execute(res, map[string]interface{}{
|
||||||
|
"Packages": cache.Packages,
|
||||||
|
"Index": true,
|
||||||
|
"Format": format,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
beaver.Error(err)
|
beaver.Errorf("could not write response: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doVanity(res http.ResponseWriter, req *http.Request) {
|
func doVanity(res http.ResponseWriter, req *http.Request) {
|
||||||
key := chi.URLParam(req, "*")
|
key := chi.URLParam(req, "*")
|
||||||
pkg, ok := cache.packages[strings.Split(key, "/")[0]]
|
pkg, ok := cache.Packages[strings.Split(key, "/")[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
http.NotFound(res, req)
|
http.NotFound(res, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := vanity.Execute(res, map[string]interface{}{
|
ctx := map[string]interface{}{
|
||||||
"Package": pkg,
|
"Package": pkg,
|
||||||
"Module": pkg.Module(flags.Domain),
|
"Module": pkg.Module(flags.Domain),
|
||||||
"AppVer": api.Version,
|
|
||||||
"GoVer": runtime.Version(),
|
|
||||||
"GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(flags.Domain), pkg.CloneHTTP, svc.GoDir(pkg), svc.GoFile(pkg)),
|
"GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(flags.Domain), pkg.CloneHTTP, svc.GoDir(pkg), svc.GoFile(pkg)),
|
||||||
}); err != nil {
|
"Index": false,
|
||||||
beaver.Error(err)
|
}
|
||||||
|
|
||||||
|
q := req.URL.Query()
|
||||||
|
if q.Get("go-get") != "" || q.Get("git-import") != "" {
|
||||||
|
if err := tmpl.Lookup("import.tmpl").Execute(res, ctx); err != nil {
|
||||||
|
beaver.Errorf("could not write response: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmpl.Lookup("vanity.tmpl").Execute(res, ctx); err != nil {
|
||||||
|
beaver.Errorf("could not write response: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"go.jolheiser.com/overlay"
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed templates
|
||||||
|
var templates embed.FS
|
||||||
|
|
||||||
|
func Templates() (*template.Template, error) {
|
||||||
|
bin, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
customPath := os.Getenv("VANITY_CUSTOM")
|
||||||
|
if customPath == "" {
|
||||||
|
customPath = filepath.Join(bin, "custom")
|
||||||
|
}
|
||||||
|
|
||||||
|
ofs, err := overlay.New(customPath, templates)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.New("vanity").Funcs(funcMap).ParseFS(ofs, "templates/*")
|
||||||
|
}
|
||||||
|
|
||||||
|
var funcMap = template.FuncMap{
|
||||||
|
"AppVer": func() string {
|
||||||
|
return api.Version
|
||||||
|
},
|
||||||
|
"GoVer": func() string {
|
||||||
|
return runtime.Version()
|
||||||
|
},
|
||||||
|
"CanUpdate": func() bool {
|
||||||
|
return canUpdate
|
||||||
|
},
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
package templates
|
|
||||||
|
|
||||||
var Foot = `
|
|
||||||
<strong>Version: </strong>{{.AppVer}} | {{.GoVer}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<hr/>
|
||||||
|
<button id="update-imports" type="button" {{if not CanUpdate}}disabled{{end}}>Update Imports</button>
|
||||||
|
<br/><br/>
|
||||||
|
<strong>Vanity Version:</strong>
|
||||||
|
{{AppVer}}
|
||||||
|
<br/><br/>
|
||||||
|
<strong>Go Version:</strong>
|
||||||
|
{{GoVer}}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const updateImports = document.querySelector('#update-imports');
|
||||||
|
updateImports.addEventListener('click', () => {
|
||||||
|
updateImports.disabled = true;
|
||||||
|
updateImports.innerHTML = 'Updating...';
|
||||||
|
fetch('{{if .Index}}{{else}}../{{end}}_/update', {
|
||||||
|
method: 'GET'
|
||||||
|
}).then(() => {
|
||||||
|
location.reload();
|
||||||
|
}).catch(() => {
|
||||||
|
updateImports.innerHTML = 'Update Failed';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,23 +0,0 @@
|
||||||
package templates
|
|
||||||
|
|
||||||
var Head = `
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
{{if .Package}}
|
|
||||||
<!-- OGP -->
|
|
||||||
<meta name="og:title" content="{{.Package.Name}}"/>
|
|
||||||
<meta name="og:description" content="{{.Package.Description}}"/>
|
|
||||||
|
|
||||||
<!-- Go -->
|
|
||||||
<meta name="go-import" content="{{.Module}} git {{.Package.CloneHTTP}}"/>
|
|
||||||
<meta name="go-source" content="{{.GoSource}}">
|
|
||||||
|
|
||||||
<!-- Git Import -->
|
|
||||||
<meta name="git-import" content="{{.Package.Name}} {{.Package.CloneHTTP}} {{.Package.CloneSSH}}"/>
|
|
||||||
{{end}}
|
|
||||||
<title>Vanity - {{if .Package}}{{.Package.Name}}{{else}}Index{{end}}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
`
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
{{if .Package}}
|
||||||
|
<!-- OGP -->
|
||||||
|
<meta name="og:title" content="{{.Package.Name}}"/>
|
||||||
|
<meta name="og:description" content="{{.Package.Description}}"/>
|
||||||
|
|
||||||
|
<!-- Go -->
|
||||||
|
<meta name="go-import" content="{{.Module}} git {{.Package.CloneHTTP}}"/>
|
||||||
|
<meta name="go-source" content="{{.GoSource}}">
|
||||||
|
|
||||||
|
<!-- Git Import -->
|
||||||
|
<meta name="git-import" content="{{.Package.Name}} {{.Package.CloneHTTP}} {{.Package.CloneSSH}}"/>
|
||||||
|
{{end}}
|
||||||
|
<title>Vanity - {{if .Package}}{{.Package.Name}}{{else}}Index{{end}}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><a href="{{if .Index}}.{{else}}../{{end}}">Index</a></h1>
|
||||||
|
<hr/>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
<!-- Go -->
|
||||||
|
<meta name="go-import" content="{{.Module}} git {{.Package.CloneHTTP}}"/>
|
||||||
|
<meta name="go-source" content="{{.GoSource}}">
|
||||||
|
|
||||||
|
<!-- Git Import -->
|
||||||
|
<meta name="git-import" content="{{.Package.Name}} {{.Package.CloneHTTP}} {{.Package.CloneSSH}}"/>
|
||||||
|
|
||||||
|
<title>{{.Module}}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<code>go get {{.Module}}</code>
|
||||||
|
<br/>
|
||||||
|
<code>git-import {{.Module}}</code>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,12 +0,0 @@
|
||||||
package templates
|
|
||||||
|
|
||||||
var Index = `
|
|
||||||
<h1><a href=".">Index</a></h1>
|
|
||||||
<hr/>
|
|
||||||
<h3>Imports:</h3>
|
|
||||||
<ul>
|
|
||||||
{{range $path, $package := .Packages}}
|
|
||||||
<li><a href="{{$package.Name}}">{{$package.Name}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
`
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{{template "head.tmpl" .}}
|
||||||
|
<h3>{{if eq .Format "list"}}Imports{{else}}Topics{{end}}:</h3>
|
||||||
|
{{if eq .Format "list"}}
|
||||||
|
<ul>
|
||||||
|
{{range $path, $package := .Packages}}
|
||||||
|
<li><a href="{{$package.Name}}">{{$package.Name}}</a></li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
{{else}}
|
||||||
|
{{range $topic, $packages := .Packages.Topics}}
|
||||||
|
<details>
|
||||||
|
<summary>{{$topic}}</summary>
|
||||||
|
<ul>
|
||||||
|
{{range $package := $packages}}
|
||||||
|
<li><a href="{{$package.Name}}">{{$package.Name}}</a></li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
<br/>
|
||||||
|
<form method="get">
|
||||||
|
{{if eq .Format "list"}}
|
||||||
|
<button type="submit" name="format" value="topics">See Topics</button>
|
||||||
|
{{else}}
|
||||||
|
<button type="submit" name="format" value="list"> See List</button>
|
||||||
|
{{end}}
|
||||||
|
</form>
|
||||||
|
{{template "foot.tmpl" .}}
|
|
@ -1,10 +0,0 @@
|
||||||
package templates
|
|
||||||
|
|
||||||
var Vanity = `
|
|
||||||
<h1><a href="../">Index</a></h1>
|
|
||||||
<hr/>
|
|
||||||
<p><strong>Name: </strong>{{.Package.Name}}</p>
|
|
||||||
<p><strong>Source: </strong><a href="{{.Package.WebURL}}">{{.Package.WebURL}}</a></p>
|
|
||||||
{{if .Package.Description}}<p><strong>Description: </strong>{{.Package.Description}}</p>{{end}}
|
|
||||||
<p><strong>Documentation: <a href="https://pkg.go.dev/{{.Module}}">https://pkg.go.dev/{{.Module}}</a></strong></p>
|
|
||||||
`
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{{template "head.tmpl" .}}
|
||||||
|
<p>
|
||||||
|
<strong>Name:</strong>
|
||||||
|
{{.Package.Name}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Source:</strong>
|
||||||
|
<a href="{{.Package.WebURL}}">{{.Package.WebURL}}</a>
|
||||||
|
</p>
|
||||||
|
{{if .Package.Description}}
|
||||||
|
<p>
|
||||||
|
<strong>Description:</strong>
|
||||||
|
{{.Package.Description}}
|
||||||
|
</p>
|
||||||
|
{{end}}
|
||||||
|
<p>
|
||||||
|
<strong>Documentation:</strong>
|
||||||
|
<a href="https://pkg.go.dev/{{.Module}}">https://pkg.go.dev/{{.Module}}</a>
|
||||||
|
</p>
|
||||||
|
{{template "foot.tmpl" .}}
|
|
@ -7,12 +7,16 @@ import (
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Service = &Gitea{}
|
var _ Service = &Gitea{}
|
||||||
|
|
||||||
func NewGitea() *Gitea {
|
func NewGitea() *Gitea {
|
||||||
client := gitea.NewClient(flags.BaseURL.String(), flags.Token)
|
client, err := gitea.NewClient(flags.BaseURL.String(), gitea.SetToken(flags.Token))
|
||||||
|
if err != nil {
|
||||||
|
beaver.Errorf("could not create Gitea client: %v", err)
|
||||||
|
}
|
||||||
return &Gitea{
|
return &Gitea{
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
|
@ -24,6 +28,12 @@ type Gitea struct {
|
||||||
|
|
||||||
func (g Gitea) Packages() (map[string]*api.Package, error) {
|
func (g Gitea) Packages() (map[string]*api.Package, error) {
|
||||||
packages := make(map[string]*api.Package)
|
packages := make(map[string]*api.Package)
|
||||||
|
topicOpts := gitea.ListRepoTopicsOptions{
|
||||||
|
ListOptions: gitea.ListOptions{
|
||||||
|
Page: 1,
|
||||||
|
PageSize: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
page := 0
|
page := 0
|
||||||
for {
|
for {
|
||||||
opts := gitea.ListReposOptions{
|
opts := gitea.ListReposOptions{
|
||||||
|
@ -33,13 +43,13 @@ func (g Gitea) Packages() (map[string]*api.Package, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := g.client.ListUserRepos(flags.Namespace, opts)
|
repos, _, err := g.client.ListUserRepos(flags.Namespace, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
packages[repo.Name] = &api.Package{
|
pkg := &api.Package{
|
||||||
Name: repo.Name,
|
Name: repo.Name,
|
||||||
Description: repo.Description,
|
Description: repo.Description,
|
||||||
Branch: repo.DefaultBranch,
|
Branch: repo.DefaultBranch,
|
||||||
|
@ -51,6 +61,15 @@ func (g Gitea) Packages() (map[string]*api.Package, error) {
|
||||||
Mirror: repo.Mirror,
|
Mirror: repo.Mirror,
|
||||||
Archive: repo.Archived,
|
Archive: repo.Archived,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get tags
|
||||||
|
topics, _, err := g.client.ListRepoTopics(flags.Namespace, repo.Name, topicOpts)
|
||||||
|
if err != nil {
|
||||||
|
beaver.Warnf("could not get topics for %s: %v", repo.Name, err)
|
||||||
|
}
|
||||||
|
pkg.Topics = topics
|
||||||
|
|
||||||
|
packages[repo.Name] = pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
page++
|
page++
|
||||||
|
@ -71,6 +90,6 @@ func (g Gitea) GoFile(pkg *api.Package) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Gitea) GoMod(pkg *api.Package) (string, error) {
|
func (g Gitea) GoMod(pkg *api.Package) (string, error) {
|
||||||
content, err := g.client.GetFile(flags.Namespace, pkg.Name, pkg.Branch, "go.mod")
|
content, _, err := g.client.GetFile(flags.Namespace, pkg.Name, pkg.Branch, "go.mod")
|
||||||
return string(content), err
|
return string(content), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ func (g GitHub) Packages() (map[string]*api.Package, error) {
|
||||||
Fork: repo.GetFork(),
|
Fork: repo.GetFork(),
|
||||||
Mirror: false,
|
Mirror: false,
|
||||||
Archive: repo.GetArchived(),
|
Archive: repo.GetArchived(),
|
||||||
|
Topics: repo.Topics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ func (g GitLab) Packages() (map[string]*api.Package, error) {
|
||||||
Fork: repo.ForkedFromProject != nil,
|
Fork: repo.ForkedFromProject != nil,
|
||||||
Mirror: repo.Mirror,
|
Mirror: repo.Mirror,
|
||||||
Archive: repo.Archived,
|
Archive: repo.Archived,
|
||||||
|
Topics: repo.TagList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,17 @@ func Check(pkg *api.Package) error {
|
||||||
|
|
||||||
// Inclusions
|
// Inclusions
|
||||||
if len(flags.Include) > 0 {
|
if len(flags.Include) > 0 {
|
||||||
|
var included bool
|
||||||
for _, include := range flags.Include {
|
for _, include := range flags.Include {
|
||||||
if include.MatchString(pkg.Name) {
|
if include.MatchString(pkg.Name) {
|
||||||
return fmt.Errorf("%s was included by the rule %s", pkg.Name, include.String())
|
included = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !included {
|
||||||
return fmt.Errorf("%s wasn't included by any existing inclusion rule", pkg.Name)
|
return fmt.Errorf("%s wasn't included by any existing inclusion rule", pkg.Name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue