# ftsync A terminal-based FTP sync tool built with Ratatui. Local directory is always authoritative — new and modified files are uploaded to the server. --- ## Requirements - Rust 1.80+ (install via [rustup](https://rustup.rs)) - OpenSSL development headers (for FTPS/TLS support) ```bash # Debian / Ubuntu sudo apt install libssl-dev pkg-config # Arch sudo pacman -S openssl # Fedora sudo dnf install openssl-devel ``` --- ## Build ```bash cargo build --release # Binary: ./target/release/ftsync ``` Optionally install system-wide: ```bash cargo install --path . ``` --- ## Running ### Option A — environment variables (credentials never written to disk) ```bash FTP_HOST=ftp.example.com \ FTP_USER=ian \ FTP_PASS=secret \ FTP_LOCAL=/home/ian/dist \ FTP_REMOTE=/public_html \ ./target/release/ftsync ``` Full list of env vars: | Variable | Description | Default | |-------------|------------------------------------|---------| | `FTP_HOST` | FTP server hostname or IP | — | | `FTP_PORT` | FTP port | 21 | | `FTP_USER` | FTP username | — | | `FTP_PASS` | FTP password | — | | `FTP_LOCAL` | Local directory to sync from | — | | `FTP_REMOTE`| Remote directory to sync to | — | | `FTP_TLS` | Enable FTPS/TLS (`1`/`true`/`yes`) | false | ### Option B — interactive config screen Run `ftsync` with no env vars. A config form will appear. Fill in your credentials and press **Enter** — they are saved to `~/.ftpsync.conf`. --- ## Keybindings ### Config screen | Key | Action | |------------------|-------------------------| | `Tab` / `↓` | Next field | | `Shift+Tab` / `↑`| Previous field | | `Enter` | Save and go to sync | | `q` / `Esc` | Quit | ### Sync screen | Key | Action | |-----|-----------------------------| | `s` | Start sync | | `d` | Dry run (preview only) | | `c` | Back to config | | `q` | Quit (or abort active sync) | ### Summary screen | Key | Action | |-----|-----------------| | `s` | Sync again | | `c` | Back to config | | `q` | Quit | --- ## Config file Stored at `~/.ftpsync.conf` (TOML). Environment variables always override values in this file. ```toml host = "ftp.example.com" port = 21 user = "ian" password = "secret" local_dir = "/home/ian/dist" remote_dir = "/public_html" tls = false excludes = [".git", "node_modules", "__pycache__", ".DS_Store", "Thumbs.db"] ``` --- ## How sync works 1. Connects to the FTP server (plain or FTPS). 2. Recursively lists all files on the remote, recording their sizes. 3. Walks the local directory tree, skipping excluded patterns. 4. For each local file: if the remote file exists with the same byte size, it is **skipped**. Otherwise it is **uploaded**. 5. Remote directories are created automatically as needed. 6. The sync task runs on a Tokio async thread; the Ratatui UI stays responsive throughout via an `mpsc` channel. --- ## Project structure ``` src/ ├── main.rs Terminal setup, Tokio event loop, keyboard handling ├── app.rs App state machine (screens, fields, sync state) ├── ftp.rs FTP/FTPS connection and sync engine (suppaftp) ├── ui.rs All Ratatui widget rendering (3 screens) └── config.rs Config loading/saving, env var overlay ```