config confirmation

This commit is contained in:
2025-08-01 00:56:05 +03:00
parent 08e96aa32a
commit 5cdfb2a543
9 changed files with 131 additions and 81 deletions

View File

@@ -6,8 +6,8 @@ import (
"os" "os"
"github.com/akyaiy/GoSally-mvp/hooks" "github.com/akyaiy/GoSally-mvp/hooks"
"github.com/akyaiy/GoSally-mvp/internal/colors"
"github.com/akyaiy/GoSally-mvp/internal/core/corestate" "github.com/akyaiy/GoSally-mvp/internal/core/corestate"
"github.com/akyaiy/GoSally-mvp/internal/engine/logs"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -24,7 +24,7 @@ scripts in a given directory. For more information, visit: https://gosally.oblat
func Execute() { func Execute() {
log.SetOutput(os.Stdout) log.SetOutput(os.Stdout)
log.SetPrefix(logs.SetBrightBlack(fmt.Sprintf("(%s) ", corestate.StageNotReady))) log.SetPrefix(colors.SetBrightBlack(fmt.Sprintf("(%s) ", corestate.StageNotReady)))
log.SetFlags(log.Ldate | log.Ltime) log.SetFlags(log.Ldate | log.Ltime)
hooks.Compositor.LoadCMDLine(rootCmd) hooks.Compositor.LoadCMDLine(rootCmd)
_ = rootCmd.Execute() _ = rootCmd.Execute()

3
go.mod
View File

@@ -4,6 +4,7 @@ go 1.24.4
require ( require (
github.com/go-chi/chi/v5 v5.2.2 github.com/go-chi/chi/v5 v5.2.2
github.com/google/uuid v1.6.0
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.20.1 github.com/spf13/viper v1.20.1
github.com/yuin/gopher-lua v1.1.1 github.com/yuin/gopher-lua v1.1.1
@@ -17,7 +18,6 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
@@ -29,7 +29,6 @@ require (
github.com/spf13/cast v1.9.2 // indirect github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/pflag v1.0.7 // indirect github.com/spf13/pflag v1.0.7 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect golang.org/x/text v0.27.0 // indirect

32
go.sum
View File

@@ -15,6 +15,8 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -36,12 +38,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
github.com/sagikazarmark/locafero v0.10.0 h1:FM8Cv6j2KqIhM2ZK7HZjm4mpj9NBktLgowT1aN9q5Cc= github.com/sagikazarmark/locafero v0.10.0 h1:FM8Cv6j2KqIhM2ZK7HZjm4mpj9NBktLgowT1aN9q5Cc=
github.com/sagikazarmark/locafero v0.10.0/go.mod h1:Ieo3EUsjifvQu4NZwV5sPd4dwvu0OCgEQV7vjc9yDjw= github.com/sagikazarmark/locafero v0.10.0/go.mod h1:Ieo3EUsjifvQu4NZwV5sPd4dwvu0OCgEQV7vjc9yDjw=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
@@ -61,17 +59,21 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4= golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4=
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -81,11 +83,29 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.26.3 h1:yEN8dzrkRFnn4PUUKXLYIqVf2PJYAEjMTFjO3BDGc3I=
modernc.org/cc/v4 v4.26.3/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM=
modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.6 h1:RyQpwAhM/19nXD8y3iejM/AjmKwY2TjxZTlUWTsWw2U= modernc.org/libc v1.66.6 h1:RyQpwAhM/19nXD8y3iejM/AjmKwY2TjxZTlUWTsWw2U=
modernc.org/libc v1.66.6/go.mod h1:j8z0EYAuumoMQ3+cWXtmw6m+LYn3qm8dcZDFtFTSq+M= modernc.org/libc v1.66.6/go.mod h1:j8z0EYAuumoMQ3+cWXtmw6m+LYn3qm8dcZDFtFTSq+M=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

View File

@@ -2,6 +2,7 @@ package hooks
import ( import (
"bufio" "bufio"
"context"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@@ -9,12 +10,14 @@ import (
"log" "log"
"log/slog" "log/slog"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"slices" "slices"
"strings" "strings"
"syscall" "syscall"
"time" "time"
"github.com/akyaiy/GoSally-mvp/internal/colors"
"github.com/akyaiy/GoSally-mvp/internal/core/corestate" "github.com/akyaiy/GoSally-mvp/internal/core/corestate"
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager" "github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
"github.com/akyaiy/GoSally-mvp/internal/core/utils" "github.com/akyaiy/GoSally-mvp/internal/core/utils"
@@ -26,15 +29,15 @@ import (
var Compositor *config.Compositor = config.NewCompositor() var Compositor *config.Compositor = config.NewCompositor()
func Init0Hook(cs *corestate.CoreState, x *app.AppX) { func Init0Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
x.Config = Compositor x.Config = Compositor
x.Log.SetOutput(os.Stdout) x.Log.SetOutput(os.Stdout)
x.Log.SetPrefix(logs.SetBrightBlack(fmt.Sprintf("(%s) ", cs.Stage))) x.Log.SetPrefix(colors.SetBrightBlack(fmt.Sprintf("(%s) ", cs.Stage)))
x.Log.SetFlags(log.Ldate | log.Ltime) x.Log.SetFlags(log.Ldate | log.Ltime)
} }
// First stage: pre-init // First stage: pre-init
func Init1Hook(cs *corestate.CoreState, x *app.AppX) { func Init1Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
*cs = *corestate.NewCorestate(&corestate.CoreState{ *cs = *corestate.NewCorestate(&corestate.CoreState{
UUID32DirName: "uuid", UUID32DirName: "uuid",
NodeBinName: filepath.Base(os.Args[0]), NodeBinName: filepath.Base(os.Args[0]),
@@ -45,8 +48,8 @@ func Init1Hook(cs *corestate.CoreState, x *app.AppX) {
}) })
} }
func Init2Hook(cs *corestate.CoreState, x *app.AppX) { func Init2Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
x.Log.SetPrefix(logs.SetYellow(fmt.Sprintf("(%s) ", cs.Stage))) x.Log.SetPrefix(colors.SetYellow(fmt.Sprintf("(%s) ", cs.Stage)))
if err := x.Config.LoadEnv(); err != nil { if err := x.Config.LoadEnv(); err != nil {
x.Log.Fatalf("env load error: %s", err) x.Log.Fatalf("env load error: %s", err)
@@ -61,7 +64,7 @@ func Init2Hook(cs *corestate.CoreState, x *app.AppX) {
} }
} }
func Init3Hook(cs *corestate.CoreState, x *app.AppX) { func Init3Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
uuid32, err := corestate.GetNodeUUID(filepath.Join(cs.MetaDir, "uuid")) uuid32, err := corestate.GetNodeUUID(filepath.Join(cs.MetaDir, "uuid"))
if errors.Is(err, fs.ErrNotExist) { if errors.Is(err, fs.ErrNotExist) {
if err := corestate.SetNodeUUID(filepath.Join(cs.NodePath, cs.MetaDir, cs.UUID32DirName)); err != nil { if err := corestate.SetNodeUUID(filepath.Join(cs.NodePath, cs.MetaDir, cs.UUID32DirName)); err != nil {
@@ -78,7 +81,7 @@ func Init3Hook(cs *corestate.CoreState, x *app.AppX) {
cs.UUID32 = uuid32 cs.UUID32 = uuid32
} }
func Init4Hook(cs *corestate.CoreState, x *app.AppX) { func Init4Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
if *x.Config.Env.ParentStagePID != os.Getpid() { if *x.Config.Env.ParentStagePID != os.Getpid() {
// still pre-init stage // still pre-init stage
runDir, err := run_manager.Create(cs.UUID32) runDir, err := run_manager.Create(cs.UUID32)
@@ -129,9 +132,18 @@ func Init4Hook(cs *corestate.CoreState, x *app.AppX) {
} }
// post-init stage // post-init stage
func Init5Hook(cs *corestate.CoreState, x *app.AppX) { func Init5Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
nodeApp.Fallback(func(ctx context.Context, cs *corestate.CoreState, x *app.AppX) {
x.Log.Println("Cleaning up...")
if err := run_manager.Clean(); err != nil {
x.Log.Printf("%s: Cleanup error: %s", colors.PrintError(), err.Error())
}
x.Log.Println("bye!")
})
cs.Stage = corestate.StagePostInit cs.Stage = corestate.StagePostInit
x.Log.SetPrefix(logs.SetBlue(fmt.Sprintf("(%s) ", cs.Stage))) x.Log.SetPrefix(colors.SetBlue(fmt.Sprintf("(%s) ", cs.Stage)))
cs.RunDir = run_manager.Toggle() cs.RunDir = run_manager.Toggle()
exist, err := utils.ExistsMatchingDirs(filepath.Join(os.TempDir(), fmt.Sprintf("/*-%s-%s", cs.UUID32, "gosally-runtime")), cs.RunDir) exist, err := utils.ExistsMatchingDirs(filepath.Join(os.TempDir(), fmt.Sprintf("/*-%s-%s", cs.UUID32, "gosally-runtime")), cs.RunDir)
@@ -172,9 +184,9 @@ func Init5Hook(cs *corestate.CoreState, x *app.AppX) {
} }
} }
func Init6Hook(cs *corestate.CoreState, x *app.AppX) { func Init6Hook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) {
if !slices.Contains(*x.Config.Conf.DisableWarnings, "--WNonStdTmpDir") && os.TempDir() != "/tmp" { if !slices.Contains(*x.Config.Conf.DisableWarnings, "--WNonStdTmpDir") && os.TempDir() != "/tmp" {
x.Log.Printf("%s: %s", logs.PrintWarn(), "Non-standard value specified for temporary directory") x.Log.Printf("%s: %s", colors.PrintWarn(), "Non-standard value specified for temporary directory")
} }
if strings.Contains(*x.Config.Conf.Log.OutPath, `%tmp%`) { if strings.Contains(*x.Config.Conf.Log.OutPath, `%tmp%`) {
replaced := strings.ReplaceAll(*x.Config.Conf.Log.OutPath, "%tmp%", filepath.Clean(run_manager.RuntimeDir())) replaced := strings.ReplaceAll(*x.Config.Conf.Log.OutPath, "%tmp%", filepath.Clean(run_manager.RuntimeDir()))
@@ -182,7 +194,7 @@ func Init6Hook(cs *corestate.CoreState, x *app.AppX) {
} }
if !slices.Contains(logs.Levels.Available, *x.Config.Conf.Log.Level) { if !slices.Contains(logs.Levels.Available, *x.Config.Conf.Log.Level) {
if !slices.Contains(*x.Config.Conf.DisableWarnings, "--WUndefLogLevel") { if !slices.Contains(*x.Config.Conf.DisableWarnings, "--WUndefLogLevel") {
x.Log.Printf("%s: %s", logs.PrintWarn(), fmt.Sprintf("Unknown logging level %s, fallback level: %s", *x.Config.Conf.Log.Level, logs.Levels.Fallback)) x.Log.Printf("%s: %s", colors.PrintWarn(), fmt.Sprintf("Unknown logging level %s, fallback level: %s", *x.Config.Conf.Log.Level, logs.Levels.Fallback))
} }
x.Config.Conf.Log.Level = &logs.Levels.Fallback x.Config.Conf.Log.Level = &logs.Levels.Fallback
} }
@@ -193,28 +205,19 @@ func Init6Hook(cs *corestate.CoreState, x *app.AppX) {
fmt.Printf("Environment:\n") fmt.Printf("Environment:\n")
x.Config.Print(x.Config.Env) x.Config.Print(x.Config.Env)
ok := true
fmt.Printf("%s (%s/%s): ", "Is that ok?", logs.SetBrightGreen("Y"), logs.SetBrightRed("n")) if !askConfirm("Is that ok?", true) {
x.Log.Printf("Cancel launch")
reader := bufio.NewReader(os.Stdin) nodeApp.CallFallback(ctx)
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(strings.ToLower(input))
ok = input == "" || input == "y" || input == "yes"
if !ok {
_ = run_manager.Clean()
x.Log.Fatalf("Cancel launch")
} }
} }
x.Log.Printf("Starting \"%s\" node", *x.Config.Conf.Node.Name) x.Log.Printf("Starting \"%s\" node", *x.Config.Conf.Node.Name)
} }
func Init7Hook(cs *corestate.CoreState, x *app.AppX) { func Init7Hook(_ context.Context, cs *corestate.CoreState, x *app.AppX) {
cs.Stage = corestate.StageReady cs.Stage = corestate.StageReady
x.Log.SetPrefix(logs.SetGreen(fmt.Sprintf("(%s) ", cs.Stage))) x.Log.SetPrefix(colors.SetGreen(fmt.Sprintf("(%s) ", cs.Stage)))
x.SLog = new(slog.Logger) x.SLog = new(slog.Logger)
newSlog, err := logs.SetupLogger(x.Config.Conf.Log) newSlog, err := logs.SetupLogger(x.Config.Conf.Log)
@@ -225,26 +228,38 @@ func Init7Hook(cs *corestate.CoreState, x *app.AppX) {
*x.SLog = *newSlog *x.SLog = *newSlog
} }
// repl := map[string]string{ func askConfirm(prompt string, defaultYes bool) bool {
// "tmp": filepath.Clean(run_manager.RuntimeDir()), ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
// }
// re := regexp.MustCompile(`%(\w+)%`)
// result := re.ReplaceAllStringFunc(x.Config.Conf.Log.OutPath, func(match string) string {
// sub := re.FindStringSubmatch(match)
// if len(sub) < 2 {
// return match
// }
// key := sub[1]
// if val, ok := repl[key]; ok {
// return val
// }
// return match
// })
// if strings.Contains(x.Config.Conf.Log.OutPath, "%tmp%") { fmt.Print(prompt)
// relPath := strings.TrimPrefix(result, filepath.Clean(run_manager.RuntimeDir())) if defaultYes {
// if err := run_manager.SetDir(relPath); err != nil { fmt.Printf(" (%s/%s): ", colors.SetBrightGreen("Y"), colors.SetBrightRed("n"))
// _ = run_manager.Clean() } else {
// x.Log.Fatalf("Unexpected failure: %s", err.Error()) fmt.Printf(" (%s/%s): ", colors.SetBrightGreen("n"), colors.SetBrightRed("Y"))
// } }
// }
inputChan := make(chan string, 1)
go func() {
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
inputChan <- text
}()
select {
case <-ctx.Done():
fmt.Println("")
nodeApp.CallFallback(ctx)
os.Exit(3)
case text := <-inputChan:
text = strings.TrimSpace(strings.ToLower(text))
if text == "" {
return defaultYes
}
if text == "y" || text == "yes" {
return true
}
return false
}
return defaultYes
}

View File

@@ -11,6 +11,7 @@ import (
"regexp" "regexp"
"time" "time"
"github.com/akyaiy/GoSally-mvp/internal/colors"
"github.com/akyaiy/GoSally-mvp/internal/core/corestate" "github.com/akyaiy/GoSally-mvp/internal/core/corestate"
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager" "github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
"github.com/akyaiy/GoSally-mvp/internal/core/update" "github.com/akyaiy/GoSally-mvp/internal/core/update"
@@ -97,7 +98,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
nodeApp.Fallback(func(ctx context.Context, cs *corestate.CoreState, x *app.AppX) { nodeApp.Fallback(func(ctx context.Context, cs *corestate.CoreState, x *app.AppX) {
if err := srv.Shutdown(ctxMain); err != nil { if err := srv.Shutdown(ctxMain); err != nil {
x.Log.Printf("%s: Failed to stop the server gracefully: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to stop the server gracefully: %s", colors.PrintError(), err.Error())
} else { } else {
x.Log.Printf("Server stopped gracefully") x.Log.Printf("Server stopped gracefully")
} }
@@ -105,7 +106,7 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
x.Log.Println("Cleaning up...") x.Log.Println("Cleaning up...")
if err := run_manager.Clean(); err != nil { if err := run_manager.Clean(); err != nil {
x.Log.Printf("%s: Cleanup error: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Cleanup error: %s", colors.PrintError(), err.Error())
} }
x.Log.Println("bye!") x.Log.Println("bye!")
}) })
@@ -115,27 +116,27 @@ func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
if *x.Config.Conf.TLS.TlsEnabled { if *x.Config.Conf.TLS.TlsEnabled {
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port)) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
if err != nil { if err != nil {
x.Log.Printf("%s: Failed to start TLS listener: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start TLS listener: %s", colors.PrintError(), err.Error())
cancelMain() cancelMain()
return return
} }
x.Log.Printf("Serving on %s port %s with TLS... (https://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute) x.Log.Printf("Serving on %s port %s with TLS... (https://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
limitedListener := netutil.LimitListener(listener, 100) limitedListener := netutil.LimitListener(listener, 100)
if err := srv.ServeTLS(limitedListener, *x.Config.Conf.TLS.CertFile, *x.Config.Conf.TLS.KeyFile); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := srv.ServeTLS(limitedListener, *x.Config.Conf.TLS.CertFile, *x.Config.Conf.TLS.KeyFile); err != nil && !errors.Is(err, http.ErrServerClosed) {
x.Log.Printf("%s: Failed to start HTTPS server: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start HTTPS server: %s", colors.PrintError(), err.Error())
cancelMain() cancelMain()
} }
} else { } else {
x.Log.Printf("Serving on %s port %s... (http://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute) x.Log.Printf("Serving on %s port %s... (http://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port)) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
if err != nil { if err != nil {
x.Log.Printf("%s: Failed to start listener: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start listener: %s", colors.PrintError(), err.Error())
cancelMain() cancelMain()
return return
} }
limitedListener := netutil.LimitListener(listener, 100) limitedListener := netutil.LimitListener(listener, 100)
if err := srv.Serve(limitedListener); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := srv.Serve(limitedListener); err != nil && !errors.Is(err, http.ErrServerClosed) {
x.Log.Printf("%s: Failed to start HTTP server: %s", logs.PrintError(), err.Error()) x.Log.Printf("%s: Failed to start HTTP server: %s", colors.PrintError(), err.Error())
cancelMain() cancelMain()
} }
} }

View File

@@ -1,4 +1,4 @@
package logs package colors
import "fmt" import "fmt"

View File

@@ -14,7 +14,7 @@ import (
) )
type AppContract interface { type AppContract interface {
InitialHooks(fn ...func(cs *corestate.CoreState, x *AppX)) InitialHooks(fn ...func(ctx context.Context, cs *corestate.CoreState, x *AppX))
Run(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX) error) Run(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX) error)
Fallback(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX)) Fallback(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX))
@@ -22,7 +22,7 @@ type AppContract interface {
} }
type App struct { type App struct {
initHooks []func(cs *corestate.CoreState, x *AppX) initHooks []func(ctx context.Context, cs *corestate.CoreState, x *AppX)
runHook func(ctx context.Context, cs *corestate.CoreState, x *AppX) error runHook func(ctx context.Context, cs *corestate.CoreState, x *AppX) error
fallback func(ctx context.Context, cs *corestate.CoreState, x *AppX) fallback func(ctx context.Context, cs *corestate.CoreState, x *AppX)
@@ -47,7 +47,7 @@ func New() AppContract {
} }
} }
func (a *App) InitialHooks(fn ...func(cs *corestate.CoreState, x *AppX)) { func (a *App) InitialHooks(fn ...func(ctx context.Context, cs *corestate.CoreState, x *AppX)) {
a.initHooks = append(a.initHooks, fn...) a.initHooks = append(a.initHooks, fn...)
} }
@@ -58,13 +58,13 @@ func (a *App) Fallback(fn func(ctx context.Context, cs *corestate.CoreState, x *
func (a *App) Run(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX) error) { func (a *App) Run(fn func(ctx context.Context, cs *corestate.CoreState, x *AppX) error) {
a.runHook = fn a.runHook = fn
for _, hook := range a.initHooks {
hook(a.Corestate, a.AppX)
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
defer stop() defer stop()
for _, hook := range a.initHooks {
hook(ctx, a.Corestate, a.AppX)
}
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
a.AppX.Log.Printf("PANIC recovered: %v", r) a.AppX.Log.Printf("PANIC recovered: %v", r)
@@ -90,5 +90,6 @@ func (a *App) CallFallback(ctx context.Context) {
if a.fallback != nil { if a.fallback != nil {
a.fallback(ctx, a.Corestate, a.AppX) a.fallback(ctx, a.Corestate, a.AppX)
} }
os.Exit(3)
}) })
} }

View File

@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"time" "time"
"github.com/akyaiy/GoSally-mvp/internal/colors"
) )
func (c *Compositor) Print(v any) { func (c *Compositor) Print(v any) {
@@ -29,9 +31,11 @@ func (c *Compositor) printConfig(v any, prefix string) {
} }
} }
coloredFieldName := colors.SetBrightCyan(fieldName)
if field.Kind() == reflect.Ptr { if field.Kind() == reflect.Ptr {
if field.IsNil() { if field.IsNil() {
fmt.Printf("%s%s: <nil>\n", prefix, fieldName) fmt.Printf("%s%s: %s\n", prefix, coloredFieldName, colors.SetBrightRed("<nil>"))
continue continue
} }
field = field.Elem() field = field.Elem()
@@ -40,19 +44,29 @@ func (c *Compositor) printConfig(v any, prefix string) {
if field.Kind() == reflect.Struct { if field.Kind() == reflect.Struct {
if field.Type() == reflect.TypeOf(time.Duration(0)) { if field.Type() == reflect.TypeOf(time.Duration(0)) {
duration := field.Interface().(time.Duration) duration := field.Interface().(time.Duration)
fmt.Printf("%s%s: %s\n", prefix, fieldName, duration.String()) fmt.Printf("%s%s: %s\n",
prefix,
coloredFieldName,
colors.SetBrightYellow(duration.String()))
} else { } else {
fmt.Printf("%s%s:\n", prefix, fieldName) fmt.Printf("%s%s:\n", prefix, coloredFieldName)
c.printConfig(field.Addr().Interface(), prefix+" ") c.printConfig(field.Addr().Interface(), prefix+" ")
} }
} else if field.Kind() == reflect.Slice { } else if field.Kind() == reflect.Slice {
fmt.Printf("%s%s: %v\n", prefix, fieldName, field.Interface()) fmt.Printf("%s%s: %s\n",
prefix,
coloredFieldName,
colors.SetBrightYellow(fmt.Sprintf("%v", field.Interface())))
} else { } else {
value := field.Interface() value := field.Interface()
valueStr := fmt.Sprintf("%v", value)
if field.Kind() == reflect.String { if field.Kind() == reflect.String {
value = fmt.Sprintf("\"%s\"", value) valueStr = fmt.Sprintf("\"%s\"", value)
} }
fmt.Printf("%s%s: %v\n", prefix, fieldName, value) fmt.Printf("%s%s: %s\n",
prefix,
coloredFieldName,
colors.SetBrightYellow(valueStr))
} }
} }
} }

View File

@@ -10,7 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/akyaiy/GoSally-mvp/internal/engine/logs" "github.com/akyaiy/GoSally-mvp/internal/colors"
"github.com/akyaiy/GoSally-mvp/internal/server/rpc" "github.com/akyaiy/GoSally-mvp/internal/server/rpc"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
@@ -78,13 +78,13 @@ func (h *HandlerV1) handleLUA(sid string, r *http.Request, req *rpc.RPCRequest,
L.SetField(logTable, "EventError", L.NewFunction(func(L *lua.LState) int { L.SetField(logTable, "EventError", L.NewFunction(func(L *lua.LState) int {
msg := L.ToString(1) msg := L.ToString(1)
h.x.Log.Printf("%s: %s: %s", logs.PrintError(), path, msg) h.x.Log.Printf("%s: %s: %s", colors.PrintError(), path, msg)
return 0 return 0
})) }))
L.SetField(logTable, "EventWarn", L.NewFunction(func(L *lua.LState) int { L.SetField(logTable, "EventWarn", L.NewFunction(func(L *lua.LState) int {
msg := L.ToString(1) msg := L.ToString(1)
h.x.Log.Printf("%s: %s: %s", logs.PrintWarn(), path, msg) h.x.Log.Printf("%s: %s: %s", colors.PrintWarn(), path, msg)
return 0 return 0
})) }))