From b7d1e1eed0b5ffdc40a6162e1a8df3c26b428420 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Wed, 15 Jan 2025 00:41:31 +0200 Subject: [PATCH] refactor: platform --- appconfig/appconfig.go | 81 ++++++++----------------------------- appconfig/appconfig_test.go | 14 +++---- installer/installer.go | 22 ++-------- installer/installer_test.go | 16 +++++--- logger/logger.go | 10 ++--- main.go | 3 ++ platform/platform.go | 74 +++++++++++++++++++++++++++++++++ utils/command.go | 43 ++++++++++---------- utils/{os.go => fs.go} | 0 9 files changed, 139 insertions(+), 124 deletions(-) create mode 100644 platform/platform.go rename utils/{os.go => fs.go} (100%) diff --git a/appconfig/appconfig.go b/appconfig/appconfig.go index c3aa49b..c3e3fee 100644 --- a/appconfig/appconfig.go +++ b/appconfig/appconfig.go @@ -6,10 +6,10 @@ import ( "io/fs" "os" "path/filepath" - "runtime" "strings" "github.com/chenasraf/sofmani/logger" + "github.com/chenasraf/sofmani/platform" "github.com/eschao/config" ) @@ -34,20 +34,20 @@ type AppConfigDefaults struct { } type Installer struct { - Name *string `json:"name" yaml:"name"` - Type InstallerType `json:"type" yaml:"type"` - Env *map[string]string `json:"env" yaml:"env"` - Platforms *Platforms `json:"platforms" yaml:"platforms"` - Steps *[]Installer `json:"steps" yaml:"steps"` - Opts *map[string]any `json:"opts" yaml:"opts"` - BinName *string `json:"bin_name" yaml:"bin_name"` - CheckHasUpdate *string `json:"check_has_update" yaml:"check_has_update"` - CheckInstalled *string `json:"check_installed" yaml:"check_installed"` - PostInstall *string `json:"post_install" yaml:"post_install"` - PreInstall *string `json:"pre_install" yaml:"pre_install"` - PostUpdate *string `json:"post_update" yaml:"post_update"` - PreUpdate *string `json:"pre_update" yaml:"pre_update"` - EnvShell *PlatformMap[string] `json:"env_shell" yaml:"env_shell"` + Name *string `json:"name" yaml:"name"` + Type InstallerType `json:"type" yaml:"type"` + Env *map[string]string `json:"env" yaml:"env"` + Platforms *platform.Platforms `json:"platforms" yaml:"platforms"` + Steps *[]Installer `json:"steps" yaml:"steps"` + Opts *map[string]any `json:"opts" yaml:"opts"` + BinName *string `json:"bin_name" yaml:"bin_name"` + CheckHasUpdate *string `json:"check_has_update" yaml:"check_has_update"` + CheckInstalled *string `json:"check_installed" yaml:"check_installed"` + PostInstall *string `json:"post_install" yaml:"post_install"` + PreInstall *string `json:"pre_install" yaml:"pre_install"` + PostUpdate *string `json:"post_update" yaml:"post_update"` + PreUpdate *string `json:"pre_update" yaml:"pre_update"` + EnvShell *platform.PlatformMap[string] `json:"env_shell" yaml:"env_shell"` } type InstallerType string @@ -65,55 +65,6 @@ const ( InstallerTypeManifest InstallerType = "manifest" ) -type Platforms struct { - Only *[]Platform `json:"only" yaml:"only"` - Except *[]Platform `json:"except" yaml:"except"` -} - -type Platform string - -const ( - PlatformMacos Platform = "macos" - PlatformLinux Platform = "linux" - PlatformWindows Platform = "windows" -) - -type PlatformMap[T any] struct { - MacOS *T `json:"macos" yaml:"macos"` - Linux *T `json:"linux" yaml:"linux"` - Windows *T `json:"windows" yaml:"windows"` -} - -func (p *PlatformMap[T]) Resolve() *T { - switch runtime.GOOS { - case "darwin": - if p.MacOS != nil { - return p.MacOS - } - return nil - case "linux": - if p.Linux != nil { - return p.Linux - } - return nil - case "windows": - if p.Windows != nil { - return p.Windows - } - return nil - default: - return nil - } -} - -func (o *PlatformMap[T]) ResolveWithFallback(fallback PlatformMap[T]) T { - val := o.Resolve() - if val == nil { - return *fallback.Resolve() - } - return *val -} - func (c *AppConfig) Environ() []string { if c.Env == nil { return []string{} @@ -136,7 +87,7 @@ func (i *Installer) Environ() []string { return out } -func ContainsPlatform(platforms *[]Platform, platform Platform) bool { +func ContainsPlatform(platforms *[]platform.Platform, platform platform.Platform) bool { for _, p := range *platforms { if p == platform { return true diff --git a/appconfig/appconfig_test.go b/appconfig/appconfig_test.go index 7b0ed03..8f4ced4 100644 --- a/appconfig/appconfig_test.go +++ b/appconfig/appconfig_test.go @@ -3,10 +3,10 @@ package appconfig import ( "os" "path/filepath" - "runtime" "strings" "testing" + "github.com/chenasraf/sofmani/platform" "github.com/stretchr/testify/assert" ) @@ -23,10 +23,8 @@ func TestPlatformMapResolve(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if runtime.GOOS != tt.platform { - t.Skipf("Skipping test on %s", runtime.GOOS) - } - pm := PlatformMap[string]{ + platform.SetOS(tt.platform) + pm := platform.PlatformMap[string]{ MacOS: strPtr("macos"), Linux: strPtr("linux"), Windows: strPtr("windows"), @@ -51,9 +49,9 @@ func TestInstallerEnviron(t *testing.T) { } func TestContainsPlatform(t *testing.T) { - platforms := []Platform{PlatformMacos, PlatformLinux} - assert.True(t, ContainsPlatform(&platforms, PlatformMacos)) - assert.False(t, ContainsPlatform(&platforms, PlatformWindows)) + platforms := []platform.Platform{platform.PlatformMacos, platform.PlatformLinux} + assert.True(t, ContainsPlatform(&platforms, platform.PlatformMacos)) + assert.False(t, ContainsPlatform(&platforms, platform.PlatformWindows)) } func TestParseConfig(t *testing.T) { diff --git a/installer/installer.go b/installer/installer.go index 937a35a..5ee7379 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -1,11 +1,9 @@ package installer import ( - "fmt" - "runtime" - "github.com/chenasraf/sofmani/appconfig" "github.com/chenasraf/sofmani/logger" + "github.com/chenasraf/sofmani/platform" "github.com/chenasraf/sofmani/utils" ) @@ -84,23 +82,11 @@ func InstallerWithDefaults( return installer } -func GetCurrentPlatform() appconfig.Platform { - switch runtime.GOOS { - case "darwin": - return appconfig.PlatformMacos - case "linux": - return appconfig.PlatformLinux - case "windows": - return appconfig.PlatformWindows - } - panic(fmt.Sprintf("Unsupported platform %s", runtime.GOOS)) -} - func RunInstaller(config *appconfig.AppConfig, installer IInstaller) error { info := installer.GetInfo() name := *info.Name - logger.Debug("Checking if %s (%s) should run on %s", name, info.Type, GetCurrentPlatform()) - curOS := GetCurrentPlatform() + curOS := platform.GetPlatform() + logger.Debug("Checking if %s (%s) should run on %s", name, info.Type, curOS) env := config.Environ() if !GetShouldRunOnOS(installer, curOS) { logger.Debug("%s should not run on %s, skipping", name, curOS) @@ -170,7 +156,7 @@ func RunInstaller(config *appconfig.AppConfig, installer IInstaller) error { return nil } -func GetShouldRunOnOS(installer IInstaller, curOS appconfig.Platform) bool { +func GetShouldRunOnOS(installer IInstaller, curOS platform.Platform) bool { platforms := installer.GetInfo().Platforms if platforms == nil { return true diff --git a/installer/installer_test.go b/installer/installer_test.go index c58ab6a..c35017c 100644 --- a/installer/installer_test.go +++ b/installer/installer_test.go @@ -1,10 +1,12 @@ package installer import ( + "runtime" "testing" "github.com/chenasraf/sofmani/appconfig" "github.com/chenasraf/sofmani/logger" + "github.com/chenasraf/sofmani/platform" "github.com/stretchr/testify/assert" ) @@ -40,6 +42,7 @@ func (m *MockInstaller) Update() error { func TestGetInstaller(t *testing.T) { config := &appconfig.AppConfig{} + platform.SetOS(runtime.GOOS) logger.InitLogger(config.Debug) installer := &appconfig.Installer{Type: appconfig.InstallerTypeBrew} err, inst := GetInstaller(config, installer) @@ -60,8 +63,9 @@ func TestInstallerWithDefaults(t *testing.T) { } func TestGetCurrentPlatform(t *testing.T) { - platform := GetCurrentPlatform() - assert.Contains(t, []appconfig.Platform{appconfig.PlatformMacos, appconfig.PlatformLinux, appconfig.PlatformWindows}, platform) + platform.SetOS(runtime.GOOS) + pl := platform.GetPlatform() + assert.Contains(t, []platform.Platform{platform.PlatformMacos, platform.PlatformLinux, platform.PlatformWindows}, pl) } func TestRunInstaller(t *testing.T) { @@ -77,13 +81,13 @@ func TestRunInstaller(t *testing.T) { func TestGetShouldRunOnOS(t *testing.T) { installer := &MockInstaller{ info: &appconfig.Installer{ - Platforms: &appconfig.Platforms{ - Only: &[]appconfig.Platform{appconfig.PlatformMacos}, + Platforms: &platform.Platforms{ + Only: &[]platform.Platform{platform.PlatformMacos}, }, }, } - assert.True(t, GetShouldRunOnOS(installer, appconfig.PlatformMacos)) - assert.False(t, GetShouldRunOnOS(installer, appconfig.PlatformLinux)) + assert.True(t, GetShouldRunOnOS(installer, platform.PlatformMacos)) + assert.False(t, GetShouldRunOnOS(installer, platform.PlatformLinux)) } func strPtr(s string) *string { diff --git a/logger/logger.go b/logger/logger.go index 23874d6..63cf7e0 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -5,8 +5,8 @@ import ( "log" "os" "path/filepath" - "runtime" + "github.com/chenasraf/sofmani/platform" "github.com/davecgh/go-spew/spew" "github.com/fatih/color" ) @@ -22,17 +22,17 @@ var logger *Logger func GetLogDir() string { var logDir string - switch runtime.GOOS { - case "linux": + switch platform.GetPlatform() { + case platform.PlatformLinux: logDir = filepath.Join("var", "log", "sofmani") - case "darwin": + case platform.PlatformMacos: home, err := os.UserHomeDir() if err != nil { fmt.Printf("Could not get user home directory: %v\n", err) panic(err) } logDir = filepath.Join(home, "Library", "Logs", "sofmani") - case "windows": + case platform.PlatformWindows: appData := os.Getenv("APPDATA") logDir = filepath.Join(appData, "sofmani", "Logs") } diff --git a/main.go b/main.go index c8c5335..25ced91 100644 --- a/main.go +++ b/main.go @@ -4,17 +4,20 @@ import ( _ "embed" "fmt" "os" + "runtime" "strings" "github.com/chenasraf/sofmani/appconfig" "github.com/chenasraf/sofmani/installer" "github.com/chenasraf/sofmani/logger" + "github.com/chenasraf/sofmani/platform" ) //go:embed version.txt var appVersion []byte func main() { + platform.SetOS(runtime.GOOS) appconfig.SetVersion(strings.TrimSpace(string(appVersion))) cfg, err := LoadConfig() if err != nil { diff --git a/platform/platform.go b/platform/platform.go new file mode 100644 index 0000000..6213613 --- /dev/null +++ b/platform/platform.go @@ -0,0 +1,74 @@ +package platform + +import "fmt" + +var osValue string + +func getOS() string { + return osValue +} + +func SetOS(v string) { + osValue = v +} + +func GetPlatform() Platform { + switch getOS() { + case "darwin": + return PlatformMacos + case "linux": + return PlatformLinux + case "windows": + return PlatformWindows + } + panic(fmt.Sprintf("Unsupported platform %s", getOS())) +} + +type Platforms struct { + Only *[]Platform `json:"only" yaml:"only"` + Except *[]Platform `json:"except" yaml:"except"` +} + +type Platform string + +const ( + PlatformMacos Platform = "macos" + PlatformLinux Platform = "linux" + PlatformWindows Platform = "windows" +) + +type PlatformMap[T any] struct { + MacOS *T `json:"macos" yaml:"macos"` + Linux *T `json:"linux" yaml:"linux"` + Windows *T `json:"windows" yaml:"windows"` +} + +func (p *PlatformMap[T]) Resolve() *T { + switch getOS() { + case "darwin": + if p.MacOS != nil { + return p.MacOS + } + return nil + case "linux": + if p.Linux != nil { + return p.Linux + } + return nil + case "windows": + if p.Windows != nil { + return p.Windows + } + return nil + default: + return nil + } +} + +func (o *PlatformMap[T]) ResolveWithFallback(fallback PlatformMap[T]) T { + val := o.Resolve() + if val == nil { + return *fallback.Resolve() + } + return *val +} diff --git a/utils/command.go b/utils/command.go index 66a85f3..3adf147 100644 --- a/utils/command.go +++ b/utils/command.go @@ -6,11 +6,10 @@ import ( "os" "os/exec" "path/filepath" - "runtime" "strings" - "github.com/chenasraf/sofmani/appconfig" "github.com/chenasraf/sofmani/logger" + "github.com/chenasraf/sofmani/platform" ) const UNIX_DEFAULT_SHELL string = "bash" @@ -63,23 +62,23 @@ func RunCmdGetOutput(env []string, bin string, args ...string) ([]byte, error) { func getShellScript(dir string) string { var filename string - switch runtime.GOOS { - case "windows": + switch platform.GetPlatform() { + case platform.PlatformWindows: filename = "install.bat" - case "linux", "darwin": + case platform.PlatformLinux, platform.PlatformMacos: filename = "install" } tmpfile := filepath.Join(dir, filename) return tmpfile } -func getScriptContents(script string, envShell *appconfig.PlatformMap[string]) (string, error) { - switch runtime.GOOS { - case "windows": +func getScriptContents(script string, envShell *platform.PlatformMap[string]) (string, error) { + switch platform.GetPlatform() { + case platform.PlatformWindows: preScript := "@echo off" postScript := "exit /b %ERRORLEVEL%" return fmt.Sprintf("%s\n%s\n\n%s\n", preScript, script, postScript), nil - case "linux", "darwin": + case platform.PlatformLinux, platform.PlatformMacos: shell := GetOSShell(envShell) preScript := fmt.Sprintf("#!/usr/bin/env %s", shell) home, err := os.UserHomeDir() @@ -90,10 +89,10 @@ func getScriptContents(script string, envShell *appconfig.PlatformMap[string]) ( postScript := "exit $?" return fmt.Sprintf("%s\n%s\n\n%s\n", preScript, script, postScript), nil } - return "", fmt.Errorf("unsupported OS: %s", runtime.GOOS) + return "", fmt.Errorf("unsupported OS: %s", platform.GetPlatform()) } -func RunCmdAsFile(env []string, contents string, envShell *appconfig.PlatformMap[string]) error { +func RunCmdAsFile(env []string, contents string, envShell *platform.PlatformMap[string]) error { tmpdir := os.TempDir() tmpfile := getShellScript(tmpdir) commandStr, err := getScriptContents(contents, envShell) @@ -112,26 +111,26 @@ func RunCmdAsFile(env []string, contents string, envShell *appconfig.PlatformMap } func GetShellWhich() string { - switch runtime.GOOS { - case "windows": + switch platform.GetPlatform() { + case platform.PlatformWindows: return "where" - case "linux", "darwin": + case platform.PlatformLinux, platform.PlatformMacos: return "which" } return "" } -func GetOSShell(envShell *appconfig.PlatformMap[string]) string { - switch runtime.GOOS { - case "windows": +func GetOSShell(envShell *platform.PlatformMap[string]) string { + switch platform.GetPlatform() { + case platform.PlatformWindows: return "cmd" - case "linux", "darwin": + case platform.PlatformLinux, platform.PlatformMacos: def := os.Getenv("SHELL") if def == "" { def = UNIX_DEFAULT_SHELL } if envShell != nil { - return envShell.ResolveWithFallback(appconfig.PlatformMap[string]{Linux: &def, MacOS: &def}) + return envShell.ResolveWithFallback(platform.PlatformMap[string]{Linux: &def, MacOS: &def}) } return def } @@ -139,10 +138,10 @@ func GetOSShell(envShell *appconfig.PlatformMap[string]) string { } func GetOSShellArgs(cmd string) []string { - switch runtime.GOOS { - case "windows": + switch platform.GetPlatform() { + case platform.PlatformWindows: return []string{"/C", cmd + " & exit %ERRORLEVEL%"} - case "linux", "darwin": + case platform.PlatformLinux, platform.PlatformMacos: return []string{"-c", cmd + "; exit $?"} } return []string{} diff --git a/utils/os.go b/utils/fs.go similarity index 100% rename from utils/os.go rename to utils/fs.go