mirror of
https://github.com/Slug-Boi/cocommit.git
synced 2026-05-13 12:45:47 +00:00
Merge branch 'main' into docs_completely_redo_docs
This commit is contained in:
@@ -13,7 +13,7 @@ jobs:
|
|||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup Go Workfile
|
- name: Setup Go Workfile
|
||||||
run: go work init ./ci ./
|
run: go work init ./ci ./ && rm src_code/go_src/cmd/cmd_test.go
|
||||||
- run: cd ci && go get dagger.io/dagger@latest && cd ..
|
- run: cd ci && go get dagger.io/dagger@latest && cd ..
|
||||||
- run: mkdir ./dist
|
- run: mkdir ./dist
|
||||||
- run: go run ci/build_test_release.go
|
- run: go run ci/build_test_release.go
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# Custom
|
# Custom
|
||||||
dist
|
dist
|
||||||
|
author_file
|
||||||
|
|
||||||
go.work
|
go.work
|
||||||
go.sum
|
go.sum
|
||||||
|
|||||||
@@ -25,20 +25,20 @@ func main() {
|
|||||||
// at /src in the container
|
// at /src in the container
|
||||||
source := client.Container().
|
source := client.Container().
|
||||||
From("golang:1.23").
|
From("golang:1.23").
|
||||||
WithDirectory("/src", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||||
Exclude: []string{},
|
Exclude: []string{},
|
||||||
})).WithMountedCache("/src/dagger_dep_cache/go_dep", goCache)
|
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
||||||
|
|
||||||
geese := []string{"darwin", "linux", "windows"}
|
geese := []string{"darwin", "linux", "windows"}
|
||||||
goarch := "amd64"
|
goarch := "amd64"
|
||||||
|
|
||||||
// set the working directory in the container
|
// set the working directory in the container
|
||||||
// install application dependencies
|
// install application dependencies
|
||||||
runner := source.WithWorkdir("/src/src_code/go_src/").
|
runner := source.WithWorkdir("/src_d/src/").
|
||||||
WithExec([]string{"go", "mod", "tidy"})
|
WithExec([]string{"go", "mod", "tidy"})
|
||||||
|
|
||||||
// run application tests
|
// run application tests
|
||||||
test := runner.WithWorkdir("/src/src_code/go_src").WithExec([]string{"go", "test"})
|
test := runner.WithWorkdir("/src_d/src/").WithExec([]string{"go", "test", "./..."}).WithEnvVariable("CI", "true")
|
||||||
|
|
||||||
buildDir := test.Directory("/src/")
|
buildDir := test.Directory("/src/")
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ func main() {
|
|||||||
build := test.
|
build := test.
|
||||||
WithEnvVariable("GOOS", goos).
|
WithEnvVariable("GOOS", goos).
|
||||||
WithEnvVariable("GOARCH", goarch).
|
WithEnvVariable("GOARCH", goarch).
|
||||||
WithExec([]string{"go", "build", "-o", filename})
|
WithExec([]string{"go", "build", "-o", filename}).WithEnvVariable("CI", "true")
|
||||||
|
|
||||||
buildDir = buildDir.WithDirectory(path, build.Directory(path))
|
buildDir = buildDir.WithDirectory(path, build.Directory(path))
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,43 @@
|
|||||||
module ci
|
module ci
|
||||||
|
|
||||||
go 1.21.9
|
go 1.23.2
|
||||||
|
|
||||||
require dagger.io/dagger v0.11.4
|
require dagger.io/dagger v0.13.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.17.44 // indirect
|
github.com/99designs/gqlgen v0.17.55 // indirect
|
||||||
github.com/Khan/genqlient v0.7.0 // indirect
|
github.com/Khan/genqlient v0.7.0 // indirect
|
||||||
github.com/adrg/xdg v0.4.0 // indirect
|
github.com/adrg/xdg v0.5.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/sosodev/duration v1.2.0 // indirect
|
github.com/sosodev/duration v1.3.1 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.5.15 // indirect
|
github.com/vektah/gqlparser/v2 v2.5.17 // indirect
|
||||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/log v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/log v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/net v0.29.0 // indirect
|
||||||
golang.org/x/sys v0.17.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
|
golang.org/x/text v0.18.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
google.golang.org/grpc v1.65.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
+5
-5
@@ -25,17 +25,17 @@ func main() {
|
|||||||
// at /src in the container
|
// at /src in the container
|
||||||
source := client.Container().
|
source := client.Container().
|
||||||
From("golang:1.23").
|
From("golang:1.23").
|
||||||
WithDirectory("/src", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||||
Exclude: []string{"build/"},
|
Exclude: []string{"build/"},
|
||||||
})).WithMountedCache("/src/dagger_dep_cache/go_dep", goCache)
|
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
||||||
|
|
||||||
// set the working directory in the container
|
// set the working directory in the container
|
||||||
// install application dependencies
|
// install application dependencies
|
||||||
runner := source.WithWorkdir("/src/src_code/go_src/").
|
runner := source.WithWorkdir("/src_d/src").
|
||||||
WithExec([]string{"go", "mod", "tidy"})
|
WithExec([]string{"go", "mod", "tidy"}).WithEnvVariable("CI", "true")
|
||||||
|
|
||||||
// run application tests
|
// run application tests
|
||||||
out, err := runner.WithWorkdir("/src/src_code/go_src").WithExec([]string{"go", "test"}).
|
out, err := runner.WithWorkdir("/src_d/src").WithExec([]string{"go", "test", "./..."}).
|
||||||
Stderr(ctx)
|
Stderr(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -13,36 +13,68 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
dagger.io/dagger v0.13.6 // indirect
|
||||||
|
github.com/99designs/gqlgen v0.17.55 // indirect
|
||||||
|
github.com/Khan/genqlient v0.7.0 // indirect
|
||||||
|
github.com/adrg/xdg v0.5.1 // indirect
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/aymanbagabas/go-udiff v0.2.0 // indirect
|
github.com/aymanbagabas/go-udiff v0.2.0 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.4.0 // indirect
|
github.com/charmbracelet/x/ansi v0.4.0 // indirect
|
||||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
|
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/muesli/reflow v0.3.0 // indirect
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
|
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||||
|
github.com/sosodev/duration v1.3.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/vektah/gqlparser/v2 v2.5.17 // indirect
|
||||||
github.com/yuin/goldmark v1.7.4 // indirect
|
github.com/yuin/goldmark v1.7.4 // indirect
|
||||||
github.com/yuin/goldmark-emoji v1.0.3 // indirect
|
github.com/yuin/goldmark-emoji v1.0.3 // indirect
|
||||||
golang.org/x/crypto v0.25.0 // indirect
|
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||||
golang.org/x/net v0.27.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/log v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/log v0.3.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||||
|
golang.org/x/net v0.29.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
golang.org/x/term v0.22.0 // indirect
|
golang.org/x/term v0.24.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
google.golang.org/grpc v1.65.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
dagger.io/dagger v0.13.6 h1:SB/0zQtxAjFpLjSX+t9LfSbCxPCVwaPz9yWRROGEOD8=
|
||||||
|
dagger.io/dagger v0.13.6/go.mod h1:YCNpoHLR3fiqE7a0yZs06rqD4+oXI9r/u7l6om1w0pI=
|
||||||
|
github.com/99designs/gqlgen v0.17.55 h1:3vzrNWYyzSZjGDFo68e5j9sSauLxfKvLp+6ioRokVtM=
|
||||||
|
github.com/99designs/gqlgen v0.17.55/go.mod h1:3Bq768f8hgVPGZxL8aY9MaYmbxa6llPM/qu1IGH1EJo=
|
||||||
|
github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w=
|
||||||
|
github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM=
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U=
|
||||||
|
github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||||
|
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||||
|
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
|
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||||
|
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
||||||
|
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||||
|
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
|
||||||
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||||
|
github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc=
|
||||||
|
github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E=
|
||||||
|
github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs=
|
||||||
|
github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw=
|
||||||
|
github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A=
|
||||||
|
github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U=
|
||||||
|
github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU=
|
||||||
|
github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||||
|
github.com/charmbracelet/x/exp/teatest v0.0.0-20241024145942-ad25fd0d5a9e h1:A5VhIlbaXz5qhDecxpzFrOYBhlNpWQNM9ylA97fyNY4=
|
||||||
|
github.com/charmbracelet/x/exp/teatest v0.0.0-20241024145942-ad25fd0d5a9e/go.mod h1:ektxP4TiEONm1mTGILRfo8F0a4rZMwsT1fEkXslQKtU=
|
||||||
|
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
|
||||||
|
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||||
|
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
|
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
|
github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 h1:fO9A67/izFYFYky7l1pDP5Dr0BTCRkaQJUG6Jm5ehsk=
|
||||||
|
github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3/go.mod h1:Ey4uAp+LvIl+s5jRbOHLcZpUDnkjLBROl15fZLwPlTM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
|
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||||
|
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||||
|
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
|
||||||
|
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
|
||||||
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
|
github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
|
||||||
|
github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
||||||
|
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/vektah/gqlparser/v2 v2.5.17 h1:9At7WblLV7/36nulgekUgIaqHZWn5hxqluxrxGUhOmI=
|
||||||
|
github.com/vektah/gqlparser/v2 v2.5.17/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww=
|
||||||
|
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
|
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
||||||
|
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
|
github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4=
|
||||||
|
github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
||||||
|
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
||||||
|
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 h1:oM0GTNKGlc5qHctWeIGTVyda4iFFalOzMZ3Ehj5rwB4=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88/go.mod h1:JGG8ebaMO5nXOPnvKEl+DiA4MGwFjCbjsxT1WHIEBPY=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0 h1:ccBrA8nCY5mM0y5uO7FT0ze4S0TuFcWdDB2FxGMTjkI=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0/go.mod h1:/9pb6634zi2Lk8LYg9Q0X8Ar6jka4dkFOylBLbVQPCE=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 h1:bFgvUr3/O4PHj3VQcFEuYKvRZJX1SJDQ+11JXuSB3/w=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY=
|
||||||
|
go.opentelemetry.io/otel/log v0.3.0 h1:kJRFkpUFYtny37NQzL386WbznUByZx186DpEMKhEGZs=
|
||||||
|
go.opentelemetry.io/otel/log v0.3.0/go.mod h1:ziCwqZr9soYDwGNbIL+6kAvQC+ANvjgG367HVcyR/ys=
|
||||||
|
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
|
||||||
|
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
|
||||||
|
go.opentelemetry.io/otel/sdk/log v0.3.0 h1:GEjJ8iftz2l+XO1GF2856r7yYVh74URiF9JMcAacr5U=
|
||||||
|
go.opentelemetry.io/otel/sdk/log v0.3.0/go.mod h1:BwCxtmux6ACLuys1wlbc0+vGBd+xytjmjajwqqIul2g=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
|
||||||
|
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
||||||
|
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||||
|
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||||
|
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||||
|
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||||
|
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||||
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||||
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||||
|
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||||
|
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||||
|
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||||
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||||
|
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||||
|
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||||
|
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||||
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||||
|
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||||
|
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||||
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Syntax: name_short|Name|Username|email (opt: |ex) (opt: ;;group1|group2|group3...)
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const author_data = `syntax for the test file
|
const author_data = `syntax for the test file
|
||||||
@@ -32,6 +32,14 @@ func teardown() {
|
|||||||
os.Setenv("author_file", envVar)
|
os.Setenv("author_file", envVar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip cobra cmd tests on CI causes problems apparenly idk why
|
||||||
|
// test will be run locally before releasing a new version
|
||||||
|
func skipCI(t *testing.T) {
|
||||||
|
if os.Getenv("CI") != "" {
|
||||||
|
t.Skip("Skipping testing in CI environment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func StdoutReader() (chan string, *os.File, *os.File, *os.File) {
|
func StdoutReader() (chan string, *os.File, *os.File, *os.File) {
|
||||||
old := os.Stdout
|
old := os.Stdout
|
||||||
r, w, _ := os.Pipe()
|
r, w, _ := os.Pipe()
|
||||||
@@ -43,6 +51,7 @@ func StdoutReader() (chan string, *os.File, *os.File, *os.File) {
|
|||||||
|
|
||||||
// users CMD TEST BEGIN
|
// users CMD TEST BEGIN
|
||||||
func Test_UsersCmd(t *testing.T) {
|
func Test_UsersCmd(t *testing.T) {
|
||||||
|
skipCI(t)
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
@@ -87,6 +96,7 @@ func Test_UsersCmd(t *testing.T) {
|
|||||||
|
|
||||||
// root CMD TEST BEGIN
|
// root CMD TEST BEGIN
|
||||||
func Test_CommitCmd(t *testing.T) {
|
func Test_CommitCmd(t *testing.T) {
|
||||||
|
skipCI(t)
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
@@ -99,7 +109,7 @@ func Test_CommitCmd(t *testing.T) {
|
|||||||
outC <- buf.String()
|
outC <- buf.String()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
cmd := rootCmD
|
cmd := rootCmd
|
||||||
cmd.SetArgs([]string{"-t", "Test commit message"})
|
cmd.SetArgs([]string{"-t", "Test commit message"})
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
||||||
@@ -117,6 +127,7 @@ func Test_CommitCmd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_CommitCmdWithM(t *testing.T) {
|
func Test_CommitCmdWithM(t *testing.T) {
|
||||||
|
skipCI(t)
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
@@ -129,7 +140,7 @@ func Test_CommitCmdWithM(t *testing.T) {
|
|||||||
outC <- buf.String()
|
outC <- buf.String()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
cmd := rootCmD
|
cmd := rootCmd
|
||||||
cmd.SetArgs([]string{"-m", "-t", "Test commit message"})
|
cmd.SetArgs([]string{"-m", "-t", "Test commit message"})
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
||||||
@@ -144,6 +155,6 @@ func Test_CommitCmdWithM(t *testing.T) {
|
|||||||
t.Errorf("Expected to find 'Test commit message' in output but got %s", outStr)
|
t.Errorf("Expected to find 'Test commit message' in output but got %s", outStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// root CMD TEST END
|
// root CMD TEST END
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/tui"
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
"github.com/inancgumus/screen"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// czCmd represents the cz command
|
||||||
|
var czCmd = &cobra.Command{
|
||||||
|
Use: "cz",
|
||||||
|
Short: "Allows for commitizen commit messages",
|
||||||
|
Long: `This command will allow the user to use commitizen to craft the commit message
|
||||||
|
after which the user will be able to add co-authors to the commit message. This will require
|
||||||
|
the user to have commitizen installed on their system.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var message string
|
||||||
|
var authors []string
|
||||||
|
|
||||||
|
// check if the print flag is set
|
||||||
|
pflag, _ := cmd.Flags().GetBool("print")
|
||||||
|
cflag, _ := cmd.Flags().GetBool("cli")
|
||||||
|
|
||||||
|
// run execute commands again as root run will not call this part
|
||||||
|
message = utils.Cz_Call()
|
||||||
|
|
||||||
|
if cflag {
|
||||||
|
// call the cli style syntax
|
||||||
|
authors = args
|
||||||
|
goto skip_tui
|
||||||
|
}
|
||||||
|
|
||||||
|
// for good measure clear the screen
|
||||||
|
screen.Clear()
|
||||||
|
screen.MoveTopLeft()
|
||||||
|
|
||||||
|
// call tui
|
||||||
|
authors = tui.Entry()
|
||||||
|
|
||||||
|
skip_tui:
|
||||||
|
// build the commit message
|
||||||
|
message = utils.Commit(message, authors)
|
||||||
|
|
||||||
|
// commit the message
|
||||||
|
utils.GitWrapper(message)
|
||||||
|
|
||||||
|
if pflag {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(czCmd)
|
||||||
|
czCmd.Flags().BoolP("print", "p", false, "Print the commit message")
|
||||||
|
czCmd.Flags().BoolP("cli", "c", false, "[co-author1] [co-author2] ...")
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/tui"
|
"github.com/Slug-Boi/cocommit/src/cmd/tui"
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
|
||||||
"github.com/inancgumus/screen"
|
"github.com/inancgumus/screen"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
// rootCmd represents the base command when called without any subcommands
|
||||||
// func RootCmd() *cobra.Command {
|
// func RootCmd() *cobra.Command {
|
||||||
var rootCmD = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: `cocommit <commit message> <co-author1> [co-author2] ... ||
|
Use: `cocommit <commit message> <co-author1> [co-author2] ... ||
|
||||||
cocommit <commit message> <co-author1:email> [co-author2:email] ... ||
|
cocommit <commit message> <co-author1:email> [co-author2:email] ... ||
|
||||||
cocommit <commit message> all ||
|
cocommit <commit message> all ||
|
||||||
@@ -31,6 +31,12 @@ var rootCmD = &cobra.Command{
|
|||||||
// check if the print flag is set
|
// check if the print flag is set
|
||||||
pflag, _ := cmd.Flags().GetBool("print")
|
pflag, _ := cmd.Flags().GetBool("print")
|
||||||
tflag, _ := cmd.Flags().GetBool("test_print")
|
tflag, _ := cmd.Flags().GetBool("test_print")
|
||||||
|
aflag, _ := cmd.Flags().GetBool("authors")
|
||||||
|
|
||||||
|
if aflag {
|
||||||
|
tui.Entry()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
// run execute commands again as root run will not call this part
|
// run execute commands again as root run will not call this part
|
||||||
// redundant check for now but will be useful later when we add tui
|
// redundant check for now but will be useful later when we add tui
|
||||||
wrap_around:
|
wrap_around:
|
||||||
@@ -85,7 +91,7 @@ func Execute() {
|
|||||||
// define users
|
// define users
|
||||||
utils.Define_users(author_file)
|
utils.Define_users(author_file)
|
||||||
|
|
||||||
err := rootCmD.Execute()
|
err := rootCmd.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -93,7 +99,8 @@ func Execute() {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
//rootCmD := RootCmd()
|
//rootCmD := RootCmd()
|
||||||
rootCmD.Flags().BoolP("print", "p", false, "Prints the commit message to the console")
|
rootCmd.Flags().BoolP("print", "p", false, "Prints the commit message to the console")
|
||||||
rootCmD.Flags().BoolP("test_print", "t", false, "Prints the commit message to the console without running the git commit command")
|
rootCmd.Flags().BoolP("test_print", "t", false, "Prints the commit message to the console without running the git commit command")
|
||||||
rootCmD.Flags().BoolP("message", "m", false, "Does nothing but allows for -m to be used in the command")
|
rootCmd.Flags().BoolP("message", "m", false, "Does nothing but allows for -m to be used in the command")
|
||||||
|
rootCmd.Flags().BoolP("authors", "a", false, "Runs the author list TUI")
|
||||||
}
|
}
|
||||||
@@ -5,10 +5,11 @@ package tui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
@@ -27,7 +28,7 @@ var (
|
|||||||
excludeButton = fmt.Sprintf("[ %s ]", blurredStyle.Render("Exclude"))
|
excludeButton = fmt.Sprintf("[ %s ]", blurredStyle.Render("Exclude"))
|
||||||
)
|
)
|
||||||
|
|
||||||
var removeButton bool
|
var tempAuthorToggle bool
|
||||||
|
|
||||||
type model_ca struct {
|
type model_ca struct {
|
||||||
focusIndex int
|
focusIndex int
|
||||||
@@ -36,7 +37,11 @@ type model_ca struct {
|
|||||||
exclude bool
|
exclude bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAuthorModel() model_ca {
|
var parent_m *model
|
||||||
|
|
||||||
|
func createAuthorModel(old_m *model) model_ca {
|
||||||
|
parent_m = old_m
|
||||||
|
|
||||||
m := model_ca{
|
m := model_ca{
|
||||||
inputs: make([]textinput.Model, 5),
|
inputs: make([]textinput.Model, 5),
|
||||||
}
|
}
|
||||||
@@ -69,7 +74,9 @@ func createAuthorModel() model_ca {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func tempAuthorModel() model_ca {
|
func tempAuthorModel(old_m *model) model_ca {
|
||||||
|
parent_m = old_m
|
||||||
|
|
||||||
m := model_ca{
|
m := model_ca{
|
||||||
inputs: make([]textinput.Model, 2),
|
inputs: make([]textinput.Model, 2),
|
||||||
}
|
}
|
||||||
@@ -93,20 +100,11 @@ func tempAuthorModel() model_ca {
|
|||||||
m.inputs[i] = t
|
m.inputs[i] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
removeButton = true
|
tempAuthorToggle = true
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialModel(model string) model_ca {
|
|
||||||
if model == "author" {
|
|
||||||
return createAuthorModel()
|
|
||||||
} else {
|
|
||||||
return tempAuthorModel()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m model_ca) Init() tea.Cmd {
|
func (m model_ca) Init() tea.Cmd {
|
||||||
return textinput.Blink
|
return textinput.Blink
|
||||||
}
|
}
|
||||||
@@ -117,18 +115,18 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "ctrl+c", "esc":
|
case "ctrl+c", "esc":
|
||||||
m.inputs = nil
|
m.inputs = nil
|
||||||
return m, tea.Quit
|
return nil, nil
|
||||||
|
|
||||||
// Set focus to next input
|
// Set focus to next input
|
||||||
case "tab", "shift+tab", "enter", "up", "down":
|
case "tab", "shift+tab", "enter", "up", "down":
|
||||||
s := msg.String()
|
s := msg.String()
|
||||||
|
|
||||||
// Did the user press enter while the submit button was focused?
|
// Did the user press enter while the submit button was focused?
|
||||||
// If so, exit.
|
// If so, exit.
|
||||||
if !removeButton {
|
if !tempAuthorToggle {
|
||||||
if s == "enter" && m.focusIndex == len(m.inputs)+1 {
|
if s == "enter" && m.focusIndex == len(m.inputs)+1 {
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
return m, tea.Quit
|
m.AddAuthor()
|
||||||
|
return model{list: parent_m.list}, tea.ClearScreen
|
||||||
} else if s == "enter" && m.focusIndex == len(m.inputs) {
|
} else if s == "enter" && m.focusIndex == len(m.inputs) {
|
||||||
// toggle exclude
|
// toggle exclude
|
||||||
m.exclude = !m.exclude
|
m.exclude = !m.exclude
|
||||||
@@ -137,7 +135,8 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
} else {
|
} else {
|
||||||
if s == "enter" && m.focusIndex == len(m.inputs) {
|
if s == "enter" && m.focusIndex == len(m.inputs) {
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
return m, tea.Quit
|
m.TempAddAuthor()
|
||||||
|
return model{list: parent_m.list}, tea.ClearScreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +207,7 @@ func (m model_ca) View() string {
|
|||||||
//TODO: add check here for wether this button is needed
|
//TODO: add check here for wether this button is needed
|
||||||
var exclude *string
|
var exclude *string
|
||||||
var button *string
|
var button *string
|
||||||
if !removeButton {
|
if !tempAuthorToggle {
|
||||||
exclude = &excludeButton
|
exclude = &excludeButton
|
||||||
if m.focusIndex == len(m.inputs) {
|
if m.focusIndex == len(m.inputs) {
|
||||||
exclude = &focusedExclude
|
exclude = &focusedExclude
|
||||||
@@ -237,18 +236,12 @@ func (m model_ca) View() string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Entry_CA() string {
|
func (m *model_ca) AddAuthor() {
|
||||||
m, err := tea.NewProgram(initialModel("author")).Run()
|
if len(m.inputs) > 0 &&
|
||||||
if err != nil {
|
m.inputs[0].Value() != "" &&
|
||||||
fmt.Printf("could not start program: %s\n", err)
|
m.inputs[1].Value() != "" &&
|
||||||
os.Exit(1)
|
m.inputs[2].Value() != "" &&
|
||||||
}
|
m.inputs[3].Value() != "" {
|
||||||
|
|
||||||
if len(m.(model_ca).inputs) > 0 &&
|
|
||||||
m.(model_ca).inputs[0].Value() != "" &&
|
|
||||||
m.(model_ca).inputs[1].Value() != "" &&
|
|
||||||
m.(model_ca).inputs[2].Value() != "" &&
|
|
||||||
m.(model_ca).inputs[3].Value() != "" {
|
|
||||||
author_file := utils.Find_authorfile()
|
author_file := utils.Find_authorfile()
|
||||||
f, err := os.OpenFile(author_file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
f, err := os.OpenFile(author_file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -261,17 +254,17 @@ func Entry_CA() string {
|
|||||||
sb.WriteRune('\n')
|
sb.WriteRune('\n')
|
||||||
|
|
||||||
sb.WriteString(fmt.Sprintf("%s|%s|%s|%s",
|
sb.WriteString(fmt.Sprintf("%s|%s|%s|%s",
|
||||||
m.(model_ca).inputs[0].Value(),
|
m.inputs[0].Value(),
|
||||||
m.(model_ca).inputs[1].Value(),
|
m.inputs[1].Value(),
|
||||||
m.(model_ca).inputs[2].Value(),
|
m.inputs[2].Value(),
|
||||||
m.(model_ca).inputs[3].Value()))
|
m.inputs[3].Value()))
|
||||||
|
|
||||||
if m.(model_ca).exclude {
|
if m.exclude {
|
||||||
sb.WriteString(fmt.Sprintf("|%s", "ex"))
|
sb.WriteString(fmt.Sprintf("|%s", "ex"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.(model_ca).inputs[4].Value() != "" {
|
if m.inputs[4].Value() != "" {
|
||||||
sb.WriteString(fmt.Sprintf(";;%s", m.(model_ca).inputs[4].Value()))
|
sb.WriteString(fmt.Sprintf(";;%s", m.inputs[4].Value()))
|
||||||
}
|
}
|
||||||
|
|
||||||
//sb.WriteRune('\n')
|
//sb.WriteRune('\n')
|
||||||
@@ -280,25 +273,90 @@ func Entry_CA() string {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
utils.Define_users(utils.Find_authorfile())
|
utils.Define_users(utils.Find_authorfile())
|
||||||
return m.(model_ca).inputs[0].Value()
|
|
||||||
|
author := m.inputs[0].Value()
|
||||||
|
|
||||||
|
item_str := utils.Users[author].Username + " - " + utils.Users[author].Email
|
||||||
|
dupProtect[item_str] = author
|
||||||
|
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
|
||||||
|
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Entry_TA() string {
|
func (m *model_ca) TempAddAuthor() {
|
||||||
m, err := tea.NewProgram(initialModel("temp")).Run()
|
if len(m.inputs) > 1 && m.inputs[0].Value() != "" && m.inputs[1].Value() != "" {
|
||||||
if err != nil {
|
item_str := m.inputs[0].Value() + " - " + m.inputs[1].Value()
|
||||||
fmt.Printf("could not start program: %s\n", err)
|
dupProtect[item_str] = m.inputs[0].Value() + ":" + m.inputs[1].Value()
|
||||||
os.Exit(1)
|
i := item(item_str)
|
||||||
|
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
|
||||||
|
selectToggle(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.(model_ca).inputs) > 0 &&
|
|
||||||
m.(model_ca).inputs[0].Value() != "" &&
|
|
||||||
m.(model_ca).inputs[1].Value() != "" {
|
|
||||||
utils.TempAddUser(m.(model_ca).inputs[0].Value(), m.(model_ca).inputs[1].Value())
|
|
||||||
return m.(model_ca).inputs[0].Value() + ":" + m.(model_ca).inputs[1].Value()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func Entry_CA() string {
|
||||||
|
// m, err := tea.NewProgram(initialModel("author")).Run()
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Printf("could not start program: %s\n", err)
|
||||||
|
// os.Exit(1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if len(m.(model_ca).inputs) > 0 &&
|
||||||
|
// m.(model_ca).inputs[0].Value() != "" &&
|
||||||
|
// m.(model_ca).inputs[1].Value() != "" &&
|
||||||
|
// m.(model_ca).inputs[2].Value() != "" &&
|
||||||
|
// m.(model_ca).inputs[3].Value() != "" {
|
||||||
|
// author_file := utils.Find_authorfile()
|
||||||
|
// f, err := os.OpenFile(author_file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// defer f.Close()
|
||||||
|
|
||||||
|
// sb := strings.Builder{}
|
||||||
|
// sb.WriteRune('\n')
|
||||||
|
|
||||||
|
// sb.WriteString(fmt.Sprintf("%s|%s|%s|%s",
|
||||||
|
// m.(model_ca).inputs[0].Value(),
|
||||||
|
// m.(model_ca).inputs[1].Value(),
|
||||||
|
// m.(model_ca).inputs[2].Value(),
|
||||||
|
// m.(model_ca).inputs[3].Value()))
|
||||||
|
|
||||||
|
// if m.(model_ca).exclude {
|
||||||
|
// sb.WriteString(fmt.Sprintf("|%s", "ex"))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if m.(model_ca).inputs[4].Value() != "" {
|
||||||
|
// sb.WriteString(fmt.Sprintf(";;%s", m.(model_ca).inputs[4].Value()))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //sb.WriteRune('\n')
|
||||||
|
|
||||||
|
// if _, err = f.WriteString(sb.String()); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// utils.Define_users(utils.Find_authorfile())
|
||||||
|
// return m.(model_ca).inputs[0].Value()
|
||||||
|
// }
|
||||||
|
// return ""
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func Entry_TA() string {
|
||||||
|
// //old_m = old_m
|
||||||
|
|
||||||
|
// m, err := tea.NewProgram(initialModel("temp")).Run()
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Printf("could not start program: %s\n", err)
|
||||||
|
// os.Exit(1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if len(m.(model_ca).inputs) > 0 &&
|
||||||
|
// m.(model_ca).inputs[0].Value() != "" &&
|
||||||
|
// m.(model_ca).inputs[1].Value() != "" {
|
||||||
|
// utils.TempAddUser(m.(model_ca).inputs[0].Value(), m.(model_ca).inputs[1].Value())
|
||||||
|
// return m.(model_ca).inputs[0].Value() + ":" + m.(model_ca).inputs[1].Value()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return ""
|
||||||
|
|
||||||
|
// }
|
||||||
@@ -14,10 +14,12 @@ import (
|
|||||||
"github.com/charmbracelet/bubbles/textarea"
|
"github.com/charmbracelet/bubbles/textarea"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/inancgumus/screen"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyMap struct {
|
type KeyMap struct {
|
||||||
EndWithMes key.Binding
|
EndWithMes key.Binding
|
||||||
|
NewLine key.Binding
|
||||||
}
|
}
|
||||||
|
|
||||||
func newKeyMap() *KeyMap {
|
func newKeyMap() *KeyMap {
|
||||||
@@ -25,6 +27,9 @@ func newKeyMap() *KeyMap {
|
|||||||
EndWithMes: key.NewBinding(
|
EndWithMes: key.NewBinding(
|
||||||
key.WithKeys("enter"),
|
key.WithKeys("enter"),
|
||||||
),
|
),
|
||||||
|
NewLine: key.NewBinding(
|
||||||
|
key.WithKeys("shift+tab"),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +43,10 @@ func Entry_CM() string {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if m.(model_cm).textarea.Value() == "" {
|
if m.(model_cm).textarea.Value() == "" {
|
||||||
|
screen.Clear()
|
||||||
|
screen.MoveTopLeft()
|
||||||
fmt.Println("No commit message provided. Exiting...")
|
fmt.Println("No commit message provided. Exiting...")
|
||||||
os.Exit(1)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
return m.(model_cm).textarea.Value() + "\n"
|
return m.(model_cm).textarea.Value() + "\n"
|
||||||
}
|
}
|
||||||
@@ -55,6 +62,8 @@ type model_cm struct {
|
|||||||
func initialModel_cm() model_cm {
|
func initialModel_cm() model_cm {
|
||||||
ti := textarea.New()
|
ti := textarea.New()
|
||||||
ti.FocusedStyle = textarea.Style{Base: lipgloss.NewStyle().Foreground(lipgloss.Color("170"))}
|
ti.FocusedStyle = textarea.Style{Base: lipgloss.NewStyle().Foreground(lipgloss.Color("170"))}
|
||||||
|
ti.SetWidth(80)
|
||||||
|
ti.SetHeight(8)
|
||||||
|
|
||||||
ti.Placeholder = "Write your commit message here..."
|
ti.Placeholder = "Write your commit message here..."
|
||||||
ti.Focus()
|
ti.Focus()
|
||||||
@@ -73,12 +82,17 @@ func (m model_cm) Init() tea.Cmd {
|
|||||||
func (m model_cm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m model_cm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
var cmds []tea.Cmd
|
var cmds []tea.Cmd
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch {
|
switch {
|
||||||
case key.Matches(msg, m.keys.EndWithMes):
|
case key.Matches(msg, m.keys.EndWithMes):
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
|
case key.Matches(msg, m.keys.NewLine):
|
||||||
|
m.textarea.SetValue(m.textarea.Value() + "\n")
|
||||||
|
return m, nil
|
||||||
|
case msg.String() == "esc":
|
||||||
|
m.textarea.SetValue("")
|
||||||
|
return m, tea.Quit
|
||||||
}
|
}
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case tea.KeyCtrlC:
|
case tea.KeyCtrlC:
|
||||||
@@ -106,6 +120,6 @@ func (m model_cm) View() string {
|
|||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Commit message:\n\n%s\n\n%s",
|
"Commit message:\n\n%s\n\n%s",
|
||||||
m.textarea.View(),
|
m.textarea.View(),
|
||||||
"(alt+enter | Submit)\n(ctrl+c | Cancel)",
|
"(enter | Submit)\n(shift+tab | Newline)\n(ctrl+c | Cancel)",
|
||||||
) + "\n\n"
|
) + "\n\n"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sessionState is used to track which model is focused
|
||||||
|
|
||||||
|
var (
|
||||||
|
modelStyle = lipgloss.NewStyle().
|
||||||
|
Width(20).
|
||||||
|
Height(8).
|
||||||
|
Align(lipgloss.Center, lipgloss.Center).
|
||||||
|
BorderStyle(lipgloss.NormalBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("241"))
|
||||||
|
focusedModelStyle = lipgloss.NewStyle().
|
||||||
|
Width(20).
|
||||||
|
Height(8).
|
||||||
|
Align(lipgloss.Center, lipgloss.Center).
|
||||||
|
BorderStyle(lipgloss.DoubleBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("170"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type mainModel struct {
|
||||||
|
content []string
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newModel() mainModel {
|
||||||
|
groups := utils.Groups
|
||||||
|
|
||||||
|
content := []string{}
|
||||||
|
|
||||||
|
for name, users := range groups {
|
||||||
|
newUser := strings.Builder{}
|
||||||
|
newUser.WriteString(name + ":\n")
|
||||||
|
for _, user := range users {
|
||||||
|
newUser.WriteString(user.Username + "\n")
|
||||||
|
}
|
||||||
|
content = append(content, newUser.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Sort(content)
|
||||||
|
|
||||||
|
m := mainModel{content: content}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) Init() tea.Cmd {
|
||||||
|
// start the timer and spinner on program start
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
//var cmd tea.Cmd
|
||||||
|
var cmds []tea.Cmd
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "ctrl+c", "q", "esc":
|
||||||
|
m.content = nil
|
||||||
|
return nil, nil
|
||||||
|
case "enter":
|
||||||
|
var group string
|
||||||
|
if m.currentFocusedModel() != "" {
|
||||||
|
group = strings.Split(m.currentFocusedModel(), ":")[0]
|
||||||
|
}
|
||||||
|
if group != "" {
|
||||||
|
for _, sel := range selected {
|
||||||
|
delete(selected, string(sel))
|
||||||
|
}
|
||||||
|
users := utils.Groups[group]
|
||||||
|
for k, v := range dupProtect {
|
||||||
|
if _, ok := selected[k]; !ok {
|
||||||
|
for _, user := range users {
|
||||||
|
if strings.Contains(user.Names, v) {
|
||||||
|
selected[k] = item(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
case "tab", "right":
|
||||||
|
m.Next()
|
||||||
|
case "left":
|
||||||
|
if m.index == 0 {
|
||||||
|
m.index = len(m.content) - 1
|
||||||
|
} else {
|
||||||
|
m.index--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) View() string {
|
||||||
|
var s string
|
||||||
|
var squares []string
|
||||||
|
for i, c := range m.content {
|
||||||
|
// uses joinhorizontal to create a grid of squares
|
||||||
|
if i == m.index {
|
||||||
|
squares = append(squares, focusedModelStyle.Render(c))
|
||||||
|
} else {
|
||||||
|
squares = append(squares, modelStyle.Render(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += lipgloss.JoinHorizontal(lipgloss.Top, squares...)
|
||||||
|
|
||||||
|
s += helpStyle.Render("\ntab/right: focus next • left: focus previous • enter: select group • q/esq: exit\n")
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) currentFocusedModel() string {
|
||||||
|
if m.index < len(m.content) {
|
||||||
|
return m.content[m.index]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mainModel) Next() {
|
||||||
|
if m.index == len(m.content)-1 {
|
||||||
|
m.index = 0
|
||||||
|
} else {
|
||||||
|
m.index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Entry_GR() string {
|
||||||
|
p := tea.NewProgram(newModel())
|
||||||
|
|
||||||
|
m, err := p.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.(mainModel).currentFocusedModel() != "" {
|
||||||
|
// returns the group name
|
||||||
|
return strings.Split(m.(mainModel).currentFocusedModel(), ":")[0]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@ package tui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
"io"
|
"io"
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -37,6 +37,8 @@ var negation = false
|
|||||||
|
|
||||||
var dupProtect = map[string]string{}
|
var dupProtect = map[string]string{}
|
||||||
|
|
||||||
|
var sub_model tea.Model
|
||||||
|
|
||||||
type listKeyMap struct {
|
type listKeyMap struct {
|
||||||
selectAll key.Binding
|
selectAll key.Binding
|
||||||
negation key.Binding
|
negation key.Binding
|
||||||
@@ -147,6 +149,17 @@ func toggleNegation() {
|
|||||||
var deletion bool
|
var deletion bool
|
||||||
|
|
||||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
if sub_model != nil {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
sub_model, cmd = sub_model.Update(msg)
|
||||||
|
if sub_model_mod, ok := sub_model.(model); ok {
|
||||||
|
m.list = sub_model_mod.list
|
||||||
|
sub_model = nil
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
m.list.SetWidth(msg.Width)
|
m.list.SetWidth(msg.Width)
|
||||||
@@ -156,7 +169,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
// deletion toggle with confirmation required
|
// deletion toggle with confirmation required
|
||||||
b := false
|
b := false
|
||||||
defer func(b *bool){deletion = *b}(&b)
|
defer func(b *bool) { deletion = *b }(&b)
|
||||||
if m.list.FilterState() == list.Filtering {
|
if m.list.FilterState() == list.Filtering {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -183,31 +196,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case key.Matches(msg, m.keys.groupSelect):
|
case key.Matches(msg, m.keys.groupSelect):
|
||||||
// group code goes here
|
// TODO: Look into how to select multiple groups
|
||||||
|
sub_model = newModel()
|
||||||
|
//group := Entry_GR()
|
||||||
|
return m, tea.ClearScreen
|
||||||
|
|
||||||
case key.Matches(msg, m.keys.tempAdd):
|
case key.Matches(msg, m.keys.tempAdd):
|
||||||
screen.Clear()
|
screen.Clear()
|
||||||
screen.MoveTopLeft()
|
screen.MoveTopLeft()
|
||||||
tempAuthr := Entry_TA()
|
sub_model = tempAuthorModel(&m)
|
||||||
if tempAuthr != "" {
|
|
||||||
split := strings.Split(tempAuthr, ":")
|
|
||||||
item_str := split[0] + " - " + split[1]
|
|
||||||
dupProtect[item_str] = tempAuthr
|
|
||||||
i := item(item_str)
|
|
||||||
m.list.InsertItem(len(m.list.Items())+1, i)
|
|
||||||
selectToggle(i)
|
|
||||||
}
|
|
||||||
return m, tea.ClearScreen
|
return m, tea.ClearScreen
|
||||||
|
|
||||||
case key.Matches(msg, m.keys.createAuthor):
|
case key.Matches(msg, m.keys.createAuthor):
|
||||||
screen.Clear()
|
screen.Clear()
|
||||||
screen.MoveTopLeft()
|
screen.MoveTopLeft()
|
||||||
author := Entry_CA()
|
sub_model = createAuthorModel(&m)
|
||||||
if author != "" {
|
|
||||||
item_str := utils.Users[author].Username + " - " + utils.Users[author].Email
|
|
||||||
dupProtect[item_str] = author
|
|
||||||
m.list.InsertItem(len(m.list.Items())+1, item(item_str))
|
|
||||||
}
|
|
||||||
return m, tea.ClearScreen
|
return m, tea.ClearScreen
|
||||||
case key.Matches(msg, m.keys.deleteAuthor):
|
case key.Matches(msg, m.keys.deleteAuthor):
|
||||||
if deletion {
|
if deletion {
|
||||||
@@ -224,11 +227,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
// extra key options
|
// extra key options
|
||||||
switch keypress := msg.String(); keypress {
|
switch keypress := msg.String(); keypress {
|
||||||
case "q", "ctrl+c", "esc":
|
case "q", "ctrl+c", "esc":
|
||||||
|
if sub_model != nil {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
sub_model, cmd = sub_model.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
selected = nil
|
selected = nil
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
|
|
||||||
case "enter":
|
case "enter":
|
||||||
|
if sub_model != nil {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
sub_model, cmd = sub_model.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
}
|
}
|
||||||
@@ -241,6 +254,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m model) View() string {
|
func (m model) View() string {
|
||||||
|
if sub_model != nil {
|
||||||
|
return sub_model.View()
|
||||||
|
}
|
||||||
if m.quitting {
|
if m.quitting {
|
||||||
return "" //quitTextStyle.Render(strings.Join(m.choice, " "))
|
return "" //quitTextStyle.Render(strings.Join(m.choice, " "))
|
||||||
}
|
}
|
||||||
@@ -301,6 +317,7 @@ func listModel() model {
|
|||||||
listKeys.negation,
|
listKeys.negation,
|
||||||
listKeys.groupSelect,
|
listKeys.groupSelect,
|
||||||
listKeys.createAuthor,
|
listKeys.createAuthor,
|
||||||
|
listKeys.tempAdd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.Styles.HelpStyle = helpStyle
|
l.Styles.HelpStyle = helpStyle
|
||||||
@@ -108,8 +108,9 @@ func loadData(author_file string) {
|
|||||||
cnt.WriteString(header + "\n")
|
cnt.WriteString(header + "\n")
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
//very hacky it basically just ensure glamour doesn't format the email
|
//very hacky it basically just ensure glamour doesn't format the email whole line as an email
|
||||||
cnt.WriteString(":\b" + scanner.Text() + "\n")
|
// if only the styling had options for what to format grrrrrrr
|
||||||
|
cnt.WriteString("" + scanner.Text() + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
content = cnt.String()
|
content = cnt.String()
|
||||||
@@ -3,10 +3,11 @@ package tui
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/x/exp/teatest"
|
"github.com/charmbracelet/x/exp/teatest"
|
||||||
)
|
)
|
||||||
@@ -25,13 +26,17 @@ func setup() {
|
|||||||
}
|
}
|
||||||
os.Setenv("author_file", "author_file_test")
|
os.Setenv("author_file", "author_file_test")
|
||||||
envVar = os.Getenv("author_file")
|
envVar = os.Getenv("author_file")
|
||||||
|
|
||||||
|
utils.Define_users("author_file_test")
|
||||||
}
|
}
|
||||||
|
|
||||||
func teardown() {
|
func teardown() {
|
||||||
// remove test data
|
// remove test data
|
||||||
os.Remove("author_file_test")
|
os.Remove("author_file_test")
|
||||||
os.Setenv("author_file", envVar)
|
os.Setenv("author_file", envVar)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tui_show_users TESTS BEGIN
|
// tui_show_users TESTS BEGIN
|
||||||
func TestShowUser(t *testing.T) {
|
func TestShowUser(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
@@ -62,10 +67,17 @@ func TestEntryTA(t *testing.T) {
|
|||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
m := initialModel("temp")
|
m := listModel()
|
||||||
|
|
||||||
|
// m := tempAuthorModel(&old_m)
|
||||||
tm := teatest.NewTestModel(
|
tm := teatest.NewTestModel(
|
||||||
t, m, teatest.WithInitialTermSize(300, 300),
|
t, m, teatest.WithInitialTermSize(300, 300),
|
||||||
)
|
)
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("T"),
|
||||||
|
})
|
||||||
|
|
||||||
tm.Type("test")
|
tm.Type("test")
|
||||||
|
|
||||||
tm.Send(tea.KeyMsg{
|
tm.Send(tea.KeyMsg{
|
||||||
@@ -85,20 +97,30 @@ func TestEntryTA(t *testing.T) {
|
|||||||
Runes: []rune("enter"),
|
Runes: []rune("enter"),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("esc"),
|
||||||
|
})
|
||||||
|
|
||||||
fm := tm.FinalModel(t)
|
fm := tm.FinalModel(t)
|
||||||
m, ok := fm.(model_ca)
|
m, ok := fm.(model)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Expected model_ca, got %T", fm)
|
t.Errorf("Expected model_ca, got %T", fm)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.inputs) != 2 {
|
if len(m.list.Items()) != 3 {
|
||||||
t.Errorf("Expected 2 inputs, got %d", len(m.inputs))
|
t.Errorf("Expected 3 inputs, got %d", len(m.list.Items()))
|
||||||
}
|
}
|
||||||
if m.inputs[0].Value() != "test" {
|
|
||||||
t.Errorf("Expected 'test', got %s", m.inputs[0].Value())
|
item := string(m.list.Items()[len(m.list.Items())-1].(item))
|
||||||
|
split := strings.Split(item, " - ")
|
||||||
|
|
||||||
|
if split[0] != "test" {
|
||||||
|
t.Errorf("Expected 'test', got %s", split[0])
|
||||||
}
|
}
|
||||||
if m.inputs[1].Value() != "testtest@temp.io" {
|
|
||||||
t.Errorf("Expected 'testtest@temp.io', got %s", m.inputs[1].Value())
|
if split[1] != "testtest@temp.io" {
|
||||||
|
t.Errorf("Expected 'testtest@temp.io', got %s", split[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,10 +128,17 @@ func Test_EntryCA(t *testing.T) {
|
|||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
m := initialModel("author")
|
m := listModel()
|
||||||
|
|
||||||
|
// mm := createAuthorModel(&m)
|
||||||
tm := teatest.NewTestModel(
|
tm := teatest.NewTestModel(
|
||||||
t, m, teatest.WithInitialTermSize(300, 300),
|
t, m, teatest.WithInitialTermSize(300, 300),
|
||||||
)
|
)
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("C"),
|
||||||
|
})
|
||||||
|
|
||||||
tm.Type("test")
|
tm.Type("test")
|
||||||
|
|
||||||
tm.Send(tea.KeyMsg{
|
tm.Send(tea.KeyMsg{
|
||||||
@@ -117,13 +146,13 @@ func Test_EntryCA(t *testing.T) {
|
|||||||
Runes: []rune("enter"),
|
Runes: []rune("enter"),
|
||||||
})
|
})
|
||||||
|
|
||||||
tm.Type("testtest")
|
tm.Type("testing2")
|
||||||
tm.Send(tea.KeyMsg{
|
tm.Send(tea.KeyMsg{
|
||||||
Type: tea.KeyRunes,
|
Type: tea.KeyRunes,
|
||||||
Runes: []rune("enter"),
|
Runes: []rune("enter"),
|
||||||
})
|
})
|
||||||
|
|
||||||
tm.Type ("TestUser")
|
tm.Type("TestUser")
|
||||||
tm.Send(tea.KeyMsg{
|
tm.Send(tea.KeyMsg{
|
||||||
Type: tea.KeyRunes,
|
Type: tea.KeyRunes,
|
||||||
Runes: []rune("enter"),
|
Runes: []rune("enter"),
|
||||||
@@ -152,37 +181,44 @@ func Test_EntryCA(t *testing.T) {
|
|||||||
Type: tea.KeyRunes,
|
Type: tea.KeyRunes,
|
||||||
Runes: []rune("enter"),
|
Runes: []rune("enter"),
|
||||||
})
|
})
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("esc"),
|
||||||
|
})
|
||||||
|
|
||||||
fm := tm.FinalModel(t)
|
fm := tm.FinalModel(t)
|
||||||
m, ok := fm.(model_ca)
|
m, ok := fm.(model)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Expected model_ca, got %T", fm)
|
t.Errorf("Expected model, got %T", fm)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.inputs) != 5 {
|
if len(m.list.Items()) != 3 {
|
||||||
t.Errorf("Expected 5 inputs, got %d", len(m.inputs))
|
t.Errorf("Expected 3 inputs, got %d\n%v", len(m.list.Items()), m.list.Items())
|
||||||
}
|
|
||||||
if m.inputs[0].Value() != "test" {
|
|
||||||
t.Errorf("Expected 'test', got %s", m.inputs[0].Value())
|
|
||||||
}
|
|
||||||
if m.inputs[1].Value() != "testtest" {
|
|
||||||
t.Errorf("Expected 'testtest', got %s", m.inputs[1].Value())
|
|
||||||
}
|
|
||||||
if m.inputs[2].Value() != "TestUser" {
|
|
||||||
t.Errorf("Expected 'TestUser', got %s", m.inputs[2].Value())
|
|
||||||
}
|
|
||||||
if m.inputs[3].Value() != "test@temp.io" {
|
|
||||||
t.Errorf("Expected 'test@temp.io', got %s", m.inputs[2].Value())
|
|
||||||
}
|
|
||||||
if m.inputs[4].Value() != "gr1" {
|
|
||||||
t.Errorf("Expected 'gr1', got %s", m.inputs[4].Value())
|
|
||||||
}
|
|
||||||
//No clue why the exclude tag isn't working fix later
|
|
||||||
//TODO: Fix this should be !m.exclude
|
|
||||||
if m.exclude {
|
|
||||||
t.Errorf("Expected exclude to be true, got %v", m.exclude)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: For some reason the test is not writing to the author file despite working in the actual program
|
||||||
|
// var user utils.User
|
||||||
|
// utils.Define_users("author_file_test")
|
||||||
|
// data, _ := os.ReadFile("author_file_test")
|
||||||
|
// t.Errorf("Data: %s", data)
|
||||||
|
|
||||||
|
// if _, ok := utils.Users["test"]; !ok {
|
||||||
|
// t.Errorf("Expected 'testing2' to be in the users map")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// user = utils.Users["testing2"]
|
||||||
|
|
||||||
|
// if user.Username != "TestUser" {
|
||||||
|
// t.Errorf("Expected 'TestUser', got %s", user.Username)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if user.Email != "test@temp.io" {
|
||||||
|
// t.Errorf("Expected 'test@temp.io', got %s", user.Email)
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tui_author TESTS END
|
// tui_author TESTS END
|
||||||
|
|
||||||
// tui_commit_message TESTS BEGIN
|
// tui_commit_message TESTS BEGIN
|
||||||
@@ -211,8 +247,8 @@ func Test_EntryCM(t *testing.T) {
|
|||||||
t.Errorf("Expected 'test commit message', got %s", m.textarea.Value())
|
t.Errorf("Expected 'test commit message', got %s", m.textarea.Value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tui_commit_message TESTS END
|
|
||||||
|
|
||||||
|
// tui_commit_message TESTS END
|
||||||
|
|
||||||
// tui_list TESTS BEGIN
|
// tui_list TESTS BEGIN
|
||||||
func Test_EntrySelectUsers(t *testing.T) {
|
func Test_EntrySelectUsers(t *testing.T) {
|
||||||
@@ -282,7 +318,7 @@ func Test_EntrySelectAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(selected) != 2 {
|
if len(selected) != 2 {
|
||||||
t.Errorf("Expected 2 selected item, got %d", len(selected))
|
t.Errorf("Expected 2 selected item, got %d\n%v", len(selected), selected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,4 +396,43 @@ func Test_EntryDeleteAuthor(t *testing.T) {
|
|||||||
t.Errorf("Expected 2 user after deletion, got %d", len(utils.Users))
|
t.Errorf("Expected 2 user after deletion, got %d", len(utils.Users))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tui_list TESTS END
|
// tui_list TESTS END
|
||||||
|
|
||||||
|
// tui_groups TESTS BEGIN
|
||||||
|
|
||||||
|
func Test_GroupSelection(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
m := listModel()
|
||||||
|
tm := teatest.NewTestModel(
|
||||||
|
t, m, teatest.WithInitialTermSize(300, 300),
|
||||||
|
)
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("f"),
|
||||||
|
})
|
||||||
|
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("enter"),
|
||||||
|
})
|
||||||
|
|
||||||
|
tm.Send(tea.KeyMsg{
|
||||||
|
Type: tea.KeyRunes,
|
||||||
|
Runes: []rune("enter"),
|
||||||
|
})
|
||||||
|
|
||||||
|
fm := tm.FinalModel(t)
|
||||||
|
m, ok := fm.(model)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Expected model, got %T", fm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(selected) != 1 {
|
||||||
|
t.Errorf("Expected 1 selected item, got %d", len(selected))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tui_groups TESTS END
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/tui"
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var authorfile = utils.Find_authorfile()
|
||||||
|
|
||||||
|
// usersCmd represents the users command
|
||||||
|
func UsersCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "users",
|
||||||
|
Short: "Displays all users from the author file located at: " + authorfile,
|
||||||
|
Long: `Displays all users from the author file located at: ` + authorfile,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
//TODO: make this print a bit prettier (sort it and maybe use a table)
|
||||||
|
// check if the no pretty print flag is set
|
||||||
|
np, _ := cmd.Flags().GetBool("np")
|
||||||
|
if np {
|
||||||
|
println("List of users:\nFormat: <shortname>/<name> -> Username: <username> Email: <email>")
|
||||||
|
seen_users := []utils.User{}
|
||||||
|
user_sb := []string{}
|
||||||
|
for name, usr := range utils.Users {
|
||||||
|
if !slices.Contains(seen_users, usr) {
|
||||||
|
user_sb = append(user_sb, utils.Users[name].Names+" ->"+" Username: "+usr.Username+" Email: "+usr.Email+"\n")
|
||||||
|
seen_users = append(seen_users, usr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(user_sb)
|
||||||
|
println(strings.Join(user_sb, ""))
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
bat_check := exec.Command("bat","--version")
|
||||||
|
out, _ := bat_check.CombinedOutput()
|
||||||
|
if string(out) == "" {
|
||||||
|
tui.Entry_US(authorfile)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
bat := exec.Command("bat", authorfile)
|
||||||
|
bat.Stdout = os.Stdout
|
||||||
|
bat.Stderr = os.Stderr
|
||||||
|
bat.Run()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
usersCmd := UsersCmd()
|
||||||
|
rootCmd.AddCommand(usersCmd)
|
||||||
|
usersCmd.Flags().BoolP("np", "n", false, "No pretty print of the users")
|
||||||
|
}
|
||||||
+28
-5
@@ -36,8 +36,31 @@ func CheckAuthorFile() string {
|
|||||||
println("Error reading response")
|
println("Error reading response")
|
||||||
}
|
}
|
||||||
if response == "y" {
|
if response == "y" {
|
||||||
//TODO: Tui response to create author file
|
if authorfile == "" {
|
||||||
//createAuthorFile(authorfile)
|
fmt.Println("author_file environment variable not set using default location:")
|
||||||
|
config, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error getting user config directory")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
authorfile = config + "/cocommit/authors"
|
||||||
|
fmt.Println(authorfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the author file
|
||||||
|
file, err := os.Create(authorfile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error creating file: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// write the header to the file
|
||||||
|
file.WriteString("Syntax: name_short|Name|Username|email (opt: |ex) (opt: ;;group1|group2|group3...)\n")
|
||||||
|
|
||||||
|
fmt.Println("Author file created. To add authors please launch the TUI with -a and press 'C'")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -59,7 +82,7 @@ func DeleteOneAuthor(author string) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
// create regex to capture author line
|
// create regex to capture author line
|
||||||
regexp, err := regexp.Compile(fmt.Sprintf("^(.+\\|%s\\|.+|%s\\|.+\\|.+)$",author,author))
|
regexp, err := regexp.Compile(fmt.Sprintf("^(.+\\|%s\\|.+|%s\\|.+\\|.+)$", author, author))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error compiling regex: ", err)
|
fmt.Println("Error compiling regex: ", err)
|
||||||
return
|
return
|
||||||
@@ -85,10 +108,10 @@ func DeleteOneAuthor(author string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
// remove the last newline character
|
// remove the last newline character
|
||||||
buf.Truncate(buf.Len()-1)
|
buf.Truncate(buf.Len() - 1)
|
||||||
|
|
||||||
file.Truncate(0)
|
file.Truncate(0)
|
||||||
file.Seek(0,0)
|
file.Seek(0, 0)
|
||||||
buf.WriteTo(file)
|
buf.WriteTo(file)
|
||||||
|
|
||||||
RemoveUser(author)
|
RemoveUser(author)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Cz_Call() string {
|
||||||
|
|
||||||
|
// create commitizen command
|
||||||
|
cmd := exec.Command("cz", "commit", "--dry-run", "--write-message-to-file", "msg")
|
||||||
|
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
// if the user exits the commitizen command, exit the program
|
||||||
|
if strings.Contains(err.Error(), "exit status 8") {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
panic(fmt.Sprint(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile("msg", os.O_RDONLY, 0644)
|
||||||
|
defer os.Remove("msg")
|
||||||
|
defer file.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint(err))
|
||||||
|
}
|
||||||
|
msg, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(msg)
|
||||||
|
}
|
||||||
@@ -18,6 +18,11 @@ var DefExclude = []string{}
|
|||||||
var Groups = map[string][]User{}
|
var Groups = map[string][]User{}
|
||||||
|
|
||||||
func Define_users(author_file string) {
|
func Define_users(author_file string) {
|
||||||
|
// wipe the users map
|
||||||
|
Users = map[string]User{}
|
||||||
|
DefExclude = []string{}
|
||||||
|
Groups = map[string][]User{}
|
||||||
|
|
||||||
file, err := os.Open(author_file)
|
file, err := os.Open(author_file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
print("File not found")
|
print("File not found")
|
||||||
@@ -57,7 +62,8 @@ func Define_users(author_file string) {
|
|||||||
if info[4] == "ex" {
|
if info[4] == "ex" {
|
||||||
DefExclude = append(DefExclude, info[2])
|
DefExclude = append(DefExclude, info[2])
|
||||||
}
|
}
|
||||||
} else if len(group_info) > 0 {
|
}
|
||||||
|
if len(group_info) > 0 {
|
||||||
// Group assignment
|
// Group assignment
|
||||||
for _, group := range group_info {
|
for _, group := range group_info {
|
||||||
if Groups[group] == nil {
|
if Groups[group] == nil {
|
||||||
@@ -89,4 +95,3 @@ func TempAddUser(username, email string) {
|
|||||||
|
|
||||||
Users[username] = usr
|
Users[username] = usr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package utils_test
|
package utils_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -4,7 +4,7 @@ Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
|||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/Slug-Boi/cocommit/src_code/go_src/cmd"
|
import "github.com/Slug-Boi/cocommit/src/cmd"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
@@ -1 +0,0 @@
|
|||||||
Syntax: name_short|Name|Username|email (opt: |ex) (opt: ;;group1|group2|group3...) !!Remember to set the env var authors_file!!
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Syntax for authorfile
|
|
||||||
test|test|test|test|ex;;test
|
|
||||||
tet|tessadsat|teta|asdadad|ex;;adsadas
|
|
||||||
teadsajdma|asdasdasda|adsdadasd|addsadasd;;adsadsadadas
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/tui"
|
|
||||||
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"slices"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var authorfile = utils.Find_authorfile()
|
|
||||||
|
|
||||||
// usersCmd represents the users command
|
|
||||||
func UsersCmd() *cobra.Command {
|
|
||||||
return &cobra.Command{
|
|
||||||
Use: "users",
|
|
||||||
Short: "Displays all users from the author file located at: " + authorfile,
|
|
||||||
Long: `Displays all users from the author file located at: ` + authorfile,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
//TODO: make this print a bit prettier (sort it and maybe use a table)
|
|
||||||
// check if the no pretty print flag is set
|
|
||||||
np, _ := cmd.Flags().GetBool("np")
|
|
||||||
if np {
|
|
||||||
println("List of users:\nFormat: <shortname>/<name> -> Username: <username> Email: <email>")
|
|
||||||
seen_users := []utils.User{}
|
|
||||||
user_sb := []string{}
|
|
||||||
for name, usr := range utils.Users {
|
|
||||||
if !slices.Contains(seen_users, usr) {
|
|
||||||
user_sb = append(user_sb, utils.Users[name].Names+" ->"+" Username: "+usr.Username+" Email: "+usr.Email+"\n")
|
|
||||||
seen_users = append(seen_users, usr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(user_sb)
|
|
||||||
println(strings.Join(user_sb, ""))
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
bat_check := exec.Command("which", "bat")
|
|
||||||
out, _ := bat_check.CombinedOutput()
|
|
||||||
if string(out) == "" {
|
|
||||||
tui.Entry_US(authorfile)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
bat := exec.Command("bat", authorfile)
|
|
||||||
bat.Stdout = os.Stdout
|
|
||||||
bat.Stderr = os.Stderr
|
|
||||||
bat.Run()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd := UsersCmd()
|
|
||||||
rootCmD.AddCommand(usersCmd)
|
|
||||||
usersCmd.Flags().BoolP("np", "n", false, "No pretty print of the users")
|
|
||||||
}
|
|
||||||
@@ -1,309 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"slices"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type user struct {
|
|
||||||
username string
|
|
||||||
email string
|
|
||||||
names string
|
|
||||||
}
|
|
||||||
//TODO: Remove later once everything is up and running with the new version
|
|
||||||
|
|
||||||
// Map of all th users in the author file
|
|
||||||
var users = make(map[string]user)
|
|
||||||
|
|
||||||
// String builder for building the commit message
|
|
||||||
var sb strings.Builder
|
|
||||||
|
|
||||||
// Flag that can be toggled to include all users in a commit message (excluding defExclude)
|
|
||||||
var all_flag = false
|
|
||||||
|
|
||||||
// DefaultExclude -> A list that contains users marked with ex meaning
|
|
||||||
// they should not be included in all and negations
|
|
||||||
var defExclude = []string{}
|
|
||||||
|
|
||||||
// Group map for adding people as a group
|
|
||||||
var groups = make(map[string][]user)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// Reads a shell env variable :: author_file
|
|
||||||
var authors string
|
|
||||||
envVar := os.Getenv("author_file")
|
|
||||||
if envVar == "" {
|
|
||||||
var err error
|
|
||||||
authors, err = os.UserConfigDir()
|
|
||||||
authors += "/cocommit/authors"
|
|
||||||
if err != nil {
|
|
||||||
println("Error: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
authors = envVar
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Open(authors)
|
|
||||||
if err != nil {
|
|
||||||
authors, _ = os.UserConfigDir()
|
|
||||||
authors += "/cocommit/authors"
|
|
||||||
println("Authors file cannot be found. Please check the path to the file. \nEither set the author_file env variable or place the file in the default location. \nDefault location: " + authors)
|
|
||||||
println("If you want to create a blank template file at the default location type y|yes or cancel with n|no")
|
|
||||||
var input string
|
|
||||||
fmt.Scanln(&input)
|
|
||||||
if input == "y" || input == "yes" {
|
|
||||||
create_author_file("yes")
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
println("Cancelled")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
|
|
||||||
// eat a single input
|
|
||||||
scanner.Scan()
|
|
||||||
|
|
||||||
// reads the input of authors file and formats accordingly
|
|
||||||
for scanner.Scan() {
|
|
||||||
input_str := scanner.Text()
|
|
||||||
group_info := []string{}
|
|
||||||
if strings.Contains(input_str, ";;") {
|
|
||||||
input := strings.Split(input_str, ";;")
|
|
||||||
input_str = input[0]
|
|
||||||
group_info = append(group_info, strings.Split(input[1], "|")...)
|
|
||||||
}
|
|
||||||
info := strings.Split(input_str, "|")
|
|
||||||
usr := user{username: info[2], email: info[3], names: info[0] + "/" + info[1]}
|
|
||||||
users[info[0]] = usr
|
|
||||||
users[info[1]] = usr
|
|
||||||
// Adds users with the ex tag to the defExclude list
|
|
||||||
if len(info) == 5 {
|
|
||||||
if info[4] == "ex" {
|
|
||||||
defExclude = append(defExclude, info[2])
|
|
||||||
}
|
|
||||||
} else if len(group_info) > 0 {
|
|
||||||
// Group assignment
|
|
||||||
for _, group := range group_info {
|
|
||||||
if groups[group] == nil {
|
|
||||||
groups[group] = []user{usr}
|
|
||||||
} else {
|
|
||||||
//TODO: Try and find a cleaner way of doing this
|
|
||||||
usr_lst := groups[group]
|
|
||||||
usr_lst = append(usr_lst, usr)
|
|
||||||
groups[group] = usr_lst
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check_err(scanner.Err())
|
|
||||||
// Removes the call command for the program
|
|
||||||
args := os.Args[1:]
|
|
||||||
|
|
||||||
// Checks if the user called the program with any inputs or with non commit args
|
|
||||||
NoInput(args, users)
|
|
||||||
|
|
||||||
// This list is used when doing negations and for removing duplicate users during string building
|
|
||||||
excludeMode := []string{}
|
|
||||||
|
|
||||||
// builds the commit message with the selected authors
|
|
||||||
sb.WriteString(string(args[0]) + "\n")
|
|
||||||
|
|
||||||
// Regex that catches one off authors
|
|
||||||
reg, _ := regexp.Compile("([^:]+):([^:]+)")
|
|
||||||
|
|
||||||
if args[1] == "all" || args[1] == "All" {
|
|
||||||
all_flag = true
|
|
||||||
goto skip_loop
|
|
||||||
} else if groups[args[1]] != nil {
|
|
||||||
// Selects everybody that isn't the group members and adds them to the defExclude
|
|
||||||
excludeMode = group_selection(groups[args[1]], excludeMode)
|
|
||||||
goto skip_loop
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop that adds users
|
|
||||||
for _, committer := range args[1:] {
|
|
||||||
if _, ok := users[committer]; ok {
|
|
||||||
sb_author(committer)
|
|
||||||
} else if match := reg.MatchString(committer); match {
|
|
||||||
str := strings.Split(committer, ":")
|
|
||||||
|
|
||||||
sb.WriteString("\nCo-authored-by: ")
|
|
||||||
sb.WriteString(str[0])
|
|
||||||
sb.WriteString(" <")
|
|
||||||
sb.WriteString(str[1])
|
|
||||||
sb.WriteRune('>')
|
|
||||||
|
|
||||||
} else if committer[0] == '^' { // Negations
|
|
||||||
excludeMode = append(excludeMode, users[committer[1:]].username)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
println(committer, " was unknown. User either not defined or name typed wrong")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip label for adding all
|
|
||||||
skip_loop:
|
|
||||||
|
|
||||||
if len(excludeMode) > 0 || all_flag {
|
|
||||||
// adds all users not in the excludeMode list
|
|
||||||
add_x_users(excludeMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// commit msg built
|
|
||||||
commit := sb_build()
|
|
||||||
|
|
||||||
print(commit)
|
|
||||||
|
|
||||||
//NOTE: Uncomment for testing
|
|
||||||
//print(commit)
|
|
||||||
|
|
||||||
// commit shell command
|
|
||||||
cmd := exec.Command("git", "commit", "-m", commit)
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/18159704/how-to-debug-exit-status-1-error-when-running-exec-command-in-golang
|
|
||||||
|
|
||||||
cmd_output, err := cmd.CombinedOutput()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
println(fmt.Sprint(err) + " : " + string(cmd_output))
|
|
||||||
} else {
|
|
||||||
println(string(cmd_output))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func group_selection(group []user, excludeMode []string) []string {
|
|
||||||
for _, user := range users {
|
|
||||||
if !(slices.Contains(group, user)) {
|
|
||||||
excludeMode = append(excludeMode, user.username)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return excludeMode
|
|
||||||
}
|
|
||||||
|
|
||||||
func add_x_users(excludeMode []string) {
|
|
||||||
if len(defExclude) > 0 {
|
|
||||||
excludeMode = append(excludeMode, defExclude...)
|
|
||||||
}
|
|
||||||
for key, user := range users {
|
|
||||||
if !slices.Contains(excludeMode, user.username) {
|
|
||||||
sb_author(key)
|
|
||||||
excludeMode = append(excludeMode, user.username)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sb_build() string {
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func sb_author(committer string) {
|
|
||||||
sb.WriteString("\nCo-authored-by: ")
|
|
||||||
sb.WriteString(users[committer].username)
|
|
||||||
sb.WriteString(" <")
|
|
||||||
sb.WriteString(users[committer].email)
|
|
||||||
sb.WriteRune('>')
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move half this into another function and call before building users to improve performance
|
|
||||||
func NoInput(args []string, users map[string]user) {
|
|
||||||
if len(args) < 2 {
|
|
||||||
// If you call binary with users prints users
|
|
||||||
if len(args) == 1 && args[0] == "users" {
|
|
||||||
println("List of users:\nFormat: <shortname>/<name> -> Username: <username> Email: <email>")
|
|
||||||
seen_users := []user{}
|
|
||||||
user_sb := []string{}
|
|
||||||
for name, usr := range users {
|
|
||||||
if !slices.Contains(seen_users, usr) {
|
|
||||||
user_sb = append(user_sb, users[name].names+" ->"+" Username: "+usr.username+" Email: "+usr.email+"\n")
|
|
||||||
seen_users = append(seen_users, usr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(user_sb)
|
|
||||||
println(strings.Join(user_sb, ""))
|
|
||||||
os.Exit(1)
|
|
||||||
} else if len(args) == 1 && args[0] == "config" {
|
|
||||||
create_author_file()
|
|
||||||
}
|
|
||||||
// if calling binary with nothing or only string
|
|
||||||
command_options := []string{
|
|
||||||
"cocommit <commit message> <co-author1> [co-author2] [co-author3]",
|
|
||||||
"cocommit <commit message> <co-author1:email> [co-author2:email] [co-author3:email]",
|
|
||||||
"cocommit <commit message> all",
|
|
||||||
"cocommit <commit message> ^<co-author1> ^[co-author2]",
|
|
||||||
"cocommit <commit message> <group>",
|
|
||||||
"cocommit users",
|
|
||||||
}
|
|
||||||
println("Usage:")
|
|
||||||
for _, v := range command_options {
|
|
||||||
print(v)
|
|
||||||
println(" ||")
|
|
||||||
}
|
|
||||||
println("Mixes of both")
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func create_author_file(param ...string) {
|
|
||||||
var input string
|
|
||||||
authors, err := os.UserConfigDir()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
println("Error: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if len(param) > 0 {
|
|
||||||
input = "yes"
|
|
||||||
goto skip
|
|
||||||
}
|
|
||||||
println("This command will create a blank template auhtor file in the default location. \nDefault location: " + authors + "\nConfirm by typing y|yes or cancel with n|no")
|
|
||||||
fmt.Scanln(&input)
|
|
||||||
if err != nil {
|
|
||||||
println("Error: ", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
skip:
|
|
||||||
if input == "y" || input == "yes" {
|
|
||||||
// create folder cocommit in .config
|
|
||||||
authors += "/cocommit"
|
|
||||||
err := os.MkdirAll(authors, 0755)
|
|
||||||
if err != nil {
|
|
||||||
println("Error in dir creation: ", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
authors += "/authors"
|
|
||||||
file, err := os.Create(authors)
|
|
||||||
if err != nil {
|
|
||||||
println("Error: ", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
file.WriteString("name_short|Name|Username|email (opt: |ex) (opt: ;;group1 or ;;group1|group2|group3...)\n")
|
|
||||||
println("File created successfully at: " + authors)
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
println("Cancelled")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func check_err(e error) {
|
|
||||||
if e != nil {
|
|
||||||
fmt.Println(e.Error())
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_emptyInput(t *testing.T) {
|
|
||||||
authors := make(map[string]user)
|
|
||||||
authors["test"] = user{username: "test", email: "test"}
|
|
||||||
if os.Getenv("BE_CRASHER") == "1" {
|
|
||||||
NoInput([]string{}, authors)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cmd := exec.Command(os.Args[0], "-test.run=Test_emptyInput")
|
|
||||||
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
|
|
||||||
err := cmd.Run()
|
|
||||||
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Fatalf("process ran with err %v, want exit status 1", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_usersInput(t *testing.T) {
|
|
||||||
authors := make(map[string]user)
|
|
||||||
authors["test"] = user{username: "test", email: "test"}
|
|
||||||
if os.Getenv("BE_CRASHER") == "1" {
|
|
||||||
NoInput([]string{"users"}, authors)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cmd := exec.Command(os.Args[0], "-test.run=Test_usersInput")
|
|
||||||
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
|
|
||||||
err := cmd.Run()
|
|
||||||
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Fatalf("process ran with err %v, want exit status 1", err)
|
|
||||||
}
|
|
||||||
//TODO: Turn this into a fuzz test
|
|
||||||
|
|
||||||
func Test_commit_message(t *testing.T) {
|
|
||||||
//authors := make(map[string]user)
|
|
||||||
users["test"] = user{username: "test", email: "test"}
|
|
||||||
sb_author("test")
|
|
||||||
commit := sb_build()
|
|
||||||
if commit != "\nCo-authored-by: test <test>" {
|
|
||||||
t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test <test>",commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO: Turn this into a fuzz test
|
|
||||||
func Test_add_all(t *testing.T) {
|
|
||||||
for k := range users {
|
|
||||||
delete(users, k)
|
|
||||||
}
|
|
||||||
sb.Reset()
|
|
||||||
users["test1"] = user{username: "test1", email: "test1"}
|
|
||||||
users["test2"] = user{username: "test2", email: "test2"}
|
|
||||||
users["test3"] = user{username: "test3", email: "test3"}
|
|
||||||
all_flag = true
|
|
||||||
add_x_users([]string{})
|
|
||||||
|
|
||||||
commit := sb_build()
|
|
||||||
if !strings.Contains(commit, "\nCo-authored-by: test1 <test1>") ||
|
|
||||||
!strings.Contains(commit, "\nCo-authored-by: test2 <test2>") ||
|
|
||||||
!strings.Contains(commit, "\nCo-authored-by: test3 <test3>") {
|
|
||||||
t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test1 <test1>\nCo-authored-by: test2 <test2>\n\nCo-authored-by: test3 <test3>",commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_exclude_user(t *testing.T) {
|
|
||||||
// Reusing users map from last test
|
|
||||||
excludeMode := []string{"test1"}
|
|
||||||
|
|
||||||
sb.Reset()
|
|
||||||
|
|
||||||
add_x_users(excludeMode)
|
|
||||||
|
|
||||||
commit := sb_build()
|
|
||||||
if strings.Contains(commit, "\nCo-authored-by: test1 <test1>") {
|
|
||||||
t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test2 <test2>\n\nCo-authored-by: test3 <test3>",commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_exclude_by_default(t *testing.T) {
|
|
||||||
// Reusing users from before
|
|
||||||
defExclude = append(defExclude, users["test1"].username)
|
|
||||||
|
|
||||||
sb.Reset()
|
|
||||||
|
|
||||||
add_x_users([]string{})
|
|
||||||
|
|
||||||
commit := sb_build()
|
|
||||||
|
|
||||||
if strings.Contains(commit, "\nCo-authored-by: test1 <test1>") {
|
|
||||||
t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test2 <test2>\n\nCo-authored-by: test3 <test3>",commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_commit_with_grouping(t *testing.T) {
|
|
||||||
for k := range groups {
|
|
||||||
delete(groups, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
defExclude = []string{}
|
|
||||||
|
|
||||||
groups["test1"] = []user{users["test1"]}
|
|
||||||
|
|
||||||
excludeMode := group_selection(groups["test1"], []string{})
|
|
||||||
|
|
||||||
sb.Reset()
|
|
||||||
|
|
||||||
add_x_users(excludeMode)
|
|
||||||
|
|
||||||
commit := sb_build()
|
|
||||||
|
|
||||||
if commit != "\nCo-authored-by: test1 <test1>" {
|
|
||||||
t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test <test>",commit)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user