1
0
mirror of https://github.com/bia-technologies/precommit4onec.git synced 2025-02-01 13:07:54 +02:00

Реализован функционал сценария разбора отчетов, обработок и расширений в первом приближении

This commit is contained in:
Maxmov Valery 2017-09-05 14:28:04 +03:00
parent 46915b32bf
commit a0a9266253
7 changed files with 497 additions and 10 deletions

View File

@ -24,8 +24,9 @@
"""
precommit4onec v1.0
Возможные команды:
help - Выводит справку по командам
version - Выводит версию приложения
help - Выводит справку по командам
version - Выводит версию приложения
precommit - Выполняет сценарии precommit
"""
И Код возврата команды "oscript" равен 0
@ -35,7 +36,8 @@
"""
precommit4onec v1.0
Возможные команды:
help - Выводит справку по командам
version - Выводит версию приложения
help - Выводит справку по командам
version - Выводит версию приложения
precommit - Выполняет сценарии precommit
"""
И Код возврата команды "oscript" равен 5

View File

@ -9,6 +9,8 @@
.ЗависитОт("logos", "0.5")
.ЗависитОт("cmdline", "0.4.1")
.ЗависитОт("1bdd", "1.5.2")
.ЗависитОт("gitrunner", "1.4.0")
.ЗависитОт("v8runner", "0.4.1")
.ВключитьФайл("src")
.ВключитьФайл("features")
.ИсполняемыйФайл("src/main.os", ИмяПродукта);

View File

