Merge branch 'main' into docs_completely_redo_docs

This commit is contained in:
Slug-Boi
2024-11-12 21:52:39 +01:00
31 changed files with 913 additions and 669 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
uses: actions/setup-go@v3
- uses: actions/checkout@v3
- 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: mkdir ./dist
- run: go run ci/build_test_release.go
+1
View File
@@ -1,5 +1,6 @@
# Custom
dist
author_file
go.work
go.sum
+5 -5
View File
@@ -25,20 +25,20 @@ func main() {
// at /src in the container
source := client.Container().
From("golang:1.23").
WithDirectory("/src", client.Host().Directory(".", dagger.HostDirectoryOpts{
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
Exclude: []string{},
})).WithMountedCache("/src/dagger_dep_cache/go_dep", goCache)
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
geese := []string{"darwin", "linux", "windows"}
goarch := "amd64"
// set the working directory in the container
// install application dependencies
runner := source.WithWorkdir("/src/src_code/go_src/").
runner := source.WithWorkdir("/src_d/src/").
WithExec([]string{"go", "mod", "tidy"})
// 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/")
@@ -50,7 +50,7 @@ func main() {
build := test.
WithEnvVariable("GOOS", goos).
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))
+32 -12
View File
@@ -1,23 +1,43 @@
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 (
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/adrg/xdg v0.4.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/adrg/xdg v0.5.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/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/sosodev/duration v1.2.0 // indirect
github.com/vektah/gqlparser/v2 v2.5.15 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
github.com/sosodev/duration v1.3.1 // indirect
github.com/vektah/gqlparser/v2 v2.5.17 // indirect
go.opentelemetry.io/otel v1.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/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/net v0.29.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
View File
@@ -25,17 +25,17 @@ func main() {
// at /src in the container
source := client.Container().
From("golang:1.23").
WithDirectory("/src", client.Host().Directory(".", dagger.HostDirectoryOpts{
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
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
// install application dependencies
runner := source.WithWorkdir("/src/src_code/go_src/").
WithExec([]string{"go", "mod", "tidy"})
runner := source.WithWorkdir("/src_d/src").
WithExec([]string{"go", "mod", "tidy"}).WithEnvVariable("CI", "true")
// 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)
if err != nil {
panic(err)
+35 -3
View File
@@ -13,36 +13,68 @@ 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/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymanbagabas/go-udiff 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/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
github.com/charmbracelet/x/term v0.2.0 // indirect
github.com/dlclark/regexp2 v1.11.0 // 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/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/inconshreveable/mousetrap v1.1.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-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // 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/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/rivo/uniseg v0.4.7 // 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/vektah/gqlparser/v2 v2.5.17 // indirect
github.com/yuin/goldmark v1.7.4 // indirect
github.com/yuin/goldmark-emoji v1.0.3 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.27.0 // indirect
go.opentelemetry.io/otel v1.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/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
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
)
+169
View File
@@ -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=
+1
View File
@@ -0,0 +1 @@
Syntax: name_short|Name|Username|email (opt: |ex) (opt: ;;group1|group2|group3...)
@@ -7,7 +7,7 @@ import (
"strings"
"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
@@ -32,6 +32,14 @@ func teardown() {
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) {
old := os.Stdout
r, w, _ := os.Pipe()
@@ -43,6 +51,7 @@ func StdoutReader() (chan string, *os.File, *os.File, *os.File) {
// users CMD TEST BEGIN
func Test_UsersCmd(t *testing.T) {
skipCI(t)
setup()
defer teardown()
@@ -87,6 +96,7 @@ func Test_UsersCmd(t *testing.T) {
// root CMD TEST BEGIN
func Test_CommitCmd(t *testing.T) {
skipCI(t)
setup()
defer teardown()
@@ -99,7 +109,7 @@ func Test_CommitCmd(t *testing.T) {
outC <- buf.String()
}()
cmd := rootCmD
cmd := rootCmd
cmd.SetArgs([]string{"-t", "Test commit message"})
cmd.Execute()
@@ -117,6 +127,7 @@ func Test_CommitCmd(t *testing.T) {
}
func Test_CommitCmdWithM(t *testing.T) {
skipCI(t)
setup()
defer teardown()
@@ -129,7 +140,7 @@ func Test_CommitCmdWithM(t *testing.T) {
outC <- buf.String()
}()
cmd := rootCmD
cmd := rootCmd
cmd.SetArgs([]string{"-m", "-t", "Test commit message"})
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)
}
}
// root CMD TEST END
+60
View File
@@ -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"
"os"
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/tui"
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
"github.com/Slug-Boi/cocommit/src/cmd/tui"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
"github.com/inancgumus/screen"
"github.com/spf13/cobra"
@@ -13,7 +13,7 @@ import (
// rootCmd represents the base command when called without any subcommands
// func RootCmd() *cobra.Command {
var rootCmD = &cobra.Command{
var rootCmd = &cobra.Command{
Use: `cocommit <commit message> <co-author1> [co-author2] ... ||
cocommit <commit message> <co-author1:email> [co-author2:email] ... ||
cocommit <commit message> all ||
@@ -31,6 +31,12 @@ var rootCmD = &cobra.Command{
// check if the print flag is set
pflag, _ := cmd.Flags().GetBool("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
// redundant check for now but will be useful later when we add tui
wrap_around:
@@ -85,7 +91,7 @@ func Execute() {
// define users
utils.Define_users(author_file)
err := rootCmD.Execute()
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
@@ -93,7 +99,8 @@ func Execute() {
func init() {
//rootCmD := RootCmd()
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("message", "m", false, "Does nothing but allows for -m to be used in the command")
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("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 (
"fmt"
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
"os"
"strings"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
@@ -27,7 +28,7 @@ var (
excludeButton = fmt.Sprintf("[ %s ]", blurredStyle.Render("Exclude"))
)
var removeButton bool
var tempAuthorToggle bool
type model_ca struct {
focusIndex int
@@ -36,7 +37,11 @@ type model_ca struct {
exclude bool
}
func createAuthorModel() model_ca {
var parent_m *model
func createAuthorModel(old_m *model) model_ca {
parent_m = old_m
m := model_ca{
inputs: make([]textinput.Model, 5),
}
@@ -69,7 +74,9 @@ func createAuthorModel() model_ca {
return m
}
func tempAuthorModel() model_ca {
func tempAuthorModel(old_m *model) model_ca {
parent_m = old_m
m := model_ca{
inputs: make([]textinput.Model, 2),
}
@@ -93,20 +100,11 @@ func tempAuthorModel() model_ca {
m.inputs[i] = t
}
removeButton = true
tempAuthorToggle = true
return m
}
func initialModel(model string) model_ca {
if model == "author" {
return createAuthorModel()
} else {
return tempAuthorModel()
}
}
func (m model_ca) Init() tea.Cmd {
return textinput.Blink
}
@@ -117,18 +115,18 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.String() {
case "ctrl+c", "esc":
m.inputs = nil
return m, tea.Quit
return nil, nil
// Set focus to next input
case "tab", "shift+tab", "enter", "up", "down":
s := msg.String()
// Did the user press enter while the submit button was focused?
// If so, exit.
if !removeButton {
if !tempAuthorToggle {
if s == "enter" && m.focusIndex == len(m.inputs)+1 {
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) {
// toggle exclude
m.exclude = !m.exclude
@@ -137,7 +135,8 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} else {
if s == "enter" && m.focusIndex == len(m.inputs) {
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
var exclude *string
var button *string
if !removeButton {
if !tempAuthorToggle {
exclude = &excludeButton
if m.focusIndex == len(m.inputs) {
exclude = &focusedExclude
@@ -237,18 +236,12 @@ func (m model_ca) View() string {
return b.String()
}
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() != "" {
func (m *model_ca) AddAuthor() {
if len(m.inputs) > 0 &&
m.inputs[0].Value() != "" &&
m.inputs[1].Value() != "" &&
m.inputs[2].Value() != "" &&
m.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 {
@@ -261,17 +254,17 @@ func Entry_CA() string {
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()))
m.inputs[0].Value(),
m.inputs[1].Value(),
m.inputs[2].Value(),
m.inputs[3].Value()))
if m.(model_ca).exclude {
if m.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()))
if m.inputs[4].Value() != "" {
sb.WriteString(fmt.Sprintf(";;%s", m.inputs[4].Value()))
}
//sb.WriteRune('\n')
@@ -280,25 +273,90 @@ func Entry_CA() string {
panic(err)
}
utils.Define_users(utils.Find_authorfile())
return m.(model_ca).inputs[0].Value()
}
return ""
}
func Entry_TA() string {
m, err := tea.NewProgram(initialModel("temp")).Run()
if err != nil {
fmt.Printf("could not start program: %s\n", err)
os.Exit(1)
}
author := m.inputs[0].Value()
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 ""
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))
}
}
func (m *model_ca) TempAddAuthor() {
if len(m.inputs) > 1 && m.inputs[0].Value() != "" && m.inputs[1].Value() != "" {
item_str := m.inputs[0].Value() + " - " + m.inputs[1].Value()
dupProtect[item_str] = m.inputs[0].Value() + ":" + m.inputs[1].Value()
i := item(item_str)
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
selectToggle(i)
}
}
// 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"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/inancgumus/screen"
)
type KeyMap struct {
EndWithMes key.Binding
NewLine key.Binding
}
func newKeyMap() *KeyMap {
@@ -25,6 +27,9 @@ func newKeyMap() *KeyMap {
EndWithMes: key.NewBinding(
key.WithKeys("enter"),
),
NewLine: key.NewBinding(
key.WithKeys("shift+tab"),
),
}
}
@@ -38,8 +43,10 @@ func Entry_CM() string {
log.Fatal(err)
}
if m.(model_cm).textarea.Value() == "" {
screen.Clear()
screen.MoveTopLeft()
fmt.Println("No commit message provided. Exiting...")
os.Exit(1)
os.Exit(0)
}
return m.(model_cm).textarea.Value() + "\n"
}
@@ -55,6 +62,8 @@ type model_cm struct {
func initialModel_cm() model_cm {
ti := textarea.New()
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.Focus()
@@ -73,12 +82,17 @@ func (m model_cm) Init() tea.Cmd {
func (m model_cm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch {
case key.Matches(msg, m.keys.EndWithMes):
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 {
case tea.KeyCtrlC:
@@ -106,6 +120,6 @@ func (m model_cm) View() string {
return fmt.Sprintf(
"Commit message:\n\n%s\n\n%s",
m.textarea.View(),
"(alt+enter | Submit)\n(ctrl+c | Cancel)",
"(enter | Submit)\n(shift+tab | Newline)\n(ctrl+c | Cancel)",
) + "\n\n"
}
+148
View File
@@ -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 (
"fmt"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
"io"
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
"os"
"sort"
"strings"
@@ -37,6 +37,8 @@ var negation = false
var dupProtect = map[string]string{}
var sub_model tea.Model
type listKeyMap struct {
selectAll key.Binding
negation key.Binding
@@ -147,6 +149,17 @@ func toggleNegation() {
var deletion bool
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) {
case tea.WindowSizeMsg:
m.list.SetWidth(msg.Width)
@@ -183,31 +196,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
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):
screen.Clear()
screen.MoveTopLeft()
tempAuthr := Entry_TA()
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)
}
sub_model = tempAuthorModel(&m)
return m, tea.ClearScreen
case key.Matches(msg, m.keys.createAuthor):
screen.Clear()
screen.MoveTopLeft()
author := Entry_CA()
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))
}
sub_model = createAuthorModel(&m)
return m, tea.ClearScreen
case key.Matches(msg, m.keys.deleteAuthor):
if deletion {
@@ -224,11 +227,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// extra key options
switch keypress := msg.String(); keypress {
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
selected = nil
return m, tea.Quit
case "enter":
if sub_model != nil {
var cmd tea.Cmd
sub_model, cmd = sub_model.Update(msg)
return m, cmd
}
m.quitting = true
return m, tea.Quit
}
@@ -241,6 +254,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (m model) View() string {
if sub_model != nil {
return sub_model.View()
}
if m.quitting {
return "" //quitTextStyle.Render(strings.Join(m.choice, " "))
}
@@ -301,6 +317,7 @@ func listModel() model {
listKeys.negation,
listKeys.groupSelect,
listKeys.createAuthor,
listKeys.tempAdd,
}
}
l.Styles.HelpStyle = helpStyle
@@ -108,8 +108,9 @@ func loadData(author_file string) {
cnt.WriteString(header + "\n")
for scanner.Scan() {
//very hacky it basically just ensure glamour doesn't format the email
cnt.WriteString(":\b" + scanner.Text() + "\n")
//very hacky it basically just ensure glamour doesn't format the email whole line as an email
// if only the styling had options for what to format grrrrrrr
cnt.WriteString("" + scanner.Text() + "\n")
}
content = cnt.String()
@@ -3,10 +3,11 @@ package tui
import (
"bytes"
"os"
"strings"
"testing"
"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"
"github.com/charmbracelet/x/exp/teatest"
)
@@ -25,13 +26,17 @@ func setup() {
}
os.Setenv("author_file", "author_file_test")
envVar = os.Getenv("author_file")
utils.Define_users("author_file_test")
}
func teardown() {
// remove test data
os.Remove("author_file_test")
os.Setenv("author_file", envVar)
}
// tui_show_users TESTS BEGIN
func TestShowUser(t *testing.T) {
setup()
@@ -62,10 +67,17 @@ func TestEntryTA(t *testing.T) {
setup()
defer teardown()
m := initialModel("temp")
m := listModel()
// m := tempAuthorModel(&old_m)
tm := teatest.NewTestModel(
t, m, teatest.WithInitialTermSize(300, 300),
)
tm.Send(tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune("T"),
})
tm.Type("test")
tm.Send(tea.KeyMsg{
@@ -85,20 +97,30 @@ func TestEntryTA(t *testing.T) {
Runes: []rune("enter"),
})
tm.Send(tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune("esc"),
})
fm := tm.FinalModel(t)
m, ok := fm.(model_ca)
m, ok := fm.(model)
if !ok {
t.Errorf("Expected model_ca, got %T", fm)
}
if len(m.inputs) != 2 {
t.Errorf("Expected 2 inputs, got %d", len(m.inputs))
if len(m.list.Items()) != 3 {
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()
defer teardown()
m := initialModel("author")
m := listModel()
// mm := createAuthorModel(&m)
tm := teatest.NewTestModel(
t, m, teatest.WithInitialTermSize(300, 300),
)
tm.Send(tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune("C"),
})
tm.Type("test")
tm.Send(tea.KeyMsg{
@@ -117,7 +146,7 @@ func Test_EntryCA(t *testing.T) {
Runes: []rune("enter"),
})
tm.Type("testtest")
tm.Type("testing2")
tm.Send(tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune("enter"),
@@ -152,37 +181,44 @@ func Test_EntryCA(t *testing.T) {
Type: tea.KeyRunes,
Runes: []rune("enter"),
})
tm.Send(tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune("esc"),
})
fm := tm.FinalModel(t)
m, ok := fm.(model_ca)
m, ok := fm.(model)
if !ok {
t.Errorf("Expected model_ca, got %T", fm)
t.Errorf("Expected model, got %T", fm)
}
if len(m.inputs) != 5 {
t.Errorf("Expected 5 inputs, got %d", len(m.inputs))
}
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)
if len(m.list.Items()) != 3 {
t.Errorf("Expected 3 inputs, got %d\n%v", len(m.list.Items()), m.list.Items())
}
//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_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())
}
}
// tui_commit_message TESTS END
// tui_commit_message TESTS END
// tui_list TESTS BEGIN
func Test_EntrySelectUsers(t *testing.T) {
@@ -282,7 +318,7 @@ func Test_EntrySelectAll(t *testing.T) {
}
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))
}
}
// 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
+60
View File
@@ -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")
}
@@ -36,8 +36,31 @@ func CheckAuthorFile() string {
println("Error reading response")
}
if response == "y" {
//TODO: Tui response to create author file
//createAuthorFile(authorfile)
if 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 {
os.Exit(1)
}
+41
View File
@@ -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{}
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)
if err != nil {
print("File not found")
@@ -57,7 +62,8 @@ func Define_users(author_file string) {
if info[4] == "ex" {
DefExclude = append(DefExclude, info[2])
}
} else if len(group_info) > 0 {
}
if len(group_info) > 0 {
// Group assignment
for _, group := range group_info {
if Groups[group] == nil {
@@ -89,4 +95,3 @@ func TempAddUser(username, email string) {
Users[username] = usr
}
@@ -1,7 +1,7 @@
package utils_test
import (
"github.com/Slug-Boi/cocommit/src_code/go_src/cmd/utils"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
"os"
"testing"
)
+1 -1
View File
@@ -4,7 +4,7 @@ Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package main
import "github.com/Slug-Boi/cocommit/src_code/go_src/cmd"
import "github.com/Slug-Boi/cocommit/src/cmd"
func main() {
cmd.Execute()
-1
View File
@@ -1 +0,0 @@
Syntax: name_short|Name|Username|email (opt: |ex) (opt: ;;group1|group2|group3...) !!Remember to set the env var authors_file!!
-4
View 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
-59
View File
@@ -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")
}
-309
View File
@@ -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)
}
}
-126
View File
@@ -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)
}
}