diff --git a/src/app/command/bootstrap.go b/src/app/command/bootstrap.go index 8f82d87..d439b41 100644 --- a/src/app/command/bootstrap.go +++ b/src/app/command/bootstrap.go @@ -2,13 +2,19 @@ package command import ( "fmt" + "log/slog" "os" "path/filepath" + "strings" "github.com/cubiest/jibberjabber" + "github.com/natefinch/lumberjack" "github.com/samber/lo" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.uber.org/zap" + "go.uber.org/zap/exp/zapslog" + "go.uber.org/zap/zapcore" "golang.org/x/text/language" "github.com/snivilised/cobrass/src/assistant" @@ -21,26 +27,6 @@ import ( "github.com/snivilised/pixa/src/i18n" ) -func ResolvePath(path string) string { - if path == "" { - return path - } - - result := path - - if result[0] == '~' { - if h, err := os.UserHomeDir(); err == nil { - result = filepath.Join(h, result[1:]) - } - } else { - if absolute, absErr := filepath.Abs(path); absErr == nil { - result = absolute - } - } - - return result -} - type LocaleDetector interface { Scan() language.Tag } @@ -63,7 +49,7 @@ func validatePositionalArgs(cmd *cobra.Command, args []string) error { return err } - directory := ResolvePath(args[0]) + directory := utils.ResolvePath(args[0]) if !utils.Exists(directory) { return xi18n.NewPathNotFoundError("shrink directory", directory) @@ -98,7 +84,6 @@ type ConfigureOptionsInfo struct { Detector LocaleDetector Program proxy.Executor Config ConfigInfo - Viper configuration.ViperConfig } type ConfigureOptionFn func(*ConfigureOptionsInfo) @@ -159,7 +144,7 @@ func (b *Bootstrap) Root(options ...ConfigureOptionFn) *cobra.Command { fmt.Printf(" ===> 🌷🌷🌷 Root Command...\n") inputs := b.getRootInputs() - inputs.ParamSet.Native.Directory = ResolvePath(args[0]) + inputs.ParamSet.Native.Directory = utils.ResolvePath(args[0]) if inputs.WorkerPoolFam.Native.CPU { inputs.WorkerPoolFam.Native.NoWorkers = 0 @@ -261,6 +246,65 @@ func (b *Bootstrap) viper() { b.ProfilesCFG, _ = b.OptionsInfo.Config.Readers.Profiles.Read(b.OptionsInfo.Config.Viper) b.SchemesCFG, _ = b.OptionsInfo.Config.Readers.Schemes.Read(b.OptionsInfo.Config.Viper) b.SamplerCFG, _ = b.OptionsInfo.Config.Readers.Sampler.Read(b.OptionsInfo.Config.Viper) - b.AdvancedCFG, _ = b.OptionsInfo.Config.Readers.Advanced.Read(b.OptionsInfo.Viper) - b.LoggingCFG, _ = b.OptionsInfo.Config.Readers.Logging.Read(b.OptionsInfo.Viper) + b.AdvancedCFG, _ = b.OptionsInfo.Config.Readers.Advanced.Read(b.OptionsInfo.Config.Viper) + b.LoggingCFG, _ = b.OptionsInfo.Config.Readers.Logging.Read(b.OptionsInfo.Config.Viper) +} + +func (b *Bootstrap) ensure(p string) string { + var ( + directory, file string + ) + + if strings.HasSuffix(p, string(os.PathSeparator)) { + directory = p + file = "pixa.log" + } else { + directory, file = filepath.Split(p) + } + + if !b.Vfs.DirectoryExists(directory) { + const perm = 0o766 + _ = b.Vfs.MkdirAll(directory, os.FileMode(perm)) + } + + return filepath.Clean(filepath.Join(directory, file)) +} + +func (b *Bootstrap) level(raw string) zapcore.LevelEnabler { + if l, err := zapcore.ParseLevel(raw); err == nil { + return l + } + + return zapcore.InfoLevel +} + +func (b *Bootstrap) logger() *slog.Logger { + noc := slog.New(zapslog.NewHandler( + zapcore.NewNopCore(), nil), + ) + + logPath := b.LoggingCFG.Path() + + if logPath == "" { + return noc + } + + logPath = utils.ResolvePath(logPath) + logPath = b.ensure(logPath) + + ws := zapcore.AddSync(&lumberjack.Logger{ + Filename: logPath, + MaxSize: int(b.LoggingCFG.MaxSizeInMb()), + MaxBackups: int(b.LoggingCFG.MaxNoOfBackups()), + MaxAge: int(b.LoggingCFG.MaxAgeInDays()), + }) + config := zap.NewProductionEncoderConfig() + config.EncodeTime = zapcore.TimeEncoderOfLayout(b.LoggingCFG.TimeFormat()) + core := zapcore.NewCore( + zapcore.NewJSONEncoder(config), + ws, + b.level(b.LoggingCFG.Level()), + ) + + return slog.New(zapslog.NewHandler(core, nil)) } diff --git a/src/app/command/bootstrap_test.go b/src/app/command/bootstrap_test.go index f6e073c..7350864 100644 --- a/src/app/command/bootstrap_test.go +++ b/src/app/command/bootstrap_test.go @@ -97,7 +97,7 @@ var _ = Describe("Bootstrap", Ordered, func() { } co.Config.Name = helpers.PixaConfigTestFilename co.Config.ConfigPath = configPath - co.Viper = &configuration.GlobalViperConfig{} + co.Config.Viper = &configuration.GlobalViperConfig{} co.Config.Readers = command.ConfigReaders{ Profiles: mockProfilesReader, Schemes: mockSchemesReader, diff --git a/src/app/command/magick-cmd_test.go b/src/app/command/magick-cmd_test.go index abf9936..f5706f4 100644 --- a/src/app/command/magick-cmd_test.go +++ b/src/app/command/magick-cmd_test.go @@ -74,7 +74,7 @@ var _ = Describe("MagickCmd", Ordered, func() { } co.Config.Name = helpers.PixaConfigTestFilename co.Config.ConfigPath = configPath - co.Viper = &configuration.GlobalViperConfig{} + co.Config.Viper = &configuration.GlobalViperConfig{} co.Config.Readers = command.ConfigReaders{ Profiles: mockProfilesReader, Schemes: mockSchemesReader, diff --git a/src/app/command/root-cmd.go b/src/app/command/root-cmd.go index 4102b3c..15ef37d 100644 --- a/src/app/command/root-cmd.go +++ b/src/app/command/root-cmd.go @@ -7,6 +7,7 @@ import ( "github.com/snivilised/cobrass/src/assistant" "github.com/snivilised/cobrass/src/store" xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/xfs/storage" "github.com/snivilised/pixa/src/app/proxy" "github.com/snivilised/pixa/src/i18n" ) @@ -24,7 +25,9 @@ const ( ) func Execute() error { - return (&Bootstrap{}).Root().Execute() + return (&Bootstrap{ + Vfs: storage.UseNativeFS(), + }).Root().Execute() } func (b *Bootstrap) buildRootCommand(container *assistant.CobraContainer) { diff --git a/src/app/command/shrink-cmd.go b/src/app/command/shrink-cmd.go index fa3bdf2..772ef24 100644 --- a/src/app/command/shrink-cmd.go +++ b/src/app/command/shrink-cmd.go @@ -2,19 +2,13 @@ package command import ( "fmt" - "log/slog" "maps" "strings" - "github.com/natefinch/lumberjack" - "github.com/pkg/errors" "github.com/snivilised/cobrass" "github.com/snivilised/cobrass/src/assistant" "github.com/snivilised/cobrass/src/store" xi18n "github.com/snivilised/extendio/i18n" - "go.uber.org/zap" - "go.uber.org/zap/exp/zapslog" - "go.uber.org/zap/zapcore" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -138,7 +132,6 @@ func (b *Bootstrap) buildShrinkCommand(container *assistant.CobraContainer) *cob } } - logger, _ := b.createLogger() appErr = proxy.EnterShrink( &proxy.ShrinkParams{ Inputs: inputs, @@ -148,7 +141,7 @@ func (b *Bootstrap) buildShrinkCommand(container *assistant.CobraContainer) *cob SchemesCFG: b.SchemesCFG, SamplerCFG: b.SamplerCFG, AdvancedCFG: b.AdvancedCFG, - Logger: logger, + Logger: b.logger(), Vfs: b.Vfs, }, ) @@ -381,39 +374,3 @@ func (b *Bootstrap) getShrinkInputs() *proxy.ShrinkCommandInputs { ).(*assistant.ParamSet[store.FilesFilterParameterSet]), } } - -func (b *Bootstrap) level(raw string) zapcore.LevelEnabler { - if l, err := zapcore.ParseLevel(raw); err == nil { - return l - } - - return zapcore.InfoLevel -} - -func (b *Bootstrap) createLogger() (*slog.Logger, error) { - path := b.LoggingCFG.Path() - - if path == "" { - noc := slog.New(zapslog.NewHandler( - zapcore.NewNopCore(), nil), - ) - - return noc, errors.New("logging path not defined") - } - - ws := zapcore.AddSync(&lumberjack.Logger{ - Filename: path, - MaxSize: int(b.LoggingCFG.MaxSizeInMb()), - MaxBackups: int(b.LoggingCFG.MaxNoOfBackups()), - MaxAge: int(b.LoggingCFG.MaxAgeInDays()), - }) - config := zap.NewProductionEncoderConfig() - config.EncodeTime = zapcore.TimeEncoderOfLayout(b.LoggingCFG.TimeFormat()) - core := zapcore.NewCore( - zapcore.NewJSONEncoder(config), - ws, - b.level(b.LoggingCFG.Level()), - ) - - return slog.New(zapslog.NewHandler(core, nil)), nil -} diff --git a/src/app/command/shrink-cmd_test.go b/src/app/command/shrink-cmd_test.go index 8113be6..535b0c0 100644 --- a/src/app/command/shrink-cmd_test.go +++ b/src/app/command/shrink-cmd_test.go @@ -95,7 +95,7 @@ func expectValidShrinkCmdInvocation(vfs storage.VirtualFS, entry *shrinkTE, root co.Config.Name = helpers.PixaConfigTestFilename co.Config.ConfigPath = entry.configPath - co.Viper = &configuration.GlobalViperConfig{} + co.Config.Viper = &configuration.GlobalViperConfig{} co.Config.Readers = command.ConfigReaders{ Profiles: mockProfilesReader, Schemes: mockSchemesReader, diff --git a/src/app/proxy/config_test.go b/src/app/proxy/config_test.go index f5cbe1f..bc2513a 100644 --- a/src/app/proxy/config_test.go +++ b/src/app/proxy/config_test.go @@ -60,7 +60,7 @@ func expectValidShrinkCmdInvocation(vfs storage.VirtualFS, entry *configTE, } co.Config.Name = helpers.PixaConfigTestFilename co.Config.ConfigPath = configPath - co.Viper = &configuration.GlobalViperConfig{} + co.Config.Viper = &configuration.GlobalViperConfig{} co.Config.Readers = command.ConfigReaders{ Profiles: mockProfilesReader, Schemes: mockSchemesReader, diff --git a/src/app/proxy/controller-sampler_test.go b/src/app/proxy/controller-sampler_test.go index aa0f2da..138bb32 100644 --- a/src/app/proxy/controller-sampler_test.go +++ b/src/app/proxy/controller-sampler_test.go @@ -121,7 +121,7 @@ var _ = Describe("SamplerController", Ordered, func() { } co.Config.Name = helpers.PixaConfigTestFilename co.Config.ConfigPath = configPath - co.Viper = &configuration.GlobalViperConfig{} + co.Config.Viper = &configuration.GlobalViperConfig{} co.Config.Readers = command.ConfigReaders{ Profiles: mockProfilesReader, Schemes: mockSchemesReader, diff --git a/src/app/proxy/file-manager.go b/src/app/proxy/file-manager.go index 09f06dc..8960399 100644 --- a/src/app/proxy/file-manager.go +++ b/src/app/proxy/file-manager.go @@ -11,6 +11,7 @@ import ( const ( beezledub = os.FileMode(0o666) + perm = os.FileMode(0o766) errorDestination = "" ) @@ -53,7 +54,7 @@ func (fm *FileManager) Setup(pi *pathInfo) (destination string, err error) { // we don't want to rename/move the source... // if folder, file := fm.Finder.Destination(pi); folder != "" { - if err = fm.vfs.MkdirAll(folder, beezledub); err != nil { + if err = fm.vfs.MkdirAll(folder, perm); err != nil { return errorDestination, errors.Wrapf( err, "could not create parent setup for '%v'", pi.item.Path, )