diff --git a/CHANGELOG.md b/CHANGELOG.md index 023125aa..e86b7cea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,13 @@ See also the [v0.107.19 GitHub milestone][ms-v0.107.19]. [ms-v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/milestone/55?closed=1 --> +### Added + +- The new `--update` command-line option, which allows updating AdGuard Home + silently ([#4223]). + +[#4223]: https://github.com/AdguardTeam/AdGuardHome/issues/4223 + ## [v0.107.18] - 2022-11-08 diff --git a/internal/home/home.go b/internal/home/home.go index 61bdaba2..6ff698d3 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -542,6 +542,11 @@ func run(opts options, clientBuildFS fs.FS) { } } + // TODO(a.garipov): This could be made much earlier and could be done on + // the first run as well, but to achieve this we need to bypass requests + // over dnsforward resolver. + cmdlineUpdate(opts) + Context.web.Start() // wait indefinitely for other go-routines to complete their job @@ -927,3 +932,37 @@ type jsonError struct { // Message is the error message, an opaque string. Message string `json:"message"` } + +// cmdlineUpdate updates current application and exits. +func cmdlineUpdate(opts options) { + if !opts.performUpdate { + return + } + + log.Info("starting update") + + if Context.firstRun { + log.Info("update not allowed on first run") + + os.Exit(0) + } + + _, err := Context.updater.VersionInfo(true) + if err != nil { + vcu := Context.updater.VersionCheckURL() + log.Error("getting version info from %s: %s", vcu, err) + + os.Exit(0) + } + + if Context.updater.NewVersion() == "" { + log.Info("no updates available") + + os.Exit(0) + } + + err = Context.updater.Update() + fatalOnError(err) + + os.Exit(0) +} diff --git a/internal/home/options.go b/internal/home/options.go index e14e26f6..befc78a2 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -47,6 +47,9 @@ type options struct { // disableUpdate, if set, makes AdGuard Home not check for updates. disableUpdate bool + // performUpdate, if set, updates AdGuard Home without GUI and exits. + performUpdate bool + // verbose shows if verbose logging is enabled. verbose bool @@ -221,6 +224,14 @@ var cmdLineOpts = []cmdLineOpt{{ description: "Don't check for updates.", longName: "no-check-update", shortName: "", +}, { + updateWithValue: nil, + updateNoValue: func(o options) (options, error) { o.performUpdate = true; return o, nil }, + effect: nil, + serialize: func(o options) (val string, ok bool) { return "", o.performUpdate }, + description: "Update application and exit.", + longName: "update", + shortName: "", }, { updateWithValue: nil, updateNoValue: nil, diff --git a/internal/home/options_test.go b/internal/home/options_test.go index 32b4243a..2b507535 100644 --- a/internal/home/options_test.go +++ b/internal/home/options_test.go @@ -103,6 +103,11 @@ func TestParseDisableUpdate(t *testing.T) { assert.True(t, testParseOK(t, "--no-check-update").disableUpdate, "--no-check-update is disable update") } +func TestParsePerformUpdate(t *testing.T) { + assert.False(t, testParseOK(t).performUpdate, "empty is not perform update") + assert.True(t, testParseOK(t, "--update").performUpdate, "--update is perform update") +} + // TODO(e.burkov): Remove after v0.108.0. func TestParseDisableMemoryOptimization(t *testing.T) { o, eff, err := parseCmdOpts("", []string{"--no-mem-optimization"}) @@ -169,6 +174,10 @@ func TestOptsToArgs(t *testing.T) { name: "disable_update", args: []string{"--no-check-update"}, opts: options{disableUpdate: true}, + }, { + name: "perform_update", + args: []string{"--update"}, + opts: options{performUpdate: true}, }, { name: "control_action", args: []string{"-s", "run"},