Improve logging #2

Merged
eburk merged 6 commits from improve-logging into main 2025-07-24 15:30:33 +00:00
18 changed files with 281 additions and 223 deletions
Showing only changes of commit a1f46438d0 - Show all commits

19
main.go
View File

@@ -1,21 +1,16 @@
package main package main
import ( import (
"epochsilicon/pkg/log"
"epochsilicon/pkg/service" "epochsilicon/pkg/service"
"epochsilicon/pkg/ui" "epochsilicon/pkg/ui"
"epochsilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"strings" "strings"
) )
const appVersion = "1.0.0" const appVersion = "1.0.1"
func init() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
}
func main() { func main() {
PEApp := app.NewWithID("com.burkey.epochsilicon") PEApp := app.NewWithID("com.burkey.epochsilicon")
@@ -27,21 +22,21 @@ func main() {
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
updateInfo, updateAvailable, err := utils.CheckForUpdateWithAssets(appVersion) updateInfo, updateAvailable, err := utils.CheckForUpdateWithAssets(appVersion)
if err != nil { if err != nil {
log.Debug().Msgf("Failed to check for updates: %v", err) log.Debugf("Failed to check for updates: %v", err)
return return
} }
if !updateAvailable { if !updateAvailable {
log.Debug().Msgf("No updates available") log.Debugf("No updates available")
return return
} }
latestVersion := strings.TrimPrefix(updateInfo.TagName, "v") latestVersion := strings.TrimPrefix(updateInfo.TagName, "v")
log.Debug().Msgf("Update available: current=%s, latest=%s", appVersion, latestVersion) log.Debugf("Update available: current=%s, latest=%s", appVersion, latestVersion)
// Skip if user has suppressed this version // Skip if user has suppressed this version
if prefs.SuppressedUpdateVersion == latestVersion { if prefs.SuppressedUpdateVersion == latestVersion {
log.Debug().Msgf("Update suppressed by user: %s", latestVersion) log.Debugf("Update suppressed by user: %s", latestVersion)
return return
} }
@@ -54,7 +49,7 @@ func main() {
// Set up cleanup when window closes // Set up cleanup when window closes
PEWindow.SetCloseIntercept(func() { PEWindow.SetCloseIntercept(func() {
log.Debug().Msg("Application closing, cleaning up RosettaX87 service...") log.Debug("Application closing, cleaning up RosettaX87 service...")
service.CleanupService() service.CleanupService()
PEApp.Quit() PEApp.Quit()
}) })

View File

@@ -41,7 +41,7 @@ func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
// Parse the shell command to extract components // Parse the shell command to extract components
// The shellCmd format is: cd <path> && <envVars> <rosettaExec> <wineloader> <wowExe> // The shellCmd format is: cd <path> && <envVars> <rosettaExec> <wineloader> <wowExe>
log.Debug().Msgf("Parsing shell command: %s", shellCmd) log.Debugf("Parsing shell command: %s", shellCmd)
// Create the command without context cancellation // Create the command without context cancellation
cmd := exec.Command("sh", "-c", shellCmd) cmd := exec.Command("sh", "-c", shellCmd)
@@ -71,7 +71,7 @@ func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
scanner := bufio.NewScanner(stdout) scanner := bufio.NewScanner(stdout)
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
log.Debug().Msgf("GAME STDOUT: %s", line) log.Debugf("GAME STDOUT: %s", line)
} }
}() }()
@@ -79,7 +79,7 @@ func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
scanner := bufio.NewScanner(stderr) scanner := bufio.NewScanner(stderr)
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
log.Debug().Msgf("GAME STDERR: %s", line) log.Debugf("GAME STDERR: %s", line)
} }
}() }()
@@ -93,9 +93,9 @@ func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
}() }()
if err := cmd.Wait(); err != nil { if err := cmd.Wait(); err != nil {
log.Debug().Msgf("Game process ended with error: %v", err) log.Debugf("Game process ended with error: %v", err)
} else { } else {
log.Debug().Msg("Game process ended successfully") log.Debug("Game process ended successfully")
} }
}() }()
@@ -103,7 +103,7 @@ func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
} }
func LaunchGame(myWindow fyne.Window) { func LaunchGame(myWindow fyne.Window) {
log.Debug().Msg("Launch Game button clicked") log.Debug("Launch Game button clicked")
if paths.CrossoverPath == "" { if paths.CrossoverPath == "" {
dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it in the patcher."), myWindow) dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it in the patcher."), myWindow)
@@ -132,7 +132,7 @@ func LaunchGame(myWindow fyne.Window) {
} }
gameMutex.Unlock() gameMutex.Unlock()
log.Debug().Msg("Preparing to launch EpochSilicon...") log.Debug("Preparing to launch EpochSilicon...")
wowExePath := filepath.Join(paths.EpochPath, "Project-Epoch.exe") wowExePath := filepath.Join(paths.EpochPath, "Project-Epoch.exe")
@@ -163,20 +163,20 @@ func continueLaunch(myWindow fyne.Window, wowExePath string) {
if AutoDeleteWdb { if AutoDeleteWdb {
wdbPath := filepath.Join(paths.EpochPath, "WDB") wdbPath := filepath.Join(paths.EpochPath, "WDB")
if utils.DirExists(wdbPath) { if utils.DirExists(wdbPath) {
log.Debug().Msgf("Auto-deleting WDB directory: %s", wdbPath) log.Debugf("Auto-deleting WDB directory: %s", wdbPath)
if err := os.RemoveAll(wdbPath); err != nil { if err := os.RemoveAll(wdbPath); err != nil {
log.Debug().Msgf("Warning: failed to auto-delete WDB directory: %v", err) log.Debugf("Warning: failed to auto-delete WDB directory: %v", err)
// Don't block the launch, just log the error // Don't block the launch, just log the error
} else { } else {
log.Debug().Msgf("Successfully auto-deleted WDB directory") log.Debugf("Successfully auto-deleted WDB directory")
} }
} else { } else {
log.Debug().Msgf("WDB directory not found, nothing to delete") log.Debugf("WDB directory not found, nothing to delete")
} }
} }
// Since RosettaX87 service is already running, we can directly launch WoW // Since RosettaX87 service is already running, we can directly launch WoW
log.Debug().Msg("RosettaX87 service is running. Proceeding to launch WoW.") log.Debug("RosettaX87 service is running. Proceeding to launch WoW.")
if paths.CrossoverPath == "" || paths.EpochPath == "" { if paths.CrossoverPath == "" || paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("CrossOver path or Epoch path is not set. Cannot launch WoW."), myWindow) dialog.ShowError(fmt.Errorf("CrossOver path or Epoch path is not set. Cannot launch WoW."), myWindow)
@@ -209,21 +209,21 @@ func continueLaunch(myWindow fyne.Window, wowExePath string) {
escapedShellCmd := utils.EscapeStringForAppleScript(shellCmd) escapedShellCmd := utils.EscapeStringForAppleScript(shellCmd)
cmd2Script := fmt.Sprintf("tell application \"Terminal\" to do script \"%s\"", escapedShellCmd) cmd2Script := fmt.Sprintf("tell application \"Terminal\" to do script \"%s\"", escapedShellCmd)
log.Debug().Msg("Executing WoW launch command via AppleScript...") log.Debug("Executing WoW launch command via AppleScript...")
if !utils.RunOsascript(cmd2Script, myWindow) { if !utils.RunOsascript(cmd2Script, myWindow) {
return return
} }
log.Debug().Msg("Launch command executed. Check the new terminal window.") log.Debug("Launch command executed. Check the new terminal window.")
} else { } else {
// Use integrated terminal // Use integrated terminal
log.Debug().Msgf("Shell command for integrated terminal: %s", shellCmd) log.Debugf("Shell command for integrated terminal: %s", shellCmd)
log.Debug().Msg("Executing WoW launch command with integrated terminal...") log.Debug("Executing WoW launch command with integrated terminal...")
if err := runGameIntegrated(myWindow, shellCmd); err != nil { if err := runGameIntegrated(myWindow, shellCmd); err != nil {
dialog.ShowError(fmt.Errorf("failed to launch game: %v", err), myWindow) dialog.ShowError(fmt.Errorf("failed to launch game: %v", err), myWindow)
return return
} }
log.Debug().Msg("Game launched with integrated terminal. Check the application logs for output.") log.Debug("Game launched with integrated terminal. Check the application logs for output.")
} }
} }

View File

