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