detached 283a119

feat(updater): disable self-update for pacman/AUR installs

commit
283a119221c745792194d455ce3d139040d541bc
author
bnema · · 2025-12-30 21:25 UTC
parent
15e7c83
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +34 -1
M CHANGELOG.md +1 -0
@@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
1010 - `dumber-browser-git`: Build from source, tracks latest git.
1111 - Install with `yay -S dumber-browser-bin` or `paru -S dumber-browser-bin`.
1212 - Automatic AUR updates via GitHub Actions (1 hour delay after Flatpak build for safety).
13+- **Pacman/AUR install detection**: Self-updater is disabled when installed via pacman/AUR (uses `pacman -Qo` to detect package ownership).
1314
1415 ### Changed
1516
@@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
10 - `dumber-browser-git`: Build from source, tracks latest git.10 - `dumber-browser-git`: Build from source, tracks latest git.
11 - Install with `yay -S dumber-browser-bin` or `paru -S dumber-browser-bin`.11 - Install with `yay -S dumber-browser-bin` or `paru -S dumber-browser-bin`.
12 - Automatic AUR updates via GitHub Actions (1 hour delay after Flatpak build for safety).12 - Automatic AUR updates via GitHub Actions (1 hour delay after Flatpak build for safety).
13+- **Pacman/AUR install detection**: Self-updater is disabled when installed via pacman/AUR (uses `pacman -Qo` to detect package ownership).
13 14
14 ### Changed15 ### Changed
15 16
M internal/infrastructure/env/manager.go +25 -0
@@ -5,6 +5,7 @@ import (
55 "context"
66 "fmt"
77 "os"
8+ "os/exec"
89 "path/filepath"
910 "strings"
1011
@@ -20,6 +21,30 @@ func IsFlatpak() bool {
2021 return err == nil
2122 }
2223
24+// IsPacman returns true if the application was installed via pacman (including AUR).
25+// Packages managed by pacman should not self-update; use pacman/AUR helpers instead.
26+// Detection uses `pacman -Qo` to check if the binary is owned by a package.
27+func IsPacman() bool {
28+ exe, err := os.Executable()
29+ if err != nil {
30+ return false
31+ }
32+ resolved, err := filepath.EvalSymlinks(exe)
33+ if err != nil {
34+ return false
35+ }
36+
37+ // Check if pacman exists and if it owns this binary
38+ pacman, err := exec.LookPath("pacman")
39+ if err != nil {
40+ return false
41+ }
42+
43+ // pacman -Qo returns 0 if the file is owned by a package
44+ cmd := exec.Command(pacman, "-Qo", resolved)
45+ return cmd.Run() == nil
46+}
47+
2348 // Manager implements port.RenderingEnvManager for configuring
2449 // environment variables for GStreamer, WebKit, and GTK/GSK.
2550 type Manager struct {
@@ -5,6 +5,7 @@ import (
5 "context"5 "context"
6 "fmt"6 "fmt"
7 "os"7 "os"
8+ "os/exec"
8 "path/filepath"9 "path/filepath"
9 "strings"10 "strings"
10 11
@@ -20,6 +21,30 @@ func IsFlatpak() bool {
20 return err == nil21 return err == nil
21 }22 }
22 23
24+// IsPacman returns true if the application was installed via pacman (including AUR).
25+// Packages managed by pacman should not self-update; use pacman/AUR helpers instead.
26+// Detection uses `pacman -Qo` to check if the binary is owned by a package.
27+func IsPacman() bool {
28+ exe, err := os.Executable()
29+ if err != nil {
30+ return false
31+ }
32+ resolved, err := filepath.EvalSymlinks(exe)
33+ if err != nil {
34+ return false
35+ }
36+
37+ // Check if pacman exists and if it owns this binary
38+ pacman, err := exec.LookPath("pacman")
39+ if err != nil {
40+ return false
41+ }
42+
43+ // pacman -Qo returns 0 if the file is owned by a package
44+ cmd := exec.Command(pacman, "-Qo", resolved)
45+ return cmd.Run() == nil
46+}
47+
23 // Manager implements port.RenderingEnvManager for configuring48 // Manager implements port.RenderingEnvManager for configuring
24 // environment variables for GStreamer, WebKit, and GTK/GSK.49 // environment variables for GStreamer, WebKit, and GTK/GSK.
25 type Manager struct {50 type Manager struct {
M internal/infrastructure/updater/applier.go +8 -1
@@ -59,7 +59,8 @@ func (a *Applier) stagedBinaryPath() string {
5959 }
6060
6161 // CanSelfUpdate checks if the current binary is writable by the current user.
62-// Returns false if running inside a Flatpak sandbox (updates handled by Flatpak).
62+// Returns false if running inside a Flatpak sandbox (updates handled by Flatpak)
63+// or if installed via pacman/AUR (updates handled by package manager).
6364 func (a *Applier) CanSelfUpdate(ctx context.Context) bool {
6465 log := logging.FromContext(ctx)
6566
@@ -69,6 +70,12 @@ func (a *Applier) CanSelfUpdate(ctx context.Context) bool {
6970 return false
7071 }
7172
73+ // Pacman/AUR packages should not self-update; use pacman or AUR helper.
74+ if env.IsPacman() {
75+ log.Debug().Msg("installed via pacman/AUR, self-update disabled")
76+ return false
77+ }
78+
7279 binaryPath, err := a.GetBinaryPath()
7380 if err != nil {
7481 log.Debug().Err(err).Msg("failed to get binary path")
@@ -59,7 +59,8 @@ func (a *Applier) stagedBinaryPath() string {
59 }59 }
60 60
61 // CanSelfUpdate checks if the current binary is writable by the current user.61 // CanSelfUpdate checks if the current binary is writable by the current user.
62-// Returns false if running inside a Flatpak sandbox (updates handled by Flatpak).62+// Returns false if running inside a Flatpak sandbox (updates handled by Flatpak)
63+// or if installed via pacman/AUR (updates handled by package manager).
63 func (a *Applier) CanSelfUpdate(ctx context.Context) bool {64 func (a *Applier) CanSelfUpdate(ctx context.Context) bool {
64 log := logging.FromContext(ctx)65 log := logging.FromContext(ctx)
65 66
@@ -69,6 +70,12 @@ func (a *Applier) CanSelfUpdate(ctx context.Context) bool {
69 return false70 return false
70 }71 }
71 72
73+ // Pacman/AUR packages should not self-update; use pacman or AUR helper.
74+ if env.IsPacman() {
75+ log.Debug().Msg("installed via pacman/AUR, self-update disabled")
76+ return false
77+ }
78+
72 binaryPath, err := a.GetBinaryPath()79 binaryPath, err := a.GetBinaryPath()
73 if err != nil {80 if err != nil {
74 log.Debug().Err(err).Msg("failed to get binary path")81 log.Debug().Err(err).Msg("failed to get binary path")

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close