@@ -25,20 +25,20 @@ var RecommendedSettings = map[string]string{
// Returns true if all settings are correctly applied, false otherwise // Returns true if all settings are correctly applied, false otherwise
func CheckRecommendedSettings() bool { func CheckRecommendedSettings() bool {
if paths.EpochPath == "" { if paths.EpochPath == "" {
log.Debug().Msgf("Epoch path not set, cannot check Config.wtf") log.Debugf("Epoch path not set, cannot check Config.wtf")
return false return false
} }
configPath := filepath.Join(paths.EpochPath, "WTF", "Config.wtf") configPath := filepath.Join(paths.EpochPath, "WTF", "Config.wtf")
if _, err := os.Stat(configPath); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
log.Debug().Msgf("Config.wtf not found at %s", configPath) log.Debugf("Config.wtf not found at %s", configPath)
return false return false
} }
content, err := os.ReadFile(configPath) content, err := os.ReadFile(configPath)
if err != nil { if err != nil {
log.Debug().Msgf("Failed to read Config.wtf: %v", err) log.Debugf("Failed to read Config.wtf: %v", err)
return false return false
} }
@@ -47,12 +47,12 @@ func CheckRecommendedSettings() bool {
// Check each recommended setting // Check each recommended setting
for setting, expectedValue := range RecommendedSettings { for setting, expectedValue := range RecommendedSettings {
if !isSettingCorrect(configText, setting, expectedValue) { if !isSettingCorrect(configText, setting, expectedValue) {
log.Debug().Msgf("Setting %s not found or incorrect in Config.wtf", setting) log.Debugf("Setting %s not found or incorrect in Config.wtf", setting)
return false return false
} }
} }
log.Debug().Msgf("All recommended settings are correctly applied") log.Debugf("All recommended settings are correctly applied")
return true return true
} }
@@ -91,7 +91,7 @@ func ApplyRecommendedSettings() error {
if content, err := os.ReadFile(configPath); err == nil { if content, err := os.ReadFile(configPath); err == nil {
configText = string(content) configText = string(content)
} else { } else {
log.Debug().Msgf("Config.wtf not found, creating new file") log.Debugf("Config.wtf not found, creating new file")
configText = "" configText = ""
} }
@@ -105,7 +105,7 @@ func ApplyRecommendedSettings() error {
return fmt.Errorf("failed to write Config.wtf: %v", err) return fmt.Errorf("failed to write Config.wtf: %v", err)
} }
log.Debug().Msgf("Successfully applied recommended settings to Config.wtf") log.Debugf("Successfully applied recommended settings to Config.wtf")
return nil return nil
} }
@@ -120,14 +120,14 @@ func updateOrAddSetting(configText, setting, value string) string {
if re.MatchString(configText) { if re.MatchString(configText) {
// Replace existing setting // Replace existing setting
configText = re.ReplaceAllString(configText, newSetting) configText = re.ReplaceAllString(configText, newSetting)
log.Debug().Msgf("Updated setting %s to %s", setting, value) log.Debugf("Updated setting %s to %s", setting, value)
} else { } else {
// Add new setting // Add new setting
if configText != "" && !strings.HasSuffix(configText, "\n") { if configText != "" && !strings.HasSuffix(configText, "\n") {
configText += "\n" configText += "\n"
} }
configText += newSetting + "\n" configText += newSetting + "\n"
log.Debug().Msgf("Added new setting %s with value %s", setting, value) log.Debugf("Added new setting %s with value %s", setting, value)
} }
return configText return configText

62
pkg/log/logging.go Normal file
View File

@@ -0,0 +1,62 @@
package log
import (
"github.com/rs/zerolog"
"os"
)
var logger zerolog.Logger
func init() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
zerolog.SetGlobalLevel(zerolog.InfoLevel)
logger = zerolog.New(os.Stdout).With().Timestamp().Logger()
}
func Debug(msg string) {
logger.Debug().Msg(msg)
}
func Debugf(format string, args ...interface{}) {
logger.Debug().Msgf(format, args...)
}
func Info(msg string) {
logger.Info().Msg(msg)
}
func Infof(format string, args ...interface{}) {
logger.Info().Msgf(format, args...)
}
func Warn(msg string) {
logger.Warn().Msg(msg)
}
func Warnf(format string, args ...interface{}) {
logger.Warn().Msgf(format, args...)
}
func Error(msg string) {
logger.Error().Msg(msg)
}
func Errorf(format string, args ...interface{}) {
logger.Error().Msgf(format, args...)
}
func Fatal(msg string) {
logger.Fatal().Msg(msg)
}
func Fatalf(format string, args ...interface{}) {
logger.Fatal().Msgf(format, args...)
}
func Panic(msg string) {
logger.Panic().Msg(msg)
}
func Panicf(format string, args ...interface{}) {
logger.Panic().Msgf(format, args...)
}

View File

