33package main
44
55import (
6+ "encoding/json"
67 "encoding/xml"
78 "fmt"
89 "io"
@@ -17,6 +18,76 @@ import (
1718 "github.com/pilot-protocol/updater"
1819)
1920
21+ // autoUpdateStatePath is the JSON control file ({"enabled": bool}) shared with
22+ // the pilot-updater loop (passed as its --state-path). Automatic updates are
23+ // OFF by default: when the file is absent the updater applies nothing.
24+ func autoUpdateStatePath () string { return configDir () + "/auto-update.json" }
25+
26+ // autoUpdateEnabled reports the persisted auto-update setting (default off).
27+ func autoUpdateEnabled () bool {
28+ data , err := os .ReadFile (autoUpdateStatePath ())
29+ if err != nil {
30+ return false
31+ }
32+ var s struct {
33+ Enabled bool `json:"enabled"`
34+ }
35+ if err := json .Unmarshal (data , & s ); err != nil {
36+ return false
37+ }
38+ return s .Enabled
39+ }
40+
41+ // cmdAutoUpdateSet turns automatic updates on or off (`pilotctl update
42+ // enable|disable`). The pilot-updater re-reads the file each tick, so this
43+ // takes effect without restarting it.
44+ func cmdAutoUpdateSet (on bool ) {
45+ path := autoUpdateStatePath ()
46+ _ = os .MkdirAll (configDir (), 0o755 )
47+ data , _ := json .MarshalIndent (map [string ]bool {"enabled" : on }, "" , " " )
48+ if err := os .WriteFile (path , append (data , '\n' ), 0o644 ); err != nil {
49+ fatalCode ("internal" , "write %s: %v" , path , err )
50+ }
51+ if jsonOutput {
52+ outputOK (map [string ]interface {}{"auto_update" : on })
53+ return
54+ }
55+ if on {
56+ fmt .Println ("Automatic updates ENABLED. The updater will install new stable releases on its check interval." )
57+ fmt .Println ("Disable any time with: pilotctl update disable" )
58+ } else {
59+ fmt .Println ("Automatic updates DISABLED. Nothing will be installed automatically." )
60+ fmt .Println ("Run a one-time manual update with: pilotctl update" )
61+ }
62+ }
63+
64+ // cmdAutoUpdateStatus shows whether automatic updates are on and the current
65+ // version (`pilotctl update status`).
66+ func cmdAutoUpdateStatus () {
67+ on := autoUpdateEnabled ()
68+ if jsonOutput {
69+ outputOK (map [string ]interface {}{
70+ "auto_update" : on ,
71+ "current_version" : version ,
72+ "state_file" : autoUpdateStatePath (),
73+ })
74+ return
75+ }
76+ state := "disabled"
77+ if on {
78+ state = "enabled"
79+ }
80+ fmt .Printf ("Automatic updates: %s\n " , state )
81+ fmt .Printf ("Current version: %s\n " , version )
82+ fmt .Printf ("State file: %s\n " , autoUpdateStatePath ())
83+ if on {
84+ fmt .Println ("\n Turn off with: pilotctl update disable" )
85+ } else {
86+ fmt .Println ("\n Turn on with: pilotctl update enable" )
87+ fmt .Println ("One-time check: pilotctl update" )
88+ }
89+ }
90+
2091// changelogFeedURL is the canonical RSS 2.0 feed for the public Pilot
2192// Protocol changelog. Hosted on GitHub Pages from the pilot-changelog
2293// repo (per `pilot-changelog/README.md`). RSS chosen over feed.json so
@@ -218,6 +289,22 @@ func collapseWhitespace(s string) string {
218289// --pin <tag> : pin to a specific release tag (e.g. v1.10.5)
219290// (global) --json : emit machine-readable JSON
220291func cmdUpdate (args []string ) {
292+ // Auto-update control surface: `pilotctl update status|enable|disable`.
293+ // Bare `pilotctl update` (or with --repo/--pin flags) runs a one-shot
294+ // manual update, which works regardless of the auto-update setting.
295+ if len (args ) >= 1 {
296+ switch args [0 ] {
297+ case "status" :
298+ cmdAutoUpdateStatus ()
299+ return
300+ case "enable" , "on" :
301+ cmdAutoUpdateSet (true )
302+ return
303+ case "disable" , "off" :
304+ cmdAutoUpdateSet (false )
305+ return
306+ }
307+ }
221308 flags , _ := parseFlags (args )
222309 repo := flagString (flags , "repo" , "pilot-protocol/pilotprotocol" )
223310 pin := flagString (flags , "pin" , "" )
0 commit comments