@ -4,10 +4,18 @@
//
///////////////////////////////////////////////////////////////////////////////
#Использовать gitrunner
Перем РепозиторийGit;
Перем Лог;
Перем СценарииОбработки;
///////////////////////////////////////////////////////////////////////////////
Процедура НастроитьКоманду(Знач Команда, Знач Парсер) Экспорт
// Добавление параметров команды
// Парсер.ДобавитьПозиционныйПараметрКоманды(Команда, "ИмяПараметра", "Описание параметра");
Парсер.ДобавитьПозиционныйПараметрКоманды(Команда, "КаталогРепозитория", "Каталог анализируемого репозитория");
// Парсер.ДобавитьИменованныйПараметрКоманды(Команда, "ИмяПараметра", "Описание параметра");
// Парсер.ДобавитьПараметрФлагКоманды(Команда, "ИмяПараметра", "Описание параметра");
// Парсер.ДобавитьПараметрКоллекцияКоманды(Команда, "ИмяПараметра", "Описание параметра");
@ -23,9 +31,162 @@
//
Функция ВыполнитьКоманду(Знач ПараметрыКоманды, Знач Приложение) Экспорт
ВызватьИсключение "Не реализовано";
Лог = Приложение.ПолучитьЛог();
ЗагрузитьСценарииОбработки();
КаталогРепозитория = ПараметрыКоманды["КаталогРепозитория"];
ФайлКаталогРепозитория = Новый Файл(КаталогРепозитория);
Если НЕ ФайлКаталогРепозитория.Существует() ИЛИ ФайлКаталогРепозитория.ЭтоФайл() Тогда
Лог.Ошибка("Каталог репозитория '%1' не существует или это файл", КаталогРепозитория);
Возврат Приложение.РезультатыКоманд().НеверныеПараметры;
КонецЕсли;
КаталогИсходныхФайлов = "src";
ТекущийКаталогИсходныхФайлов = ОбъединитьПути(КаталогРепозитория, КаталогИсходныхФайлов);
КаталогРепозитория = ФайлКаталогРепозитория.ПолноеИмя;
РепозиторийGit = Новый ГитРепозиторий();
РепозиторийGit.УстановитьРабочийКаталог(КаталогРепозитория);
Если НЕ РепозиторийGit.ЭтоРепозиторий() Тогда
Лог.Ошибка("Каталог '%1' не является репозиторием git", КаталогРепозитория);
Возврат Приложение.РезультатыКоманд().НеверныеПараметры;
КонецЕсли;
ЖурналИзменений = ПолучитьЖурналИзменений();
Ит = 0;
ИзмененныеКаталоги = Новый Массив;
ПараметрыОбработки = Новый Структура("Лог, ЖурналИзменений, ИзмененныеКаталоги, КаталогРепозитория", Лог, ЖурналИзменений, ИзмененныеКаталоги, КаталогРепозитория);
Пока Ит < ЖурналИзменений.Количество() Цикл
АнализируемыйФайл = Новый Файл(ОбъединитьПути(КаталогРепозитория, ЖурналИзменений[Ит].ИмяФайла));
Лог.Отладка("Анализируется файл <%1>", АнализируемыйФайл.Имя);
ПараметрыОбработки.Вставить("ЖурналИзменений", ЖурналИзменений);
Для Каждого СценарийОбработки Из СценарииОбработки Цикл
ФайлОбработан = СценарийОбработки.Сценарий.ОбработатьФайл(АнализируемыйФайл, ТекущийКаталогИсходныхФайлов, ПараметрыОбработки);
Если ФайлОбработан Тогда
Продолжить;
КонецЕсли;
КонецЦикла;
Ит = Ит + 1;
КонецЦикла;
// измененные каталоги необходимо добавить в индекс
Лог.Отладка("Добавление измененных каталогов в индекс git");
ДобавитьИзмененныеКаталогиВИндекскGit(ПараметрыОбработки.ИзмененныеКаталоги);
// При успешном выполнении возвращает код успеха
Возврат Приложение.РезультатыКоманд().Успех;
КонецФункции // ВыполнитьКоманду
///////////////////////////////////////////////////////////////////////////////
Функция ПолучитьЖурналИзменений()
ПараметрыКомандыGit = Новый Массив;
ПараметрыКомандыGit.Добавить("diff-index --name-status --cached HEAD");
РепозиторийGit.ВыполнитьКоманду(ПараметрыКомандыGit);
ПараметрыКомандыGit = Новый Массив;
ПараметрыКомандыGit.Добавить("status --porcelain");
РепозиторийGit.ВыполнитьКоманду(ПараметрыКомандыGit);
РезультатВывода = РепозиторийGit.ПолучитьВыводКоманды();
СтрокиВывода = СтрРазделить(РезультатВывода, Символы.ПС);
ЖурналИзменений = Новый Массив;
Для Каждого СтрокаВывода Из СтрокиВывода Цикл
Лог.Информация(" <%1>", СтрокаВывода);
СтрокаВывода = СокрЛП(СтрокаВывода);
ПозицияПробела = СтрНайти(СтрокаВывода, " ");
СимволИзменения = Лев(СтрокаВывода, 1);
Если СимволИзменения = "?" Тогда
Продолжить;
КонецЕсли;
ТипИзменения = ВариантИзмененийФайловGit.ОпределитьВариантИзменения(СимволИзменения);
ИмяФайла = СокрЛП(СтрЗаменить(Сред(СтрокаВывода, ПозицияПробела + 1), """", ""));
Если ТипИзменения = ВариантИзмененийФайловGit.Переименован Тогда
// это два события - удален и добавлен
ПозицияСтрелки = СтрНайти(ИмяФайла, "->");
ИмяФайлаУдален = СокрЛП(Лев(ИмяФайла, ПозицияСтрелки - 1));
ЖурналИзменений.Добавить(Новый Структура("ИмяФайла, ТипИзменения", ИмяФайлаУдален, ВариантИзмененийФайловGit.Удален));
Лог.Отладка(" В журнале git %2 файл <%1>", ИмяФайлаУдален, ВариантИзмененийФайловGit.Удален);
ИмяФайла = СокрЛП(Сред(ИмяФайла, ПозицияСтрелки + 2));
ТипИзменения = ВариантИзмененийФайловGit.Добавлен;
КонецЕсли;
ЖурналИзменений.Добавить(Новый Структура("ИмяФайла, ТипИзменения", ИмяФайла, ТипИзменения));
Лог.Отладка(" В журнале git %2 файл <%1>", ИмяФайла, ТипИзменения);
КонецЦикла;
Возврат ЖурналИзменений;
КонецФункции
Процедура ЗагрузитьСценарииОбработки()
СценарииОбработки = Новый Массив;
ФайлыСценариев = НайтиФайлы(ОбъединитьПути(ТекущийСценарий().Каталог, "..", "СценарииОбработки"), "*.os");
Для Каждого ФайлСценария Из ФайлыСценариев Цикл
Если СтрСравнить(ФайлСценария.ИмяБезРасширения, "ШаблонСценария") = 0 Тогда
Продолжить;
КонецЕсли;
Попытка
СценарийОбработки = ЗагрузитьСценарий(ФайлСценария.ПолноеИмя);
СценарииОбработки.Добавить(Новый Структура("ИмяСценария, Сценарий", СценарийОбработки.ИмяСценария(), СценарийОбработки));
Исключение
Лог.Ошибка("Ошибка загрузки сценария %1: %2", ФайлСценария.ПолноеИмя, ОписаниеОшибки());
Продолжить;
КонецПопытки;
КонецЦикла;
Если СценарииОбработки.Количество() = 0 Тогда
ВызватьИсключение "Нет доступных сценариев обработки файлов";
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьИзмененныеКаталогиВИндекскGit(Знач ИзмененныеКаталоги)
Для Каждого Каталог Из ИзмененныеКаталоги Цикл
ПараметрыКомандыGit = Новый Массив;
ПараметрыКомандыGit.Добавить(СтрШаблон("add --all ""%1"""));
РепозиторийGit.ВыполнитьКоманду(ПараметрыКомандыGit);
КонецЦикла
КонецПроцедуры

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////
//
// Служебный модуль-перечисление
//
///////////////////////////////////////////////////////////////////////////////
Перем Добавлен Экспорт;
Перем Изменен Экспорт;
Перем Удален Экспорт;
Перем Переименован Экспорт;
///////////////////////////////////////////////////////////////////////////////
// ОпределитьВариантИзменения
// Определяет вариант изменения файла из терминов git
//
// Параметры:
// СимволИзменения - Строка - Символ изменения файла из лога git
//
// Возвращаемое значение:
// Строка - Значение варианта изменения
//
Функция ОпределитьВариантИзменения(СимволИзменения) Экспорт
Если СтрСравнить(СимволИзменения, "M") = 0 Тогда
Возврат Изменен;
ИначеЕсли СтрСравнить(СимволИзменения, "A") = 0 Тогда
Возврат Добавлен;
ИначеЕсли СтрСравнить(СимволИзменения, "D") = 0 Тогда
Возврат Удален;
ИначеЕсли СтрСравнить(СимволИзменения, "R") = 0 Тогда
Возврат Переименован;
КонецЕсли;
Возврат СимволИзменения;
КонецФункции
///////////////////////////////////////////////////////////////////////////////
Добавлен = "Добавлен";
Изменен = "Изменен";
Удален = "Удален";
Переименован = "Переименован";

View File

@ -12,6 +12,7 @@
///////////////////////////////////////////////////////////////////////////////
// СВОЙСТВА ПРОДУКТА
///////////////////////////////////////////////////////////////////////////////
// ВерсияПродукта
// Возвращает текущую версию продукта
@ -39,6 +40,7 @@
///////////////////////////////////////////////////////////////////////////////
// ЛОГИРОВАНИЕ
///////////////////////////////////////////////////////////////////////////////
// Форматирование логов
// См. описание метода "УстановитьРаскладку" библиотеки logos
@ -63,6 +65,7 @@
///////////////////////////////////////////////////////////////////////////////
// НАСТРОЙКА КОМАНД
///////////////////////////////////////////////////////////////////////////////
// Возвращает имя команды "version" (ключ командной строки)
//
@ -75,7 +78,6 @@
КонецФункции // ИмяКомандыВерсия
// Возвращает имя команды "help" (ключ командной строки)
//
// Возвращаемое значение:
@ -87,7 +89,6 @@
КонецФункции // ИмяКомандыПомощь()
// ИмяКомандыПоУмолчанию
// Одна из команд может вызываться неявно, без указания команды.
// Иными словами, здесь указывается какой обработчик надо вызывать, если приложение запущено без какой-либо команды
@ -97,8 +98,7 @@
// Строка - имя команды по умолчанию
Функция ИмяКомандыПоУмолчанию() Экспорт
// Возврат "default-action";
Возврат ИмяКомандыПомощь();
Возврат "precommit";
КонецФункции // ИмяКомандыПоУмолчанию

