diff --git a/lib/rclone/requests.ts b/lib/rclone/requests.ts index 953fb75..0493c47 100644 --- a/lib/rclone/requests.ts +++ b/lib/rclone/requests.ts @@ -492,6 +492,12 @@ export function buildBisyncRequests(args: BisyncArgs): RcRequest[] { const { fullDirPath: srcFullDirPath, remoteName: srcRemoteName } = getFsInfo(source) const { fullDirPath: dstFullDirPath, remoteName: dstRemoteName } = getFsInfo(destination) + const outer = { ...(options.outer || {}) } + // Forked rclone: --delta-list refuses to run without --check-access unless --force. + if (outer.deltaList && !outer.force) { + outer.checkAccess = true + } + return [ { endpoint: '/sync/bisync', @@ -504,9 +510,9 @@ export function buildBisyncRequests(args: BisyncArgs): RcRequest[] { }), ...(configParam ? { _config: configParam } : {}), ...(filterParam ? { _filter: filterParam } : {}), - ...(options.outer && Object.keys(options.outer).length > 0 + ...(Object.keys(outer).length > 0 ? Object.fromEntries( - Object.entries(options.outer).map(([key, value]) => [ + Object.entries(outer).map(([key, value]) => [ key, Array.isArray(value) ? value.join(',') : value, ]) diff --git a/src/pages/Bisync.tsx b/src/pages/Bisync.tsx index 1424554..bb5ae8f 100644 --- a/src/pages/Bisync.tsx +++ b/src/pages/Bisync.tsx @@ -42,9 +42,13 @@ Expand the accordion sections to customize your bisync operation. The Bisync sec • resync — Required for the first run, or to reset bisync after an error. This makes both paths contain a matching superset of all files by copying Path2 to Path1, then Path1 to Path2. Only use resync when starting fresh, after changing filter settings, or recovering from an error — using it routinely would prevent deletions from syncing (deleted files would keep reappearing from the other side). -• checkAccess — Safety check that looks for matching RCLONE_TEST files on both paths before syncing. You must first create these files yourself in both paths. This prevents data loss if a path is temporarily unavailable or mounted incorrectly. +• checkAccess — Safety check that looks for matching RCLONE_TEST files on both paths before syncing. You must first create these files yourself in both paths. This prevents data loss if a path is temporarily unavailable or mounted incorrectly. Required when deltaList is on (unless force). -• force — Override safety checks like max-delete protection. Use with caution, as this bypasses safeguards designed to prevent accidental mass deletions. +• deltaList — Dropbox list_folder cursor listings instead of a full walk on the Dropbox side. First run still lists recursively; later runs apply deltas. Local path still walks. workdir must be on the shared volume (JSON: workdir). Requires checkAccess. + +• recover — After an interrupted run, reconstruct listings from the last known good state instead of demanding resync. + +• force — Override safety checks like max-delete protection and empty-listing abort. Use with caution, as this bypasses safeguards designed to prevent accidental mass deletions. • createEmptySrcDirs — Sync empty directories as well as files. Without this, only files are synced and empty directories are ignored. @@ -137,6 +141,9 @@ export default function Bisync() { if (!source || !dest) { throw new Error('Please select both a source and destination path') } + if (outerBisyncOptions.deltaList && !outerBisyncOptions.checkAccess && !outerBisyncOptions.force) { + throw new Error('deltaList requires checkAccess (or force)') + } return startBisync(buildStartArgs()) }, @@ -202,7 +209,8 @@ export default function Bisync() { setOuterBisyncOptions({ ...outerBisyncOptions, @@ -214,6 +222,33 @@ export default function Bisync() { checkAccess + + setOuterBisyncOptions({ + ...outerBisyncOptions, + deltaList: value, + ...(value ? { checkAccess: true } : {}), + }) + } + size="sm" + > + deltaList + + + + setOuterBisyncOptions({ + ...outerBisyncOptions, + recover: value, + }) + } + size="sm" + > + recover + +