Skip to content

Commit 8faa59d

Browse files
committed
bump to 1.3, document terminal-free run + password + update-in-menu
- build.sh CFBundleShortVersionString 1.2 -> 1.3 - README/README.ru: password field, inline run status, run-in-terminal fallback, updates in the '...' menu; add smoke test to the Tests section - PRD: current state v1.3.0, Runner.swift + smoke test in architecture
1 parent 1b51e68 commit 8faa59d

4 files changed

Lines changed: 41 additions & 25 deletions

File tree

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ copies it to the clipboard, or runs it in a terminal.
3838
- Preview button: a dry run (`-n`) to see what would transfer before doing it
3939
- Every toggle has a tooltip explaining what the flag does
4040
- Live command with shell-safe quoting of paths
41-
- Copy to clipboard, or run in a separate terminal window (SSH password prompts work there)
41+
- Optional SSH password field (kept in memory only) so a run needs no terminal; leave empty for key-based login
42+
- Run and Preview execute inline: a spinner in the button, a brief success check, or an in-panel error banner with the output
43+
- Copy to clipboard; a "Run in terminal" fallback lives in the "•••" menu for 2FA / host-key confirmation
4244
- Interface language (English / Русский) switchable in Settings
43-
- Check for updates in Settings: compares your version against the latest GitHub release
45+
- Check for updates from the "•••" menu: compares your version against the latest GitHub release
4446

4547
## Install
4648

