Package-level declarations
Two layers. CloudStorage is the filesystem-style transport (ICloudStorage, GoogleDriveStorage). SyncEngine owns the complete-or-absent reconciliation over a SyncSnapshot and persists its SyncState through a SyncStateStore. Start with the README quickstart, then SyncEngine.sync.
Two layers. CloudStorage is the filesystem-style transport (ICloudStorage, GoogleDriveStorage). SyncEngine owns the complete-or-absent reconciliation over a SyncSnapshot and persists its SyncState through a SyncStateStore. Start with the README quickstart, then SyncEngine.sync.
Two layers. CloudStorage is the filesystem-style transport (ICloudStorage, GoogleDriveStorage). SyncEngine owns the complete-or-absent reconciliation over a SyncSnapshot and persists its SyncState through a SyncStateStore. Start with the README quickstart, then SyncEngine.sync.
Types
The Ktor client BackupKit uses when the app does not pass its own.
Plug your logger in through BackupKit.logger. The default discards everything.
Whether the transport can be used right now, without touching the network.
The only failure vocabulary the library exposes. Render these; never parse messages.
CloudKit transport: one custom zone in the user's private database, one record per file, the bytes as a CKAsset. Unlike the iCloud Drive container there are no placeholder files: a save completes when Apple's server has the record, and a read is a network fetch with a definite outcome.
Where the user's own copy lives. One per platform.
Layer 1: filesystem-style access to the user's own cloud.
Every transport failure is mapped to a CloudError the app can show.
Google's one-time permission dialog for the app-data folder. Call request; when it returns Request.Needed, launch the IntentSender with ActivityResultContracts.StartIntentSenderForResult and hand the result's data to wasGranted. No Compose dependency: the app owns the launcher.
A short-lived OAuth access token for the drive.appdata scope.
Supplies Drive access tokens. The default, PlayServicesTokenProvider, needs no sign-in UI. Apps that already run Google Sign-In can plug their own token in here instead.
Marks the restore half of BackupKit: unit-tested, not yet run on a device by a shipping app. Opt in knowingly; the API may change in 0.2.0.
JSON file at path, written atomically. A corrupt or absent file reads as null.
JSON file at path, written atomically (temp + rename). A corrupt or absent file is an empty state; the next sync self-heals from the remote listing.
Google Drive app-data transport. Flat folder; paths are used verbatim as Drive file names. Uploads up to 5 MB go multipart in one request; larger ones use Drive's resumable protocol in 8 MiB chunks, streamed from disk for local files. list also removes duplicate files left by interrupted creates, keeping the newest by modified time.
iCloud Drive transport: plain files under <ubiquity container>/<folder>/, OUTSIDE Documents/, so they stay private to the app and invisible in Files. Writes land locally through NSFileCoordinator and the iCloud daemon uploads on its own. Reads force a download and wait with a bounded poll (a not-yet-downloaded file is never coordinated directly: that blocks).
Severity of a BackupKitLogger line.
Silent token source for the Drive app-data scope through Play Services' AuthorizationClient. After the user grants once (see DriveConsent), authorize returns a cached one-hour access token with no UI; before that it reports DriveToken.NeedsConsent. No account identity is read or stored.
One file as the cloud sees it. remoteId is Drive's file id, null on iCloud. size is -1 when unknown (an iCloud placeholder that has not been downloaded yet).
Typed, metadata-only inspection of the remote set, for a restore offer.
Resumable download of a pinned remote set. Required files first (the commit boundary), then optional files best-effort with maxAttempts tries each. Progress is durable per file; resume revalidates the source through SyncEngine.probe before continuing, so a backup that changed under the plan is reported as RestoreError.SourceChanged instead of being mixed in.
One file to bring down. required files form the commit boundary: all of them must succeed before any optional file is attempted, and one failure fails the run. Optional files are best-effort with a per-file attempt cap and stay pending across runs.
Where a downloaded group goes. Called once every downloadable file of a group is local (per file when the file has no group), with the records whose RestoreFileRecord.toLocalPath now holds the bytes. The app validates, moves or imports them however it likes and answers. The default keeps files where they landed.
What to restore, pinned to the SourceRef the offer was built from (RemoteProbe.Found.source).
Progress in files and in the app's own unit, its groups.
Durable progress of one restore chain. Saved after every file so a killed process resumes exactly where it stopped.
Refuses a run that would delete more than maxDeleteFraction of the remote set once the remote holds at least minRemoteEntries non-marker files. A device that lost most of its data, or an app bug that projected an empty model, must not turn a healthy backup into a copy of the damage. The run answers UnavailableReason.ShrinkSuspected and writes nothing; the app asks the user and retries with SyncSnapshot(allowShrink = true).
hash is sha256-hex for hash-compared entries, null for size-compared ones (identity = path + size).
Layer 2: ONE reconciliation run per sync. Lists the remote, self-heals the state cache, diffs the snapshot against it, uploads size-compared entries, then hash-compared entries, then the marker, then deletes what is no longer in the snapshot. State is saved after every put, so a killed process resumes exactly where it stopped. See docs/contract.md.
One file the app wants mirrored. hash (use sha256Hex) makes the entry hash-compared; null makes it size-compared, which suits write-once media. Hash-compared entries upload in snapshot order after the size-compared ones.
The complete desired remote set. Anything the engine knows about that is not here gets deleted.
Where an entry's bytes come from.
What the last successful writes left remote. A CACHE: every SyncEngine.sync re-lists the remote and reconciles against it, so a lost or stale state only costs a re-upload, never correctness.
Persists SyncState between runs. Implement it yourself or use FileSyncStateStore.