updater_windows.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package lifecycle
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "log/slog"
  7. "os"
  8. "os/exec"
  9. "path/filepath"
  10. )
  11. func DoUpgrade(cancel context.CancelFunc, done chan int) error {
  12. files, err := filepath.Glob(filepath.Join(UpdateStageDir, "*", "*.exe")) // TODO generalize for multiplatform
  13. if err != nil {
  14. return fmt.Errorf("failed to lookup downloads: %s", err)
  15. }
  16. if len(files) == 0 {
  17. return errors.New("no update downloads found")
  18. } else if len(files) > 1 {
  19. // Shouldn't happen
  20. slog.Warn(fmt.Sprintf("multiple downloads found, using first one %v", files))
  21. }
  22. installerExe := files[0]
  23. slog.Info("starting upgrade with " + installerExe)
  24. slog.Info("upgrade log file " + UpgradeLogFile)
  25. // When running in debug mode, we'll be "verbose" and let the installer pop up and prompt
  26. installArgs := []string{
  27. "/CLOSEAPPLICATIONS", // Quit the tray app if it's still running
  28. "/LOG=" + filepath.Base(UpgradeLogFile), // Only relative seems reliable, so set pwd
  29. "/FORCECLOSEAPPLICATIONS", // Force close the tray app - might be needed
  30. }
  31. // make the upgrade as quiet as possible (no GUI, no prompts)
  32. installArgs = append(installArgs,
  33. "/SP", // Skip the "This will install... Do you wish to continue" prompt
  34. "/SUPPRESSMSGBOXES",
  35. "/SILENT",
  36. "/VERYSILENT",
  37. )
  38. // Safeguard in case we have requests in flight that need to drain...
  39. slog.Info("Waiting for server to shutdown")
  40. cancel()
  41. if done != nil {
  42. <-done
  43. } else {
  44. // Shouldn't happen
  45. slog.Warn("done chan was nil, not actually waiting")
  46. }
  47. slog.Debug(fmt.Sprintf("starting installer: %s %v", installerExe, installArgs))
  48. os.Chdir(filepath.Dir(UpgradeLogFile)) //nolint:errcheck
  49. cmd := exec.Command(installerExe, installArgs...)
  50. if err := cmd.Start(); err != nil {
  51. return fmt.Errorf("unable to start ollama app %w", err)
  52. }
  53. if cmd.Process != nil {
  54. err = cmd.Process.Release()
  55. if err != nil {
  56. slog.Error(fmt.Sprintf("failed to release server process: %s", err))
  57. }
  58. } else {
  59. // TODO - some details about why it didn't start, or is this a pedantic error case?
  60. return errors.New("installer process did not start")
  61. }
  62. // TODO should we linger for a moment and check to make sure it's actually running by checking the pid?
  63. slog.Info("Installer started in background, exiting")
  64. os.Exit(0)
  65. // Not reached
  66. return nil
  67. }