View File

@ -0,0 +1,231 @@
///////////////////////////////////////////////////////////////////////////////
// Служебный модуль с реализацией сценариев обработки файлов
// "РазборОтчетовОбработокРасширений"
///////////////////////////////////////////////////////////////////////////////
#Использовать v8runner
Перем Лог;
///////////////////////////////////////////////////////////////////////////////
// Стандартный программный интерфейс
///////////////////////////////////////////////////////////////////////////////
// ИмяСценария
// Возвращает имя сценария обработки файлов
//
// Возвращаемое значение:
// Строка - Имя текущего сценария обработки файлов
//
Функция ИмяСценария() Экспорт
Возврат "РазборОтчетовОбработокРасширений";
КонецФункции // ИмяСценария()
// ОбработатьФайл
// Выполняет обработку файла
//
// Параметры:
// АнализиремыйАнализируемыйФайлФайл - Файл - Файл из журнала git для анализа
// КаталогИсходныхФайлов - Строка - Каталог расположения исходных файлов относительно каталог репозитория
// ДополнительныеПараметры - Структура - Набор дополнительных параметров, которые можно использовать
// * ЖурналИзменений - Массив - Набор описаний анализируемых файлов
// * Лог - Объект - Текущий лог
// * ИзмененныеКаталоги - Массив - Каталоги, которые необходимо добавить в индекс
// * КаталогРепозитория - Строка - Адрес каталога репозитория
//
// Возвращаемое значение:
// Булево - Признак выполненной обработки файла
//
Функция ОбработатьФайл(АнализируемыйФайл, КаталогИсходныхФайлов, ДополнительныеПараметры) Экспорт
Лог = ДополнительныеПараметры.Лог;
Если ТипФайлаПоддерживается(АнализируемыйФайл) Тогда
Лог.Информация("Обработка файла '%1' по сценарию '%2'", АнализируемыйФайл.ПолноеИмя, ИмяСценария());
КаталогВыгрузки = ПодготовитьКаталогВыгрузки(КаталогИсходныхФайлов, АнализируемыйФайл, ДополнительныеПараметры);
Если Не АнализируемыйФайл.Существует() Тогда
Возврат ИСТИНА;
КонецЕсли;
Если СтрСравнить(АнализируемыйФайл.Расширение, ".cfe") <> 0 Тогда
РаспаковатьОтчетОбработку(АнализируемыйФайл, КаталогВыгрузки);
Иначе
РаспаковатьРасширение(АнализируемыйФайл, КаталогВыгрузки);
КонецЕсли;
// // Добавим файлы для дальнейшей обработки
// // Понятно, что добавить удаленные не получится
// ФайлыВКаталогеТВФ = НайтиФайлы(КаталогВыгрузки, "*", ИСТИНА);
// Для каждого ФайлВКателогеТВФ Из ФайлыВКаталогеТВФ Цикл
// ДополнительныеПараметры.ЖурналИзменений.Добавить(
// Новый Структура("Имя")СтрЗаменить(ФайлВКателогеТВФ.ПолноееИмя, ДополнительныеПараметры.КаталогРепозитория, ""));
// КонецЦикла;
Возврат ИСТИНА;
КонецЕсли;
Возврат ЛОЖЬ;
КонецФункции // ОбработатьФайл()
///////////////////////////////////////////////////////////////////////////////
Функция ПодготовитьКаталогВыгрузки(КаталогИсходныхФайлов, ОбрабатываемыйФайл, ДополнительныеПараметры)
ФайлУдален = НЕ ОбрабатываемыйФайл.Существует();
СоставПутиФайл = СтрРазделить(ОбрабатываемыйФайл.Путь, ПолучитьРазделительПути());
СоставПутиКаталогИсходныхФайлов = СтрРазделить(КаталогИсходныхФайлов, ПолучитьРазделительПути());
ИмяКаталогаВыгрузки = ОбрабатываемыйФайл.ИмяБезРасширения;
Для Ит = 0 По Мин(СоставПутиКаталогИсходныхФайлов.Количество(), СоставПутиФайл.Количество()) - 1 Цикл
Если СоставПутиФайл[Ит] = СоставПутиКаталогИсходныхФайлов[Ит] Тогда
Продолжить;
КонецЕсли;
Пока Ит > 0 Цикл
СоставПутиФайл.Удалить(0);
Ит = Ит - 1;
КонецЦикла;
ИмяКаталогаВыгрузки = СтрСоединить(СоставПутиФайл, ПолучитьРазделительПути());
Прервать;
КонецЦикла;
Если ИмяКаталогаВыгрузки <> ОбрабатываемыйФайл.ИмяБезРасширения Тогда
ИмяКаталогаВыгрузки = ОбъединитьПути(ИмяКаталогаВыгрузки, ОбрабатываемыйФайл.ИмяБезРасширения);
КонецЕсли;
КаталогТекущегоВнешнегоФайла = ОбъединитьПути(КаталогИсходныхФайлов, Сред(НРег(ОбрабатываемыйФайл.Расширение), 2), ИмяКаталогаВыгрузки);
ФайлКаталогТекущегоВнешнегоФайла = Новый Файл(КаталогТекущегоВнешнегоФайла);
Если НЕ ФайлКаталогТекущегоВнешнегоФайла.Существует() Тогда
Если ФайлУдален Тогда
КаталогТекущегоВнешнегоФайла = "";
Иначе
СоздатьКаталог(КаталогТекущегоВнешнегоФайла);
КонецЕсли;
Иначе
ФайлыВКаталогеТВФ = НайтиФайлы(КаталогТекущегоВнешнегоФайла, "*", ИСТИНА);
Для каждого ФайлВКателогеТВФ Из ФайлыВКаталогеТВФ Цикл
Если НЕ ФайлВКателогеТВФ.Существует() Тогда
Продолжить;
КонецЕсли;
УдалитьФайлы(ФайлВКателогеТВФ.ПолноеИмя);
КонецЦикла;
Если ФайлУдален Тогда
УдалитьФайлы(КаталогТекущегоВнешнегоФайла);
КонецЕсли;
КонецЕсли;
Если НЕ ПустаяСтрока(КаталогТекущегоВнешнегоФайла) Тогда
ДополнительныеПараметры.ИзмененныеКаталоги.Добавить(КаталогТекущегоВнешнегоФайла);
КонецЕсли;
Если Не ФайлУдален Тогда
Возврат КаталогТекущегоВнешнегоФайла;
КонецЕсли;
Возврат "";
КонецФункции // ПодготовитьКаталогВыгрузки()
Функция ТипФайлаПоддерживается(Файл)
Если ПустаяСтрока(Файл.Расширение) Тогда
Возврат Ложь;
КонецЕсли;
Поз = Найти(".epf,.erf,.cfe,", НРег(Файл.Расширение + ","));
Возврат Поз > 0;
КонецФункции
Процедура РаспаковатьОтчетОбработку(Знач Файл, Знач КаталогВыгрузки)
Лог.Отладка("Распаковка файла внешнего отчета обработки %1", Файл.ПолноеИмя);
Конфигуратор = ПодготовитьКонфигуратор();
Параметры = Конфигуратор.ПолучитьПараметрыЗапуска();
Параметры.Добавить("/DumpExternalDataProcessorOrReportToFiles");
Параметры.Добавить(СтрШаблон("%1", КаталогВыгрузки));
Параметры.Добавить(СтрШаблон("%1", Файл.ПолноеИмя));
Конфигуратор.ВыполнитьКоманду(Параметры);
Лог.Отладка("Вывод 1С:Предприятия - " + Конфигуратор.ВыводКоманды());
КонецПроцедуры
Процедура РаспаковатьРасширение(Знач Файл, Знач КаталогВыгрузки)
Лог.Отладка("Распаковка файла расширения %1", Файл.ПолноеИмя);
ИмяРасширения = Файл.ИмяБезРасширения;
Конфигуратор = ПодготовитьКонфигуратор();
Параметры = Конфигуратор.ПолучитьПараметрыЗапуска();
Параметры.Добавить(СтрШаблон("/LoadCfg ""%1""", Файл.ПолноеИмя));
Параметры.Добавить(СтрШаблон("-Extension %1", ИмяРасширения));
Конфигуратор.ВыполнитьКоманду(Параметры);
Лог.Отладка("Вывод 1С:Предприятия - " + Конфигуратор.ВыводКоманды());
Параметры = Конфигуратор.ПолучитьПараметрыЗапуска();
Параметры.Добавить(СтрШаблон("/DumpConfigToFiles ""%1""", КаталогВыгрузки));
Параметры.Добавить(СтрШаблон("-Extension %1", ИмяРасширения));
Конфигуратор.ВыполнитьКоманду(Параметры);
Лог.Отладка("Вывод 1С:Предприятия - " + Конфигуратор.ВыводКоманды());
КонецПроцедуры
Функция ПодготовитьКонфигуратор()
Конфигуратор = Новый УправлениеКонфигуратором();
КаталогВременнойИБ = ВременныеФайлы.СоздатьКаталог();
Конфигуратор.КаталогСборки(КаталогВременнойИБ);
ЛогКонфигуратора = Логирование.ПолучитьЛог("oscript.lib.v8runner");
ЛогКонфигуратора.УстановитьУровень(Лог.Уровень());
ЛогКонфигуратора.Закрыть();
Возврат Конфигуратор;
КонецФункции // ПодготовитьКонфигуратор()

