Skip to content

feat(utf8): cfg записывается в нативной кодировке (#3787) - #3794

Open
bylins wants to merge 2 commits into
masterfrom
feat/utf8-cfg-write
Open

feat(utf8): cfg записывается в нативной кодировке (#3787)#3794
bylins wants to merge 2 commits into
masterfrom
feat/utf8-cfg-write

Conversation

@bylins

@bylins bylins commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Первый шаг перевода lib/cfg на UTF-8 (#3787) — граница записи. Данные этот PR не трогает.

Как сейчас

Чтение уже всеядно: DataNode берёт файл через native_text::read_data_file, а from_disk_text считает валидный UTF-8 уже переведённым, всё остальное — KOI8-R.

А запись всегда переводила в KOI8-R:

decl.attribute("encoding").set_value("koi8-r");
...
const std::string on_disk = native_text::to_disk(xml.str());

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

Что сделано

Запись стала зеркалом чтения: XML пишется как есть, в UTF-8, объявление в шапке — utf-8. Файлы, которые лежат в KOI8-R, читаются по-прежнему; первое сохранение через ведуна переводит такой файл в UTF-8.

Порядок выката

Эта правка должна ехать вместе со снятием working-tree-encoding с /lib/cfg/**. Пока атрибут стоит, git ждёт в рабочем дереве KOI8-R, и файл, сохранённый ведуном в UTF-8, при git add перекодируется повторно — в блоб уедет каша. До снятия атрибута конфиги через ведуна лучше не править.

Что дальше по данным (в этом PR не делается)

  • 121 файл lib/cfg трекается, 19 — нет (privilege.xml, shops.xml, daily_quest.xml, obj_sets.xml, guards.xml, celebrates.xml, cases.xml, craft/metacraft/*), их переводит только конвертация на диске.
  • На диске сейчас: 64 файла KOI8-R, 74 чисто ASCII, 2 уже UTF-8.
  • В 100 файлах в шапке стоит encoding="koi8-r" — это содержимое, а не кодировка, так что для трекаемых понадобится отдельный коммит с правкой объявления.

Отдельно замечено

Шесть мест читают XML сырым load_file() мимо границы кодировки: craft.cpp (4 раза — как раз craft/metacraft/*), sets_drop.cpp и config.cpp. Сегодня они получают KOI8-байты как UTF-8; после перевода данных начнут читать правильно сами собой, но привести их к read_data_file всё равно стоит — отдельной правкой.

Проверено

Сборка чистая, 669 тестов зелёные.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XUwDWDnYdXrJdvjDVd36QH


Инструкция по переезду

Порядок важен: пока движок пишет cfg в KOI8-R, любая правка через ведуна откатывает файл назад, а пока стоит working-tree-encoding, git ждёт в рабочем дереве KOI8-R и портит блоб при git add.

Шаг 0. Выкатить движок

Влить этот PR и поставить новый бинарь. До этого конфиги через ведуна не править.

Шаг 1. Бэкап

tar czf ~/cfg-before-utf8-$(date +%F).tgz -C /home/mud/mud/lib cfg

Шаг 2. Снять атрибут (в репозитории движка)

cd ~/repos/mud
git pull
sed -i 's|^/lib/cfg/\*\* working-tree-encoding=KOI8-R eol=lf$|/lib/cfg/** eol=lf|' .gitattributes
git diff --cached --stat            # должно быть пусто
git commit -m "utf8: снять working-tree-encoding с конфигов (#3787)" -- .gitattributes

Только .gitattributes, через -- путь. Не git commit -am: в этот момент git считает изменёнными все конфиги, и -a записал бы их в блобы в KOI8-R — так мы уже потеряли мир и commands.hlp.

Шаг 3. Перевыкачать трекаемые конфиги

git ls-files -z lib/cfg | xargs -0 rm -f
git checkout -- lib/cfg

Именно git ls-files, а не rm -rf lib/cfg: 19 конфигов в git не опубликованы (privilege.xml, shops.xml, shop_item_sets.xml, daily_quest.xml, obj_sets.xml, guards.xml, celebrates.xml, cases.xml, animate_dead.*, craft/metacraft/*), и rm -rf снёс бы их без возврата.

Без удаления не обойтись: git смотрит на mtime и размер и считает файлы неизменившимися, поэтому git checkout -- lib/cfg сам по себе ничего не перезапишет.

Шаг 4. Поправить шапки и перевести неопубликованные

./tools/convert_cfg_to_utf8.py lib/cfg              # посмотреть
./tools/convert_cfg_to_utf8.py lib/cfg --apply

Скрипт идемпотентен: содержимое переводит только у файлов в KOI8-R, объявление encoding="koi8-r" правит везде, где оно есть. На трекаемых файлах после шага 3 остаётся только правка шапки, на неопубликованных — и то, и другое.

Закоммитить шапки трекаемых файлов:

git diff --stat -- lib/cfg | tail -1
git commit -m "utf8: конфиги объявляют utf-8 (#3787)" -- lib/cfg
git push

Шаг 5. Боевой сервер

cd /home/mud/mud
git pull                                            # придут .gitattributes и шапки
git ls-files -z lib/cfg | xargs -0 rm -f
git checkout -- lib/cfg
./tools/convert_cfg_to_utf8.py lib/cfg --apply      # неопубликованные 19

Шаг 6. Проверка

git ls-files -z lib/cfg | xargs -0 file | grep -v 'UTF-8\|ASCII'   # пусто
grep -rl 'encoding="koi8-r"' lib/cfg                                # пусто
git status --porcelain lib/cfg                                      # пусто

И в игре: ведун открыть любой конфиг, сохранить, затем file на этот файл — должен остаться UTF-8, а в шапке utf-8.

Откат

Данные откатывать не нужно: чтение принимает обе кодировки (from_disk_text). Если понадобится вернуть старый бинарь — он прочитает UTF-8-конфиги нормально, но при сохранении через ведуна переведёт файл обратно в KOI8-R.

Что осталось за рамками

  • lib.template/cfg — ещё 28 файлов, тот же приём, отдельным заходом;
  • lib/etc/board/** — доски пишет сам движок, там нужен разбор пути записи;
  • шесть мест с сырым load_file() мимо границы кодировки (craft.cpp, sets_drop.cpp, config.cpp).

bylins and others added 2 commits August 29, 2026 08:30
Читать конфиги движок умеет в обеих кодировках: DataNode берёт файл через
read_data_file, а from_disk_text считает валидный UTF-8 уже переведённым. Писал
же он всегда в KOI8-R -- через native_text::to_disk и с encoding="koi8-r" в
шапке. То есть любой файл, сохранённый через ведуна, возвращался в старую
кодировку, и cfg никогда не сошёлся бы к одной: ровно та же history, что была у
мира до #3792.

Теперь запись -- зеркало чтения: XML пишется как есть, в UTF-8, и объявление в
шапке говорит utf-8. Файлы, которые сейчас лежат в KOI8-R, читаются по-прежнему;
первое же сохранение через ведуна переводит такой файл в UTF-8.

Правка обязана ехать вместе со снятием working-tree-encoding с lib/cfg: пока
атрибут стоит, git ждёт в рабочем дереве KOI8-R, и сохранённый ведуном UTF-8
попадёт в блоб перекодированным дважды.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUwDWDnYdXrJdvjDVd36QH
Делает две вещи, обе идемпотентно: переводит содержимое из KOI8-R в UTF-8 (по той
же логике, что и движок -- валидный UTF-8 считается уже переведённым) и правит
объявление кодировки в шапке XML на utf-8.

Второе нужно отдельно: объявление -- это содержимое файла, а не его кодировка,
поэтому у трекаемых в git файлов оно не поменяется само собой при снятии
working-tree-encoding.

Проверено на копии lib/cfg: 64 файла переведены, 100 шапок поправлены, повторный
прогон ничего не находит, а текст всех 140 файлов совпадает с исходным
посимвольно (кроме самого объявления).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUwDWDnYdXrJdvjDVd36QH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant