Глава 23 · Часть IV · Реализуем SafeSort

Режим предварительного просмотра

Команда plan — предварительный просмотр без побочных эффектов: тот же план, что и у apply, но без единого изменения диска.

SafeSort · Часть 4 из 6Реализация
GitHubIssue #4 · Project «SafeSort — первый релиз»
Add dry-run CLI (scan/plan)
Area: CLIPriority: Medium
git switch -c feat/cli

Команда plan — единственное, что нужно сделать с готовым объектом SortPlan, чтобы получить полноценный предварительный просмотр (dry run): она собирает план и выводит его размер на экран, ни разу не вызывая ничего, что меняет диск.

src/safesort/cli.py
def cmd_plan(args: argparse.Namespace) -> int:
    root = args.root
    config, code = _load_config(root)
    files = scan(root, config)
    plan = build_plan(files, root, config)
    print(f"{len(plan.operations)} move operations planned.")
    print("No files have been changed.")
    return 0
~/safesort $ safesort plan ~/Downloads
9 move operations planned.
No files have been changed.

Вторая строка вывода — "No files have been changed." — не формальность. Проверим её честно: посчитаем контрольные суммы файлов до и после plan и сравним.

~ $ sha256sum Downloads/* > before.txt
~ $ safesort plan ~/Downloads
9 move operations planned.
No files have been changed.
~ $ sha256sum Downloads/* > after.txt
~ $ diff before.txt after.txt
 

diff не вывел ни строки — файлы действительно не изменились. Позже такую же проверку сделает автоматический тест, а не ручное сравнение.

scan, plan и duplicates используют один и тот же список файлов
Три read-only команды SafeSort — scan, plan и duplicates — начинаются одинаково: вызывают scan(), чтобы получить список файлов. Дальше их пути расходятся: plan строит план, duplicates ищет совпадения по содержимому, а scan просто считает файлы по категориям.
В истории репозитория cli.py собрали одним PR, в самом конце
Эта книга вводит cli.py постепенно: cmd_plan() здесь, остальные подкоманды дальше по мере готовности функций, которые они вызывают. В реальном репозитории SafeSort всё было наоборот: argparse-обвязка для всех пяти подкоманд (scan, plan, apply, duplicates, undo) была написана и слита одним PR в самом конце, уже когда все пять функций существовали. Это два разных порядка: порядок, в котором удобно объяснять, и порядок, в котором реально писали код.

Коротко

  • plan строит тот же SortPlan, что и apply, но только выводит его размер на экран.
  • scan, plan и duplicates начинаются одинаково — с вызова scan() — и расходятся дальше.
  • Утверждение «файлы не изменены» после plan — не текст для красоты, а поведение, которое проверяется автоматическим тестом.
Чекпойнт · Issue #4
git commit -m "feat: add command-line interface"
В реальной истории репозитория это Pull Request #21, который слился последним из девяти, после Issue #9 (дубликаты), а не сразу после плана, как в порядке этой книги: к этому моменту в репозитории уже существовали все функции, которые предстоит обвязать интерфейсом командной строки.
Статус в реальном Project: Done