Split the README into a short front page and task-oriented pages under docs/: installation, user guide, CLI reference, configuration and troubleshooting, with an index in docs/README.md. Rewrite RECOVERY.md around Continue This Backup Here and Restore Folders, and DEVELOPMENT.md around running, debugging and releasing from source. Bring ARCHITECTURE.md up to date with the read path, push events, the thread map, conflict copies and the machine profile, and move the feature design notes there. Collect planned work in ROADMAP.md. Link the threat model from SECURITY.md and the translation rules from CONTRIBUTING.md. Add scripts/publish-wiki.sh, which mirrors the user pages to the GitHub wiki with rewritten links and only pushes with --push.
6.9 KiB
Development guide
How to build, run, debug and release the client from source. Read CONTRIBUTING.md for the review rules and ARCHITECTURE.md for how the pieces fit together.
Setup
You need Rust 1.96 or newer and the native development packages listed under Build dependencies for your distribution. Then:
git clone https://github.com/narrrl/proton-drive-linux.git
cd proton-drive-linux
cargo build --workspace
The GUI builds against libadwaita 1.5, the version in Ubuntu 24.04, and uses newer widgets at run
time when the installed library has them (crates/pdfs-gui/src/compat.rs).
Repository layout
| Path | Contents |
|---|---|
crates/pdfs-core |
Shared library: authentication and keyring (auth), configuration (config), SQLite schema and queries (db/), content cache (cache), control protocol (control), search scoring, sync ignore rules, Google Takeout parsing, machine profile |
crates/pdfs-fuse |
The daemon: FUSE filesystem, read path (reads), write queue (queue, drain, upload), sync engine (sync/), remote events (background), push events for front ends (events), control handlers (control), photos, devices, supervisor |
crates/pdfs-cli |
The pdfs binary |
crates/pdfs-gui |
pdfs-app, pdfs-tray and pdfs-prompt. Pages in src/app/pages/, shared widgets in src/app/widgets/, CSS and icons in resources/ |
po/ |
Translation template, catalogs and the scripts that maintain them |
packaging/ |
systemd unit, desktop files, icon, PKGBUILD, RPM spec, AUR recipes |
scripts/ |
FUSE acceptance suite, map-data generators |
docs/ |
This documentation |
The GUI talks to the daemon only through the control socket. Anything a front end needs that the
daemon does not offer yet is a new request in pdfs_core::control, not a database read.
Running from source
The packaged service and a daemon run from source cannot share the same state directory. Stop the service before you run your own build:
systemctl --user stop proton-drive.service
RUST_LOG=pdfs_fuse=debug,info cargo run -p pdfs-cli -- daemon
In another terminal:
cargo run -p pdfs-cli -- status
po/build.sh target/locale # compile translations once
PDFS_LOCALEDIR=target/locale cargo run -p pdfs-gui --bin pdfs-app
cargo run -p pdfs-gui --bin pdfs-tray
cargo run -p pdfs-gui --bin pdfs-prompt -- --fzf
To keep the systemd unit but point it at your build, see INSTALL.md.
Caution
Develop against a test account. The acceptance suite and a buggy daemon can delete or rewrite files in Proton Drive.
Tip
A daemon stopped in a debugger or deadlocked freezes every process that touches the mount, including your shell if its prompt reads the current directory. Keep your shell outside
~/ProtonDrive, prefix commands that touch it withtimeout, and unmount a dead mount withfusermount3 -uz ~/ProtonDrive.
Quality gates
CI (.github/workflows/ci.yml) runs these on every push to main and every pull request. Run them before you
push:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace --locked
scripts/fuse-acceptance.sh --offline-only
For changes to the FUSE layer, the write queue or the sync engine, also run the live acceptance cases described in TESTING.md.
For changes to GUI strings, check that every catalog is complete:
for l in $(cat po/LINGUAS); do msgfmt --check --statistics -o /dev/null po/$l.po; done
Debugging
| Tool | Use |
|---|---|
RUST_LOG |
Log filter for every binary, for example RUST_LOG=pdfs_fuse::sync=trace,info |
pdfs diagnose |
Static checks: directories, FUSE, keyring, socket, database integrity. Works without the daemon |
pdfs diagnostics |
Live state of a running daemon: each worker's current job and its age, queue depth, control requests in flight, memory |
pdfs cache inspect --deep |
Database size, row counts and SQLite integrity_check |
pdfs --json … |
Raw protocol payloads for query commands |
GTK_DEBUG=interactive |
The GTK inspector for pdfs-app |
PDFS_STAND_IN_WIDGETS=1 |
Force the libadwaita 1.5 fallback widgets on a newer system |
G_DEBUG=fatal-criticals |
Turn GLib criticals into crashes to get a backtrace |
The databases are ordinary SQLite files. Open a copy, not the live file:
cp ~/.local/state/proton-drive-linux/cache.db /tmp/cache.db
sqlite3 /tmp/cache.db '.tables'
Common changes
A new control request. Add the variant to Request (and a Response if it returns data) in
crates/pdfs-core/src/control.rs, handle it in crates/pdfs-fuse/src/control.rs, and list the
Topics it changes in the same file so subscribed front ends refresh. A daemon from the previous
release may still be running when a new front end starts, so treat an error reply to a new
request as "not supported".
A schema change. Migrations are forward-only. Add a new step to
crates/pdfs-core/src/db/migrations.rs and bump SCHEMA_VERSION; never edit a shipped step. Add
a test in crates/pdfs-core/src/db/tests.rs that migrates from the previous version.
A GUI string. Wrap it in the helpers from crates/pdfs-gui/src/i18n.rs, add any new source
file to po/POTFILES.in, run po/update.sh, and translate the new entries in every catalog. See
TRANSLATING.md. The CLI and daemon messages stay in English.
A setting. Add the field to AppConfig in crates/pdfs-core/src/config.rs with
#[serde(default)], so older files still load, and document it in
CONFIGURATION.md.
Releasing
Releases are cut from main by pushing a v* tag. .github/workflows/release.yml then:
- checks that the tag, the workspace version in
Cargo.tomlandpkgverinpackaging/PKGBUILDagree; - runs the quality gates;
- builds the release binaries and packages a
.tar.gz, a.deband a GPG-signed.rpm; - publishes them as a GitHub release;
- calls
.github/workflows/aur.yml, which updates and pushes the AUR recipes and commits them back tomain.
To prepare a release:
# 1. Bump the version in Cargo.toml and packaging/PKGBUILD, then refresh the lock file.
cargo update --workspace
# 2. Move the [Unreleased] notes in docs/CHANGELOG.md under the new version.
# 3. Commit, tag and push.
git commit -am "chore(release): X.Y.Z"
git tag vX.Y.Z
git push origin main vX.Y.Z
Before a release that touches the filesystem or sync, run the managed live mode matrix from TESTING.md. Open release-assurance items are listed in ROADMAP.md.