diff --git a/README.md b/README.md index af8f943..f6b9c48 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ -rclone-dropbox-bisync 1.0.0 -=========================== +rclone-dropbox-bisync +==================== -Forked rclone (ListR + --delta-list, fail-closed) plus a tray/timer. -rclone-ui (Tauri GUI) is NOT inside this zip: this host cannot cross-build -NSIS. Point rclone-ui at the bundled rclone.exe after install. +NTFS volume label DataStorage (Windows D:), folder Dropbox. +Local path: D:\Dropbox / /Dropbox +Workdir: D:\rclone-bisync (created if missing) -Windows (one-click) - 1. Unzip. Double-click Install.cmd - 2. Edit %LOCALAPPDATA%\rclone-dropbox-bisync\config.json - set enabled=true, path1, path2, workdir (NTFS share) - 3. Put RCLONE_TEST on both sides - 4. Tray icon + HKCU Run + schtasks every 15 min - Flags baked in: --delta-list --check-access --max-delete 10 - --compare size,modtime,checksum --slow-hash-sync-only - --resilient --recover --conflict-resolve none +Windows (paste in PowerShell): -Linux (.deb) - sudo apt install ./rclone-dropbox-bisync_1.0.0_amd64.deb - (or ar x / dpkg -i) - Log in: autostart enables systemd --user rclone-bisync.timer - Edit ~/.config/rclone-dropbox-bisync/config.json (enabled=true) + irm https://git.denkena-consulting.com/f-denkena/rclone-dropbox-bisync/raw/branch/master/windows/bootstrap.ps1 | iex + +Linux: + + curl -fsSL https://git.denkena-consulting.com/f-denkena/rclone-dropbox-bisync/raw/branch/master/linux/install.sh | bash + +Needs git + go. Clones public f-denkena/rclone (bisync-delta-list) and this repo, +builds, writes config, creates workdir, RCLONE_TEST on the local Dropbox folder, +sync on logon/startup and every 15 minutes, Windows tray / Linux systemd --user. + +Remote dropbox: must already be in rclone.conf. Copy RCLONE_TEST to dropbox: once +so --check-access passes. diff --git a/config.example.json b/config.example.json index 12dd1d8..2f5a8f7 100644 --- a/config.example.json +++ b/config.example.json @@ -1,9 +1,9 @@ { - "enabled": false, - "path1": "/mnt/ntfs/Dropbox", + "enabled": true, + "path1": "/mnt/DataStorage/Dropbox", "path2": "dropbox:", - "workdir": "/mnt/ntfs/rclone-bisync", + "workdir": "/mnt/DataStorage/rclone-bisync", "interval_minutes": 15, - "rclone": "/opt/rclone-dropbox-bisync/bin/rclone", + "rclone": "rclone", "check_filename": "RCLONE_TEST" } diff --git a/linux/install.sh b/linux/install.sh new file mode 100755 index 0000000..774aeb2 --- /dev/null +++ b/linux/install.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# rclone-dropbox-bisync Linux setup +# Dual-boot: NTFS volume labeled DataStorage, Dropbox at /Dropbox +# Paste: curl -fsSL https://git.denkena-consulting.com/f-denkena/rclone-dropbox-bisync/raw/branch/master/linux/install.sh | bash + +set -euo pipefail +GIT_BASE='https://git.denkena-consulting.com/f-denkena' +PACK_REPO="$GIT_BASE/rclone-dropbox-bisync.git" +RCLONE_REPO="$GIT_BASE/rclone.git" +SRC="${XDG_CACHE_HOME:-$HOME/.cache}/rclone-dropbox-bisync/src" +BIN="$HOME/.local/bin" +CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/rclone-dropbox-bisync" +UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user" + +find_datastorage() { + local m + if command -v findmnt >/dev/null 2>&1; then + m=$(findmnt -n -o TARGET -S LABEL=DataStorage 2>/dev/null | head -1 || true) + if [ -n "$m" ]; then + echo "$m" + return + fi + fi + for m in /mnt/DataStorage /media/"$USER"/DataStorage /run/media/"$USER"/DataStorage /d /mnt/d /mnt/data; do + if [ -d "$m/Dropbox" ]; then + echo "$m" + return + fi + done + return 1 +} + +need() { + command -v "$1" >/dev/null 2>&1 +} + +if ! need git; then + echo "install git first" >&2 + exit 1 +fi +if ! need go; then + echo "install go first (needed to build the forked rclone)" >&2 + exit 1 +fi + +VOL=$(find_datastorage) || { + echo "NTFS volume LABEL=DataStorage (or .../Dropbox) not mounted" >&2 + exit 1 +} +DROPBOX="$VOL/Dropbox" +WORKDIR="$VOL/rclone-bisync" +[ -d "$DROPBOX" ] || { + echo "missing $DROPBOX" >&2 + exit 1 +} +mkdir -p "$WORKDIR" "$SRC" "$BIN" "$CFG_DIR" "$UNIT_DIR" "$HOME/.config/autostart" +[ -f "$DROPBOX/RCLONE_TEST" ] || : >"$DROPBOX/RCLONE_TEST" + +if [ ! -d "$SRC/packaging/.git" ]; then + git clone --depth 1 "$PACK_REPO" "$SRC/packaging" +else + git -C "$SRC/packaging" pull --ff-only +fi +if [ ! -d "$SRC/rclone/.git" ]; then + git clone --depth 1 --branch bisync-delta-list "$RCLONE_REPO" "$SRC/rclone" +else + git -C "$SRC/rclone" fetch origin bisync-delta-list + git -C "$SRC/rclone" checkout bisync-delta-list + git -C "$SRC/rclone" pull --ff-only +fi + +export CGO_ENABLED=0 +echo "building rclone..." +(cd "$SRC/rclone" && go build -trimpath -o "$BIN/rclone" .) +echo "building rclone-bisyncd..." +(cd "$SRC/packaging/cmd/rclone-bisyncd" && go build -trimpath -o "$BIN/rclone-bisyncd" .) + +cat >"$CFG_DIR/config.json" <"$HOME/.config/autostart/rclone-bisync.desktop" </windows/bootstrap.ps1 | iex + +$ErrorActionPreference = 'Stop' +$GitBase = 'https://git.denkena-consulting.com/f-denkena' +$PackRepo = "$GitBase/rclone-dropbox-bisync.git" +$RcloneRepo = "$GitBase/rclone.git" +$Src = Join-Path $env:LOCALAPPDATA 'rclone-dropbox-bisync\src' +$Dest = Join-Path $env:LOCALAPPDATA 'rclone-dropbox-bisync' +$Dropbox = 'D:\Dropbox' +$Workdir = 'D:\rclone-bisync' + +function Ensure-Cmd($Name, $WingetId) { + if (Get-Command $Name -ErrorAction SilentlyContinue) { return } + if (-not (Get-Command winget -ErrorAction SilentlyContinue)) { + throw "Need $Name on PATH (or winget to install $WingetId)" + } + winget install -e --id $WingetId --accept-package-agreements --accept-source-agreements + $env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + + [Environment]::GetEnvironmentVariable('Path', 'User') +} + +Ensure-Cmd git Git.Git +Ensure-Cmd go GoLang.Go + +New-Item -ItemType Directory -Force -Path $Src, (Join-Path $Dest 'bin') | Out-Null +if (-not (Test-Path (Join-Path $Src 'packaging\.git'))) { + git clone --depth 1 $PackRepo (Join-Path $Src 'packaging') +} else { + git -C (Join-Path $Src 'packaging') pull --ff-only +} +if (-not (Test-Path (Join-Path $Src 'rclone\.git'))) { + git clone --depth 1 --branch bisync-delta-list $RcloneRepo (Join-Path $Src 'rclone') +} else { + git -C (Join-Path $Src 'rclone') fetch origin bisync-delta-list + git -C (Join-Path $Src 'rclone') checkout bisync-delta-list + git -C (Join-Path $Src 'rclone') pull --ff-only +} + +Write-Host 'Building rclone (forked)...' +Push-Location (Join-Path $Src 'rclone') +$env:CGO_ENABLED = '0' +go build -trimpath -o (Join-Path $Dest 'bin\rclone.exe') . +Pop-Location +Write-Host 'Building rclone-bisyncd...' +Push-Location (Join-Path $Src 'packaging\cmd\rclone-bisyncd') +go build -trimpath -o (Join-Path $Dest 'bin\rclone-bisyncd.exe') . +Pop-Location + +Copy-Item -Force (Join-Path $Src 'packaging\windows\tray.ps1') (Join-Path $Dest 'tray.ps1') + +if (-not (Test-Path 'D:\')) { throw 'D: is missing (expected DataStorage volume)' } +if (-not (Test-Path $Dropbox)) { throw "Dropbox folder not found: $Dropbox" } +New-Item -ItemType Directory -Force -Path $Workdir | Out-Null +$testFile = Join-Path $Dropbox 'RCLONE_TEST' +if (-not (Test-Path $testFile)) { New-Item -ItemType File -Path $testFile | Out-Null } + +$cfgPath = Join-Path $Dest 'config.json' +@{ + enabled = $true + path1 = $Dropbox + path2 = 'dropbox:' + workdir = $Workdir + interval_minutes = 15 + rclone = (Join-Path $Dest 'bin\rclone.exe') + check_filename = 'RCLONE_TEST' +} | ConvertTo-Json | Set-Content -Encoding UTF8 $cfgPath +$env:RCLONE_BISYNC_CONFIG = $cfgPath + +$bin = Join-Path $Dest 'bin' +$userPath = [Environment]::GetEnvironmentVariable('Path', 'User') +if ($userPath -notlike "*$bin*") { + [Environment]::SetEnvironmentVariable('Path', "$bin;$userPath", 'User') +} + +$run = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' +$tray = Join-Path $Dest 'tray.ps1' +New-ItemProperty -Path $run -Name 'rclone-dropbox-bisync-tray' -PropertyType String -Force ` + -Value "powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$tray`"" | Out-Null + +# Sync at logon and every 15 minutes +$daemon = Join-Path $Dest 'bin\rclone-bisyncd.exe' +schtasks /Create /F /TN 'rclone-dropbox-bisync-startup' /SC ONLOGON /RL LIMITED /TR "`"$daemon`" --once" | Out-Null +schtasks /Create /F /TN 'rclone-dropbox-bisync' /SC MINUTE /MO 15 /TR "`"$daemon`" --once" /ST 00:00 | Out-Null + +Start-Process powershell.exe -WindowStyle Hidden -ArgumentList @( + '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $tray +) +Start-Process $daemon -ArgumentList '--once' -WindowStyle Hidden + +Write-Host @" +Configured: + path1 $Dropbox (D: DataStorage) + workdir $Workdir + path2 dropbox: + startup ONLOGON + tray + interval 15 min +Put RCLONE_TEST on the Dropbox remote as well (rclone copy $testFile dropbox:RCLONE_TEST). +rclone remote 'dropbox:' must already exist in rclone.conf. +"@ diff --git a/windows/config.example.json b/windows/config.example.json index 7f20883..da18e3c 100644 --- a/windows/config.example.json +++ b/windows/config.example.json @@ -1,5 +1,5 @@ { - "enabled": false, + "enabled": true, "path1": "D:\\Dropbox", "path2": "dropbox:", "workdir": "D:\\rclone-bisync",