mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 00:47:00 +01:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e402981708 | ||
|
|
453c439b74 | ||
|
|
ceba0f5849 |
No files matched your search
@@ -0,0 +1,52 @@
|
||||
name: Nix
|
||||
|
||||
# Builds the flake (docs/INSTALL.md#nixos-flake) whenever its recipe, the lock
|
||||
# files or the code change, so a NixOS user's `nix build` keeps working. Run it
|
||||
# from the Actions tab for any branch to get a build to try.
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'packaging/nix/**'
|
||||
- 'Cargo.lock'
|
||||
- 'Cargo.toml'
|
||||
- 'crates/**'
|
||||
- 'po/**'
|
||||
- '.github/workflows/nix.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'packaging/nix/**'
|
||||
- 'Cargo.lock'
|
||||
- '.github/workflows/nix.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: nix-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: cachix/install-nix-action@v31
|
||||
|
||||
- name: Check the flake
|
||||
run: nix flake check --print-build-logs --no-build
|
||||
|
||||
- name: Build the package
|
||||
run: nix build --print-build-logs .#proton-drive-linux
|
||||
|
||||
- name: Smoke test
|
||||
run: |
|
||||
./result/bin/pdfs --version
|
||||
for bin in pdfs-app pdfs-tray pdfs-prompt; do test -x "result/bin/$bin"; done
|
||||
grep -q "ExecStart=$(readlink -f result)/bin/pdfs" result/lib/systemd/user/proton-drive.service
|
||||
ls result/share/locale/*/LC_MESSAGES/pdfs.mo
|
||||
@@ -3,3 +3,5 @@
|
||||
*.pdb
|
||||
.env
|
||||
/rpmbuild
|
||||
/result
|
||||
/result-*
|
||||
Generated
+4
-4
@@ -3474,7 +3474,7 @@ checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
|
||||
|
||||
[[package]]
|
||||
name = "pdfs-cli"
|
||||
version = "3.2.1"
|
||||
version = "3.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -3490,7 +3490,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfs-core"
|
||||
version = "3.2.1"
|
||||
version = "3.2.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.23.1",
|
||||
@@ -3516,7 +3516,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfs-fuse"
|
||||
version = "3.2.1"
|
||||
version = "3.2.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.23.1",
|
||||
@@ -3538,7 +3538,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfs-gui"
|
||||
version = "3.2.1"
|
||||
version = "3.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel",
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ resolver = "2"
|
||||
members = ["crates/pdfs-core", "crates/pdfs-fuse", "crates/pdfs-cli", "crates/pdfs-gui"]
|
||||
|
||||
[workspace.package]
|
||||
version = "3.2.1"
|
||||
version = "3.2.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
authors = ["Nils Pukropp <contact@narl.io>"]
|
||||
|
||||
@@ -76,6 +76,7 @@ scriptable CLI.
|
||||
| Debian, Ubuntu 24.04 or newer | `.deb` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
||||
| Fedora 44 or newer | `.rpm` from the [latest release](https://github.com/narrrl/proton-drive-linux/releases/latest) |
|
||||
| Arch Linux | [`proton-drive-for-linux`](https://aur.archlinux.org/packages/proton-drive-for-linux) (also `-bin` and `-git`) in the AUR |
|
||||
| NixOS | The flake in this repository: see [Install → NixOS](docs/INSTALL.md#nixos-flake) |
|
||||
| Anything else | [Build from source](docs/INSTALL.md#build-from-source) |
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1689,16 +1689,9 @@ fn writing_nodes_does_not_scale_with_the_size_of_the_index() {
|
||||
.collect();
|
||||
db.upsert_nodes(&batch).unwrap();
|
||||
|
||||
// The fastest of a few runs: the rest of the suite runs alongside, and
|
||||
// one run that lost the CPU to it read as the regression.
|
||||
(0..5)
|
||||
.map(|_| {
|
||||
let t = Instant::now();
|
||||
db.upsert_nodes(&batch).unwrap();
|
||||
t.elapsed()
|
||||
})
|
||||
.min()
|
||||
.unwrap()
|
||||
let t = Instant::now();
|
||||
db.upsert_nodes(&batch).unwrap();
|
||||
t.elapsed()
|
||||
}
|
||||
|
||||
let small = cost_against_index_of(200);
|
||||
|
||||
+5
-21
@@ -11,9 +11,11 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.2.1] — 2026-10-11
|
||||
|
||||
Schema: **42**, unchanged.
|
||||
### Added
|
||||
- **A Nix flake for NixOS.** `nix build github:narrrl/proton-drive-linux` builds the client, and
|
||||
the flake's NixOS module installs it and runs the mount in every graphical session. See
|
||||
[Install → NixOS](INSTALL.md#nixos-flake).
|
||||
([#37](https://github.com/narrrl/proton-drive-linux/issues/37))
|
||||
|
||||
### Fixed
|
||||
- **Writing to a file again soon after a partial write could fail with an I/O error.** When the
|
||||
@@ -24,22 +26,6 @@ Schema: **42**, unchanged.
|
||||
the app, as on secureblue, the app now offers it in your browser and continues the sign-in
|
||||
once you are done. `pdfs login` now handles a CAPTCHA the same way instead of failing.
|
||||
([#29](https://github.com/narrrl/proton-drive-linux/issues/29))
|
||||
- **The daemon kept several CPU cores busy while offline with changes queued.** Its upload
|
||||
workers checked the queue in a tight loop for as long as the outage lasted. They now sleep
|
||||
until the connection comes back. ([#35](https://github.com/narrrl/proton-drive-linux/issues/35))
|
||||
- **An expired sign-in was shown as "offline" for good.** When Proton refuses the session, the
|
||||
tray now says "Session expired — sign in again" with a Sign In Again… item, the app shows the
|
||||
same with a button, and `pdfs status` and `pdfs diagnose` tell you to run `pdfs login`. Cached
|
||||
files stay readable and changes stay queued until you sign in.
|
||||
([#35](https://github.com/narrrl/proton-drive-linux/issues/35))
|
||||
- **The sign-in could be lost after `pdfs login`, `pdfs unlock` or a slow network.** The old
|
||||
daemon wrote its spent tokens over a new sign-in when it stopped, a timeout could drop a token
|
||||
refresh halfway, and a refresh was retried with a token Proton had already used. Each process
|
||||
now writes only into its own session, a refresh always finishes, and it is never repeated.
|
||||
([#35](https://github.com/narrrl/proton-drive-linux/issues/35))
|
||||
- **A sign-in refreshed while the keyring was locked was lost on the next restart.** The client
|
||||
now keeps retrying, holds the new tokens in the kernel keyring meanwhile, and the tray says
|
||||
"Sign-in not saved — unlock your keyring" until it is written.
|
||||
|
||||
## [3.2.0] — 2026-10-08
|
||||
|
||||
@@ -1736,8 +1722,6 @@ First stable release: FUSE files-on-demand mount, sync daemon under `proton-driv
|
||||
- The outstanding FUSE defects tracked in `docs/BUGS.md`, plus a truncate defect, validated
|
||||
by a new POSIX compliance suite for the filesystem.
|
||||
|
||||
[3.2.1]: https://github.com/narrrl/proton-drive-linux/releases/tag/v3.2.1
|
||||
|
||||
[3.2.0]: https://github.com/narrrl/proton-drive-linux/releases/tag/v3.2.0
|
||||
|
||||
[3.1.2]: https://github.com/narrrl/proton-drive-linux/releases/tag/v3.1.2
|
||||
|
||||
@@ -82,6 +82,39 @@ paru -S proton-drive-for-linux # or yay, or any other AUR helper
|
||||
|
||||
The recipes live in [`packaging/aur/`](../packaging/aur/README.md).
|
||||
|
||||
### NixOS (flake)
|
||||
|
||||
The repository is a flake. Add it as an input and enable the module, which installs the package,
|
||||
links the user service into every graphical session and turns on the `fusermount3` wrapper and
|
||||
GNOME Keyring for you:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.proton-drive-linux.url = "github:narrrl/proton-drive-linux";
|
||||
|
||||
outputs = { nixpkgs, proton-drive-linux, ... }: {
|
||||
nixosConfigurations.<host> = nixpkgs.lib.nixosSystem {
|
||||
modules = [
|
||||
proton-drive-linux.nixosModules.default
|
||||
{ services.proton-drive-linux.enable = true; }
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
To try it without changing your system, run the app straight from the flake:
|
||||
|
||||
```bash
|
||||
nix run github:narrrl/proton-drive-linux#proton-drive-linux -- --help # the CLI
|
||||
nix shell github:narrrl/proton-drive-linux -c pdfs-app # the desktop app
|
||||
```
|
||||
|
||||
The mount itself needs the setuid `fusermount3` from NixOS (`programs.fuse.enable`, on by default
|
||||
with the module) and a Secret Service such as GNOME Keyring or KWallet. To leave out ffmpeg and
|
||||
with it video thumbnails, override the package with `withFfmpeg = false`. The recipe lives in
|
||||
[`packaging/nix/`](../packaging/nix/).
|
||||
|
||||
### Other distributions
|
||||
|
||||
Unpack the `.tar.gz` into a directory on your `PATH`, then install the service unit as shown in
|
||||
|
||||
Generated
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1791456040,
|
||||
"narHash": "sha256-H83yz/do+hjOO0uujHyH8RgtIQP2v7Mw+cLwcZK/xKc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e7439b6b14ad3cc35d05608ebca9bce01a25f5f8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
description = "Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app and tray";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs }:
|
||||
let
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (pkgs: rec {
|
||||
proton-drive-linux = pkgs.callPackage ./packaging/nix/package.nix { };
|
||||
default = proton-drive-linux;
|
||||
});
|
||||
|
||||
overlays.default = final: _: {
|
||||
proton-drive-linux = final.callPackage ./packaging/nix/package.nix { };
|
||||
};
|
||||
|
||||
nixosModules.default = import ./packaging/nix/module.nix self;
|
||||
|
||||
devShells = forAllSystems (pkgs: {
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [ self.packages.${pkgs.stdenv.hostPlatform.system}.proton-drive-linux ];
|
||||
packages = with pkgs; [
|
||||
cargo
|
||||
clippy
|
||||
rustfmt
|
||||
rust-analyzer
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
formatter = forAllSystems (pkgs: pkgs.nixfmt);
|
||||
};
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
# Build + install: cd packaging && makepkg -fi
|
||||
|
||||
pkgname=proton-drive-linux
|
||||
pkgver=3.2.1
|
||||
pkgver=3.2.0
|
||||
pkgrel=1
|
||||
pkgdesc="Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app + tray"
|
||||
arch=('x86_64')
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# NixOS module: installs the package and runs the mount daemon in every
|
||||
# graphical session, as the other packages' user service does.
|
||||
#
|
||||
# services.proton-drive-linux.enable = true;
|
||||
self:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.proton-drive-linux;
|
||||
in
|
||||
{
|
||||
options.services.proton-drive-linux = {
|
||||
enable = lib.mkEnableOption "the Proton Drive for Linux mount daemon, app and tray";
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = self.packages.${pkgs.stdenv.hostPlatform.system}.proton-drive-linux;
|
||||
defaultText = lib.literalExpression "proton-drive-linux.packages.\${system}.proton-drive-linux";
|
||||
description = "The package to use.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
# The unit ships in the package; this links it and pulls it into the
|
||||
# graphical session, which is what `systemctl --user enable` would do.
|
||||
systemd.packages = [ cfg.package ];
|
||||
systemd.user.services.proton-drive = {
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
# The mount runs fusermount3 from PATH, and it has to be the setuid
|
||||
# wrapper; the PATH NixOS gives a unit does not include it.
|
||||
path = [ "/run/wrappers" ];
|
||||
};
|
||||
programs.fuse.enable = lib.mkDefault true;
|
||||
# Session tokens are kept in the Secret Service.
|
||||
services.gnome.gnome-keyring.enable = lib.mkDefault true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
# Nix package for the workspace, built from the checkout this file lives in.
|
||||
# The flake at the repository root exposes it; `nix build` builds it.
|
||||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
adwaita-icon-theme,
|
||||
pkg-config,
|
||||
gettext,
|
||||
glib,
|
||||
wrapGAppsHook4,
|
||||
fuse3,
|
||||
glib-networking,
|
||||
gtk4,
|
||||
libadwaita,
|
||||
webkitgtk_6_0,
|
||||
libsecret,
|
||||
dbus,
|
||||
exiftool,
|
||||
ffmpeg-headless,
|
||||
withFfmpeg ? true,
|
||||
}:
|
||||
|
||||
let
|
||||
cargoToml = lib.importTOML ../../Cargo.toml;
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
pname = "proton-drive-linux";
|
||||
inherit (cargoToml.workspace.package) version;
|
||||
|
||||
# Only what the build reads, so editing docs or CI does not rebuild.
|
||||
src = lib.fileset.toSource {
|
||||
root = ../..;
|
||||
fileset = lib.fileset.unions [
|
||||
../../Cargo.toml
|
||||
../../Cargo.lock
|
||||
../../crates
|
||||
../../po
|
||||
../../LICENSE
|
||||
../proton-drive.service
|
||||
../io.narl.proton-drive-linux.desktop
|
||||
../io.narl.proton-drive-linux-tray.desktop
|
||||
../io.narl.proton-drive-linux.svg
|
||||
];
|
||||
};
|
||||
|
||||
cargoLock.lockFile = ../../Cargo.lock;
|
||||
|
||||
cargoBuildFlags = [
|
||||
"--bin"
|
||||
"pdfs"
|
||||
"--bin"
|
||||
"pdfs-tray"
|
||||
"--bin"
|
||||
"pdfs-app"
|
||||
"--bin"
|
||||
"pdfs-prompt"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
gettext # msgfmt, for po/build.sh
|
||||
glib # glib-compile-resources, for the GUI's build.rs
|
||||
wrapGAppsHook4
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
fuse3
|
||||
# TLS for WebKitGTK's GIO: without it the CAPTCHA page fails with "TLS
|
||||
# support is not available". wrapGAppsHook4 adds it to GIO_EXTRA_MODULES.
|
||||
glib-networking
|
||||
# The stock icons the app asks for, such as the Photos and Computers
|
||||
# sidebar entries. GTK ships only a few itself, and a session without
|
||||
# Adwaita installed showed the rest as missing. wrapGAppsHook4 adds it to
|
||||
# XDG_DATA_DIRS.
|
||||
adwaita-icon-theme
|
||||
gtk4
|
||||
libadwaita
|
||||
webkitgtk_6_0
|
||||
libsecret
|
||||
dbus
|
||||
];
|
||||
|
||||
# The app looks for its catalogs here instead of /usr/share/locale.
|
||||
env.PDFS_LOCALEDIR = "${placeholder "out"}/share/locale";
|
||||
|
||||
# The suite mounts FUSE, talks to D-Bus and the kernel keyring, and checks
|
||||
# permissions a build sandbox does not have; CI runs it on every push.
|
||||
doCheck = false;
|
||||
|
||||
postInstall = ''
|
||||
install -Dm644 packaging/io.narl.proton-drive-linux.desktop \
|
||||
$out/share/applications/io.narl.proton-drive-linux.desktop
|
||||
install -Dm644 packaging/io.narl.proton-drive-linux-tray.desktop \
|
||||
$out/etc/xdg/autostart/io.narl.proton-drive-linux-tray.desktop
|
||||
install -Dm644 packaging/io.narl.proton-drive-linux.svg \
|
||||
$out/share/icons/hicolor/scalable/apps/io.narl.proton-drive-linux.svg
|
||||
substituteInPlace $out/share/applications/io.narl.proton-drive-linux.desktop \
|
||||
--replace-fail "Exec=pdfs-app" "Exec=$out/bin/pdfs-app"
|
||||
substituteInPlace $out/etc/xdg/autostart/io.narl.proton-drive-linux-tray.desktop \
|
||||
--replace-fail "Exec=pdfs-tray" "Exec=$out/bin/pdfs-tray"
|
||||
|
||||
install -Dm644 packaging/proton-drive.service \
|
||||
$out/lib/systemd/user/proton-drive.service
|
||||
substituteInPlace $out/lib/systemd/user/proton-drive.service \
|
||||
--replace-fail "ExecStart=/usr/bin/pdfs" "ExecStart=$out/bin/pdfs"
|
||||
|
||||
patchShebangs po/build.sh
|
||||
po/build.sh $out/share/locale
|
||||
'';
|
||||
|
||||
# Thumbnails shell out to exiftool, and to ffmpeg for video. Suffixed, so a
|
||||
# user's own builds on PATH win. fusermount3 comes from the system: on NixOS
|
||||
# it is the setuid wrapper in /run/wrappers/bin.
|
||||
preFixup = ''
|
||||
gappsWrapperArgs+=(--suffix PATH : ${
|
||||
lib.makeBinPath ([ exiftool ] ++ lib.optional withFfmpeg ffmpeg-headless)
|
||||
})
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app and tray";
|
||||
homepage = "https://proton-drive.narl.io";
|
||||
license = lib.licenses.mit;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "pdfs";
|
||||
};
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: proton-drive-linux 3.2.1\n"
|
||||
"Project-Id-Version: proton-drive-linux 3.2.0\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/narrrl/proton-drive-linux/issues\n"
|
||||
"POT-Creation-Date: 2026-10-09 12:17+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
|
||||
Reference in new issue
Block a user