Skip to main content

max / alloy

4.0 KB · 80 lines History Blame Raw
1 //! `alloy sync` — the file sync view.
2 //!
3 //! See docs/CONTINUITY.md: a mesh VPN and a file sync are what make an Alloy
4 //! machine feel like the same machine as the last one, so the console fronts
5 //! both. This is the sync half, and the sibling of [`mesh`](crate::mesh) in
6 //! shape as well as in purpose: a [`Backend`] trait, one real implementation
7 //! and one mock, a tabbed list, and every string on screen generic except the
8 //! backend name in the title.
9 //!
10 //! # Fronting the CLI, not the REST API
11 //!
12 //! Syncthing's documented interface is an HTTP API on `127.0.0.1:8384` behind
13 //! an API key in `config.xml`. Fronting it directly would mean an HTTP client
14 //! in a binary that has none, plus reading a key out of a file the daemon owns.
15 //! `syncthing cli` is a first-party client for that same API which finds the
16 //! key itself, so the console keeps the shape every other view has: a command
17 //! front, logged in the pane, teaching a command the user could have typed.
18 //!
19 //! Four invocations cover a refresh. `config dump-json` carries every folder
20 //! and device with its paused flag, `show connections` carries who is actually
21 //! connected right now, `show system` names which device is this one, and
22 //! `show pending devices` carries whoever is knocking. Configuration,
23 //! liveness and invitations are genuinely different endpoints; merging them is
24 //! this module's job rather than something to wish for from the tool. Only the
25 //! first is fatal — the other three decorate, and losing one costs a column
26 //! rather than the screen.
27 //!
28 //! # Accepting is possible, declining is not
29 //!
30 //! The pending tab is how a pairing finishes: the other machine adds this one,
31 //! dials it, and waits. Accepting is `config devices add` with the id and name
32 //! already known, and Syncthing drops the entry once the device is configured.
33 //!
34 //! There is no matching decline. Syncthing's REST API can drop a pending entry
35 //! and `syncthing cli` does not expose that, so the console can let a device in
36 //! and cannot turn one away; an unaccepted device just stays listed. That
37 //! asymmetry is shipped as-is and said out loud on screen when `d` is pressed,
38 //! because a dismiss button that silently did nothing would be worse than not
39 //! having one.
40 //!
41 //! # The daemon not running is a state, not an error
42 //!
43 //! Syncthing ships preset-disabled (docs/CONTINUITY.md: "a running daemon with
44 //! nothing to do is unjustified surface"), so on a fresh install the expected
45 //! answer from every command here is `connection refused`. That is not a
46 //! failure to report, it is the un-enrolled machine this screen exists to
47 //! enroll, and it renders as an offer rather than as a red line.
48 //!
49 //! Enrollment is `systemctl --user enable --now syncthing.service`. User scope
50 //! on purpose: the unit is a user service, the files it syncs are the user's,
51 //! and nothing here needs or asks for root. That is the whole of the
52 //! difference from [`mesh`](crate::mesh), whose `tailscale up` is a system
53 //! daemon and a privileged action.
54 //!
55 //! <!-- wiki: alloy-console -->
56
57 mod backend;
58 mod model;
59 mod parse;
60 mod view;
61
62 // The whole vocabulary crosses the boundary and keeps the path it had before
63 // the split, `crate::sync::Folder` and the rest. What stays inside is the
64 // machinery: the serde shapes, the two backends `detect` picks between, the
65 // draft overlay and the validators.
66 pub(crate) use backend::{Backend, detect};
67 pub(crate) use model::Reach;
68 pub(crate) use view::{SyncView, Tab};
69
70 // The trait's own signature types, which is why they are re-exported rather
71 // than narrowed: implementing `sync::Backend` from outside the verb means
72 // naming them, and `setup.rs` does exactly that with its stub. That stub is
73 // test code, so nothing in the shipped binary reaches these names and rustc
74 // lints the re-export as unused on the bin target alone. Narrowing them would
75 // move the boundary rather than tidy it.
76 #[allow(unused_imports)]
77 pub(crate) use backend::{DeviceDraft, FolderDraft};
78 #[allow(unused_imports)]
79 pub(crate) use model::{Device, Folder, PendingDevice, SyncState};
80