fix(packaging): stop the service before the package is removed

Removing the package left the user service running from the deleted
binary, with ~/ProtonDrive still mounted. A user who then deleted the
folder to clean up had every file in it moved to the Proton Drive trash,
as any delete through the mount is.

The .deb (prerm on remove), the .rpm (%preun on erase) and the Arch
packages (pre_remove) now stop proton-drive.service for every user with
a running user manager, through runuser with that user's
XDG_RUNTIME_DIR, so no systemd-machined is needed. Upgrades are left
alone. Queued writes stay in the state directory for a later install.

The pacman install script lives once in packaging/ and the AUR
directories link it; push.sh copies its content into each AUR
repository. The uninstall guide now warns not to delete the mount point
while the service runs.

Reported on Reddit by a user who restored the files from the trash.
This commit is contained in:
nvrl committed 2026-10-12 00:07:07 +02:00
1 parent ee76f4ac60
commit e0442c56b9
21 files changed
+99 -5

No files matched your search

+3
View File
@@ -153,6 +153,9 @@ jobs:
cp LICENSE deb/usr/share/licenses/proton-drive-linux/
po/build.sh deb/usr/share/locale
# Stops the running daemon before removal, so the mount stops mirroring deletes
install -m755 packaging/deb/prerm deb/DEBIAN/prerm
# Calculate Installed-Size in KB for the control file
INSTALLED_SIZE=$(du -sk deb | cut -f1)
+4
View File
@@ -18,6 +18,10 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
([#37](https://github.com/narrrl/proton-drive-linux/issues/37))
### Fixed
- **Removing the package left the drive mounted, and deletes there still reached Proton Drive.**
The service kept running from the removed program, so deleting `~/ProtonDrive` afterwards moved
its files to the Proton Drive trash. The .deb, .rpm and Arch packages now stop the service of
every logged-in user before they are removed. Upgrades are not affected.
- **The Fedora package installed KDE packages on GNOME.** Its recommendation of KWallet is now
only for Plasma, the GNOME keyring only for desktops other than Plasma, and the AppIndicator
extension only for GNOME.
+9 -2
View File
@@ -302,8 +302,15 @@ pdfs logout # removes the session from the
```
Then remove the package (`sudo apt remove proton-drive-linux`, `sudo dnf remove
proton-drive-linux`, or `sudo pacman -R proton-drive-for-linux`), and, if you want no trace left,
the local data:
proton-drive-linux`, or `sudo pacman -R proton-drive-for-linux`). Removing the package also stops
the service of every logged-in user, in case a step above was skipped.
> [!CAUTION]
> Do not delete `~/ProtonDrive` while it is mounted. It is your Proton Drive, not a copy: every
> file deleted there is moved to the Proton Drive trash. Once the service is stopped the folder is
> an empty mount point, and removing it is safe.
If you want no trace left, remove the local data as well:
```bash
rm -rf ~/.config/proton-drive-linux ~/.local/state/proton-drive-linux ~/.cache/proton-drive-linux
+2
View File
@@ -26,6 +26,8 @@ optdepends=('gnome-keyring: credential storage via Secret Service'
'fzf: live search-as-you-type launcher (pdfs-prompt --fzf)'
'foot: terminal for pdfs-prompt --fzf started from a keybinding')
options=('!lto' '!debug')
# Stops the running daemon before removal, so the mount stops mirroring deletes.
install=proton-drive.install
# Built in place from the checkout; nothing to fetch or checksum.
source=()
+2 -1
View File
@@ -13,7 +13,8 @@ The three packages conflict with each other and with the in-tree
`packaging/PKGBUILD` package (`proton-drive-linux`), and every one of them
`provides` `proton-drive-for-linux`, `proton-drive-linux`, and `pdfs`.
Each directory tracks only `PKGBUILD`, `.SRCINFO`, `.gitignore`, and `LICENSE`
Each directory tracks only `PKGBUILD`, `.SRCINFO`, `.gitignore`, `LICENSE` and
`proton-drive.install` (a link to `packaging/proton-drive.install`, copied as a file on push)
(the 0BSD license of the packaging sources, per
[RFC40](https://rfc.archlinux.page/0040-license-package-sources/)); the
`.gitignore` ignores everything else so downloaded sources, `src/`, `pkg/`, and
@@ -3,6 +3,7 @@ pkgbase = proton-drive-for-linux-bin
pkgver = 3.3.0
pkgrel = 1
url = https://proton-drive.narl.io
install = proton-drive.install
arch = x86_64
license = MIT
depends = fuse3
@@ -5,3 +5,4 @@
!.SRCINFO
!LICENSE
!PKGBUILD
!proton-drive.install
@@ -22,6 +22,8 @@ provides=("${pkgname%-bin}=$pkgver" "proton-drive-linux=$pkgver" 'pdfs')
conflicts=('proton-drive-linux' 'proton-drive-for-linux' 'proton-drive-for-linux-git')
# Upstream ships the binaries already built on Ubuntu 24.04; do not rewrite them.
options=('!strip' '!debug')
# Stops the running daemon before removal, so the mount stops mirroring deletes.
install=proton-drive.install
_tag="v$pkgver"
_raw="https://raw.githubusercontent.com/narrrl/proton-drive-linux/$_tag"
# The release tarball holds the four binaries only, so the desktop integration
@@ -0,0 +1 @@
../../proton-drive.install
@@ -3,6 +3,7 @@ pkgbase = proton-drive-for-linux-git
pkgver = 3.3.0.r0.g160626b
pkgrel = 1
url = https://proton-drive.narl.io
install = proton-drive.install
arch = x86_64
license = MIT
makedepends = cargo
@@ -5,3 +5,4 @@
!.SRCINFO
!LICENSE
!PKGBUILD
!proton-drive.install
@@ -23,6 +23,8 @@ provides=("${pkgname%-git}=$pkgver" "proton-drive-linux=$pkgver" 'pdfs')
conflicts=('proton-drive-linux' 'proton-drive-for-linux' 'proton-drive-for-linux-bin')
# LTO has broken GTK/Rust links for this workspace; the release profile keeps it off.
options=('!lto')
# Stops the running daemon before removal, so the mount stops mirroring deletes.
install=proton-drive.install
source=("$pkgname::git+$_repo.git")
sha256sums=('SKIP')
@@ -0,0 +1 @@
../../proton-drive.install
@@ -3,6 +3,7 @@ pkgbase = proton-drive-for-linux
pkgver = 3.3.0
pkgrel = 1
url = https://proton-drive.narl.io
install = proton-drive.install
arch = x86_64
license = MIT
makedepends = cargo
@@ -5,3 +5,4 @@
!.SRCINFO
!LICENSE
!PKGBUILD
!proton-drive.install
@@ -23,6 +23,8 @@ provides=("proton-drive-linux=$pkgver" 'pdfs')
conflicts=('proton-drive-linux' 'proton-drive-for-linux-bin' 'proton-drive-for-linux-git')
# LTO has broken GTK/Rust links for this workspace; the release profile keeps it off.
options=('!lto')
# Stops the running daemon before removal, so the mount stops mirroring deletes.
install=proton-drive.install
source=("$pkgname-$pkgver.tar.gz::$_repo/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('ef58e96e64697917168f111958aaadf01c8eaac9fb482d0f6e70dfdc8ed4f167')
@@ -0,0 +1 @@
../../proton-drive.install
+4 -2
View File
@@ -21,9 +21,11 @@ for pkg in "${packages[@]}"; do
# A fresh clone every time: the AUR repository, not this checkout, is what the
# commit history has to build on.
git -c init.defaultBranch=master clone -q "ssh://aur@aur.archlinux.org/$pkg.git" "$workdir/$pkg"
install -m644 "$pkg/PKGBUILD" "$pkg/.SRCINFO" "$pkg/.gitignore" "$pkg/LICENSE" "$workdir/$pkg/"
# proton-drive.install is a link into packaging/; install copies its content.
install -m644 "$pkg/PKGBUILD" "$pkg/.SRCINFO" "$pkg/.gitignore" "$pkg/LICENSE" \
"$pkg/proton-drive.install" "$workdir/$pkg/"
git -C "$workdir/$pkg" add -f PKGBUILD .SRCINFO .gitignore LICENSE
git -C "$workdir/$pkg" add -f PKGBUILD .SRCINFO .gitignore LICENSE proton-drive.install
if git -C "$workdir/$pkg" diff --cached --quiet; then
echo "$pkg: no changes"
continue
+22
View File
@@ -0,0 +1,22 @@
#!/bin/sh
# Removing the package does not stop a running daemon: it keeps serving the
# mount from the deleted binary, so files deleted under the mount afterwards,
# `rm -rf ~/ProtonDrive` included, are still deleted on Proton Drive. Stop every
# logged-in user's service first; anything still queued stays on disk for the
# next install. Same loop as packaging/proton-drive.install.
set -e
case "$1" in
remove) ;;
*) exit 0 ;;
esac
for dir in /run/user/*; do
user=$(id -nu "${dir##*/}" 2>/dev/null) || continue
if runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user --quiet is-active proton-drive.service 2>/dev/null; then
echo "Stopping Proton Drive for $user, which unmounts its drive."
runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user stop proton-drive.service 2>/dev/null || :
fi
done
+19
View File
@@ -92,6 +92,25 @@ install -D -m0644 %{git_dir}/packaging/proton-drive.service \
%{buildroot}/usr/lib/systemd/user/proton-drive.service
%{git_dir}/po/build.sh %{buildroot}%{_datadir}/locale
# Removing the package does not stop a running daemon: it keeps serving the
# mount from the deleted binary, so files deleted under the mount afterwards,
# `rm -rf ~/ProtonDrive` included, are still deleted on Proton Drive. Stop every
# logged-in user's service first; anything still queued stays on disk for the
# next install. $1 is 0 on an erase and 1 on an upgrade. Same loop as
# packaging/proton-drive.install.
%preun
if [ "$1" -eq 0 ]; then
for dir in /run/user/*; do
user=$(id -nu "${dir##*/}" 2>/dev/null) || continue
if runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user --quiet is-active proton-drive.service 2>/dev/null; then
echo "Stopping Proton Drive for $user, which unmounts its drive."
runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user stop proton-drive.service 2>/dev/null || :
fi
done
fi
%files
%license LICENSE
%{_bindir}/pdfs
+19
View File
@@ -0,0 +1,19 @@
# pacman install script, shared by packaging/PKGBUILD and the three AUR packages
# (each links it). The same loop is in packaging/deb/prerm and the RPM %preun.
# Removing the package does not stop a running daemon: it keeps serving the
# mount from the deleted binary, so files deleted under the mount afterwards,
# `rm -rf ~/ProtonDrive` included, are still deleted on Proton Drive. Stop every
# logged-in user's service first; anything still queued stays on disk for the
# next install. Upgrades call pre_upgrade, not this.
pre_remove() {
for dir in /run/user/*; do
user=$(id -nu "${dir##*/}" 2>/dev/null) || continue
if runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user --quiet is-active proton-drive.service 2>/dev/null; then
echo "Stopping Proton Drive for $user, which unmounts its drive."
runuser -u "$user" -- env XDG_RUNTIME_DIR="$dir" \
systemctl --user stop proton-drive.service 2>/dev/null || :
fi
done
}