Commit 6863ea3
feat: per-source toggle to back up OneDrive cloud-only placeholder files (#133)
## What & why
Issue #4: give each backup source a policy for OneDrive / cloud-only
placeholder
files. Windows OneDrive Files-On-Demand marks a dehydrated placeholder
with
`FILE_ATTRIBUTE_RECALL_ON_OPEN`; opening it forces a network hydration,
so the
scanner has always skipped these by default (DESIGN s5.2.1) to avoid
silently
pulling down terabytes of cloud-only data. Some users, though, *want*
those files
backed up. This adds a per-source opt-in to do exactly that.
## Policy semantics
New `PlaceholderPolicy` (serde snake_case) carried end-to-end:
- **`skip`** (default): unchanged behaviour - a cloud-only placeholder
is skipped
before stat/hash and its existing `file_state` row is preserved (not
treated as
a deletion).
- **`force_download`**: the scanner does NOT skip on the recall
attribute; the
file flows through the normal open/read path and Windows hydrates it on
read
(the byte read happens downstream at hash/upload time, so scan-time
`stat`
never triggers hydration).
Stored as a new **nullable** `placeholder_policy` TEXT column (migration
`0008`).
`NULL` (every pre-migration row) and any unrecognised value decode to
`skip`, so
the change is fully backward compatible with no data migration.
## Shape
- `crates/driven-core`: `PlaceholderPolicy` enum +
`SourceRow.placeholder_policy`,
migration `0008`, 5 sqlx query sites (2 SELECT + 3 upsert) + regenerated
committed `.sqlx/`. Scanner gates the skip via a pure
`should_skip_placeholder(attrs, policy)` fn (mirrors the repo's
`classify_*` / `fallback_decision` pure-decision pattern) so both
branches are
unit-testable cross-platform (the real attribute cannot be synthesised
on a
temp file portably).
- IPC: `AddSourceRequest` (`#[serde(default)]`), `SourcePatch`
(`Option<PlaceholderPolicy>`), and `SourceDto` gain the field; wired
through
`add_source` / `update_source`. TS mirrors updated in `ipc/types.ts`.
- UI: a "Back up OneDrive cloud-only files" toggle with an explanatory
caption in
BOTH the add-source wizard (exclusions step) and the SourceTable inline
edit
panel; strings localized in `en-US.json`.
## Tests
- Rust: `should_skip_placeholder` both-policy unit test; `from_db`
NULL/unknown ->
skip + encode round-trip; sqlite `placeholder_policy_round_trip`
(default +
force_download persist/reload/flip). `cargo fmt --check`, `clippy
--workspace
--all-targets -D warnings`, `cargo test -p driven-core / -p driven-app /
-p driven-cli / -p driven-chaos` all green. Migration `0008` verified
applying
in order.
- UI: extended `settings-components.test.ts` with mount tests exercising
the new
toggle in the wizard and both SourceTable states (reflect current policy
+
patch on save). `pnpm lint`, `vue-tsc --noEmit`, `pnpm test:unit` all
green.
Note: the scanner import of `PlaceholderPolicy` is `#[cfg(any(windows,
test))]`
gated to match its only (cfg-gated) consumer, so the non-Windows CI
clippy legs
stay warning-free.
Refs #34 (backlog item: OneDrive cloud-only placeholders).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 4e9fde6 commit 6863ea3
43 files changed
Lines changed: 573 additions & 46 deletions
File tree
- .sqlx
- crates
- driven-chaos/src/scenarios
- driven-cli
- src
- tests
- driven-core
- src
- migrations
- state
- tests
- src-tauri/src
- commands
- ui/src
- __tests__
- components
- ipc
- locales
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 0 additions & 12 deletions
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
| 144 | + | |
144 | 145 | | |
145 | 146 | | |
146 | 147 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| 100 | + | |
100 | 101 | | |
101 | 102 | | |
102 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
| 148 | + | |
148 | 149 | | |
149 | 150 | | |
150 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
240 | 240 | | |
241 | 241 | | |
242 | 242 | | |
| 243 | + | |
243 | 244 | | |
244 | 245 | | |
245 | 246 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
| 191 | + | |
191 | 192 | | |
192 | 193 | | |
193 | 194 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
147 | 147 | | |
148 | 148 | | |
149 | 149 | | |
| 150 | + | |
150 | 151 | | |
151 | 152 | | |
152 | 153 | | |
| |||
0 commit comments