@@ -2,10 +2,10 @@ package patching
import ( import (
"bytes" "bytes"
"epochsilicon/pkg/log"
"errors" "errors"
"fmt" "fmt"
"git.burkey.co/eburk/epochcli/pkg/epoch" "git.burkey.co/eburk/epochcli/pkg/epoch"
"github.com/rs/zerolog/log"
"io" "io"
"os" "os"
"os/exec" "os/exec"
@@ -21,7 +21,7 @@ import (
) )
func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) { func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
log.Debug().Msg("Patch Epoch clicked") log.Debug("Patch Epoch clicked")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow)
return return
@@ -37,25 +37,25 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
for resourceName, destPath := range filesToCopy { for resourceName, destPath := range filesToCopy {
log.Debug().Msgf("Processing resource: %s to %s", resourceName, destPath) log.Debugf("Processing resource: %s to %s", resourceName, destPath)
// Check if file already exists and has correct size // Check if file already exists and has correct size
if utils.PathExists(destPath) && utils.CompareFileWithBundledResource(destPath, resourceName) { if utils.PathExists(destPath) && utils.CompareFileWithBundledResource(destPath, resourceName) {
log.Debug().Msgf("File %s already exists with correct size, skipping copy", destPath) log.Debugf("File %s already exists with correct size, skipping copy", destPath)
continue continue
} }
if utils.PathExists(destPath) { if utils.PathExists(destPath) {
log.Debug().Msgf("File %s exists but has incorrect size, updating...", destPath) log.Debugf("File %s exists but has incorrect size, updating...", destPath)
} else { } else {
log.Debug().Msgf("File %s does not exist, creating...", destPath) log.Debugf("File %s does not exist, creating...", destPath)
} }
resource, err := fyne.LoadResourceFromPath(resourceName) resource, err := fyne.LoadResourceFromPath(resourceName)
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err) errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -65,7 +65,7 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err) errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -76,22 +76,22 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err) errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
} }
log.Debug().Msgf("Successfully copied %s to %s", resourceName, destPath) log.Debugf("Successfully copied %s to %s", resourceName, destPath)
} }
log.Debug().Msgf("Preparing rosettax87 directory at: %s", targetRosettaX87Dir) log.Debugf("Preparing rosettax87 directory at: %s", targetRosettaX87Dir)
if err := os.RemoveAll(targetRosettaX87Dir); err != nil { if err := os.RemoveAll(targetRosettaX87Dir); err != nil {
log.Debug().Msgf("Warning: could not remove existing rosettax87 folder '%s': %v", targetRosettaX87Dir, err) log.Debugf("Warning: could not remove existing rosettax87 folder '%s': %v", targetRosettaX87Dir, err)
} }
if err := os.MkdirAll(targetRosettaX87Dir, 0755); err != nil { if err := os.MkdirAll(targetRosettaX87Dir, 0755); err != nil {
errMsg := fmt.Sprintf("failed to create directory %s: %v", targetRosettaX87Dir, err) errMsg := fmt.Sprintf("failed to create directory %s: %v", targetRosettaX87Dir, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -103,12 +103,12 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
for resourceName, destPath := range rosettaFilesToCopy { for resourceName, destPath := range rosettaFilesToCopy {
log.Debug().Msgf("Processing rosetta resource: %s to %s", resourceName, destPath) log.Debugf("Processing rosetta resource: %s to %s", resourceName, destPath)
resource, err := fyne.LoadResourceFromPath(resourceName) resource, err := fyne.LoadResourceFromPath(resourceName)
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err) errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -118,7 +118,7 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err) errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -129,7 +129,7 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
destinationFile.Close() destinationFile.Close()
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err) errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
@@ -137,31 +137,31 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
destinationFile.Close() destinationFile.Close()
if filepath.Base(destPath) == "rosettax87" { if filepath.Base(destPath) == "rosettax87" {
log.Debug().Msgf("Setting execute permission for %s", destPath) log.Debugf("Setting execute permission for %s", destPath)
if err := os.Chmod(destPath, 0755); err != nil { if err := os.Chmod(destPath, 0755); err != nil {
errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", destPath, err) errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
updateAllStatuses() updateAllStatuses()
return return
} }
} }
log.Debug().Msgf("Successfully copied %s to %s", resourceName, destPath) log.Debugf("Successfully copied %s to %s", resourceName, destPath)
} }
log.Debug().Msgf("Checking dlls.txt file at: %s", dllsTextFile) log.Debugf("Checking dlls.txt file at: %s", dllsTextFile)
winerosettaEntry := "winerosetta.dll" winerosettaEntry := "winerosetta.dll"
needsWinerosettaUpdate := true needsWinerosettaUpdate := true
if fileContentBytes, err := os.ReadFile(dllsTextFile); err == nil { if fileContentBytes, err := os.ReadFile(dllsTextFile); err == nil {
fileContent := string(fileContentBytes) fileContent := string(fileContentBytes)
if strings.Contains(fileContent, winerosettaEntry) { if strings.Contains(fileContent, winerosettaEntry) {
log.Debug().Msgf("dlls.txt already contains %s", winerosettaEntry) log.Debugf("dlls.txt already contains %s", winerosettaEntry)
needsWinerosettaUpdate = false needsWinerosettaUpdate = false
} }
} else { } else {
log.Debug().Msgf("dlls.txt not found, will create a new one") log.Debugf("dlls.txt not found, will create a new one")
} }
if needsWinerosettaUpdate { if needsWinerosettaUpdate {
@@ -172,7 +172,7 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to read dlls.txt for update: %v", err) errMsg := fmt.Sprintf("failed to read dlls.txt for update: %v", err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} }
} }
@@ -186,20 +186,20 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if needsWinerosettaUpdate { if needsWinerosettaUpdate {
if !strings.Contains(updatedContent, winerosettaEntry+"\n") { if !strings.Contains(updatedContent, winerosettaEntry+"\n") {
updatedContent += winerosettaEntry + "\n" updatedContent += winerosettaEntry + "\n"
log.Debug().Msgf("Adding %s to dlls.txt", winerosettaEntry) log.Debugf("Adding %s to dlls.txt", winerosettaEntry)
} }
} }
if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil { if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil {
errMsg := fmt.Sprintf("failed to update dlls.txt: %v", err) errMsg := fmt.Sprintf("failed to update dlls.txt: %v", err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} else { } else {
log.Debug().Msgf("Successfully updated dlls.txt") log.Debugf("Successfully updated dlls.txt")
} }
} }
log.Debug().Msg("Downloading updates from Project Epoch servers.") log.Debug("Downloading updates from Project Epoch servers.")
// TODO: Change from dialog to pulsing animation // TODO: Change from dialog to pulsing animation
dialog.ShowInformation("Downloading patches", "Downloading patches for Project Epoch, this will take some time. Please wait until the status changes to \"Patched\"", myWindow) dialog.ShowInformation("Downloading patches", "Downloading patches for Project Epoch, this will take some time. Please wait until the status changes to \"Patched\"", myWindow)
@@ -212,10 +212,10 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
}) })
paths.DownloadingPatches = false paths.DownloadingPatches = false
log.Error().Msg(errMsg) log.Error(errMsg)
} }
log.Info().Msgf("Successfully updated %d Epoch files", stats.Updated) log.Infof("Successfully updated %d Epoch files", stats.Updated)
log.Debug().Msg("Epoch patching with bundled resources completed successfully.") log.Debug("Epoch patching with bundled resources completed successfully.")
fyne.Do(func() { fyne.Do(func() {
dialog.ShowInformation("Success", "Epoch patching process completed.", myWindow) dialog.ShowInformation("Success", "Epoch patching process completed.", myWindow)
}) })
@@ -228,7 +228,7 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) { func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
log.Debug().Msg("Patch CrossOver clicked") log.Debug("Patch CrossOver clicked")
if paths.CrossoverPath == "" { if paths.CrossoverPath == "" {
dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it first."), myWindow)
return return
@@ -245,7 +245,7 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
return return
} }
log.Debug().Msgf("Copying %s to %s", wineloaderOrig, wineloaderCopy) log.Debugf("Copying %s to %s", wineloaderOrig, wineloaderCopy)
if err := utils.CopyFile(wineloaderOrig, wineloaderCopy); err != nil { if err := utils.CopyFile(wineloaderOrig, wineloaderCopy); err != nil {
errMsg := fmt.Sprintf("failed to copy wineloader: %v", err) errMsg := fmt.Sprintf("failed to copy wineloader: %v", err)
if strings.Contains(err.Error(), "operation not permitted") { if strings.Contains(err.Error(), "operation not permitted") {
@@ -257,40 +257,40 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
return return
} }
log.Debug().Msgf("Executing: codesign --remove-signature %s", wineloaderCopy) log.Debugf("Executing: codesign --remove-signature %s", wineloaderCopy)
cmd := exec.Command("codesign", "--remove-signature", wineloaderCopy) cmd := exec.Command("codesign", "--remove-signature", wineloaderCopy)
combinedOutput, err := cmd.CombinedOutput() combinedOutput, err := cmd.CombinedOutput()
if err != nil { if err != nil {
derrMsg := fmt.Sprintf("failed to remove signature from %s: %v\nOutput: %s", wineloaderCopy, err, string(combinedOutput)) derrMsg := fmt.Sprintf("failed to remove signature from %s: %v\nOutput: %s", wineloaderCopy, err, string(combinedOutput))
dialog.ShowError(errors.New(derrMsg), myWindow) dialog.ShowError(errors.New(derrMsg), myWindow)
log.Debug().Msg(derrMsg) log.Debug(derrMsg)
paths.PatchesAppliedCrossOver = false paths.PatchesAppliedCrossOver = false
if err := os.Remove(wineloaderCopy); err != nil { if err := os.Remove(wineloaderCopy); err != nil {
log.Debug().Msgf("Warning: failed to cleanup wineloader2 after codesign failure: %v", err) log.Debugf("Warning: failed to cleanup wineloader2 after codesign failure: %v", err)
} }
updateAllStatuses() updateAllStatuses()
return return
} }
log.Debug().Msgf("codesign output: %s", string(combinedOutput)) log.Debugf("codesign output: %s", string(combinedOutput))
log.Debug().Msgf("Setting execute permissions for %s", wineloaderCopy) log.Debugf("Setting execute permissions for %s", wineloaderCopy)
if err := os.Chmod(wineloaderCopy, 0755); err != nil { if err := os.Chmod(wineloaderCopy, 0755); err != nil {
errMsg := fmt.Sprintf("failed to set executable permissions for %s: %v", wineloaderCopy, err) errMsg := fmt.Sprintf("failed to set executable permissions for %s: %v", wineloaderCopy, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
paths.PatchesAppliedCrossOver = false paths.PatchesAppliedCrossOver = false
updateAllStatuses() updateAllStatuses()
return return
} }
log.Debug().Msg("CrossOver patching completed successfully.") log.Debug("CrossOver patching completed successfully.")
paths.PatchesAppliedCrossOver = true paths.PatchesAppliedCrossOver = true
dialog.ShowInformation("Success", "CrossOver patching process completed.", myWindow) dialog.ShowInformation("Success", "CrossOver patching process completed.", myWindow)
updateAllStatuses() updateAllStatuses()
} }
func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) { func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
log.Debug().Msg("Unpatch Epoch clicked") log.Debug("Unpatch Epoch clicked")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow)
return return
@@ -304,13 +304,13 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
// Remove the rosettaX87 directory // Remove the rosettaX87 directory
if utils.DirExists(rosettaX87DirPath) { if utils.DirExists(rosettaX87DirPath) {
log.Debug().Msgf("Removing directory: %s", rosettaX87DirPath) log.Debugf("Removing directory: %s", rosettaX87DirPath)
if err := os.RemoveAll(rosettaX87DirPath); err != nil { if err := os.RemoveAll(rosettaX87DirPath); err != nil {
errMsg := fmt.Sprintf("failed to remove directory %s: %v", rosettaX87DirPath, err) errMsg := fmt.Sprintf("failed to remove directory %s: %v", rosettaX87DirPath, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} else { } else {
log.Debug().Msgf("Successfully removed directory: %s", rosettaX87DirPath) log.Debugf("Successfully removed directory: %s", rosettaX87DirPath)
} }
} }
@@ -318,25 +318,25 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
filesToRemove := []string{winerosettaDllPath, d3d9DllPath} filesToRemove := []string{winerosettaDllPath, d3d9DllPath}
for _, file := range filesToRemove { for _, file := range filesToRemove {
if utils.PathExists(file) { if utils.PathExists(file) {
log.Debug().Msgf("Removing file: %s", file) log.Debugf("Removing file: %s", file)
if err := os.Remove(file); err != nil { if err := os.Remove(file); err != nil {
errMsg := fmt.Sprintf("failed to remove file %s: %v", file, err) errMsg := fmt.Sprintf("failed to remove file %s: %v", file, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} else { } else {
log.Debug().Msgf("Successfully removed file: %s", file) log.Debugf("Successfully removed file: %s", file)
} }
} }
} }
// Update dlls.txt file - remove winerosetta.dll // Update dlls.txt file - remove winerosetta.dll
if utils.PathExists(dllsTextFile) { if utils.PathExists(dllsTextFile) {
log.Debug().Msgf("Updating dlls.txt file: %s", dllsTextFile) log.Debugf("Updating dlls.txt file: %s", dllsTextFile)
content, err := os.ReadFile(dllsTextFile) content, err := os.ReadFile(dllsTextFile)
if err != nil { if err != nil {
errMsg := fmt.Sprintf("failed to read dlls.txt file: %v", err) errMsg := fmt.Sprintf("failed to read dlls.txt file: %v", err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} else { } else {
lines := strings.Split(string(content), "\n") lines := strings.Split(string(content), "\n")
filteredLines := make([]string, 0, len(lines)) filteredLines := make([]string, 0, len(lines))
@@ -352,21 +352,21 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil { if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil {
errMsg := fmt.Sprintf("failed to update dlls.txt file: %v", err) errMsg := fmt.Sprintf("failed to update dlls.txt file: %v", err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
} else { } else {
log.Debug().Msgf("Successfully updated dlls.txt file") log.Debugf("Successfully updated dlls.txt file")
} }
} }
} }
log.Debug().Msg("Epoch unpatching completed successfully.") log.Debug("Epoch unpatching completed successfully.")
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
dialog.ShowInformation("Success", "Epoch unpatching process completed.", myWindow) dialog.ShowInformation("Success", "Epoch unpatching process completed.", myWindow)
updateAllStatuses() updateAllStatuses()
} }
func UnpatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) { func UnpatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
log.Debug().Msg("Unpatch CrossOver clicked") log.Debug("Unpatch CrossOver clicked")
if paths.CrossoverPath == "" { if paths.CrossoverPath == "" {
dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("CrossOver path not set. Please set it first."), myWindow)
return return
@@ -375,21 +375,21 @@ func UnpatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
wineloaderCopy := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2") wineloaderCopy := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
if utils.PathExists(wineloaderCopy) { if utils.PathExists(wineloaderCopy) {
log.Debug().Msgf("Removing file: %s", wineloaderCopy) log.Debugf("Removing file: %s", wineloaderCopy)
if err := os.Remove(wineloaderCopy); err != nil { if err := os.Remove(wineloaderCopy); err != nil {
errMsg := fmt.Sprintf("failed to remove file %s: %v", wineloaderCopy, err) errMsg := fmt.Sprintf("failed to remove file %s: %v", wineloaderCopy, err)
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
updateAllStatuses() updateAllStatuses()
return return
} else { } else {
log.Debug().Msgf("Successfully removed file: %s", wineloaderCopy) log.Debugf("Successfully removed file: %s", wineloaderCopy)
} }
} else { } else {
log.Debug().Msgf("File not found to remove: %s", wineloaderCopy) log.Debugf("File not found to remove: %s", wineloaderCopy)
} }
log.Debug().Msg("CrossOver unpatching completed successfully.") log.Debug("CrossOver unpatching completed successfully.")
paths.PatchesAppliedCrossOver = false paths.PatchesAppliedCrossOver = false
dialog.ShowInformation("Success", "CrossOver unpatching process completed.", myWindow) dialog.ShowInformation("Success", "CrossOver unpatching process completed.", myWindow)
updateAllStatuses() updateAllStatuses()
@@ -406,14 +406,14 @@ func updateOrAddConfigSetting(configText, setting, value string) string {
if re.MatchString(configText) { if re.MatchString(configText) {
// Replace existing setting // Replace existing setting
configText = re.ReplaceAllString(configText, newSetting) configText = re.ReplaceAllString(configText, newSetting)
log.Debug().Msgf("Updated setting %s to %s", setting, value) log.Debugf("Updated setting %s to %s", setting, value)
} else { } else {
// Add new setting // Add new setting
if configText != "" && !strings.HasSuffix(configText, "\n") { if configText != "" && !strings.HasSuffix(configText, "\n") {
configText += "\n" configText += "\n"
} }
configText += newSetting + "\n" configText += newSetting + "\n"
log.Debug().Msgf("Added new setting %s with value %s", setting, value) log.Debugf("Added new setting %s with value %s", setting, value)
} }
return configText return configText
@@ -427,7 +427,7 @@ func removeConfigSetting(configText, setting string) string {
if re.MatchString(configText) { if re.MatchString(configText) {
configText = re.ReplaceAllString(configText, "") configText = re.ReplaceAllString(configText, "")
log.Debug().Msgf("Removed setting %s from config", setting) log.Debugf("Removed setting %s from config", setting)
} }
return configText return configText

View File

@@ -1,12 +1,12 @@
package paths package paths
import ( import (
"epochsilicon/pkg/log"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"epochsilicon/pkg/utils" "epochsilicon/pkg/utils"
"github.com/rs/zerolog/log"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
@@ -33,7 +33,7 @@ func SelectCrossOverPath(myWindow fyne.Window, crossoverPathLabel *widget.RichTe
return return
} }
if uri == nil { if uri == nil {
log.Info().Msg("CrossOver path selection cancelled.") log.Info("CrossOver path selection cancelled.")
updateAllStatuses() updateAllStatuses()
return return
} }
@@ -41,14 +41,14 @@ func SelectCrossOverPath(myWindow fyne.Window, crossoverPathLabel *widget.RichTe
if filepath.Ext(selectedPath) == ".app" && utils.DirExists(selectedPath) { if filepath.Ext(selectedPath) == ".app" && utils.DirExists(selectedPath) {
CrossoverPath = selectedPath CrossoverPath = selectedPath
PatchesAppliedCrossOver = false PatchesAppliedCrossOver = false
log.Info().Msgf("CrossOver path set to:", CrossoverPath) log.Infof("CrossOver path set to:", CrossoverPath)
// Save to prefs // Save to prefs
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.CrossOverPath = selectedPath prefs.CrossOverPath = selectedPath
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
} else { } else {
dialog.ShowError(fmt.Errorf("invalid selection: '%s'. Please select a valid .app bundle", selectedPath), myWindow) dialog.ShowError(fmt.Errorf("invalid selection: '%s'. Please select a valid .app bundle", selectedPath), myWindow)
log.Info().Msgf("Invalid CrossOver path selected:", selectedPath) log.Infof("Invalid CrossOver path selected:", selectedPath)
} }
updateAllStatuses() updateAllStatuses()
}, myWindow) }, myWindow)
@@ -61,7 +61,7 @@ func SelectEpochPath(myWindow fyne.Window, epochPathLabel *widget.RichText, upda
return return
} }
if uri == nil { if uri == nil {
log.Info().Msg("Epoch path selection cancelled.") log.Info("Epoch path selection cancelled.")
updateAllStatuses() updateAllStatuses()
return return
} }
@@ -69,14 +69,14 @@ func SelectEpochPath(myWindow fyne.Window, epochPathLabel *widget.RichText, upda
if utils.DirExists(selectedPath) { if utils.DirExists(selectedPath) {
EpochPath = selectedPath EpochPath = selectedPath
PatchesAppliedEpoch = false PatchesAppliedEpoch = false
log.Info().Msgf("Epoch path set to:", EpochPath) log.Infof("Epoch path set to:", EpochPath)
// Save to prefs // Save to prefs
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.EpochPath = selectedPath prefs.EpochPath = selectedPath
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
} else { } else {
dialog.ShowError(fmt.Errorf("invalid selection: '%s' is not a valid directory", selectedPath), myWindow) dialog.ShowError(fmt.Errorf("invalid selection: '%s' is not a valid directory", selectedPath), myWindow)
log.Info().Msgf("Invalid Epoch path selected:", selectedPath) log.Infof("Invalid Epoch path selected:", selectedPath)
} }
updateAllStatuses() updateAllStatuses()
}, myWindow) }, myWindow)
@@ -102,7 +102,7 @@ func CheckDefaultCrossOverPath() {
if CrossoverPath == "" { if CrossoverPath == "" {
if info, err := os.Stat(DefaultCrossOverPath); err == nil && info.IsDir() { if info, err := os.Stat(DefaultCrossOverPath); err == nil && info.IsDir() {
CrossoverPath = DefaultCrossOverPath CrossoverPath = DefaultCrossOverPath
log.Info().Msgf("Pre-set CrossOver to default:", DefaultCrossOverPath) log.Infof("Pre-set CrossOver to default:", DefaultCrossOverPath)
} }
} }
} }