@@ -68,10 +70,11 @@ With [InjectionIII](https://github.com/johnno1962/InjectionIII) running, method-
6870
edits are hot-swapped at runtime. There is no `Inject` dependency, so SwiftUI views
6971
do not auto-refresh - it is a plain debug build plus `-interposable`.
7072

71-
## Logic check
73+
## Tests
7274

7375
```sh
74-
swiftc Sources/rsync-builder/Command.swift tests/main.swift -o /tmp/rsync_check && /tmp/rsync_check
76+
swiftc Sources/rsync-builder/Command.swift tests/main.swift -o /tmp/rsync_check && /tmp/rsync_check # logic
77+
swiftc Sources/rsync-builder/Command.swift tests/smoke.swift -o /tmp/rsync_smoke && /tmp/rsync_smoke # smoke: local rsync + SSH_ASKPASS wiring
7578
```
7679

7780
## Dependencies

README.ru.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@
3838
- Кнопка Preview: пробный прогон (`-n`), чтобы увидеть, что будет перенесено, до реального запуска
3939
- У каждого переключателя подсказка, за что отвечает флаг
4040
- Живая команда с безопасным shell-квотингом путей
41-
- Копирование в буфер или запуск в отдельном окне терминала (там же вводится пароль SSH)
41+
- Необязательное поле пароля SSH (хранится только в памяти) - запуск без терминала; пусто = вход по ключу
42+
- Run и Preview выполняются прямо в панели: крутилка в кнопке, короткая галочка успеха либо баннер ошибки с выводом
43+
- Копирование в буфер; запасной «Запустить в терминале» - в меню «•••» (для 2FA / подтверждения host key)
4244
- Язык интерфейса (English / Русский) переключается в Настройках
43-
- Проверка обновлений в Настройках: сверяет твою версию с последним релизом на GitHub
45+
- Проверка обновлений в меню «•••»: сверяет твою версию с последним релизом на GitHub
4446

4547
## Установка
4648

@@ -68,10 +70,11 @@ open rsync-builder.app
6870
подхватываются на лету. Зависимости `Inject` нет, поэтому SwiftUI-вью не обновляются
6971
автоматически - это просто debug-сборка с `-interposable`.
7072

71-
## Проверка логики
73+
## Тесты
7274

7375
```sh
74-
swiftc Sources/rsync-builder/Command.swift tests/main.swift -o /tmp/rsync_check && /tmp/rsync_check
76+
swiftc Sources/rsync-builder/Command.swift tests/main.swift -o /tmp/rsync_check && /tmp/rsync_check # логика
77+
swiftc Sources/rsync-builder/Command.swift tests/smoke.swift -o /tmp/rsync_smoke && /tmp/rsync_smoke # смоук: локальный rsync + проводка SSH_ASKPASS
7578
```
7679

7780
## Зависимости

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ cat > "$APP/Contents/Info.plist" <<'PLIST'
2323
<key>CFBundleExecutable</key><string>rsync-builder</string>
2424
<key>CFBundleIconFile</key><string>AppIcon</string>
2525
<key>CFBundlePackageType</key><string>APPL</string>
26-
<key>CFBundleShortVersionString</key><string>1.2</string>
26+
<key>CFBundleShortVersionString</key><string>1.3</string>
2727
<key>LSMinimumSystemVersion</key><string>26.0</string>
2828
<key>NSHighResolutionCapable</key><true/>
2929
<key>LSUIElement</key><true/>

docs/PRD.md

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# rsync builder - PRD
22

3-
Status: v1.2 shipped (Phases 1-2 of the expansion done). This document records the
4-
current state and the planned expansion so nothing gets lost.
3+
Status: v1.3 shipped (Phases 1-2 of the expansion done, plus terminal-free run + password auth).
4+
This document records the current state and the planned expansion so nothing gets lost.
55

66
Last updated: 2026-07-04
77

@@ -14,7 +14,7 @@ folders to servers and wants the correct command without memorising flags.
1414
Non-goals: multi-source lists (decided against), code signing/notarization,
1515
being a general file manager.
1616

17-
## 2. Current state (shipped, v1.2.0)
17+
## 2. Current state (shipped, v1.3.0)
1818

1919
### UX
2020
- Menu bar only app (`MenuBarExtra`, `.window` style, `LSUIElement`): no Dock icon,
@@ -31,28 +31,38 @@ being a general file manager.
3131
`--rsync-path="sudo rsync"`) and an upload-only post-sync command appended as
3232
`rsync … && ssh -p N user@host '<cmd>'`. (v1.2)
3333
- Live command with shell-safe quoting of every path (`shellQuote`).
34-
- Copy to clipboard; Run in a separate terminal window (SwiftTerm), where SSH
35-
password/passphrase prompts work.
36-
- Buttons in a top bar (direction + Copy + Run + "•••" menu with Settings / About / Quit).
34+
- Optional SSH password field (`SecureField`, in-memory only, never persisted). Run/Preview
35+
execute inline via `Process` (`/bin/sh -c`) with no terminal; the password is fed to ssh
36+
through an `SSH_ASKPASS` helper reading it from the child env (`RSYNC_BUILDER_PASS`), never
37+
written to disk. Empty password = key-based login. Host key auto-accepted via
38+
`RSYNC_RSH=ssh -o StrictHostKeyChecking=accept-new`. (v1.3)
39+
- Run state shown inline: a spinner in the Run/Preview button (doubling as cancel), a brief
40+
green success check for Run, or an in-panel error banner with the exit code + output.
41+
Preview surfaces its dry-run output in that banner. (v1.3)
42+
- Copy to clipboard; a "Run in terminal" fallback (SwiftTerm) stays in the "•••" menu for
43+
2FA / host-key confirmation. (v1.3)
44+
- Buttons in a top bar (direction + Preview + Copy + Run + "•••" menu).
3745
- Localization EN / RU, language switch in the Settings window (default EN).
38-
- "Check for updates" in Settings: queries the GitHub Releases API (native `URLSession`,
46+
- "Check for updates" in the "•••" menu: queries the GitHub Releases API (native `URLSession`,
3947
no new dependency) and compares `tag_name` against the app version. A silent auto-check
40-
runs at most once a day and surfaces only when an update is available.
48+
runs at most once a day and surfaces only when an update is available. (v1.3: moved from Settings)
4149
- Native Liquid Glass, Pow button effects (gated by Reduce Motion), accessibility
4250
labels, `@FocusState`, incomplete-command guard (Run disabled until server + both paths).
4351
- Form state persisted between launches (`@AppStorage`); server profiles and exclude
4452
list persisted via Defaults; real servers live only in local `UserDefaults`, never in source.
4553

4654
### Architecture
47-
- `Command.swift`: pure `buildCommand(...)`, `shellQuote`, `ServerProfile`, `ExcludeItem`,
48-
`Direction`, `defaultProfiles` (single `example` profile), `defaultExcludes`.
49-
- `App.swift`: `ContentView` (the popover) + `RsyncBuilderApp` scene (`MenuBarExtra` + `Settings`).
50-
- `Terminal.swift`: `TerminalWindow` (SwiftTerm run window).
51-
- `Persistence.swift`: Defaults key for profiles.
52-
- `Localization.swift`, `Settings.swift`, `Menu.swift`.
55+
- `Command.swift`: pure `buildCommand(...)`, `shellQuote`, `runTransport`, `runEnvironment`,
56+
`askpassScript`, `ServerProfile`, `ExcludeItem`, `Direction`, defaults.
57+
- `Runner.swift`: `CommandRunner` (runs rsync via `Process`, publishes state/output; no window).
58+
- `App.swift`: `ContentView` (the popover, spinner-in-button + result banner) + `RsyncBuilderApp` scene.
59+
- `Terminal.swift`: `TerminalWindow` (SwiftTerm fallback run window).
60+
- `Persistence.swift`: Defaults keys for profiles/excludes.
61+
- `Localization.swift`, `Settings.swift`, `Menu.swift`, `Update.swift`.
5362
- Deps: SwiftTerm, Pow, Defaults. Requires macOS 26+.
54-
- Tests: assert-based logic check for `buildCommand` (`tests/main.swift`).
55-
- CI: `ci` (build + logic test), `lint` (swift-format, non-blocking), `release`
63+
- Tests: assert-based logic (`tests/main.swift`) + server-free smoke (`tests/smoke.swift`:
64+
local rsync run + `SSH_ASKPASS` password delivery).
65+
- CI: `ci` (build + logic + smoke), `lint` (swift-format, non-blocking), `release`
5666
(DMG on tag `v*`), `stale`, `dependency-review`. Public repo, BSD-3.
5767

5868
## 3. Planned expansion

0 commit comments

Comments
 (0)