diff --git a/README.md b/README.md index 09750a7..6c0c238 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,42 @@ - `РазборОтчетОбработокРасширений` - при выполнении данного сценария, файлы внешних отчетов, обработок и расширений средствами платформы будут разложены на исходные файлы и помещены в каталог исходных файлов репозитория в подкаталоги, соответствующие расширениям. Например внешний отчет `ВнешнийОтчет1.erf` будет разложен в каталог `src\erf\ВнешнийОтчет1` - `РазборОбычныхФормНаИсходники` - при выполнении данного сценария, файлы обычных форм (`Form.bin`) раскладываются на исходные файлы с помощью инструмента `v8unpack` +## Изменение настроек + +precommit4onec может читать настройки своей работы из специального конфигурационного файла. + +Управление настройками происходит с использованием команды `configure`: + +- Печать настроек - `precommit4onec configure -global` +- Сброс настроек на заводские - `precommit4onec configure -global -reset` +- Интерактивное изменение настроек - `precommit4onec configure -global -config`. + +Конфигурирование дает возможности: + +- Изменить список сценариев обработки файлов +- Активизировать алгоритм подключния сценариев из каталогов репозитория + ## Расширение функциональности -Для добавления своих сценариев обработки файлов необходимо создать новый сценарий в каталоге `СценарииОбработки` скрипта используя соответствующий шаблон. Новый сценарий автоматически подключится. +Для создания нового сценария обработки файлов необходимо воспользваться шаблоном, находящимся в каталоге `СценарииОбработки` скрипта. + +### Установка сценария для всех репозиториев + +Чтобы сценарий работал для всех репозиториев необходимо + +- сохранить файл сценария в каталог `СценарииОбработки` +- выполнить команду сброса настроек либо интерактивного изменения, где указать сценарий в списке загружаемых + +### Установка сценария для конкретного репозитория + +Чтобы сценарий работал в конкретном репозитории необходимо + +- Решить, в каком каталоге в репозиториях будут хранится сценарии, например `tools\СценарииОбработки` +- Создать каталог в репозитории и скопировать в него файл сценария +- Вызвать команду конфигурирования, в которой включить использование сценариев из репозитория +- Указать имя каталога + +Если при выполнении precommit4onec не найдет файлов сценариев в указанном каталоге, либо не найдет каталог, он об этом сообщит в лог и продолжит работу без ошибок. ## Ссылки diff --git a/features/Конфигурирование.feature b/features/Конфигурирование.feature new file mode 100644 index 0000000..6c0ff5f --- /dev/null +++ b/features/Конфигурирование.feature @@ -0,0 +1,32 @@ +# language: ru + +Функциональность: Настройка конфигурации прекоммита + +Как разработчик +Я хочу иметь возможность изменять настройки precommit4onec +Чтобы автоматически выполнять обработку исходников перед фиксацией изменений в репозитории + +Сценарий: Печать текущих настроек precommit4onec + Когда Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os configure -global" + Тогда Код возврата команды "oscript" равен 0 + И Я сообщаю вывод команды "oscript" + И Вывод команды "oscript" содержит "precommit4onec v1.0.2" + И Вывод команды "oscript" содержит "Установленные настройки:" + И Вывод команды "oscript" содержит "ИспользоватьСценарииРепозитория =" + И Вывод команды "oscript" содержит "КаталогЛокальныхСценариев =" + И Вывод команды "oscript" содержит "ГлобальныеСценарии =" + +Сценарий: Сброс настроек к значениям по умолчанию + Когда Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os configure -global -reset" + Тогда Код возврата команды "oscript" равен 0 + И Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os configure -global" + И Код возврата команды "oscript" равен 0 + И Я сообщаю вывод команды "oscript" + И Вывод команды "oscript" содержит + """ + precommit4onec v1.0.2 + Установленные настройки: + ИспользоватьСценарииРепозитория = Нет + КаталогЛокальныхСценариев = + ГлобальныеСценарии = РазборОбычныхФормНаИсходники.os,РазборОтчетовОбработокРасширений.os + """ diff --git a/features/ПростыеКоманды.feature b/features/ПростыеКоманды.feature index d4345e1..7619b05 100644 --- a/features/ПростыеКоманды.feature +++ b/features/ПростыеКоманды.feature @@ -14,7 +14,7 @@ Сценарий: Получение версии продукта Когда Я выполняю команду "oscript" c параметрами "src/main.os version" Тогда Я сообщаю вывод команды "oscript" - И Вывод команды "oscript" содержит "1.0.1" + И Вывод команды "oscript" содержит "1.0.2" И Вывод команды "oscript" не содержит "precommit4onec v" И Код возврата команды "oscript" равен 0 @@ -22,12 +22,13 @@ Когда Я выполняю команду "oscript" c параметрами "src/main.os help" Тогда Вывод команды "oscript" содержит """ - precommit4onec v1.0.1 + precommit4onec v1.0.2 Возможные команды: help - Выводит справку по командам version - Выводит версию приложения precommit - Выполняет сценарии precommit install - Выполняет подключение (установку) precommit hook'а в репозиторий + configure - Выполняет настройку репозитория """ И Код возврата команды "oscript" равен 0 @@ -35,11 +36,12 @@ Когда Я выполняю команду "oscript" c параметрами "src/main.os" Тогда Вывод команды "oscript" содержит """ - precommit4onec v1.0.1 + precommit4onec v1.0.2 Возможные команды: help - Выводит справку по командам version - Выводит версию приложения precommit - Выполняет сценарии precommit install - Выполняет подключение (установку) precommit hook'а в репозиторий + configure - Выполняет настройку репозитория """ И Код возврата команды "oscript" равен 5 diff --git a/features/УстановкаПрекоммита.feature b/features/УстановкаПрекоммита.feature index ad8f082..eee694c 100644 --- a/features/УстановкаПрекоммита.feature +++ b/features/УстановкаПрекоммита.feature @@ -14,25 +14,25 @@ И я создаю новый репозиторий "rep1" в каталоге "КаталогРепозиториев" и запоминаю его как "Репозиторий1" И я создаю новый репозиторий "rep2" в каталоге "КаталогРепозиториев" и запоминаю его как "Репозиторий2" -Сценарий: Установка precommi4onec в репозиторий +Сценарий: Установка precommit4onec в репозиторий Когда Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os install rep1" Тогда Код возврата команды "oscript" равен 0 И Я сообщаю вывод команды "oscript" - И Вывод команды "oscript" содержит "precommit4onec v1.0.1" + И Вывод команды "oscript" содержит "precommit4onec v1.0.2" И Вывод команды "oscript" содержит "Pre-commit hook для rep1 создан" И В каталоге ".git/hooks" репозитория "Репозиторий1" есть файл "pre-commit" -Сценарий: precommi4onec не устанавливается в пустой каталог +Сценарий: precommit4onec не устанавливается в пустой каталог Когда Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os install ./" Тогда Код возврата команды "oscript" равен 0 И Я сообщаю вывод команды "oscript" - И Вывод команды "oscript" содержит "precommit4onec v1.0.1" + И Вывод команды "oscript" содержит "precommit4onec v1.0.2" И Вывод команды "oscript" содержит "не является репозиторием git" -Сценарий: Установка precommi4onec во вложенные каталоги +Сценарий: Установка precommit4onec во вложенные каталоги Когда Я выполняю команду "oscript" c параметрами "<КаталогПроекта>/src/main.os install ./ -r" Тогда Код возврата команды "oscript" равен 0 И Я сообщаю вывод команды "oscript" - И Вывод команды "oscript" содержит "precommit4onec v1.0.1" + И Вывод команды "oscript" содержит "precommit4onec v1.0.2" И В каталоге ".git/hooks" репозитория "Репозиторий1" есть файл "pre-commit" И В каталоге ".git/hooks" репозитория "Репозиторий2" есть файл "pre-commit" diff --git a/packagedef b/packagedef index 6b1a216..0bb2942 100644 --- a/packagedef +++ b/packagedef @@ -15,4 +15,5 @@ .ВключитьФайл("src") .ВключитьФайл("features") .ВключитьФайл("tasks") + .ВключитьФайл("v8config.json") .ИсполняемыйФайл("src/main.os", ИмяПродукта); diff --git a/src/Классы/КомандаКонфигуратион.os b/src/Классы/КомандаКонфигуратион.os new file mode 100644 index 0000000..8b2ad2f --- /dev/null +++ b/src/Классы/КомандаКонфигуратион.os @@ -0,0 +1,266 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Служебный модуль с реализацией работы команды +// +// (с) BIA Technologies, LLC +// +/////////////////////////////////////////////////////////////////////////////// + +#Использовать gitrunner +Перем Лог; + +/////////////////////////////////////////////////////////////////////////////// + +Процедура НастроитьКоманду(Знач Команда, Знач Парсер) Экспорт + + // Добавление параметров команды + Парсер.ДобавитьПараметрФлагКоманды(Команда, "-global", "Работа с глобальными настройками."); + // TODO: пока оция не используется Парсер.ДобавитьИменованныйПараметрКоманды(Команда, "-rep-path", "Каталог репозитория, настройки которого интересуют."); + Парсер.ДобавитьПараметрФлагКоманды(Команда, "-reset", "Сброс настроек на значения по умолчанию. Если редактируются настройки репозитория, то происходит удаление файла настроек."); + Парсер.ДобавитьПараметрФлагКоманды(Команда, "-config", "Интерактивное конфигурирование настроек."); + +КонецПроцедуры // НастроитьКоманду + +// Выполняет логику команды +// +// Параметры: +// ПараметрыКоманды - Соответствие - Соответствие ключей командной строки и их значений +// Приложение - Модуль - Модуль менеджера приложения +// +Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач Приложение) Экспорт + + Лог = Приложение.ПолучитьЛог(); + Если НЕ ПараметрыКоманды["-global"] Тогда + // TODO: Пока не используется И НЕ ЗначениеЗаполнено(ПараметрыКоманды["-rep-path"]) Тогда + + // TODO: пока не используется Лог.Ошибка("Для конфгурирования необходимо передать флаг -global или указать каталог репозитория параметром -rep-path"); + Лог.Ошибка("Для конфгурирования необходимо передать флаг -global"); + Возврат Приложение.РезультатыКоманд().НеверныеПараметры; + + КонецЕсли; + + Если ПараметрыКоманды["-global"] Тогда + + КаталогРепозитория = Приложение.ПутьКРодительскомуКаталогу(); + + Иначе + + КаталогРепозитория = ПараметрыКоманды["-rep-path"]; + + КонецЕсли; + + УправлениеНастройками = Новый НастройкиРепозитория(КаталогРепозитория); + + Если ПараметрыКоманды["-reset"] Тогда + + Если ПараметрыКоманды["-global"] Тогда + + ЗаписатьГлобальныеНастройкиПоУмолчанию(УправлениеНастройками, Приложение.КаталогСценариев()); + + Иначе + + СброситьНастройкиРепозитория(УправлениеНастройками); + + КонецЕсли; + + ИначеЕсли ПараметрыКоманды["-config"] Тогда + + ИнтерактивнаяНастройка(КаталогРепозитория, УправлениеНастройками, ПараметрыКоманды["-global"], Приложение.КаталогСценариев()); + + Иначе + + НапечататьНастройки(УправлениеНастройками); + + КонецЕсли; + + // При успешном выполнении возвращает код успеха + Возврат Приложение.РезультатыКоманд().Успех; + +КонецФункции // ВыполнитьКоманду + +Процедура НапечататьНастройки(УправлениеНастройками) + + Если УправлениеНастройками.ЭтоНовый() Тогда + + Лог.Информация("Файл настроек не обнаружен"); + Возврат; + + КонецЕсли; + + НастройкиПрекоммита = УправлениеНастройками.НастройкиПриложения("Precommt4onecСценарии"); + Если НЕ ЗначениеЗаполнено(НастройкиПрекоммита) Тогда + + Лог.Информация("Настройки в файле отсутствуют"); + Возврат; + + КонецЕсли; + + Сообщить("Установленные настройки: "); + + Для Каждого НастройкаПрекоммита Из НастройкиПрекоммита Цикл + + Если ТипЗнч(НастройкаПрекоммита.Значение) = Тип("Массив") Тогда + + ЗначениеПараметра = СтрСоединить(НастройкаПрекоммита.Значение, ","); + + Иначе + + ЗначениеПараметра = НастройкаПрекоммита.Значение; + + КонецЕсли; + + Сообщить(Символы.Таб + НастройкаПрекоммита.Ключ + " = " + ЗначениеПараметра); + + КонецЦикла; + +КонецПроцедуры + +Процедура ЗаписатьГлобальныеНастройкиПоУмолчанию(УправлениеНастройками, ТекущийКаталогСценариев) + + ИмяПриложения = "Precommt4onecСценарии"; + СброситьНастройкиРепозитория(УправлениеНастройками); + + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\ИспользоватьСценарииРепозитория", Ложь); + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\КаталогЛокальныхСценариев", ""); + + ГлобальныеСценарии = ПолучитьИменаСценариев(ТекущийКаталогСценариев); + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\ГлобальныеСценарии", ГлобальныеСценарии); + +КонецПроцедуры + +Процедура СброситьНастройкиРепозитория(УправлениеНастройками) + + Если УправлениеНастройками.ЭтоНовый() Тогда + + Возврат; + + КонецЕсли; + + ИмяПриложения = "Precommt4onecСценарии"; + УправлениеНастройками.УдалитьНастройкиПриложения(ИмяПриложения); + +КонецПроцедуры + +Функция ПолучитьИменаСценариев(КаталогСценариев) + + НайденныеСценарии = Новый Массив; + ФайлыСценариев = НайтиФайлы(КаталогСценариев, "*.os"); + Для Каждого ФайлСценария Из ФайлыСценариев Цикл + + Если СтрСравнить(ФайлСценария.ИмяБезРасширения, "ШаблонСценария") = 0 Тогда + + Продолжить; + + КонецЕсли; + + НайденныеСценарии.Добавить(ФайлСценария.Имя); + + КонецЦикла; + + Возврат НайденныеСценарии; + +КонецФункции + +Процедура ИнтерактивнаяНастройка(КаталогРепозитория, УправлениеНастройками, ГлобальныеНастройки, КаталогГлобальныхСценариев) + + Сообщить("Настройка конфигурации precommit"); + Если ГлобальныеНастройки Тогда + + ГлобальныеСценарии = ПолучитьНастройкуМассив("Выберите подключаемые глобальные сценарии: ", ПолучитьИменаСценариев(КаталогГлобальныхСценариев)); + ИспользоватьСценарииРепозитория = ПолучитьНастройкуБулево("Нужно использовать сценарии локальных репозиториев?", ЛОЖЬ); + + КаталогЛокальныхСценариев = ""; + Если ИспользоватьСценарииРепозитория Тогда + + КаталогЛокальныхСценариев = ПолучитьНастройкуСтрока("Укажите относительный путь к сценариям в репозитории: "); + + КонецЕсли; + + ИмяПриложения = "Precommt4onecСценарии"; + СброситьНастройкиРепозитория(УправлениеНастройками); + + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\ИспользоватьСценарииРепозитория", ИспользоватьСценарииРепозитория); + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\КаталогЛокальныхСценариев", КаталогЛокальныхСценариев); + + УправлениеНастройками.ЗаписатьНастройку(ИмяПриложения + "\ГлобальныеСценарии", ГлобальныеСценарии); + + Иначе + + // todo + // пока нет, будет в будущем + + КонецЕсли; + +КонецПроцедуры + +Функция ПолучитьНастройкуБулево(ТекстПодсказки, ЗначениеПоУмолчанию) + + ВыбранноеЗначение = Формат(ЗначениеПоУмолчанию, "БЛ=n; БИ=y"); + Пока ИСТИНА Цикл + + Сообщить(ТекстПодсказки + " [" + Формат(ЗначениеПоУмолчанию, "БЛ=n; БИ=y") + "]. Введите y[es]/n[o]"); + ВвестиСтроку(ВыбранноеЗначение); + + Если СтрНайти("yY", ВыбранноеЗначение) Тогда + + ВыбранноеЗначение = ИСТИНА; + Прервать; + + ИначеЕсли СтрНайти("nN", ВыбранноеЗначение) Тогда + + ВыбранноеЗначение = ЛОЖЬ; + Прервать; + + ИначеЕсли ВыбранноеЗначение = Символы.ПС Тогда + + ВыбранноеЗначение = ИСТИНА; + Прервать; + + КонецЕсли; + + КонецЦикла; + + Возврат ВыбранноеЗначение; + +КонецФункции + +Функция ПолучитьНастройкуМассив(ТекстПодсказки, ДоступныйМассив) + + Сообщить(ТекстПодсказки); + ВыбранныеЭлементы = Новый Массив; + Для Ит = 0 По ДоступныйМассив.Количество() - 1 Цикл + + ЗначениеМассива = ДоступныйМассив[Ит]; + ТекстПодсказкиМассив = Символы.Таб + ЗначениеМассива; + Если ПолучитьНастройкуБулево(ТекстПодсказкиМассив, ИСТИНА) Тогда + + ВыбранныеЭлементы.Добавить(ЗначениеМассива); + + КонецЕсли; + + КонецЦикла; + + Возврат ВыбранныеЭлементы; + +КонецФункции + +Функция ПолучитьНастройкуСтрока(ТекстПодсказки) + + ВыбранноеЗначение = ""; + Пока Истина Цикл + + Сообщить(ТекстПодсказки); + ВвестиСтроку(ВыбранноеЗначение); + + ВыбранноеЗначение = СокрЛП(ВыбранноеЗначение); + Если Не ПустаяСтрока(ВыбранноеЗначение) Тогда + + Прервать; + + КонецЕсли; + + КонецЦикла; + + Возврат ВыбранноеЗначение; + +КонецФункции \ No newline at end of file diff --git a/src/Классы/КомандаПрекоммит.os b/src/Классы/КомандаПрекоммит.os index cea7567..84b5dcd 100644 --- a/src/Классы/КомандаПрекоммит.os +++ b/src/Классы/КомандаПрекоммит.os @@ -15,7 +15,7 @@ /////////////////////////////////////////////////////////////////////////////// Процедура НастроитьКоманду(Знач Команда, Знач Парсер) Экспорт - + // Добавление параметров команды Парсер.ДобавитьПозиционныйПараметрКоманды(Команда, "КаталогРепозитория", "Каталог анализируемого репозитория"); Парсер.ДобавитьИменованныйПараметрКоманды(Команда, "-source-dir", "Каталог расположения исходных файлов относительно корня репозитория. По умолчанию "); @@ -31,77 +31,78 @@ Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач Приложение) Экспорт Лог = Приложение.ПолучитьЛог(); - - ЗагрузитьСценарииОбработки(); - + КаталогРепозитория = ПараметрыКоманды["КаталогРепозитория"]; ФайлКаталогРепозитория = Новый Файл(КаталогРепозитория); Если НЕ ФайлКаталогРепозитория.Существует() ИЛИ ФайлКаталогРепозитория.ЭтоФайл() Тогда Лог.Ошибка("Каталог репозитория '%1' не существует или это файл", КаталогРепозитория); Возврат Приложение.РезультатыКоманд().НеверныеПараметры; - + КонецЕсли; - + + УправлениеНастройками = Новый НастройкиРепозитория(Приложение.ПутьКРодительскомуКаталогу()); + ЗагрузитьСценарииОбработки(Приложение.КаталогСценариев(), УправлениеНастройками, КаталогРепозитория); + КаталогИсходныхФайлов = ПараметрыКоманды["-source-dir"]; Если Не ЗначениеЗаполнено(КаталогИсходныхФайлов) Тогда - + КаталогИсходныхФайлов = "src"; - + КонецЕсли; - + ТекущийКаталогИсходныхФайлов = ОбъединитьПути(КаталогРепозитория, КаталогИсходныхФайлов); ФайлТекущийКаталогИсходныхФайлов = Новый Файл(ТекущийКаталогИсходныхФайлов); ТекущийКаталогИсходныхФайлов = ФайлТекущийКаталогИсходныхФайлов.ПолноеИмя; Если НЕ ФайлТекущийКаталогИсходныхФайлов.Существует() Тогда СоздатьКаталог(ТекущийКаталогИсходныхФайлов); - + КонецЕсли; - + КаталогРепозитория = ФайлКаталогРепозитория.ПолноеИмя; РепозиторийGit = Новый ГитРепозиторий(); РепозиторийGit.УстановитьРабочийКаталог(КаталогРепозитория); - - Если НЕ РепозиторийGit.ЭтоРепозиторий() Тогда + Если НЕ РепозиторийGit.ЭтоРепозиторий() Тогда + Лог.Ошибка("Каталог '%1' не является репозиторием git", КаталогРепозитория); Возврат Приложение.РезультатыКоманд().НеверныеПараметры; - + КонецЕсли; - + ЖурналИзменений = ПолучитьЖурналИзменений(); - + Ит = 0; ПараметрыОбработки = Новый Структура("Лог, ФайлыДляПостОбработки, ИзмененныеКаталоги, КаталогРепозитория", Лог, Новый Массив, Новый Массив, КаталогРепозитория); Пока Ит < ЖурналИзменений.Количество() Цикл - + АнализируемыйФайл = Новый Файл(ОбъединитьПути(КаталогРепозитория, ЖурналИзменений[Ит].ИмяФайла)); Лог.Отладка("Анализируется файл <%1>", АнализируемыйФайл.Имя); Для Каждого СценарийОбработки Из СценарииОбработки Цикл - + ФайлОбработан = СценарийОбработки.Сценарий.ОбработатьФайл(АнализируемыйФайл, ТекущийКаталогИсходныхФайлов, ПараметрыОбработки); Если ФайлОбработан Тогда Для каждого ФайлДляДопОбработки Из ПараметрыОбработки.ФайлыДляПостОбработки Цикл - + ЖурналИзменений.Добавить(Новый Структура("ИмяФайла, ТипИзменения", СтрЗаменить(ФайлДляДопОбработки, КаталогРепозитория, ""), ВариантИзмененийФайловGit.Изменен)); КонецЦикла; - + ПараметрыОбработки.ФайлыДляПостОбработки.Очистить(); Продолжить; - + КонецЕсли; - + КонецЦикла; Ит = Ит + 1; - + КонецЦикла; - + // измененные каталоги необходимо добавить в индекс Лог.Отладка("Добавление измененных каталогов в индекс git"); Для Каждого Каталог Из ПараметрыОбработки.ИзмененныеКаталоги Цикл @@ -118,7 +119,7 @@ /////////////////////////////////////////////////////////////////////////////// Функция ПолучитьЖурналИзменений() - + ПараметрыКомандыGit = Новый Массив; ПараметрыКомандыGit.Добавить("diff-index --name-status --cached HEAD"); РепозиторийGit.ВыполнитьКоманду(ПараметрыКомандыGit); @@ -127,35 +128,35 @@ РепозиторийGit.ВыполнитьКоманду(ПараметрыКомандыGit); РезультатВывода = РепозиторийGit.ПолучитьВыводКоманды(); СтрокиВывода = СтрРазделить(РезультатВывода, Символы.ПС); - + ЖурналИзменений = Новый Массив; Для Каждого СтрокаВывода Из СтрокиВывода Цикл - + Лог.Отладка(" <%1>", СтрокаВывода); СтрокаВывода = СокрЛП(СтрокаВывода); ПозицияПробела = СтрНайти(СтрокаВывода, " "); СимволИзменения = Лев(СтрокаВывода, 1); Если СимволИзменения = "?" Тогда - + Продолжить; - + КонецЕсли; - + ТипИзменения = ВариантИзмененийФайловGit.ОпределитьВариантИзменения(СимволИзменения); - + ИмяФайла = СокрЛП(СтрЗаменить(Сред(СтрокаВывода, ПозицияПробела + 1), """", "")); - + Если ТипИзменения = ВариантИзмененийФайловGit.Переименован Тогда - + // это два события - удален и добавлен ПозицияСтрелки = СтрНайти(ИмяФайла, "->"); ИмяФайлаУдален = СокрЛП(Лев(ИмяФайла, ПозицияСтрелки - 1)); ЖурналИзменений.Добавить(Новый Структура("ИмяФайла, ТипИзменения", ИмяФайлаУдален, ВариантИзмененийФайловGit.Удален)); Лог.Отладка(" В журнале git %2 файл <%1>", ИмяФайлаУдален, ВариантИзмененийФайловGit.Удален); - + ИмяФайла = СокрЛП(Сред(ИмяФайла, ПозицияСтрелки + 2)); ТипИзменения = ВариантИзмененийФайловGit.Добавлен; - + КонецЕсли; ЖурналИзменений.Добавить(Новый Структура("ИмяФайла, ТипИзменения", ИмяФайла, ТипИзменения)); @@ -167,36 +168,82 @@ КонецФункции -Процедура ЗагрузитьСценарииОбработки() +Процедура ЗагрузитьСценарииОбработки(ТекущийКаталогСценариев, УправлениеНастройками, КаталогРепозитория) СценарииОбработки = Новый Массив; - ФайлыСценариев = НайтиФайлы(ОбъединитьПути(ТекущийСценарий().Каталог, "..", "СценарииОбработки"), "*.os"); - Для Каждого ФайлСценария Из ФайлыСценариев Цикл + ФайлыГлобальныхСценариев = НайтиФайлы(ТекущийКаталогСценариев, "*.os"); + ФайлыЛокальныхСценариев = Новый Массив; + ИменаЗагружаемыхСценариев = Новый Массив; + + Если НЕ УправлениеНастройками.ЭтоНовый() Тогда - Если СтрСравнить(ФайлСценария.ИмяБезРасширения, "ШаблонСценария") = 0 Тогда - - Продолжить; + Лог.Информация("Читаем настройки"); + ИменаЗагружаемыхСценариев = УправлениеНастройками.Настройка("Precommt4onecСценарии\ГлобальныеСценарии"); + Если УправлениеНастройками.Настройка("Precommt4onecСценарии\ИспользоватьСценарииРепозитория") Тогда + + ЛокальныйКаталог = УправлениеНастройками.Настройка("Precommt4onecСценарии\КаталогЛокальныхСценариев"); + ПутьКЛокальнымСценариям = ОбъединитьПути(КаталогРепозитория, ЛокальныйКаталог); + ФайлПутьКЛокальнымСценариям = Новый Файл(ПутьКЛокальнымСценариям); + Если Не ФайлПутьКЛокальнымСценариям.Существует() ИЛИ ФайлПутьКЛокальнымСценариям.ЭтоФайл() Тогда + + Лог.Ошибка("Сценарии из репозитория не загружены т.к. отсутствует каталог %1", ЛокальныйКаталог); + + Иначе + + ФайлыЛокальныхСценариев = НайтиФайлы(ФайлПутьКЛокальнымСценариям.ПолноеИмя, "*.os"); + + КонецЕсли; + КонецЕсли; - - Попытка - - СценарийОбработки = ЗагрузитьСценарий(ФайлСценария.ПолноеИмя); - СценарииОбработки.Добавить(Новый Структура("ИмяСценария, Сценарий", СценарийОбработки.ИмяСценария(), СценарийОбработки)); + + КонецЕсли; - Исключение - - Лог.Ошибка("Ошибка загрузки сценария %1: %2", ФайлСценария.ПолноеИмя, ОписаниеОшибки()); - Продолжить; - - КонецПопытки; - - КонецЦикла; + ЗагрузитьСценарииИзКаталога(СценарииОбработки, ФайлыГлобальныхСценариев, ИменаЗагружаемыхСценариев); + ЗагрузитьСценарииИзКаталога(СценарииОбработки, ФайлыЛокальныхСценариев); Если СценарииОбработки.Количество() = 0 Тогда - + ВызватьИсключение "Нет доступных сценариев обработки файлов"; - + КонецЕсли; КонецПроцедуры + +Процедура ЗагрузитьСценарииИзКаталога(СценарииОбработки, ФайлыСценариев, Знач ИменаЗагружаемыхСценариев = Неопределено) + + Если ИменаЗагружаемыхСценариев = Неопределено Тогда + + ИменаЗагружаемыхСценариев = Новый Массив; + + КонецЕсли; + + Для Каждого ФайлСценария Из ФайлыСценариев Цикл + + Если СтрСравнить(ФайлСценария.ИмяБезРасширения, "ШаблонСценария") = 0 Тогда + + Продолжить; + + КонецЕсли; + + Если ИменаЗагружаемыхСценариев.Количество() И ИменаЗагружаемыхСценариев.Найти(ФайлСценария.Имя) = Неопределено Тогда + + Продолжить; + + КонецЕсли; + + Попытка + + СценарийОбработки = ЗагрузитьСценарий(ФайлСценария.ПолноеИмя); + СценарииОбработки.Добавить(Новый Структура("ИмяСценария, Сценарий", СценарийОбработки.ИмяСценария(), СценарийОбработки)); + + Исключение + + Лог.Ошибка("Ошибка загрузки сценария %1: %2", ФайлСценария.ПолноеИмя, ОписаниеОшибки()); + Продолжить; + + КонецПопытки; + + КонецЦикла; + +КонецПроцедуры diff --git a/src/Классы/НастройкиРепозитория.os b/src/Классы/НастройкиРепозитория.os new file mode 100644 index 0000000..e17e7e6 --- /dev/null +++ b/src/Классы/НастройкиРепозитория.os @@ -0,0 +1,269 @@ +/////////////////////////////////////////////////////////////////// +// +// Работает с настройками в конфигурационном файле репозитория 1С +// в Git +// +// (с) BIA Technologies, LLC +// +/////////////////////////////////////////////////////////////////// + +#Использовать json + +/////////////////////////////////////////////////////////////////// + +Перем ИнициализацияВыпонена; // содержит признак инициализации репозитория +Перем НовыйКонфиг; // содержит признак нового конфига +Перем Конфигурация; // описание конфигурации +Перем АдресКонфигурационногоФайла; // адрес нахождения конфигурационного файла +Перем ОбновлятьКонфигурацию; // флаг необходимости обновления конфигурации / затирания + +/////////////////////////////////////////////////////////////////// +// Программный интерфейс +/////////////////////////////////////////////////////////////////// + +// ЭтоНовый +// Возвращает признак нового конфига, т.е. отсутствие файла +// +// Возвращаемое значение: +// Булево - Признак отсутствия файла +// +Функция ЭтоНовый() Экспорт + + Возврат НовыйКонфиг; + +КонецФункции // ЭтоНовый() + +// ГлобальныеНастройки +// Возврает набор глобальных настроек +// +// Возвращаемое значение: +// Соответствие - Набор глобальных настроек при их наличии, если настроек нет то будет возвращено пустое соответствие +// +Функция ГлобальныеНастройки() Экспорт + + ПроверкаИницализации(); + + Возврат НастройкиПриложения("GLOBAL"); + +КонецФункции // ГлобальныеНастройки() Экспорт + +// НастройкиПриложения +// Возврает набор настроек для приложения +// +// Параметры: +// ИмяПриложения - Строка - Имя приложения +// +// Возвращаемое значение: +// Соответствие - Набор гнастроек при их наличии, если настроек нет то будет возвращено пустое соответствие +// +Функция НастройкиПриложения(ИмяПриложения) Экспорт + + ПроверкаИницализации(); + Если ПустаяСтрока(ИмяПриложения) Тогда + + ВызватьИсключение "Не указано имя приложения"; + + КонецЕсли; + + ИскомыеНастройки = Конфигурация.Получить(ИмяПриложения); + Если ИскомыеНастройки = Неопределено Тогда + + ИскомыеНастройки = Новый Соответствие; + + КонецЕсли; + + Возврат ИскомыеНастройки; + +КонецФункции // НастройкиПриложения() + +// Настройка +// Возвращает значение искомой настройки +// +// Параметры: +// ИмяНастройки - Строка - Имя искомой настройки. Возможные форматы +// - "МояНастройка" - для чтения глобальной настройки +// - "МоеПриложение\МояНастройка" - для чтения настройки приложения +// +// Возвращаемое значение: +// Произвольный - Значение настройки +// +Функция Настройка(ИмяНастройки)Экспорт + + ПроверкаИницализации(); + + РазложенноеИмяНастройки = РазобратьИмяНастройки(ИмяНастройки); + ИскомоеПриложение = НастройкиПриложения(РазложенноеИмяНастройки.ИмяПриложения); + Возврат ИскомоеПриложение.Получить(РазложенноеИмяНастройки.ИмяНастройки); + +КонецФункции // Настройка(ИмяНастройки) + +// ЗаписатьНастройку +// Записывает настройку в конфигурационный файл +// +// Параметры: +// ИмяНастройки - Строка - Имя искомой настройки. Возможные форматы +// - "МояНастройка" - для чтения глобальной настройки +// - "МоеПриложение\МояНастройка" - для чтения настройки приложения +// +// Значение - Произвольный - Значение настройки, сериализуемое в JSON +// +Процедура ЗаписатьНастройку(ИмяНастройки, Значение) Экспорт + + ПроверкаИницализации(); + + РазложенноеИмяНастройки = РазобратьИмяНастройки(ИмяНастройки); + ИскомоеПриложение = НастройкиПриложения(РазложенноеИмяНастройки.ИмяПриложения); + Если ОбновлятьКонфигурацию ИЛИ ИскомоеПриложение.Получить(РазложенноеИмяНастройки.ИмяНастройки) = Неопределено Тогда + + ИскомоеПриложение.Вставить(РазложенноеИмяНастройки.ИмяНастройки, Значение); + + КонецЕсли; + Конфигурация.Вставить(РазложенноеИмяНастройки.ИмяПриложения, ИскомоеПриложение); + + ОбновитьКонфигурационныйФайл(); + +КонецПроцедуры // ЗаписатьНастройку(ИмяНастройки, Значение) + +// ЗаписатьНастройкиПриложения +// Записывает набор настроек приложения +// +// Параметры: +// ИмяПриложения - Строка - Имя приложения +// Значение - Соответствие - Набор настроек приложения +// +Процедура ЗаписатьНастройкиПриложения(ИмяПриложения, Значение) Экспорт + + ПроверкаИницализации(); + + Если ПустаяСтрока(ИмяПриложения) Тогда + + ВызватьИсключение "Не указано имя приложения"; + + КонецЕсли; + + Если ТипЗнч(Значение) <> Тип("Соответствие") Тогда + + ВызватьИсключение "Тип значения должен быть Соответствие"; + + КонецЕсли; + + Конфигурация.Вставить(ИмяПриложения, Значение); + + ОбновитьКонфигурационныйФайл(); + +КонецПроцедуры // ЗаписатьНастройкиПриложения() + +// УдалитьНастройкиПриложения +// Удаляет набор набор настроек приложения +// +// Параметры: +// ИмяПриложения - Строка - Имя приложения +// +Процедура УдалитьНастройкиПриложения(ИмяПриложения) Экспорт + + ПроверкаИницализации(); + + Если ПустаяСтрока(ИмяПриложения) Тогда + + ВызватьИсключение "Не указано имя приложения"; + + КонецЕсли; + + Конфигурация.Удалить(ИмяПриложения); + + ОбновитьКонфигурационныйФайл(); + +КонецПроцедуры // УдалитьНастройкиПриложения() + +/////////////////////////////////////////////////////////////////// +// Служебный функционал +/////////////////////////////////////////////////////////////////// + +Функция ПроверкаИницализации() + + Если Не ИнициализацияВыпонена Тогда + + ВызватьИсключение "Необходимо выполнить инициализацию" + + КонецЕсли; + +КонецФункции // ПроверкаИницализации() + +Функция РазобратьИмяНастройки(Знач ИмяНастройки) + + Если ПустаяСтрока(ИмяНастройки) Тогда + + ВызватьИсключение "Не передано имя настройки" + + КонецЕсли; + + ИмяПриложения = "GLOBAL"; + ПозицияРазделителя = СтрНайти(ИмяНастройки, "\"); + Если ПозицияРазделителя > 0 Тогда + + ИмяПриложения = Лев(ИмяНастройки, ПозицияРазделителя - 1); + ИмяНастройки = Сред(ИмяНастройки, ПозицияРазделителя + 1); + + КонецЕсли; + + Возврат Новый Структура("ИмяПриложения, ИмяНастройки", ИмяПриложения, ИмяНастройки); + +КонецФункции // РазобратьИмяНастройки() + +Функция ОбновитьКонфигурационныйФайл() + + ПарсерJSON = Новый ПарсерJSON; + ТекстКонфигурации = ПарсерJSON.ЗаписатьJSON(Конфигурация); + Запись = Новый ЗаписьТекста(АдресКонфигурационногоФайла); + Запись.Записать(ТекстКонфигурации); + Запись.Закрыть(); + + НовыйКонфиг = ЛОЖЬ; + +КонецФункции // ОбновитьКонфигурационныйФайл() + +/////////////////////////////////////////////////////////////////// + +// ПриСозданииОбъекта +// Инициализирует объект при создании +// +// Параметры: +// КаталогРепозитория - Строка - Адрес каталога репозитория +// ОбновлятьКонф - Булево - флаг необходимости обновления конфигурации / затирания +// +Процедура ПриСозданииОбъекта(КаталогРепозитория, ОбновлятьКонф = ЛОЖЬ) + + ИнициализацияВыпонена = ЛОЖЬ; + НовыйКонфиг = ЛОЖЬ; + Конфигурация = Неопределено; + АдресКонфигурационногоФайла = ""; + ОбновлятьКонфигурацию = ?(ОбновлятьКонф = Неопределено, ЛОЖЬ, ОбновлятьКонф); + + Файл = Новый Файл(КаталогРепозитория); + Если НЕ (Файл.Существует() И Файл.ЭтоКаталог()) Тогда + + ВызватьИсключение "Каталог репозитория '" + КаталогРепозитория + "' не обнаружен либо это файл" + + КонецЕсли; + + АдресКонфигурационногоФайла = ОбъединитьПути(КаталогРепозитория, "v8config.json"); + Файл = Новый Файл(АдресКонфигурационногоФайла); + Если Файл.Существует() Тогда + + Чтение = Новый ЧтениеТекста(АдресКонфигурационногоФайла); + ТекстКонфигурации = Чтение.Прочитать(); + Чтение.Закрыть(); + + ПарсерJSON = Новый ПарсерJSON; + Конфигурация = ПарсерJSON.ПрочитатьJSON(ТекстКонфигурации); + + Иначе + + НовыйКонфиг = ИСТИНА; + Конфигурация = Новый Соответствие; + + КонецЕсли; + + ИнициализацияВыпонена = ИСТИНА; + +КонецПроцедуры // ПриСозданииОбъекта() \ No newline at end of file diff --git a/src/Модули/МенеджерПриложения.os b/src/Модули/МенеджерПриложения.os index 0264eca..9908c9e 100644 --- a/src/Модули/МенеджерПриложения.os +++ b/src/Модули/МенеджерПриложения.os @@ -209,13 +209,27 @@ КонецФункции // ИмяПродукта -//Возвращает путь к исполняемому файлу +// Возвращает путь к исполняемому файлу Функция ПутьКИсполняемомуФайлу() Экспорт Возврат ОбъектНастроек.ПутьКИсполняемомуФайлу(); КонецФункции // ПутьКИсполняемомуФайлу +// Возвращает путь к каталогу основного скрипта +Функция ПутьКРодительскомуКаталогу() Экспорт + + Возврат ОбъектНастроек.ПутьКРодительскомуКаталогу(); + +КонецФункции // ПутьКРодительскомуКаталогу + +// Возвращает путь к каталогу сценариев +Функция КаталогСценариев() Экспорт + + Возврат ОбъектНастроек.КаталогСценариев(); + +КонецФункции // КаталогСценариев + // Выводит справку по всем командам приложения Процедура ВывестиСправкуПоКомандам() Экспорт diff --git a/src/Модули/ПараметрыПриложения.os b/src/Модули/ПараметрыПриложения.os index 3c4bedf..3d205d9 100644 --- a/src/Модули/ПараметрыПриложения.os +++ b/src/Модули/ПараметрыПриложения.os @@ -22,7 +22,7 @@ // Функция ВерсияПродукта() Экспорт - Возврат "1.0.1"; + Возврат "1.0.2"; КонецФункции // ВерсияПродукта @@ -46,10 +46,35 @@ // Функция ПутьКИсполняемомуФайлу() Экспорт - Возврат ОбъединитьПути(ТекущийСценарий().Каталог, "..", "main.os"); + Возврат ОбъединитьПути(ПутьКРодительскомуКаталогу(), "src", "main.os"); КонецФункции // ПутьКИсполняемомуФайлу +// ПутьКРодительскомуКаталогу +// Возвращает путь к каталогу основного скрипта +// +// Возвращаемое значение: +// Строка - Путь к каталогу основного скрипта +// +Функция ПутьКРодительскомуКаталогу() Экспорт + + Файл = Новый Файл(ОбъединитьПути(ТекущийСценарий().Каталог, "..", "..")); + Возврат Файл.ПолноеИмя; + +КонецФункции // ПутьКРодительскомуКаталогу + +// КаталогСценариев +// Возвращает путь к каталогу сценариев +// +// Возвращаемое значение: +// Строка - Путь к каталогу сценариев +// +Функция КаталогСценариев() Экспорт + + Возврат ОбъединитьПути(ПутьКРодительскомуКаталогу(), "src", "СценарииОбработки"); + +КонецФункции // КаталогСценариев + /////////////////////////////////////////////////////////////////////////////// // ЛОГИРОВАНИЕ /////////////////////////////////////////////////////////////////////////////// @@ -125,5 +150,6 @@ Приложение.ДобавитьКоманду(ИмяКомандыВерсия(), "КомандаVersion", "Выводит версию приложения"); Приложение.ДобавитьКоманду("precommit", "КомандаПрекоммит", "Выполняет сценарии precommit"); Приложение.ДобавитьКоманду("install", "КомандаИнсталл", "Выполняет подключение (установку) precommit hook'а в репозиторий"); + Приложение.ДобавитьКоманду("configure", "КомандаКонфигуратион", "Выполняет настройку репозитория"); КонецПроцедуры // ПриРегистрацииКомандПриложения diff --git a/v8config.json b/v8config.json new file mode 100644 index 0000000..8d07a33 --- /dev/null +++ b/v8config.json @@ -0,0 +1,10 @@ +{ + "Precommt4onecСценарии": { + "ИспользоватьСценарииРепозитория": false, + "КаталогЛокальныхСценариев": "", + "ГлобальныеСценарии": [ + "РазборОбычныхФормНаИсходники.os", + "РазборОтчетовОбработокРасширений.os" + ] + } +} \ No newline at end of file