View File

@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// Служебный модуль с реализацией сценариев обработки файлов <ИмяСценария>
///////////////////////////////////////////////////////////////////////////////
// ИмяСценария
// Возвращает имя сценария обработки файлов
//
// Возвращаемое значение:
// Строка - Имя текущего сценария обработки файлов
//
Функция ИмяСценария() Экспорт
ВызватьИсключение "Имя сценария не установлено";
Возврат "ИмяСценария";
КонецФункции // ИмяСценария()
// ОбработатьФайл
// Выполняет обработку файла
//
// Параметры:
// АнализируемыйФайл - Файл - Файл из журнала git для анализа
// КаталогИсходныхФайлов - Строка - Каталог расположения исходных файлов относительно каталог репозитория
// ДополнительныеПараметры - Структура - Набор дополнительных параметров, которые можно использовать
// * ЖурналИзменений - Массив - Набор описаний анализируемых файлов
// * Лог - Объект - Текущий лог
// * ИзмененныеКаталоги - Массив - Каталоги, которые необходимо добавить в индекс
// * КаталогРепозитория - Строка - Адрес каталога репозитория
//
// Возвращаемое значение:
// Булево - Признак выполненной обработки файла
//
Функция ОбработатьФайл(АнализируемыйФайл, КаталогИсходныхФайлов, ДополнительныеПараметры) Экспорт
ВызватьИсключение "Обработка файла не реализована"
Лог.Информация("Обработка файла '%1' по сценарию '%2'", АнализируемыйФайл.ПолноеИмя, ИмяСценария());
Возврат ЛОЖЬ;
КонецФункции // ОбработатьФайл()