refactor: platform

This commit is contained in:
2025-01-15 00:41:31 +02:00
parent 008165d676
commit b7d1e1eed0
9 changed files with 139 additions and 124 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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")
}

View File

@@ -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 {

74
platform/platform.go Normal file
View File

@@ -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
}

View File

@@ -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{}