View File

@@ -2,8 +2,8 @@ package service
import ( import (
"bytes" "bytes"
"epochsilicon/pkg/log"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -27,7 +27,7 @@ var (
// CleanupExistingServices kills any existing rosettax87 processes // CleanupExistingServices kills any existing rosettax87 processes
func CleanupExistingServices() error { func CleanupExistingServices() error {
log.Info().Msg("Cleaning up any existing rosettax87 processes...") log.Info("Cleaning up any existing rosettax87 processes...")
// Find all rosettax87 processes // Find all rosettax87 processes
cmd := exec.Command("pgrep", "-f", "rosettax87") cmd := exec.Command("pgrep", "-f", "rosettax87")
@@ -49,16 +49,16 @@ func CleanupExistingServices() error {
err := killCmd.Run() err := killCmd.Run()
if err != nil { if err != nil {
// If regular kill fails, try with sudo (but this might fail too) // If regular kill fails, try with sudo (but this might fail too)
log.Info().Msgf("Regular kill failed for process %s, trying sudo: %v", pid, err) log.Infof("Regular kill failed for process %s, trying sudo: %v", pid, err)
sudoKillCmd := exec.Command("sudo", "kill", "-9", pid) sudoKillCmd := exec.Command("sudo", "kill", "-9", pid)
err2 := sudoKillCmd.Run() err2 := sudoKillCmd.Run()
if err2 != nil { if err2 != nil {
log.Info().Msgf("Failed to kill process %s with sudo: %v", pid, err2) log.Infof("Failed to kill process %s with sudo: %v", pid, err2)
} else { } else {
log.Info().Msgf("Killed existing rosettax87 process with sudo: %s", pid) log.Infof("Killed existing rosettax87 process with sudo: %s", pid)
} }
} else { } else {
log.Info().Msgf("Killed existing rosettax87 process: %s", pid) log.Infof("Killed existing rosettax87 process: %s", pid)
} }
} }
@@ -77,7 +77,7 @@ func isRosettaSocketActive() bool {
// StartRosettaX87Service starts the RosettaX87 service with sudo privileges // StartRosettaX87Service starts the RosettaX87 service with sudo privileges
func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) { func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
log.Info().Msg("Starting RosettaX87 service...") log.Info("Starting RosettaX87 service...")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first"), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first"), myWindow)
@@ -103,7 +103,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
// Load user preferences // Load user preferences
prefs, err := utils.LoadPrefs() prefs, err := utils.LoadPrefs()
if err != nil { if err != nil {
log.Info().Msgf("Failed to load preferences: %v", err) log.Infof("Failed to load preferences: %v", err)
prefs = &utils.UserPrefs{} // Use default prefs prefs = &utils.UserPrefs{} // Use default prefs
} }
@@ -163,7 +163,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
if shouldSavePassword { if shouldSavePassword {
// Save password to keychain // Save password to keychain
if err := utils.SaveSudoPassword(password); err != nil { if err := utils.SaveSudoPassword(password); err != nil {
log.Info().Msgf("Failed to save password to keychain: %v", err) log.Infof("Failed to save password to keychain: %v", err)
// Don't block the service start, just log the error // Don't block the service start, just log the error
} }
} else { } else {
@@ -174,7 +174,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
// Update preferences // Update preferences
prefs.SaveSudoPassword = shouldSavePassword prefs.SaveSudoPassword = shouldSavePassword
if err := utils.SavePrefs(prefs); err != nil { if err := utils.SavePrefs(prefs); err != nil {
log.Info().Msgf("Failed to save preferences: %v", err) log.Infof("Failed to save preferences: %v", err)
} }
// Close the dialog // Close the dialog
@@ -191,13 +191,13 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
err := startServiceWithPassword(rosettaX87Dir, rosettaX87Exe, password) err := startServiceWithPassword(rosettaX87Dir, rosettaX87Exe, password)
paths.ServiceStarting = false paths.ServiceStarting = false
if err != nil { if err != nil {
log.Info().Msgf("Failed to start RosettaX87 service: %v", err) log.Infof("Failed to start RosettaX87 service: %v", err)
fyne.Do(func() { fyne.Do(func() {
dialog.ShowError(fmt.Errorf("failed to start RosettaX87 service: %v", err), myWindow) dialog.ShowError(fmt.Errorf("failed to start RosettaX87 service: %v", err), myWindow)
}) })
ServiceRunning = false ServiceRunning = false
} else { } else {
log.Info().Msg("RosettaX87 service started successfully") log.Info("RosettaX87 service started successfully")
ServiceRunning = true ServiceRunning = true
} }
fyne.Do(func() { fyne.Do(func() {
@@ -215,7 +215,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
passwordContainer, passwordContainer,
func(confirmed bool) { func(confirmed bool) {
if !confirmed { if !confirmed {
log.Info().Msg("Service start cancelled by user") log.Info("Service start cancelled by user")
return return
} }
confirmFunc() confirmFunc()
@@ -263,7 +263,7 @@ func startServiceWithPassword(workingDir, executable, password string) error {
stderrOutput := stderr.String() stderrOutput := stderr.String()
stdoutOutput := stdout.String() stdoutOutput := stdout.String()
log.Info().Msgf("Password test - Exit code: %v, Stderr: %q, Stdout: %q", err, stderrOutput, stdoutOutput) log.Infof("Password test - Exit code: %v, Stderr: %q, Stdout: %q", err, stderrOutput, stdoutOutput)
// Check for authentication failure indicators // Check for authentication failure indicators
if strings.Contains(stderrOutput, "Sorry, try again") || if strings.Contains(stderrOutput, "Sorry, try again") ||
@@ -283,7 +283,7 @@ func startServiceWithPassword(workingDir, executable, password string) error {
} }
// If we get here, the password is correct, now start the actual service // If we get here, the password is correct, now start the actual service
log.Info().Msg("Password validated successfully, starting rosettax87 service...") log.Info("Password validated successfully, starting rosettax87 service...")
cmd := exec.Command("sudo", "-S", executable) cmd := exec.Command("sudo", "-S", executable)
cmd.Dir = workingDir cmd.Dir = workingDir
@@ -325,25 +325,25 @@ func startServiceWithPassword(workingDir, executable, password string) error {
if cmd.ProcessState != nil && cmd.ProcessState.Exited() { if cmd.ProcessState != nil && cmd.ProcessState.Exited() {
stderrOutput := stderr.String() stderrOutput := stderr.String()
stdoutOutput := stdout.String() stdoutOutput := stdout.String()
log.Info().Msgf("Process exited - Stdout: %q, Stderr: %q", stdoutOutput, stderrOutput) log.Infof("Process exited - Stdout: %q, Stderr: %q", stdoutOutput, stderrOutput)
return fmt.Errorf("process exited prematurely with code: %d. Stderr: %s", cmd.ProcessState.ExitCode(), stderrOutput) return fmt.Errorf("process exited prematurely with code: %d. Stderr: %s", cmd.ProcessState.ExitCode(), stderrOutput)
} }
// Verify the service is actually listening // Verify the service is actually listening
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
if !isRosettaSocketActive() { if !isRosettaSocketActive() {
log.Info().Msgf("Service started but socket not active - Stdout: %q, Stderr: %q", stdout.String(), stderr.String()) log.Infof("Service started but socket not active - Stdout: %q, Stderr: %q", stdout.String(), stderr.String())
cmd.Process.Kill() cmd.Process.Kill()
return fmt.Errorf("service started but is not listening on socket") return fmt.Errorf("service started but is not listening on socket")
} }
log.Info().Msgf("RosettaX87 service started successfully with PID: %d", servicePID) log.Infof("RosettaX87 service started successfully with PID: %d", servicePID)
return nil return nil
} }
// StopRosettaX87Service stops the running RosettaX87 service // StopRosettaX87Service stops the running RosettaX87 service
func StopRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) { func StopRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
log.Info().Msg("Stopping RosettaX87 service...") log.Info("Stopping RosettaX87 service...")
if !ServiceRunning { if !ServiceRunning {
dialog.ShowInformation("Service Status", "RosettaX87 service is not running.", myWindow) dialog.ShowInformation("Service Status", "RosettaX87 service is not running.", myWindow)
@@ -354,11 +354,11 @@ func StopRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
// Send SIGTERM to gracefully stop the process // Send SIGTERM to gracefully stop the process
err := serviceCmd.Process.Signal(syscall.SIGTERM) err := serviceCmd.Process.Signal(syscall.SIGTERM)
if err != nil { if err != nil {
log.Info().Msgf("Failed to send SIGTERM to process: %v", err) log.Infof("Failed to send SIGTERM to process: %v", err)
// Try SIGKILL as fallback // Try SIGKILL as fallback
err = serviceCmd.Process.Kill() err = serviceCmd.Process.Kill()
if err != nil { if err != nil {
log.Info().Msgf("Failed to kill process: %v", err) log.Infof("Failed to kill process: %v", err)
dialog.ShowError(fmt.Errorf("failed to stop service: %v", err), myWindow) dialog.ShowError(fmt.Errorf("failed to stop service: %v", err), myWindow)
return return
} }
@@ -370,7 +370,7 @@ func StopRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
ServiceRunning = false ServiceRunning = false
serviceCmd = nil serviceCmd = nil
servicePID = 0 servicePID = 0
log.Info().Msg("RosettaX87 service stopped") log.Info("RosettaX87 service stopped")
fyne.Do(func() { fyne.Do(func() {
dialog.ShowInformation("Service Stopped", "RosettaX87 service has been stopped.", myWindow) dialog.ShowInformation("Service Stopped", "RosettaX87 service has been stopped.", myWindow)
updateAllStatuses() updateAllStatuses()
@@ -407,7 +407,7 @@ func IsServiceRunning() bool {
// CleanupService ensures the service is stopped when the application exits // CleanupService ensures the service is stopped when the application exits
func CleanupService() { func CleanupService() {
log.Info().Msg("Cleaning up RosettaX87 service on application exit...") log.Info("Cleaning up RosettaX87 service on application exit...")
CleanupExistingServices() CleanupExistingServices()
ServiceRunning = false ServiceRunning = false
serviceCmd = nil serviceCmd = nil

View File

@@ -1,7 +1,7 @@
package ui package ui
import ( import (
"github.com/rs/zerolog/log" "epochsilicon/pkg/log"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@@ -27,7 +27,7 @@ func createOptionsComponents() {
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.EnableMetalHud = checked prefs.EnableMetalHud = checked
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
log.Debug().Msgf("Metal HUD enabled: %v", launcher.EnableMetalHud) log.Debugf("Metal HUD enabled: %v", launcher.EnableMetalHud)
}) })
metalHudCheckbox.SetChecked(prefs.EnableMetalHud) metalHudCheckbox.SetChecked(prefs.EnableMetalHud)
launcher.EnableMetalHud = prefs.EnableMetalHud launcher.EnableMetalHud = prefs.EnableMetalHud
@@ -37,7 +37,7 @@ func createOptionsComponents() {
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.ShowTerminalNormally = checked prefs.ShowTerminalNormally = checked
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
log.Debug().Msgf("Show terminal normally: %v", checked) log.Debugf("Show terminal normally: %v", checked)
}) })
showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally) showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally)
@@ -47,7 +47,7 @@ func createOptionsComponents() {
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.AutoDeleteWdb = checked prefs.AutoDeleteWdb = checked
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
log.Debug().Msgf("Auto-delete WDB enabled: %v", launcher.AutoDeleteWdb) log.Debugf("Auto-delete WDB enabled: %v", launcher.AutoDeleteWdb)
}) })
autoDeleteWdbCheckbox.SetChecked(prefs.AutoDeleteWdb) autoDeleteWdbCheckbox.SetChecked(prefs.AutoDeleteWdb)
launcher.AutoDeleteWdb = prefs.AutoDeleteWdb launcher.AutoDeleteWdb = prefs.AutoDeleteWdb
@@ -69,7 +69,7 @@ func createOptionsComponents() {
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.EnvironmentVariables = text prefs.EnvironmentVariables = text
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
log.Debug().Msgf("Environment variables updated: %v", launcher.CustomEnvVars) log.Debugf("Environment variables updated: %v", launcher.CustomEnvVars)
} }
} }
@@ -126,7 +126,7 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
githubURL := "https://git.burkey.co/eburk/epochsilicon" githubURL := "https://git.burkey.co/eburk/epochsilicon"
parsedURL, err := url.Parse(githubURL) parsedURL, err := url.Parse(githubURL)
if err != nil { if err != nil {
log.Debug().Msgf("Error parsing git URL: %v", err) log.Debugf("Error parsing git URL: %v", err)
return return
} }
fyne.CurrentApp().OpenURL(parsedURL) fyne.CurrentApp().OpenURL(parsedURL)
@@ -198,7 +198,7 @@ func createWineRegistryComponents() {
}() }()
if err := utils.SetOptionAsAltEnabled(true); err != nil { if err := utils.SetOptionAsAltEnabled(true); err != nil {
log.Debug().Msgf("Failed to enable Option-as-Alt mapping: %v", err) log.Debugf("Failed to enable Option-as-Alt mapping: %v", err)
// Update UI on main thread // Update UI on main thread
fyne.Do(func() { fyne.Do(func() {
stopPulsingEffect() stopPulsingEffect()
@@ -206,7 +206,7 @@ func createWineRegistryComponents() {
}) })
time.Sleep(2 * time.Second) // Show error briefly time.Sleep(2 * time.Second) // Show error briefly
} else { } else {
log.Debug().Msgf("Successfully enabled Option-as-Alt mapping") log.Debugf("Successfully enabled Option-as-Alt mapping")
// Update preferences // Update preferences
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.RemapOptionAsAlt = true prefs.RemapOptionAsAlt = true
@@ -240,7 +240,7 @@ func createWineRegistryComponents() {
}() }()
if err := utils.SetOptionAsAltEnabled(false); err != nil { if err := utils.SetOptionAsAltEnabled(false); err != nil {
log.Debug().Msgf("Failed to disable Option-as-Alt mapping: %v", err) log.Debugf("Failed to disable Option-as-Alt mapping: %v", err)
// Update UI on main thread // Update UI on main thread
fyne.Do(func() { fyne.Do(func() {
stopPulsingEffect() stopPulsingEffect()
@@ -248,7 +248,7 @@ func createWineRegistryComponents() {
}) })
time.Sleep(2 * time.Second) // Show error briefly time.Sleep(2 * time.Second) // Show error briefly
} else { } else {
log.Debug().Msgf("Successfully disabled Option-as-Alt mapping") log.Debugf("Successfully disabled Option-as-Alt mapping")
// Update preferences // Update preferences
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.RemapOptionAsAlt = false prefs.RemapOptionAsAlt = false

View File

@@ -1,8 +1,8 @@
package ui package ui
import ( import (
"epochsilicon/pkg/log"
"epochsilicon/pkg/paths" "epochsilicon/pkg/paths"
"github.com/rs/zerolog/log"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
@@ -34,7 +34,7 @@ func createLogoContainer() fyne.CanvasObject {
// Load the application logo // Load the application logo
logoResource, err := fyne.LoadResourceFromPath("Icon.png") logoResource, err := fyne.LoadResourceFromPath("Icon.png")
if err != nil { if err != nil {
log.Debug().Msgf("Warning: could not load logo: %v", err) log.Debugf("Warning: could not load logo: %v", err)
} }
// Create the logo image with a smaller fixed size since we have a header now // Create the logo image with a smaller fixed size since we have a header now

View File

@@ -1,8 +1,8 @@
package ui package ui
import ( import (
"epochsilicon/pkg/log"
"git.burkey.co/eburk/epochcli/pkg/epoch" "git.burkey.co/eburk/epochcli/pkg/epoch"
"github.com/rs/zerolog/log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -110,10 +110,10 @@ func updateEpochStatus() {
epochPatchesApplied := false epochPatchesApplied := false
stats, err := epoch.Update(paths.EpochPath, false, true, true) stats, err := epoch.Update(paths.EpochPath, false, true, true)
if err != nil { if err != nil {
log.Debug().Msgf("Failed to get download Epoch patches: %v", err) log.Debugf("Failed to get download Epoch patches: %v", err)
} }
if stats.Outdated == 0 { if stats.Outdated == 0 {
log.Debug().Msg("Nothing is outdated") log.Debug("Nothing is outdated")
epochPatchesApplied = true epochPatchesApplied = true
} }

View File

@@ -1,8 +1,8 @@
package ui package ui
import ( import (
"epochsilicon/pkg/log"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"strings" "strings"
"time" "time"
@@ -105,7 +105,7 @@ func ShowUpdateDialog(updateInfo *utils.UpdateInfo, currentVersion string, myWin
if err != nil { if err != nil {
progressLabel.SetText(fmt.Sprintf("Download failed: %v", err)) progressLabel.SetText(fmt.Sprintf("Download failed: %v", err))
log.Debug().Msgf("Download failed: %v", err) log.Debugf("Download failed: %v", err)
// Re-enable close button // Re-enable close button
d.SetButtons([]fyne.CanvasObject{ d.SetButtons([]fyne.CanvasObject{
@@ -123,7 +123,7 @@ func ShowUpdateDialog(updateInfo *utils.UpdateInfo, currentVersion string, myWin
err = utils.InstallUpdate(downloadPath) err = utils.InstallUpdate(downloadPath)
if err != nil { if err != nil {
progressLabel.SetText(fmt.Sprintf("Installation failed: %v", err)) progressLabel.SetText(fmt.Sprintf("Installation failed: %v", err))
log.Debug().Msgf("Installation failed: %v", err) log.Debugf("Installation failed: %v", err)
// Re-enable close button // Re-enable close button
fyne.DoAndWait(func() { fyne.DoAndWait(func() {

View File

@@ -1,9 +1,9 @@
package utils package utils
import ( import (
"epochsilicon/pkg/log"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"github.com/zalando/go-keyring" "github.com/zalando/go-keyring"
) )
@@ -23,7 +23,7 @@ func SaveSudoPassword(password string) error {
return fmt.Errorf("failed to save password to keychain: %v", err) return fmt.Errorf("failed to save password to keychain: %v", err)
} }
log.Info().Msg("Password saved securely to keychain") log.Info("Password saved securely to keychain")
return nil return nil
} }
@@ -52,7 +52,7 @@ func DeleteSudoPassword() error {
return fmt.Errorf("failed to delete password from keychain: %v", err) return fmt.Errorf("failed to delete password from keychain: %v", err)
} }
log.Info().Msg("Password removed from keychain") log.Info("Password removed from keychain")
return nil return nil
} }

View File

@@ -2,9 +2,9 @@ package utils
import ( import (
"encoding/json" "encoding/json"
"epochsilicon/pkg/log"
"errors" "errors"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"io" "io"
"net/http" "net/http"
"os" "os"
@@ -103,16 +103,16 @@ func CopyDir(src string, dst string) error {
// RunOsascript runs an AppleScript command using osascript. // RunOsascript runs an AppleScript command using osascript.
func RunOsascript(scriptString string, myWindow fyne.Window) bool { func RunOsascript(scriptString string, myWindow fyne.Window) bool {
log.Debug().Msgf("Executing AppleScript: %s", scriptString) log.Debugf("Executing AppleScript: %s", scriptString)
cmd := exec.Command("osascript", "-e", scriptString) cmd := exec.Command("osascript", "-e", scriptString)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
errMsg := fmt.Sprintf("AppleScript failed: %v\nOutput: %s", err, string(output)) errMsg := fmt.Sprintf("AppleScript failed: %v\nOutput: %s", err, string(output))
dialog.ShowError(errors.New(errMsg), myWindow) dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug().Msg(errMsg) log.Debug(errMsg)
return false return false
} }
log.Debug().Msgf("osascript output: %s", string(output)) log.Debugf("osascript output: %s", string(output))
return true return true
} }
@@ -263,14 +263,14 @@ func InstallUpdate(dmgPath string) error {
} }
// Mount the DMG and parse the mount point from plist output // Mount the DMG and parse the mount point from plist output
log.Debug().Msgf("Mounting DMG: %s", dmgPath) log.Debugf("Mounting DMG: %s", dmgPath)
mountCmd := exec.Command("hdiutil", "attach", dmgPath, "-nobrowse", "-plist") mountCmd := exec.Command("hdiutil", "attach", dmgPath, "-nobrowse", "-plist")
mountOutput, err := mountCmd.CombinedOutput() mountOutput, err := mountCmd.CombinedOutput()
if err != nil { if err != nil {
return fmt.Errorf("failed to mount DMG: %v, output: %s", err, string(mountOutput)) return fmt.Errorf("failed to mount DMG: %v, output: %s", err, string(mountOutput))
} }
log.Debug().Msgf("Mount output: %s", string(mountOutput)) log.Debugf("Mount output: %s", string(mountOutput))
mountPoint := "" mountPoint := ""
@@ -291,7 +291,7 @@ func InstallUpdate(dmgPath string) error {
end := strings.Index(nextLine, "</string>") end := strings.Index(nextLine, "</string>")
if start >= 8 && end > start { if start >= 8 && end > start {
mountPoint = nextLine[start:end] mountPoint = nextLine[start:end]
log.Debug().Msgf("Found mount point in plist: %s", mountPoint) log.Debugf("Found mount point in plist: %s", mountPoint)
break break
} }
} }
@@ -300,7 +300,7 @@ func InstallUpdate(dmgPath string) error {
// Fallback: try without -plist flag for simpler output // Fallback: try without -plist flag for simpler output
if mountPoint == "" { if mountPoint == "" {
log.Debug().Msgf("Plist parsing failed, trying simple mount") log.Debugf("Plist parsing failed, trying simple mount")
// Unmount first if something was mounted // Unmount first if something was mounted
exec.Command("hdiutil", "detach", dmgPath, "-force").Run() exec.Command("hdiutil", "detach", dmgPath, "-force").Run()
@@ -320,7 +320,7 @@ func InstallUpdate(dmgPath string) error {
for i := len(parts) - 1; i >= 0; i-- { for i := len(parts) - 1; i >= 0; i-- {
if strings.HasPrefix(parts[i], "/Volumes/") { if strings.HasPrefix(parts[i], "/Volumes/") {
mountPoint = parts[i] mountPoint = parts[i]
log.Debug().Msgf("Found mount point in simple output: %s", mountPoint) log.Debugf("Found mount point in simple output: %s", mountPoint)
break break
} }
} }
@@ -335,11 +335,11 @@ func InstallUpdate(dmgPath string) error {
return fmt.Errorf("could not find mount point. Mount output: %s", string(mountOutput)) return fmt.Errorf("could not find mount point. Mount output: %s", string(mountOutput))
} }
log.Debug().Msgf("Using mount point: %s", mountPoint) log.Debugf("Using mount point: %s", mountPoint)
defer func() { defer func() {
// Unmount the DMG // Unmount the DMG
log.Debug().Msgf("Unmounting DMG from: %s", mountPoint) log.Debugf("Unmounting DMG from: %s", mountPoint)
unmountCmd := exec.Command("hdiutil", "detach", mountPoint, "-force") unmountCmd := exec.Command("hdiutil", "detach", mountPoint, "-force")
unmountCmd.Run() unmountCmd.Run()
}() }()
@@ -353,7 +353,7 @@ func InstallUpdate(dmgPath string) error {
newAppPath = exactPath newAppPath = exactPath
} else { } else {
// Search for any .app bundle in the mount point // Search for any .app bundle in the mount point
log.Debug().Msgf("EpochSilicon.app not found at exact path, searching for .app bundles") log.Debugf("EpochSilicon.app not found at exact path, searching for .app bundles")
entries, err := os.ReadDir(mountPoint) entries, err := os.ReadDir(mountPoint)
if err != nil { if err != nil {
return fmt.Errorf("failed to read DMG contents: %v", err) return fmt.Errorf("failed to read DMG contents: %v", err)
@@ -362,7 +362,7 @@ func InstallUpdate(dmgPath string) error {
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() && strings.HasSuffix(entry.Name(), ".app") { if entry.IsDir() && strings.HasSuffix(entry.Name(), ".app") {
candidatePath := filepath.Join(mountPoint, entry.Name()) candidatePath := filepath.Join(mountPoint, entry.Name())
log.Debug().Msgf("Found .app bundle: %s", candidatePath) log.Debugf("Found .app bundle: %s", candidatePath)
newAppPath = candidatePath newAppPath = candidatePath
break break
} }
@@ -373,11 +373,11 @@ func InstallUpdate(dmgPath string) error {
return fmt.Errorf("no .app bundle found in DMG at %s", mountPoint) return fmt.Errorf("no .app bundle found in DMG at %s", mountPoint)
} }
log.Debug().Msgf("Found app to install: %s", newAppPath) log.Debugf("Found app to install: %s", newAppPath)
// Create backup of current app // Create backup of current app
backupPath := currentAppPath + ".backup" backupPath := currentAppPath + ".backup"
log.Debug().Msgf("Creating backup: %s -> %s", currentAppPath, backupPath) log.Debugf("Creating backup: %s -> %s", currentAppPath, backupPath)
// Remove old backup if it exists // Remove old backup if it exists
if PathExists(backupPath) { if PathExists(backupPath) {
@@ -389,16 +389,16 @@ func InstallUpdate(dmgPath string) error {
} }
// Remove current app // Remove current app
log.Debug().Msgf("Removing current app: %s", currentAppPath) log.Debugf("Removing current app: %s", currentAppPath)
if err := os.RemoveAll(currentAppPath); err != nil { if err := os.RemoveAll(currentAppPath); err != nil {
return fmt.Errorf("failed to remove current app: %v", err) return fmt.Errorf("failed to remove current app: %v", err)
} }
// Copy new app // Copy new app
log.Debug().Msgf("Installing new app: %s -> %s", newAppPath, currentAppPath) log.Debugf("Installing new app: %s -> %s", newAppPath, currentAppPath)
if err := CopyDir(newAppPath, currentAppPath); err != nil { if err := CopyDir(newAppPath, currentAppPath); err != nil {
// Try to restore backup on failure // Try to restore backup on failure
log.Debug().Msgf("Installation failed, restoring backup") log.Debugf("Installation failed, restoring backup")
os.RemoveAll(currentAppPath) os.RemoveAll(currentAppPath)
CopyDir(backupPath, currentAppPath) CopyDir(backupPath, currentAppPath)
return fmt.Errorf("failed to install new app: %v", err) return fmt.Errorf("failed to install new app: %v", err)
@@ -407,25 +407,25 @@ func InstallUpdate(dmgPath string) error {
// Fix executable permissions for the main binary // Fix executable permissions for the main binary
executablePath := filepath.Join(currentAppPath, "Contents", "MacOS", "epochsilicon") executablePath := filepath.Join(currentAppPath, "Contents", "MacOS", "epochsilicon")
if PathExists(executablePath) { if PathExists(executablePath) {
log.Debug().Msgf("Setting executable permissions for: %s", executablePath) log.Debugf("Setting executable permissions for: %s", executablePath)
if err := os.Chmod(executablePath, 0755); err != nil { if err := os.Chmod(executablePath, 0755); err != nil {
log.Debug().Msgf("Warning: failed to set executable permissions: %v", err) log.Debugf("Warning: failed to set executable permissions: %v", err)
// Don't fail the entire update for this, but log it // Don't fail the entire update for this, but log it
} }
} else { } else {
log.Debug().Msgf("Warning: executable not found at expected path: %s", executablePath) log.Debugf("Warning: executable not found at expected path: %s", executablePath)
} }
// Remove backup on success // Remove backup on success
os.RemoveAll(backupPath) os.RemoveAll(backupPath)
log.Debug().Msgf("Update installed successfully") log.Debugf("Update installed successfully")
return nil return nil
} }
// TestDMGMount tests DMG mounting and returns mount point and app path for debugging // TestDMGMount tests DMG mounting and returns mount point and app path for debugging
func TestDMGMount(dmgPath string) (string, string, error) { func TestDMGMount(dmgPath string) (string, string, error) {
log.Debug().Msgf("Testing DMG mount: %s", dmgPath) log.Debugf("Testing DMG mount: %s", dmgPath)
// Mount the DMG with verbose output to better parse mount point // Mount the DMG with verbose output to better parse mount point
mountCmd := exec.Command("hdiutil", "attach", dmgPath, "-nobrowse", "-plist") mountCmd := exec.Command("hdiutil", "attach", dmgPath, "-nobrowse", "-plist")
@@ -434,7 +434,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
return "", "", fmt.Errorf("failed to mount DMG: %v, output: %s", err, string(mountOutput)) return "", "", fmt.Errorf("failed to mount DMG: %v, output: %s", err, string(mountOutput))
} }
log.Debug().Msgf("Mount output: %s", string(mountOutput)) log.Debugf("Mount output: %s", string(mountOutput))
// Parse mount output to get mount point // Parse mount output to get mount point
mountPoint := "" mountPoint := ""
@@ -459,7 +459,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
// Second try: use hdiutil info to get mount points if first method failed // Second try: use hdiutil info to get mount points if first method failed
if mountPoint == "" { if mountPoint == "" {
log.Debug().Msgf("First mount point detection failed, trying hdiutil info") log.Debugf("First mount point detection failed, trying hdiutil info")
infoCmd := exec.Command("hdiutil", "info", "-plist") infoCmd := exec.Command("hdiutil", "info", "-plist")
infoOutput, infoErr := infoCmd.CombinedOutput() infoOutput, infoErr := infoCmd.CombinedOutput()
if infoErr == nil { if infoErr == nil {
@@ -480,7 +480,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
return "", "", fmt.Errorf("could not find mount point. Mount output: %s", string(mountOutput)) return "", "", fmt.Errorf("could not find mount point. Mount output: %s", string(mountOutput))
} }
log.Debug().Msgf("Using mount point: %s", mountPoint) log.Debugf("Using mount point: %s", mountPoint)
// Find the app in the mounted DMG // Find the app in the mounted DMG
var newAppPath string var newAppPath string
@@ -491,7 +491,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
newAppPath = exactPath newAppPath = exactPath
} else { } else {
// Search for any .app bundle in the mount point // Search for any .app bundle in the mount point
log.Debug().Msgf("EpochSilicon.app not found at exact path, searching for .app bundles") log.Debugf("EpochSilicon.app not found at exact path, searching for .app bundles")
entries, err := os.ReadDir(mountPoint) entries, err := os.ReadDir(mountPoint)
if err != nil { if err != nil {
// Unmount before returning error // Unmount before returning error
@@ -502,7 +502,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() && strings.HasSuffix(entry.Name(), ".app") { if entry.IsDir() && strings.HasSuffix(entry.Name(), ".app") {
candidatePath := filepath.Join(mountPoint, entry.Name()) candidatePath := filepath.Join(mountPoint, entry.Name())
log.Debug().Msgf("Found .app bundle: %s", candidatePath) log.Debugf("Found .app bundle: %s", candidatePath)
newAppPath = candidatePath newAppPath = candidatePath
break break
} }
@@ -510,7 +510,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
} }
// Unmount after testing // Unmount after testing
log.Debug().Msgf("Unmounting test DMG from: %s", mountPoint) log.Debugf("Unmounting test DMG from: %s", mountPoint)
exec.Command("hdiutil", "detach", mountPoint, "-force").Run() exec.Command("hdiutil", "detach", mountPoint, "-force").Run()
if newAppPath == "" { if newAppPath == "" {
@@ -530,14 +530,14 @@ func CompareFileWithBundledResource(filePath, resourceName string) bool {
// Get file info for the existing file // Get file info for the existing file
fileInfo, err := os.Stat(filePath) fileInfo, err := os.Stat(filePath)
if err != nil { if err != nil {
log.Debug().Msgf("Failed to stat file %s: %v", filePath, err) log.Debugf("Failed to stat file %s: %v", filePath, err)
return false return false
} }
// Load the bundled resource // Load the bundled resource
resource, err := fyne.LoadResourceFromPath(resourceName) resource, err := fyne.LoadResourceFromPath(resourceName)
if err != nil { if err != nil {
log.Debug().Msgf("Failed to load bundled resource %s: %v", resourceName, err) log.Debugf("Failed to load bundled resource %s: %v", resourceName, err)
return false return false
} }
@@ -545,7 +545,7 @@ func CompareFileWithBundledResource(filePath, resourceName string) bool {
fileSize := fileInfo.Size() fileSize := fileInfo.Size()
resourceSize := int64(len(resource.Content())) resourceSize := int64(len(resource.Content()))
log.Debug().Msgf("Comparing file sizes - %s: %d bytes vs bundled %s: %d bytes", log.Debugf("Comparing file sizes - %s: %d bytes vs bundled %s: %d bytes",
filePath, fileSize, resourceName, resourceSize) filePath, fileSize, resourceName, resourceSize)
return fileSize == resourceSize return fileSize == resourceSize

View File

@@ -1,8 +1,8 @@
package utils package utils
import ( import (
"epochsilicon/pkg/log"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -74,7 +74,7 @@ reg add "%s" /v "RightOptionIsAlt" /t REG_SZ /d "Y" /f
return fmt.Errorf("batch registry add failed: %v, output: %s", err, string(output)) return fmt.Errorf("batch registry add failed: %v, output: %s", err, string(output))
} }
log.Info().Msgf("Successfully enabled Option-as-Alt mapping in Wine registry (optimized)") log.Infof("Successfully enabled Option-as-Alt mapping in Wine registry (optimized)")
return nil return nil
} }
@@ -102,7 +102,7 @@ reg delete "%s" /v "RightOptionIsAlt" /f 2>nul
return fmt.Errorf("batch registry delete failed: %v, output: %s", err, string(output)) return fmt.Errorf("batch registry delete failed: %v, output: %s", err, string(output))
} }
log.Info().Msgf("Successfully disabled Option-as-Alt mapping in Wine registry (optimized)") log.Infof("Successfully disabled Option-as-Alt mapping in Wine registry (optimized)")
return nil return nil
} }
@@ -110,7 +110,7 @@ reg delete "%s" /v "RightOptionIsAlt" /f 2>nul
func CheckOptionAsAltEnabled() bool { func CheckOptionAsAltEnabled() bool {
homeDir, err := os.UserHomeDir() homeDir, err := os.UserHomeDir()
if err != nil { if err != nil {
log.Info().Msgf("Failed to get user home directory: %v", err) log.Infof("Failed to get user home directory: %v", err)
return false return false
} }
@@ -118,7 +118,7 @@ func CheckOptionAsAltEnabled() bool {
// Check if CrossOver wine loader exists // Check if CrossOver wine loader exists
if !PathExists(wineLoaderPath) { if !PathExists(wineLoaderPath) {
log.Info().Msgf("CrossOver wine loader not found at: %s", wineLoaderPath) log.Infof("CrossOver wine loader not found at: %s", wineLoaderPath)
return false return false
} }
@@ -133,18 +133,18 @@ func CheckOptionAsAltEnabled() bool {
func CheckOptionAsAltEnabledFast() bool { func CheckOptionAsAltEnabledFast() bool {
regPath, err := GetWineUserRegPath() regPath, err := GetWineUserRegPath()
if err != nil { if err != nil {
log.Info().Msgf("Failed to get Wine registry path: %v", err) log.Infof("Failed to get Wine registry path: %v", err)
return false return false
} }
if !PathExists(regPath) { if !PathExists(regPath) {
log.Info().Msgf("Wine user.reg file not found at: %s", regPath) log.Infof("Wine user.reg file not found at: %s", regPath)
return false return false
} }
content, err := os.ReadFile(regPath) content, err := os.ReadFile(regPath)
if err != nil { if err != nil {
log.Info().Msgf("Failed to read Wine registry file: %v", err) log.Infof("Failed to read Wine registry file: %v", err)
return false return false
} }
@@ -191,12 +191,12 @@ func SetOptionAsAltEnabled(enabled bool) error {
} else { } else {
err := setRegistryValuesOptimized(winePrefix, false) err := setRegistryValuesOptimized(winePrefix, false)
if err != nil { if err != nil {
log.Info().Msgf("Wine registry disable failed: %v", err) log.Infof("Wine registry disable failed: %v", err)
} }
err2 := setRegistryValuesFast(false) err2 := setRegistryValuesFast(false)
if err2 != nil { if err2 != nil {
log.Info().Msgf("File-based cleanup failed: %v", err2) log.Infof("File-based cleanup failed: %v", err2)
} }
if err != nil { if err != nil {
@@ -334,7 +334,7 @@ func addOptionAsAltSettingsFast(regPath string, lines []string) error {
return fmt.Errorf("failed to write registry file: %v", err) return fmt.Errorf("failed to write registry file: %v", err)
} }
log.Info().Msgf("Successfully enabled Option-as-Alt mapping in Wine registry (fast method)") log.Infof("Successfully enabled Option-as-Alt mapping in Wine registry (fast method)")
return nil return nil
} }
@@ -342,7 +342,7 @@ func addOptionAsAltSettingsFast(regPath string, lines []string) error {
func removeOptionAsAltSettingsFast(regPath string, lines []string) error { func removeOptionAsAltSettingsFast(regPath string, lines []string) error {
if !PathExists(regPath) { if !PathExists(regPath) {
// File doesn't exist, nothing to remove // File doesn't exist, nothing to remove
log.Info().Msgf("Successfully disabled Option-as-Alt mapping in Wine registry (no file to modify)") log.Infof("Successfully disabled Option-as-Alt mapping in Wine registry (no file to modify)")
return nil return nil
} }
@@ -369,7 +369,7 @@ func removeOptionAsAltSettingsFast(regPath string, lines []string) error {
return fmt.Errorf("failed to write registry file: %v", err) return fmt.Errorf("failed to write registry file: %v", err)
} }
log.Info().Msgf("Successfully disabled Option-as-Alt mapping in Wine registry (fast method)") log.Infof("Successfully disabled Option-as-Alt mapping in Wine registry (fast method)")
return nil return nil
} }