Статья показывает, как можно подготовить конфигурацию 1С к публикации в системах версионирования, отличных от хранилища конфигурации 1C. В операции задействован .Net framework и C#, позволяющий аккуратно распределить проект 1С по папкам.
Пример публикации конфигурации на основе старых обновлений БСП четырехлетней давности (с 1.0.7.5 по 1.1.3.1) можно посмотреть по адресу https://github.com/elisy/ssl. Таким же образом теоретически можно публиковать конфигурации в другие системы версионирования. Но, опыт публикации в SVN большого числа измененных файлов был неудачным: SVN-клиент зависал при просмотре лога через Tortoise SVN.
Этап 1: выгрузка конфигурации 1С 8.3 в файлы XML
Начиная с версии 8.3, 1С может выгружать конфигурацию в виде XML-файлов.
Делается это через Конфигурация – Выгрузить конфигурацию в файлы… Нужно указать каталог и нажать ОК. Конфигурация будет выгружена в набор файлов xml, txt, html.
Через командную строку выгрузить файлы можно с параметром /DumpConfigToFiles каталог выгрузки, где каталог выгрузки — каталог, в который будет выгружена конфигурация.
На этом можно было бы закончить подготовку конфигурации к публикации, но возникает одна проблема. Все файлы конфигурации будут находиться в одном каталоге. Например, для УТ 11.0.7 файлов будет около 10000 (десяти тысяч) размером примерно 430 Мбайт. Удобней было бы иметь эти файлы разложенными по каталогам, где каждая папка отвечает за файлы одного типа.
Разложить файлы по каталогам поможет специально написанная программа. В данном случае на C#.
Этап 2: распределение файлов XML по папкам
Суть помещения файлов по каталогам сводится к следующему: на основании имени файла, разложенного с разделителем «точка», получается его полный путь с тем же расширением. Так первое слово до точки определяет каталог типа объекта, следующее слово определяет каталог названия объекта внутри типа. И так далее – каждое слово за точкой – новый каталог.
Есть исключения: формы, макеты и помощь. К ним дополнительно в каталог переносится xml с определением формы/макета или помощи из родительского каталога. Подсистемы отличаются тем, что внутри подсистем есть определения подчиненных подсистем. Файлы, начинающиеся на «Configuration.» помещаются в корень.
Код по получению относительного пути будет следующим:
private string GetRelativePath(string id)
{
var nameParts = Path.GetFileNameWithoutExtension(id).Split('.');
string newPath = id;
if (String.Compare(nameParts[0], "Configuration", true) == 0)
//Configuration.ManagedApplicationModule.txt
newPath = id;
else if (nameParts.Length == 2)
//AccumulationRegister.ВыручкаИСебестоимостьПродаж.xml
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[1] + Path.GetExtension(id));
else if (nameParts.Length == 4 && String.Compare(nameParts[0], "CommonPicture", true) == 0 && String.Compare(nameParts[2], "Picture", true) == 0 && String.Compare(nameParts[3], "Picture", true) == 0)
{
//CommonPicture.BCGВопросы.Picture.Picture.png
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[3] + Path.GetExtension(id));
}
else if (nameParts.Length == 4 && String.Compare(nameParts[0], "CommonForm", true) == 0 && String.Compare(nameParts[2], "form", true) == 0 && String.Compare(nameParts[3], "module", true) == 0)
{
//CommonForm.АвтоматическийОбменСПодключаемымОборудованиемOffline.Form.Module.txt
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[3] + Path.GetExtension(id));
}
else if (nameParts.Length == 4 && String.Compare(nameParts[2], "form", true) == 0)
{
//AccumulationRegister.ДенежныеСредстваБезналичные.Form.ФормаСписка.xml
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[2], nameParts[3], nameParts[3] + Path.GetExtension(id));
}
else if (nameParts.Length == 6 && String.Compare(nameParts[4], "form", true) == 0 && String.Compare(nameParts[5], "module", true) == 0)
{
//Catalog.АвансовыйОтчетПрисоединенныеФайлы.Form.ФормаСписка.Form.Module.txt
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[2], nameParts[3], nameParts[5] + Path.GetExtension(id));
}
else if (nameParts.Length == 4 && String.Compare(nameParts[2], "template", true) == 0)
{
//Catalog.Банки.Template.КлассификаторБанков.xml
newPath = Path.Combine(nameParts[0], nameParts[1], nameParts[2], nameParts[3], nameParts[3] + Path.GetExtension(id));
}
else if (String.Compare(nameParts[nameParts.Length - 1], "help", true) == 0)
{
//AccumulationRegister.ТоварыПереданныеНаКомиссию.Help.xml
//SettingsStorage.ХранилищеВариантовОтчетов.Form.ФормаЗагрузки.Help.xml
//Subsystem.Маркетинг.Subsystem.МаркетинговыеМероприятия.Help.xml
List<string> pathParts = new List<string>();
pathParts.AddRange(nameParts.Take(nameParts.Length));
pathParts.Add(nameParts[nameParts.Length - 1] + Path.GetExtension(id));
newPath = Path.Combine(pathParts.ToArray());
}
else if (nameParts.Length > 3 && String.Compare(nameParts[nameParts.Length - 2], "Subsystem", true) == 0)
{
//Subsystem.Маркетинг.Subsystem.МаркетинговыеМероприятия.xml
List<string> pathParts = new List<string>();
pathParts.AddRange(nameParts.Take(nameParts.Length));
pathParts.Add(nameParts[nameParts.Length - 1] + Path.GetExtension(id));
newPath = Path.Combine(pathParts.ToArray());
}
else if (nameParts.Length > 2)
{
List<string> pathParts = new List<string>();
pathParts.AddRange(nameParts.Take(nameParts.Length - 1));
pathParts.Add(nameParts[nameParts.Length - 1] + Path.GetExtension(id));
newPath = Path.Combine(pathParts.ToArray());
}
return newPath;
}
Копирование файла сопровождается проверкой на наличие каталога, куда он копируется (если каталога нет — создается) и проверкой наличия конечного файла (если файл есть – перед копированием удаляется).
string fullPath = Path.Combine(destinationDirectory, file.Path);
if (File.Exists(fullPath))
File.Delete(fullPath);
string fullPathDirectory = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(fullPathDirectory))
Directory.CreateDirectory(fullPathDirectory);
File.Copy(Path.Combine(sourceDirectory, file.Id), fullPath);
Этап 3: публикация на GitHub
После регистрации на GitHub нужно создать репозитарий. В данном случае репозитарий называется ssl.
Для синхронизации локального каталога с сайтом GitHub нужно скачать Windows-клиент с веб-сайта github.com. После установки приложения запускается файл GitHub.exe.
Через настройки (плюс сверху слева приложения) локальный каталог необходимо связать с репозитарием. После этого запущенный клиент GitHub.exe начнет отслеживать изменения каталога автоматически. Выдаст добавленные или измененные файлы.
Отсылка изменений на сервер или получение измененных файлов выполняется через команду Sync – кнопка справа сверху приложения.
Выводы
В истории были примеры публикации конфигураций, выгруженных из cf-файлов. Но представление файлов во внутреннем формате 1С не обладает наглядностью. Более привлекательным представляется формат XML, выгрузка в котором появилась только в 1С 8.3.
Опыт публикации конфигурации на GitHub добавил в арсенал средств 1С еще один мощный инструмент. Преимущества GitHub по сравнению с хранилищем конфигураций 1С очевидны: ветвления, встроенный багтрэккер, возможность ревизии и обсуждения кода, исправление кода в браузере, отчеты и графики, открытый API.
Не смотря на кажущуюся привлекательность, только практика работы сможет доказать жизнеспособность методики. Хранилище 1С, не смотря на критику, худо-бедно работает годами. Какие сложности скрывает переход на другие системы версионирования можно только догадываться. Возможно, в версиях может быть неудобно отслеживать изменения XML файлов из-за специфики этого формата (см. макет).
Автор: Elisy