ENDERU
GitHub22 репозиторияDaily Tech4 подписчикаaudion.devвитрина продуктовRSSлента выпусков
← Все заметкиProjects

Audion Hub Manager — почему устроено так

English · О программе · Руководство · Устройство

Содержание

Решения, определившие программу. Каждое принято не из красоты, а потому что иначе было бы хуже.


1. Три слоя вместо одной большой папки

Решение

Проект живёт в трёх слоях, которые могут лежать под общим корнем, но остаются раздельными по смыслу.

ИСХОДНИК     живой проект целиком
GIT-КОПИЯ    техническая отфильтрованная копия с Git
DOCS         нейтральная папка заметок и описаний

Почему раздельно

ИСХОДНИК полный. Со сборками, кэшами, логами и настройками машины — иначе на нём нельзя работать. Такой папке история Git только мешает: её засоряет то, что пересобирается каждый день.

GIT-КОПИЯ техническая. Внутри — то, что пропускает профиль: исходный код, документация, настройки без секретов, запускающие файлы. Это слой для сравнения, коммитов, сервера и повторного использования кода.

DOCS нейтральны. Слой не сканирует тысячи файлов исходников. Там Markdown, указатели, обзоры, заметки. Его синхронизируют чем угодно — редактором, файловым менеджером, Obsidian, LogSeq, облаком или ничем. GIT-КОПИЯ ведётся через Git и на телефон не нужна.

Что из этого следует

Слой DOCS отдельно не сверяется: он читающий, а каноническая техническая копия уже в GIT-КОПИИ. Сверка идёт только между ИСХОДНИКОМ и GIT-КОПИЕЙ.


2. Зеркало, которое не может испортить исходник

Решение

Правила ниже собраны по следам настоящих поломок, и повторять их заново не нужно.

Единственный источник правды

ИСХОДНИК — единственный источник правды. GIT-КОПИЯ производна: зеркало вправе удалять и пересобирать её файлы, но ИСХОДНИК не изменяет никогда.

