| 32 | } |
| 33 | |
| 34 | func runUpdateCommand() error { |
| 35 | if os.Getenv("TNR_NO_SELFUPDATE") == "1" { |
| 36 | return usageErr("self-update is disabled (TNR_NO_SELFUPDATE=1)") |
| 37 | } |
| 38 | |
| 39 | // Finalize any previously staged Windows update before checking again |
| 40 | if err := autoupdate.FinalizeWindowsSwap(); err != nil { |
| 41 | fmt.Fprintln(os.Stderr, tui.RenderWarning(fmt.Sprintf("failed to finalize staged Windows update: %v", err))) |
| 42 | } |
| 43 | |
| 44 | parentCtx := context.Background() |
| 45 | ctx, cancel := context.WithTimeout(parentCtx, 5*time.Minute) |
| 46 | defer cancel() |
| 47 | |
| 48 | // Force fresh check (ignores cache) |
| 49 | policyResult, err := updatepolicy.Check(ctx, version.BuildVersion, true) |
| 50 | if err != nil { |
| 51 | return fmt.Errorf("update check failed: %w", err) |
| 52 | } |
| 53 | |
| 54 | if !policyResult.Mandatory && !policyResult.Optional { |
| 55 | fmt.Println(tui.RenderUpToDate(displayVersion(policyResult.CurrentVersion))) |
| 56 | return nil |
| 57 | } |
| 58 | |
| 59 | binPath, _ := getCurrentBinaryPath() |
| 60 | if binPath != "" && autoupdate.IsPMManaged(binPath) { |
| 61 | return handlePMUpdate(policyResult, binPath) |
| 62 | } |
| 63 | |
| 64 | if policyResult.Mandatory { |
| 65 | handleMandatoryUpdate(parentCtx, policyResult, true) |
| 66 | // handleMandatoryUpdate exits the process |
| 67 | return nil |
| 68 | } |
| 69 | |
| 70 | // Explicit request: skip TTL cache |
| 71 | return handleExplicitOptionalUpdate(parentCtx, policyResult) |
| 72 | } |
| 73 | |
| 74 | func handlePMUpdate(res updatepolicy.Result, binPath string) error { |
| 75 | pm := detectPackageManager(binPath) |