Объединение модулей из конфигуратора
Объединение текстовых файлов на диске
Предисловие
Я уже давно пользуюсь KDiff3 для объединения текстов модулей при обновлении конфигурации на поддержке.
Мне очень нравится, что большую часть работы KDiff3 делает за меня.
Но есть два момента, которые меня несколько печалили:
- KDiff3 сильно портачит, когда изменяется порядок методов в модуле (вы понимаете, о чем я, если пользуетесь KDiff3).
- По причине 1 приходится просматривать весь результат объединения, даже если не было конфликтов, чтобы убедиться, что нет фрагментов кода, "выпавших" из контекста.
Иногда в модуле в очередном обновлении изменена 1 строка в конфигурации поставщика, но т.к. в этом модуле 300 вставок наших доработок, приходится 301 раз нажать Ctrl+↓, чтобы убедиться, что всё хорошо.
Хотелось избавиться от этой рутины.
Конфигуратор умеет выделять дважды измененные объекты, а для остальных устанавливает режим объединения по умолчанию.
Хотелось сделать то же самое и для модулей, только здесь надо уметь выделить дважды измененные методы.
Использование
Тестировалось с KDiff3 версий 0.9.98 и 1.12.2, платформа 1С версии 8.3.24.1667.
ВАЖНО! Режим объединения каталогов в KDiff3 все еще, даже в версии 1.12.3, находится в статусе бета-тестирования. В моем случае на результат это ни разу не повлияло, но интерфейс иногда ведет себя неожиданно. Об этом есть соответствующие примечания по тексту ниже.
Объединение модулей из конфигуратора
На следующем скриншоте окно конфигуратора после запуска обновления конфигурации на поддержке.
Т.к. в моих настройках MMbM используется в режиме "Взять из...", "Объединить с приоритетом...", я просто нажимаю шестеренку.
Пример посложнее
Для начала возьмем пример посложнее (в данном конкретном случае). Объединим модуль УчетНДС.
Нажимаем шестеренку. Скрипт из каждой версии модуля создаст 3 папки, в каждой в отдельных файлах записаны тексты методов и дополнительный файл со структурой модуля, он называется {СтруктураМодуля}.txt.
Потом откроется KDiff3 в режиме объединения каталогов.
Если сейчас просто закрыть KDiff3 (или в любом другом случае, если до возврата в Конфигуратор произойдет ошибка), ничего страшного не произойдет. Просто будет выведено предупреждение, что результат не сформирован, и мы вернемся в Конфигуратор, как будто ничего не было.
Но мы этого делать не будем.
Скроем полностью идентичные методы, отжав кнопку "Показать идентичные файлы".
ВАЖНО! Надо будет не забыть нажать ее обратно перед финальным шагом. Иначе скрытые файлы-методы не попадут в результат.
Мы видим, что изменилась структура модуля, несколько методов удалено, несколько изменено и в конфигурации поставщика (КП) и в основной конфигурации (ОК). Также есть методы, измененные только в КП или в ОК.
Нас интересуют только "дважды измененные" методы, для которых установлено действие "Объединить (вручную)".
На счет "вручную" KDiff3 скромничает, бОльшую часть она сделает автоматически, но мы должны "утвердить" ее изменения.
Дальше можно либо вручную пройтись по каждому файлу-методу с пометкой "Объединить (вручную)", но проще просто нажать F7.
Перед этим включим обратно отображение идентичных файлов.
Нажимаем F7.
Будет выведен вопрос-предупреждение:
Внимательно читаем, и если уверены, нажимаем "Выполнить".
KDiff3 поочередно обновит файлы в соответствии с указанным Действием. Там, где указано "Объединить (вручную)", файлы будут открыты для трехстороннего объединения в обычном режиме.
В нашем случае первым на очереди оказался {СтруктураМодуля}.txt
Видим, что кроме наших методов в КП добавлены новые.
Объединяем из B и C:
Снова нажимаем F7.
Нажимаем "Сохранить и продолжить".
Лучше делать именно так: нажимать F7, а потом "Сохранить и продолжить". Если вы нажмете например Ctrl+S, то KDiff3 после этого почему-то уже не даст что-либо сделать, все время будет выводиться такое окно:
То же самое произойдет, если вы кликните по какому-то файлу-методу, "чтобы посмотреть", а потом при переключении на другой файл нажмете "Продолжить без сохранения".
Если такое случится, надо нажать Shift+F5 (или меню Папка – Сканировать повторно), и начать объединение сначала.
Но мы всё сделали, как надо. Поэтому KDiff3 продолжила объединение.
Доходим до следующего метода.
Здесь KDiff3 все сделала сама. Остается только согласиться.
Снова нажимаем F7, "Сохранить и продолжить".
И так далее, пока всё это не закончится и у каждого файла-метода не будет отметки "Готово".
Закрываем KDiff3.
Скрипт соберет результат из отдельных файлов в один итоговый и результат вернет в Конфигуратор.
На шестеренке появится зеленая галка.
Пример попроще
Теперь возьмем пример попроще, где KDiff3 все сделает сама. Объединим модуль УчетНДСБП.
Так же нажмем шестеренку.
Откроется окно KDiff3.
Если сейчас скрыть идентичные файлы, увидим, что вручную объединять ничего не надо.
Просто нажимаем F7 (предварительно отключив скрытие идентичных файлов). Закрываем KDiff3.
И возвращаемся в Конфигуратор. На шестеренке появилась зеленая галка.
Если метод переименован
Тяжелый случай. Тут надо знать, что во что переименовано.
Но если мы это знаем, то можем помочь KDiff3.
В качестве подопытного возьмем тот же УчетНДСБП. Но для эксперимента я переименую в нем один метод в основной конфигурации. СформироватьДвиженияПересортицаТоваров --> СформироватьДвиженияПересортицаТоваровНашаВерсия.
Как видим, KDiff3 не сумела сопоставить разноименные файлы.
Выбираем действие "C".
Кликаем по очереди колонки A, B, C в нужных строках.
Далее: меню Папка – Объединить явно выделенные файлы. Откроется обычный диалог трехстороннего объединения.
Убеждаемся, что в качестве результата указан файл в папке "methods-c". Выполняем объединение, как обычно.
Нажимаем F7. Далее всё, как в предыдущем разделе.
Объединение текстовых файлов на диске
Предположим, у нас есть внешняя обработка от стороннего поставщика, такая, как Диадок например (не сочтите за рекламу).
В этой обработке есть наши доработки.
Выходит новая версия обработки от поставщика. И хотелось бы воспользоваться всеми преимуществами трехстороннего объединения. Но обработки так объединяться не умеют.
Поможем.
Надо только некоторые шаги, которые скрипт делает автоматически, сделать вручную.
Сначала нам надо сохранить модули всех версий обработок в 3 файла. Я обычно сохраняю их с такими именами:
A_СКП_база.txt – старая конфигурация поставщика,
B_ОК.txt – основная конфигурация (с нашими доработками)
C_НКП.txt – новая конфигурация поставщика.
Далее поочередно на каждом файле нажимаем правую кнопку мыши, выбираем команду "Выгрузить методы".
Будет создано 3 папки:
Выделяем эти папки снизу вверх: сначала C_НКП, затем B_ОК, и наконец A_СКП_база.
Клик правой кнопки мыши, команда "KDiff3 – 3 way comparison".
Объединяем каталоги, как было описаны выше для Конфигуратора.
Результат будет помещен в папку C_НКП.
Клик правой кнопки мыши на папке C_НКП, команда "Создать модуль из методов".
Будет обновлен файл C_НКП.txt.
Осталось только скопировать текст из C_НКП.txt в модуль новой версии обработки.
Установка и настройка
1. Распаковать архив merge-modules-by-methods.zip.
Распаковать можно в любую папку, но я рекомендую
C:\Users\<имя пользователя>\AppData\Roaming\merge-modules-by-methods.
Это позволит подключить дополнительные команды в контекстное меню проводника (об этом ниже).
Должно получиться так:
2. Внести изменения в main.ini, если необходимо.
Настройки и значения по умолчанию описаны в файле.
Настройка KDiff3ForMergeIniFileName мне понадобилась для того, чтобы отключить вывод предупреждающего окна KDiff3, которое открывается в режиме объединения из-за того, что у меня добавлена команда препроцессора для скрытия номеров строк (Настройка KDiff3 для исключения номеров строк в отчетах о сравнении конфигураций).
3. Добавить команды в контекстное меню проводника
Этот пункт можно пропустить, если вы не планируете объединять отдельные файлы, сохраненные на диск. Такая возможность может быть полезна, например, для трехстороннего объединения текстов модулей внешних обработок.
Предполагается, что скрипты находятся по пути:
%UserProfile%\AppData\Roaming\merge-modules-by-methods.
Если это не так, потребуется вручную исправить пути в реестре.
Команды добавляются двойным кликом по файлам *.reg.
parse-1c-module.reg – добавляет команду "Выгрузить методы" для файлов.
assemble-1c-module.reg – добавляет команду "Создать модуль из методов" для папок.
4. Настроить Конфигуратор
4.1. Сервис – Параметры – Сравнение/объединение
4.1.1. Добавить новую внешнюю программу.
Тексты для копирования:
MMbM %UserProfile%\AppData\Roaming\merge-modules-by-methods\main.cmd %baseCfg %secondCfg --L1 %baseCfgTitle --L2 %secondCfgTitle %baseCfg %secondCfg --L1 %baseCfgTitle --L2 %secondCfgTitle -o %merged %oldVendorCfg %baseCfg %secondCfg --L1 %oldVendorCfgTitle --L2 %baseCfgTitle --L3 %secondCfgTitle -o %merged %oldVendorCfg %baseCfg %secondCfg --L1 %oldVendorCfgTitle --L2 %baseCfgTitle --L3 %secondCfgTitle -o %merged –auto
4.1.2. Указать MMbM в качестве программы для сравнения/объединения в нужных режимах.
Я, например, сделал так:
Как это работает (коротко)
main.cmd – скрипт-оболочка. Он просто перенаправляет вызов из конфигуратора в скрипт main.js.
main.js – скрипт-интегратор. Здесь мы:
- разбираем параметры командной строки,
- парсим модуль на методы,
- запускаем KDiff3 в режиме объединения каталогов,
- собираем результат в один файл, завершаем работу
Все 3 скрипта на JS довольно просты.
Самое интересное здесь – парсинг модуля на методы.
Я долго не брался за эту задачу, т.к. казалось, что это слишком трудоемко, пока однажды меня не осенило, что для парсинга можно использовать RegExp.
В итоге вся магия оказалось в одной строке скрипта parse-1c-module.js.
Вот эта строка:
/(?:^|\n)(?:[ \t]*?\/\/.*\n)*?(?:(?:[ \t]*?&.*\n)(?:[ \t]*?(?:\/\/.*)??\n)*)??[ \t]*?(?:Асинх\s*?|Async\s*?)??[ \t]*?(Процедура|Функция|Procedure|Function)\s(?:[ \t]*?(?:\/\/.*)??\n)*[ \t]*?([А-Яа-яA-Za-z_][А-Яа-я\w]*)(?:[ \t]*?(?:\/\/.*)??\n)*[ \t]*?\([\s\S]*?\n[ \t]*?(?:КонецПроцедуры|КонецФункции|EndProcedure|EndFunction).*\n?(?:(?:[ \t]*?\/\/.*\n)*(?=(?:[ \t]*?\n)|(?:\s*$)))/ig
Протестировать ее (и разобрать на запчасти) можно, например, на сервисе https://regexr.com/.
В двух словах, с помощью этого регулярного выражения мы выбираем начало объявления метода с примыкающими к нему (без разделителей - пустых строк) комментариями и директивами компиляции, затем тело метода и конец объявления, опять же с примыкающими комментариями, которые могут быть и в конце метода.
Всё, что не метод, считается текстом модуля, и остается в файле структуры {СтруктураМодуля}.txt.
Таким образом, мы легко можем перемещать метод внутри структуры модуля, и отдельно работать с самим методом, включая примыкающие директивы компиляции и комментарии.
Вступайте в нашу телеграмм-группу Инфостарт