ИСХОДНИК может быть обычным рабочим деревом Git — зеркалу до этого нет дела, оно читает только то, что разрешил профиль. GIT-КОПИЯ тоже дерево Git, и её .git/** защищён от обхода, удаления и обслуживания.

Настоящая запись требует явного намерения

Профиль объявляет предпросмотр поведением по умолчанию, и командная строка не вправе это проигнорировать:

hub_cli.cmd mirror apply ПРОЕКТ             предпросмотр, если профиль так велит
hub_cli.cmd mirror apply ПРОЕКТ --apply     настоящая запись
hub_cli.cmd mirror apply ПРОЕКТ --dry-run   принудительный предпросмотр

В окне это галочка «сухой прогон» у ПРИМЕНИТЬ.

Фильтр не может молча стать полной копией

Профиль обязан объявлять, что фильтры требуются и сколько масок минимум. Если масок нет — планирование падает, а не собирает полный дубль проекта. Полную копию разрешает только отдельный признак профиля, и ни один поставляемый профиль его не ставит.

Слово проекта стоит над профилем

Профиль общий для всех проектов, .gitignore — слово самого проекта о том, что не хранить. Что он прячет, зеркало не копирует, а check-paths не предлагает в коммит. Иначе ключи в config\keys\ или дерево сборки в build-ui\ легли бы в GIT-КОПИЮ лишней копией на диске, даже если в историю они не попадут. Профиль при этом своих запретов не снимает: проект без .gitignore защищён им одним.

Догадки профиля о папках сборки уступают тому же слову. app\ у Next.js — страницы, build\ у Electron — значки, bin\ — сценарии, vendor\ у Go — закоммиченные зависимости. Где у проекта есть .gitignore, что сборка — решает он; догадки работают только без него. Запреты безопасности — секреты, двоичные файлы, тяжёлое — действуют всегда.

Запись идёт по фазам, удаление — последним

1  создать разрешённые каталоги
2  скопировать и обновить файлы
3  проставить времена изменения
4  если ошибок и расхождений нет — удалить лишнее в GIT-КОПИИ
5  убрать опустевшие каталоги
6  маркеры пустых папок — только если профиль велит

Удаление не начинается, пока копирование не завершилось успешно. При сбое любой ранней фазы удаление пропускается, и отчёт это прямо называет. Это ровно тот случай, когда зеркало потеряло бы файлы, существующие только в нём; настройка профиля этого не отключает.

Три способа сравнения

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

Безопасный способ быстр, но намеренно не ловит случай «тот же размер, то же время, другое содержимое». Для контрольных точек нужен строгий — его и держат поставляемые профили.

Суммы всегда помечены алгоритмом: blake3:… или sha256:…. SHA-256 — запасной вариант, а не равноценная замена.

Расхождения — это не успех

Любое настоящее применение с ошибками или расхождениями возвращает ненулевой код выхода.

Мелочи, которые однажды дорого обошлись

Имена отчётов с микросекундами — иначе быстрая автоматизация перезаписывает собственные отчёты.

Область зеркалирования объявляется явно. «Отфильтрованное» значит, что GIT-КОПИЯ приводится к ИСХОДНИКУ только по выбранным маскам; файлы вне области план не трогает.

План перепроверяется перед записью. Устаревший или поправленный план мог бы удалить по пути, пересекающемуся с ИСХОДНИКОМ, — правила и запрет пересечения проверяются заново.

Проверки, которые должны оставаться зелёными

test_profile_requires_include_masks
test_strict_mode_detects_same_size_same_mtime_different_content
test_safe_mode_keeps_disk_auditor_fast_path_same_size_same_mtime
test_delete_phase_is_skipped_when_copy_phase_fails
test_projection_mirror_preserves_empty_service_dirs
test_projection_preserves_empty_dirs_with_gitkeep

Профиль может держать пустые папки маркером .gitkeep: он ставится в каждую пустую папку, снимается, когда в ней появились настоящие файлы, и не ставится в скрытые технические каталоги. Поставляемые профили маркеров не ставят: служебные папки программа создаёт сама (install\init_folders.cmd), а пустые файлы-метки только засоряют историю.


3. Программа не хранит пароли

Решение

Hub Manager не становится хранилищем токенов и паролей. Программа портативна, а учётные данные Git внутри портативной папки не живут.

Вход делегирован обычным средствам:

  • ключи SSH и ssh-agent;
  • диспетчер учётных данных для HTTPS (Git Credential Manager);
  • командные утилиты GitHub и GitLab;
  • VS Code и GitKraken — для ручного входа и наглядной работы.

Программа выполняет настоящие команды git и показывает их вывод целиком. Если вы уже вошли через любое из перечисленного, отправка и приём работают, а программа не знает ни одного секрета.

Что это значит на практике

Удалённый репозиторий — это именованный адрес:

git remote add github git@github.com:audion/Audion_Hub.git
git remote add gitlab git@gitlab.com:audion/Audion_Hub.git
git remote add local_nas file:///Z:/git-mirrors/Audion_Hub.git

Адрес с паролем или токеном внутри программа не сохраняет. Проверка доступа опознаёт вид адреса и подсказывает, чем вы будете опознаны, — но остаётся проверкой, а не редактором учётных данных.

Исключение, которое исключением не является

Для своих серверов Forgejo и Gitea программа принимает личный токен доступа: проверяет его запросом к серверу и передаёт вашему помощнику учётных данных. В файлы программы и в журнал токен не попадает, а дальше git push берёт его из хранилища сам. «Забыть токен» убирает его из хранилища этой машины.

Известные адреса серверов лежат в настройках открыто — без токенов.


4. Одна таблица Git-команд

Решение

Все Git-команды программы — одна таблица, канон: команда с местами, риск, режим, слова на двух языках «что делает» и «как отменить». Окно не пишет Git-команд само: кнопка — запись канона, подпись кнопки — команда, как её набирают в терминале.

Почему

Программа учит, пока ей пользуются. Человек видит, какая команда пошла, и читает, что она сделала и как её отменить. Через месяц он набирает её сам.

Одно место — одна правда. Тест гоняет каждую запись канона на свежей копии учебной лаборатории; таблицы в документах пишутся из канона и сверяются тестом. Кнопка, документ и проверка не могут разойтись.

Риск виден до нажатия. Читает, меняет, сеть, опасно — точкой у кнопки. Опасное спрашивает с командой целиком, тем, что сейчас не закоммичено, и способом отмены; редкое и переписывающее историю (rebase -i) — заготовка, которую дописывают сами.

Что из этого следует

pull — только перемоткой: слияние человек делает сам и видит. В индекс и коммит идёт только то, что пропускает профиль проекта, — никакого git add .: иначе смысл фильтрации теряется на первом же коммите.


5. Окно — лицо консольной команды

Решение

Всё, что окно делает вне Git, — реестр, зеркало, проверки, пакеты, лаборатория, Forgejo — идёт через hub_cli.cmd с одним JSON на ответ. Git окно зовёт само.

Почему

То, что умеет окно, умеет и сценарий, и агент, и человек в консоли — без окна и без расхождений. Движок на Python проверен тестами и не переписывается ради окна. Git же окно зовёт напрямую: команда, которую оно показывает, и есть урок, а состояние репозитория читается слишком часто, чтобы ходить за ним через посредника.


6. Лаборатория вместо примеров

Решение

Учебные репозитории не лежат в программе готовыми — их строит lab.py: десять репозиториев в известных состояниях, с постоянными авторами, датами и байтами файлов.

Почему

Учиться надо на том, что можно сломать. Сломанное строится заново одной кнопкой, с теми же хэшами на любой машине, поэтому урок, тест и описание говорят об одних и тех же коммитах. Те же репозитории — испытательный стенд канона.

Правлено 24.10.2026