|
|
|
@ -2,13 +2,14 @@
|
|
|
|
|
#
|
|
|
|
|
from pprint import pprint
|
|
|
|
|
from ..utils.package import PackageAtomParser, Package, PackageNotFound,\
|
|
|
|
|
PackageAtomName
|
|
|
|
|
PackageAtomName, Version
|
|
|
|
|
from ..utils.files import join_paths, write_file, read_file_lines, FilesError,\
|
|
|
|
|
check_directory_link, read_link, Process,\
|
|
|
|
|
get_target_from_link
|
|
|
|
|
from .template_engine import TemplateEngine, Variables, ConditionFailed,\
|
|
|
|
|
ParametersProcessor, DIR, FILE,\
|
|
|
|
|
ParametersContainer
|
|
|
|
|
from .format.base_format import BaseFormat
|
|
|
|
|
from ..utils.io_module import IOModule
|
|
|
|
|
from collections import OrderedDict, abc
|
|
|
|
|
from ..utils.mount import Mounts
|
|
|
|
@ -23,6 +24,9 @@ import re
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CALCULATE_VERSION = Version('4.0')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TemplateExecutorError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
@ -145,11 +149,13 @@ class TemplateWrapper:
|
|
|
|
|
def __init__(self, target_file_path,
|
|
|
|
|
parameters,
|
|
|
|
|
template_type,
|
|
|
|
|
template_path,
|
|
|
|
|
template_text='',
|
|
|
|
|
target_package=None,
|
|
|
|
|
chroot_path='/',
|
|
|
|
|
config_archive_path='/var/lib/calculate/config-archive'):
|
|
|
|
|
self.target_path = target_file_path
|
|
|
|
|
self.template_path = template_path
|
|
|
|
|
self.chroot_path = chroot_path
|
|
|
|
|
self.config_archive_path = config_archive_path
|
|
|
|
|
|
|
|
|
@ -244,13 +250,13 @@ class TemplateWrapper:
|
|
|
|
|
chroot_path=self.chroot_path)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.check_type_conflicts()
|
|
|
|
|
self._check_type_conflicts()
|
|
|
|
|
|
|
|
|
|
self.check_package_collision()
|
|
|
|
|
self._check_package_collision()
|
|
|
|
|
|
|
|
|
|
self.check_user_changes()
|
|
|
|
|
self._check_user_changes()
|
|
|
|
|
|
|
|
|
|
def check_type_conflicts(self):
|
|
|
|
|
def _check_type_conflicts(self):
|
|
|
|
|
'''Метод для проверки конфликтов типов.'''
|
|
|
|
|
if self.parameters.append == 'link':
|
|
|
|
|
if self.parameters.force:
|
|
|
|
@ -322,7 +328,7 @@ class TemplateWrapper:
|
|
|
|
|
raise TemplateTypeConflict("the target file is a directory"
|
|
|
|
|
" while the template is a file")
|
|
|
|
|
|
|
|
|
|
def check_package_collision(self):
|
|
|
|
|
def _check_package_collision(self):
|
|
|
|
|
'''Метод для проверки на предмет коллизии, то есть конфликта пакета
|
|
|
|
|
шаблона и целевого файла.'''
|
|
|
|
|
if self.parameters.package:
|
|
|
|
@ -370,7 +376,7 @@ class TemplateWrapper:
|
|
|
|
|
self.target_package = Package(self.target_package_name,
|
|
|
|
|
chroot_path=self.chroot_path)
|
|
|
|
|
|
|
|
|
|
def check_user_changes(self):
|
|
|
|
|
def _check_user_changes(self):
|
|
|
|
|
'''Метод для проверки наличия пользовательских изменений в
|
|
|
|
|
конфигурационных файлах.'''
|
|
|
|
|
# Эта проверка только для файлов.
|
|
|
|
@ -595,6 +601,10 @@ class TemplateExecutor:
|
|
|
|
|
self.execute_archive_path = execute_archive_path
|
|
|
|
|
self.execute_files = OrderedDict()
|
|
|
|
|
|
|
|
|
|
# Список целевых путей измененных файлов. Нужен для корректиного
|
|
|
|
|
# формирования calculate-заголовка.
|
|
|
|
|
self.processed_targets = []
|
|
|
|
|
|
|
|
|
|
self.directory_default_parameters =\
|
|
|
|
|
ParametersProcessor.directory_default_parameters
|
|
|
|
|
self.file_default_parameters =\
|
|
|
|
@ -623,6 +633,7 @@ class TemplateExecutor:
|
|
|
|
|
cl_config_path=cl_config_path,
|
|
|
|
|
cl_chroot_path=chroot_path)
|
|
|
|
|
self.cl_config_archive_path = cl_config_archive
|
|
|
|
|
BaseFormat.CALCULATE_VERSION = CALCULATE_VERSION
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def available_appends(self):
|
|
|
|
@ -633,7 +644,7 @@ class TemplateExecutor:
|
|
|
|
|
return appends_set
|
|
|
|
|
|
|
|
|
|
def execute_template(self, target_path, parameters, template_type,
|
|
|
|
|
template_text='', save_changes=True,
|
|
|
|
|
template_path, template_text='', save_changes=True,
|
|
|
|
|
target_package=None):
|
|
|
|
|
'''Метод для запуска выполнения шаблонов.'''
|
|
|
|
|
# Словарь с данными о результате работы исполнительного метода.
|
|
|
|
@ -641,10 +652,14 @@ class TemplateExecutor:
|
|
|
|
|
'stdout': None,
|
|
|
|
|
'stderr': None}
|
|
|
|
|
|
|
|
|
|
if parameters.append == 'skip':
|
|
|
|
|
return self.executor_output
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
template_object = TemplateWrapper(
|
|
|
|
|
target_path, parameters,
|
|
|
|
|
template_type,
|
|
|
|
|
template_path,
|
|
|
|
|
template_text=template_text,
|
|
|
|
|
target_package=target_package,
|
|
|
|
|
chroot_path=self.chroot_path,
|
|
|
|
@ -659,7 +674,6 @@ class TemplateExecutor:
|
|
|
|
|
# Удаляем оригинал, если это необходимо из-за наличия force или по
|
|
|
|
|
# другим причинам.
|
|
|
|
|
if template_object.remove_original:
|
|
|
|
|
print('REMOVE ORIGINAL')
|
|
|
|
|
if template_object.target_type == DIR:
|
|
|
|
|
self._remove_directory(template_object.target_path)
|
|
|
|
|
else:
|
|
|
|
@ -718,6 +732,30 @@ class TemplateExecutor:
|
|
|
|
|
# Пока сохраняем только получившееся содержимое config-файла.
|
|
|
|
|
self.calculate_config_file.save_changes()
|
|
|
|
|
|
|
|
|
|
def _get_header_and_file_text(self, input_text, target_path,
|
|
|
|
|
target_format, template_path):
|
|
|
|
|
header_pattern = (r'^{0}' + r'-' * 79 + r'\n' +
|
|
|
|
|
r'{0} Modified by Calculate Utilities [\d\w\.]*\n' +
|
|
|
|
|
r'{0} Processed template files:\n' +
|
|
|
|
|
r'(?P<template_paths>({0}\s*[/\w\d\-_\.]*\n)+)' +
|
|
|
|
|
r'{0}' + r'-' * 79 + r'\n?').format(
|
|
|
|
|
target_format.comment_symbol)
|
|
|
|
|
template_paths = [template_path]
|
|
|
|
|
if target_path in self.processed_targets:
|
|
|
|
|
header_regex = re.compile(header_pattern)
|
|
|
|
|
parsing_result = header_regex.search(input_text)
|
|
|
|
|
template_paths.extend(parsing_result.groupdict()[
|
|
|
|
|
'template_paths'].strip().split('\n'))
|
|
|
|
|
else:
|
|
|
|
|
self.processed_targets.append(target_path)
|
|
|
|
|
header = ('{0}' + '-' * 79 +
|
|
|
|
|
'{0} Modified by Calculate Utilities {1}\n' +
|
|
|
|
|
'{0} Processsed temlate files:\n' +
|
|
|
|
|
'{0}' + '\n{0} '.join + '\n' +
|
|
|
|
|
'{0}' + '-' * 79 + '\n').format(target_format.comment_symbol,
|
|
|
|
|
CALCULATE_VERSION)
|
|
|
|
|
return header, re.sub(header_pattern, '', input_text)
|
|
|
|
|
|
|
|
|
|
def _append_join_directory(self, template_object: TemplateWrapper):
|
|
|
|
|
'''Метод описывающий действия для append = "join", если шаблон --
|
|
|
|
|
директория. Создает директорию, если ее нет.'''
|
|
|
|
@ -836,12 +874,19 @@ class TemplateExecutor:
|
|
|
|
|
input_text = ''
|
|
|
|
|
|
|
|
|
|
parsed_template = template_format(template_object.template_text,
|
|
|
|
|
template_object.template_path,
|
|
|
|
|
ignore_comments=True)
|
|
|
|
|
|
|
|
|
|
if not template_object.format_class.EXECUTABLE:
|
|
|
|
|
# Если шаблон не исполнительный разбираем входной текст.
|
|
|
|
|
parsed_input = template_format(input_text,
|
|
|
|
|
join_before=join_before)
|
|
|
|
|
parsed_input = template_format(
|
|
|
|
|
input_text,
|
|
|
|
|
template_object.template_path,
|
|
|
|
|
add_header=True,
|
|
|
|
|
join_before=join_before,
|
|
|
|
|
already_changed=(template_object.target_path
|
|
|
|
|
in self.processed_targets),
|
|
|
|
|
parameters=template_object.parameters)
|
|
|
|
|
parsed_input.join_template(parsed_template)
|
|
|
|
|
# Результат наложения шаблона.
|
|
|
|
|
output_text = parsed_input.document_text
|
|
|
|
@ -903,9 +948,15 @@ class TemplateExecutor:
|
|
|
|
|
else:
|
|
|
|
|
input_text = ''
|
|
|
|
|
|
|
|
|
|
parsed_input = template_format(input_text,
|
|
|
|
|
join_before=join_before)
|
|
|
|
|
parsed_input = template_format(
|
|
|
|
|
input_text,
|
|
|
|
|
template_object.template_path,
|
|
|
|
|
add_header=True,
|
|
|
|
|
join_before=join_before,
|
|
|
|
|
already_changed=False,
|
|
|
|
|
parameters=template_object.parameters)
|
|
|
|
|
parsed_template = template_format(template_object.template_text,
|
|
|
|
|
template_object.template_path,
|
|
|
|
|
ignore_comments=True)
|
|
|
|
|
|
|
|
|
|
parsed_input.join_template(parsed_template)
|
|
|
|
@ -1477,9 +1528,12 @@ class DirectoryTree:
|
|
|
|
|
self._tree = {}
|
|
|
|
|
|
|
|
|
|
def update_tree(self, tree):
|
|
|
|
|
'''Метод, инициирующий наложение заданного дерева каталогов на данный
|
|
|
|
|
экземпляр дерева.'''
|
|
|
|
|
self._update(self._tree, tree)
|
|
|
|
|
|
|
|
|
|
def _update(self, original_tree, tree):
|
|
|
|
|
'''Метод для рекурсивного наложения одного дерева на другое.'''
|
|
|
|
|
for parent, child in tree.items():
|
|
|
|
|
if isinstance(child, abc.Mapping):
|
|
|
|
|
original_tree[parent] = self._update(original_tree.get(parent,
|
|
|
|
@ -1493,9 +1547,13 @@ class DirectoryTree:
|
|
|
|
|
pprint(self._tree)
|
|
|
|
|
|
|
|
|
|
def get_directory_tree(self, directory):
|
|
|
|
|
'''Метод для получения нового дерева из ветви данного дерева,
|
|
|
|
|
соответствующей некоторому каталогу, содержащемуся в корне данного
|
|
|
|
|
дерева.'''
|
|
|
|
|
directory_tree = DirectoryTree(os.path.join(self.base_directory,
|
|
|
|
|
directory))
|
|
|
|
|
directory_tree._tree = self._tree[directory]
|
|
|
|
|
if directory in self._tree:
|
|
|
|
|
directory_tree._tree = self._tree[directory]
|
|
|
|
|
return directory_tree
|
|
|
|
|
|
|
|
|
|
def __getitem__(self, name):
|
|
|
|
@ -1521,8 +1579,7 @@ class DirectoryTree:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DirectoryProcessor:
|
|
|
|
|
chmod_regex = re.compile(r'\d{3}')
|
|
|
|
|
|
|
|
|
|
'''Класс обработчика директорий шаблонов.'''
|
|
|
|
|
def __init__(self, action, datavars_module=Variables(), package='',
|
|
|
|
|
output_module=IOModule()):
|
|
|
|
|
self.action = action
|
|
|
|
@ -1536,7 +1593,7 @@ class DirectoryProcessor:
|
|
|
|
|
else:
|
|
|
|
|
self.cl_chroot_path = '/'
|
|
|
|
|
|
|
|
|
|
self.cl_ignore_files = self.get_cl_ignore_files()
|
|
|
|
|
self.cl_ignore_files = self._get_cl_ignore_files()
|
|
|
|
|
|
|
|
|
|
# Путь к файлу config с хэш-суммами файлов, для которых уже
|
|
|
|
|
# предлагались изменения.
|
|
|
|
@ -1556,6 +1613,8 @@ class DirectoryProcessor:
|
|
|
|
|
self.cl_config_archive = self._add_chroot_path(
|
|
|
|
|
'/var/lib/calculate/config-archive')
|
|
|
|
|
|
|
|
|
|
# Путь к директории .execute для хранения хранения файлов скриптов,
|
|
|
|
|
# полученных из шаблонов с параметром exec.
|
|
|
|
|
if 'cl_exec_dir_path' in datavars_module.main:
|
|
|
|
|
self.cl_exec_dir_path = self._add_chroot_path(
|
|
|
|
|
self.datavars_module.main.cl_exec_dir_path)
|
|
|
|
@ -1574,10 +1633,12 @@ class DirectoryProcessor:
|
|
|
|
|
|
|
|
|
|
# Инициализируем шаблонизатор.
|
|
|
|
|
self.template_engine = TemplateEngine(
|
|
|
|
|
datavars_module=datavars_module,
|
|
|
|
|
datavars_module=self.datavars_module,
|
|
|
|
|
chroot_path=self.cl_chroot_path,
|
|
|
|
|
appends_set=self.template_executor.available_appends)
|
|
|
|
|
|
|
|
|
|
# Разбираем atom имя пакета, для которого накладываем шаблоны.
|
|
|
|
|
self.for_package = False
|
|
|
|
|
if package:
|
|
|
|
|
if isinstance(package, PackageAtomName):
|
|
|
|
|
self.for_package = package
|
|
|
|
@ -1586,29 +1647,28 @@ class DirectoryProcessor:
|
|
|
|
|
self.for_package = self.template_engine.\
|
|
|
|
|
parameters_processor.check_package_parameter(package)
|
|
|
|
|
except ConditionFailed as error:
|
|
|
|
|
# ConfitionFailed потому что для проверки значения пакета,
|
|
|
|
|
# используется тот же метод, что проверяет параметр package
|
|
|
|
|
# в шаблонах, а в них этот параметр играет роль условия.
|
|
|
|
|
self.output.set_error(str(error))
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.for_package = False
|
|
|
|
|
else:
|
|
|
|
|
self.for_package = False
|
|
|
|
|
|
|
|
|
|
# Получаем список директорий шаблонов.
|
|
|
|
|
self.template_paths = (self.datavars_module.
|
|
|
|
|
main.cl_template_path.split(','))
|
|
|
|
|
|
|
|
|
|
self.inheritable_parameters = set(
|
|
|
|
|
ParametersProcessor.inheritable_parameters)
|
|
|
|
|
|
|
|
|
|
# Список обработанных пакетов.
|
|
|
|
|
self.processed_packages = []
|
|
|
|
|
|
|
|
|
|
# Список пакетов, взятый из значений параметра merge.
|
|
|
|
|
self.packages_to_merge = []
|
|
|
|
|
self.packages_file_trees = {}
|
|
|
|
|
|
|
|
|
|
# Список файлов сохраненных в .execute для выполнения после всех
|
|
|
|
|
# шаблонов.
|
|
|
|
|
self.exec_files = dict()
|
|
|
|
|
# Словарь для хранения деревьев директорий для различных пакетов.
|
|
|
|
|
self.packages_file_trees = {}
|
|
|
|
|
|
|
|
|
|
def get_cl_ignore_files(self):
|
|
|
|
|
def _get_cl_ignore_files(self):
|
|
|
|
|
'''Метод для получения из соответствующей переменной списка паттернов
|
|
|
|
|
для обнаружения игнорируемых в ходе обработки шаблонов файлов.'''
|
|
|
|
|
if 'cl_ignore_files' in self.datavars_module.main:
|
|
|
|
|
cl_ignore_files = self.datavars_module.main.cl_ignore_files
|
|
|
|
|
cl_ignore_files_list = []
|
|
|
|
@ -1620,6 +1680,8 @@ class DirectoryProcessor:
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
def _add_chroot_path(self, path_to_add: str):
|
|
|
|
|
'''Метод для добавления корневого пути к заданному пути, если таковой
|
|
|
|
|
задан и отсутствует в заданном пути.'''
|
|
|
|
|
if (self.cl_chroot_path != '/' and
|
|
|
|
|
not path_to_add.startswith(self.cl_chroot_path)):
|
|
|
|
|
return join_paths(self.cl_chroot_path, path_to_add)
|
|
|
|
@ -1627,14 +1689,11 @@ class DirectoryProcessor:
|
|
|
|
|
return path_to_add
|
|
|
|
|
|
|
|
|
|
def process_template_directories(self):
|
|
|
|
|
# Проходим каталоги из main.cl_template.path
|
|
|
|
|
|
|
|
|
|
'''Метод для обхода шаблонов, содержащихся в каталогах из
|
|
|
|
|
main.cl_template.path.'''
|
|
|
|
|
# Режим заполнения очередей директорий пакетов, необходимых для более
|
|
|
|
|
# быстрой обработки параметра merge.
|
|
|
|
|
if self.for_package:
|
|
|
|
|
self.fill_trees = True
|
|
|
|
|
else:
|
|
|
|
|
self.fill_trees = False
|
|
|
|
|
self.fill_trees = bool(self.for_package)
|
|
|
|
|
|
|
|
|
|
for directory_path in self.template_paths:
|
|
|
|
|
self.base_directory = directory_path.strip()
|
|
|
|
@ -1642,10 +1701,10 @@ class DirectoryProcessor:
|
|
|
|
|
|
|
|
|
|
for node in entries:
|
|
|
|
|
self.directory_tree = {}
|
|
|
|
|
self.walk_directory_tree(node.path,
|
|
|
|
|
self.cl_chroot_path,
|
|
|
|
|
ParametersContainer(),
|
|
|
|
|
directory_tree=self.directory_tree)
|
|
|
|
|
self._walk_directory_tree(node.path,
|
|
|
|
|
self.cl_chroot_path,
|
|
|
|
|
ParametersContainer(),
|
|
|
|
|
directory_tree=self.directory_tree)
|
|
|
|
|
|
|
|
|
|
# Теперь когда дерево заполнено, можно выключить этот режим.
|
|
|
|
|
self.fill_trees = False
|
|
|
|
@ -1653,9 +1712,11 @@ class DirectoryProcessor:
|
|
|
|
|
if self.for_package:
|
|
|
|
|
self.output.set_info('Processing packages from merge parameter...')
|
|
|
|
|
self.processed_packages.append(self.for_package)
|
|
|
|
|
self.merge_packages()
|
|
|
|
|
self._merge_packages()
|
|
|
|
|
|
|
|
|
|
def merge_packages(self):
|
|
|
|
|
def _merge_packages(self):
|
|
|
|
|
'''Метод для выполнения шаблонов относящихся к пакетам, указанным во
|
|
|
|
|
всех встреченных значениях параметра merge.'''
|
|
|
|
|
not_merged_packages = []
|
|
|
|
|
|
|
|
|
|
while self.packages_to_merge:
|
|
|
|
@ -1673,10 +1734,10 @@ class DirectoryProcessor:
|
|
|
|
|
directory_tree = self.packages_file_trees[self.for_package].\
|
|
|
|
|
get_directory_tree(directory_name)
|
|
|
|
|
|
|
|
|
|
self.walk_directory_tree(directory_tree.base_directory,
|
|
|
|
|
self.cl_chroot_path,
|
|
|
|
|
ParametersContainer(),
|
|
|
|
|
directory_tree=directory_tree)
|
|
|
|
|
self._walk_directory_tree(directory_tree.base_directory,
|
|
|
|
|
self.cl_chroot_path,
|
|
|
|
|
ParametersContainer(),
|
|
|
|
|
directory_tree=directory_tree)
|
|
|
|
|
|
|
|
|
|
self.processed_packages.append(self.for_package)
|
|
|
|
|
|
|
|
|
@ -1686,7 +1747,7 @@ class DirectoryProcessor:
|
|
|
|
|
else:
|
|
|
|
|
self.output.set_success('All packages are merged...')
|
|
|
|
|
|
|
|
|
|
def get_directories_queue(self, path):
|
|
|
|
|
def _get_directories_queue(self, path):
|
|
|
|
|
'''Уже не актуальный метод для построение очередей из путей к
|
|
|
|
|
шаблонам. Хотя возможно еще пригодится.'''
|
|
|
|
|
directories_queue = []
|
|
|
|
@ -1703,120 +1764,53 @@ class DirectoryProcessor:
|
|
|
|
|
|
|
|
|
|
return base_directory, directories_queue
|
|
|
|
|
|
|
|
|
|
def check_file_name(self, filename: str):
|
|
|
|
|
'''Метод для проверки соответствия имени файла содержимому переменной
|
|
|
|
|
main.cl_ignore_files.'''
|
|
|
|
|
for pattern in self.cl_ignore_files:
|
|
|
|
|
if not fnmatch.fnmatch(filename, pattern):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def walk_directory_tree(self, current_directory_path, target_path,
|
|
|
|
|
directory_parameters, directory_tree={}):
|
|
|
|
|
def _walk_directory_tree(self, current_directory_path, current_target_path,
|
|
|
|
|
directory_parameters, directory_tree={}):
|
|
|
|
|
'''Метод для рекурсивного обхода директорий с шаблонами, а также, при
|
|
|
|
|
необходимости, заполнения деревьев директорий шаблонов, с помощью
|
|
|
|
|
которых далее выполняются шаблоны пакетов из merge.'''
|
|
|
|
|
print('current_directory: {}'.format(current_directory_path))
|
|
|
|
|
print('fill trees = {}'.format(self.fill_trees))
|
|
|
|
|
template_files = []
|
|
|
|
|
template_directories = []
|
|
|
|
|
|
|
|
|
|
directory_name = os.path.basename(current_directory_path)
|
|
|
|
|
|
|
|
|
|
# Если включено заполнение дерева создаем пустой словарь для сбора
|
|
|
|
|
# содержимого текущей директории.
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
directory_tree[directory_name] = {}
|
|
|
|
|
|
|
|
|
|
current_target_path = target_path
|
|
|
|
|
|
|
|
|
|
entries = os.scandir(current_directory_path)
|
|
|
|
|
self.template_engine.change_directory(current_directory_path)
|
|
|
|
|
|
|
|
|
|
for node in entries:
|
|
|
|
|
if self.check_file_name(node.name):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if node.is_symlink():
|
|
|
|
|
self.output.set_warning('symlink: {} is ignored'.
|
|
|
|
|
format(node.path))
|
|
|
|
|
continue
|
|
|
|
|
elif node.is_dir():
|
|
|
|
|
template_directories.append(node.path)
|
|
|
|
|
elif node.is_file():
|
|
|
|
|
template_files.append(node.name)
|
|
|
|
|
template_directories, template_files = self._scan_directory(
|
|
|
|
|
current_directory_path)
|
|
|
|
|
|
|
|
|
|
# обрабатываем в первую очередь шаблон директории.
|
|
|
|
|
if '.calculate_directory' in template_files:
|
|
|
|
|
template_files.remove('.calculate_directory')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
self.template_engine.process_template(
|
|
|
|
|
'.calculate_directory',
|
|
|
|
|
template_type=DIR,
|
|
|
|
|
parameters=directory_parameters)
|
|
|
|
|
except ConditionFailed as error:
|
|
|
|
|
self.output.set_warning('{}. Template: {}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
current_directory_path))
|
|
|
|
|
directory_tree = {}
|
|
|
|
|
return
|
|
|
|
|
except Exception as error:
|
|
|
|
|
self.output.set_error('Template error: {0} Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
current_directory_path))
|
|
|
|
|
template_text = self._parse_template(directory_parameters,
|
|
|
|
|
'.calculate_directory',
|
|
|
|
|
DIR, current_directory_path)
|
|
|
|
|
if template_text is False:
|
|
|
|
|
directory_tree = {}
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
directory_parameters.print_parameters_for_debug()
|
|
|
|
|
|
|
|
|
|
# Если есть параметр name -- меняем имя текущего каталога.
|
|
|
|
|
if directory_parameters.name:
|
|
|
|
|
directory_name = directory_parameters.name
|
|
|
|
|
|
|
|
|
|
# Если есть параметр path -- меняем текущий путь к целевому
|
|
|
|
|
# каталогу.
|
|
|
|
|
if directory_parameters.path:
|
|
|
|
|
current_target_path = join_paths(self.cl_chroot_path,
|
|
|
|
|
directory_parameters.path)
|
|
|
|
|
|
|
|
|
|
# В зависимости от того, нужно ли нам заполнять дерево директорий,
|
|
|
|
|
# отправляем в метод для проверки параметров package и action
|
|
|
|
|
# или текущее дерево, или пустое значение.
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
tree_for_checker = directory_tree
|
|
|
|
|
else:
|
|
|
|
|
tree_for_checker = None
|
|
|
|
|
|
|
|
|
|
if self.check_package_and_action(directory_parameters,
|
|
|
|
|
current_directory_path,
|
|
|
|
|
directory_tree=tree_for_checker):
|
|
|
|
|
# Если проверка параметров package и action пройдена и
|
|
|
|
|
# и параметр append не равен skip -- обновляем целевой путь
|
|
|
|
|
# именем текущей директории.
|
|
|
|
|
if not directory_parameters.append == 'skip':
|
|
|
|
|
current_target_path = os.path.join(current_target_path,
|
|
|
|
|
directory_name)
|
|
|
|
|
else:
|
|
|
|
|
# Если проверка не пройдена, включено заполнение дерева, а
|
|
|
|
|
# метод для проверки заменил для текущей директории значение {}
|
|
|
|
|
# на None (являющейся для этого дерева заглушкой), то,
|
|
|
|
|
# Корректируем путь к целевой директории.
|
|
|
|
|
current_target_path = self._make_target_path(current_target_path,
|
|
|
|
|
directory_name,
|
|
|
|
|
directory_parameters)
|
|
|
|
|
|
|
|
|
|
# Если нужно заполнять дерево директорий, отправляем в метод для
|
|
|
|
|
# проверки параметров package и action текущее дерево.
|
|
|
|
|
if not self._check_package_and_action(
|
|
|
|
|
directory_parameters,
|
|
|
|
|
current_directory_path,
|
|
|
|
|
directory_tree=(directory_tree if
|
|
|
|
|
self.fill_trees else None)):
|
|
|
|
|
# Если проверка не пройдена и включено заполнение дерева, то,
|
|
|
|
|
# используя нынешнее состояние дерева директорий, обновляем
|
|
|
|
|
# дерево пакета текущего шаблона директории.
|
|
|
|
|
if (self.fill_trees and
|
|
|
|
|
directory_tree[directory_name] is None):
|
|
|
|
|
package_name = directory_parameters.package
|
|
|
|
|
if package_name in self.packages_file_trees:
|
|
|
|
|
# Если для данного пакета уже есть дерево --
|
|
|
|
|
# накладываем на него текущее.
|
|
|
|
|
self.packages_file_trees[package_name].update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# Если для данного пакета еще нет дерева --
|
|
|
|
|
# копируем для него текущее.
|
|
|
|
|
directory_tree = DirectoryTree(self.base_directory)
|
|
|
|
|
directory_tree.update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree))
|
|
|
|
|
self.packages_file_trees[package_name] = directory_tree
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
self._update_package_tree(directory_parameters.package,
|
|
|
|
|
directory_tree[directory_name])
|
|
|
|
|
# Перед выходом из директории очищаем текущий уровень
|
|
|
|
|
# дерева.
|
|
|
|
|
directory_tree = {}
|
|
|
|
@ -1828,238 +1822,119 @@ class DirectoryProcessor:
|
|
|
|
|
self.packages_to_merge.extend(directory_parameters.merge)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
# Если .calculate_directory отсутствует -- создаем директорию
|
|
|
|
|
# Если .calculate_directory отсутствует -- создаем директорию,
|
|
|
|
|
# используя унаследованные параметры и имя самой директории.
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
tree_for_checker = directory_tree
|
|
|
|
|
else:
|
|
|
|
|
tree_for_checker = None
|
|
|
|
|
if not self.check_package_and_action(
|
|
|
|
|
directory_parameters,
|
|
|
|
|
current_directory_path,
|
|
|
|
|
directory_tree=tree_for_checker):
|
|
|
|
|
if not self._check_package_and_action(
|
|
|
|
|
directory_parameters,
|
|
|
|
|
current_directory_path,
|
|
|
|
|
directory_tree=(directory_tree if
|
|
|
|
|
self.fill_trees else None)):
|
|
|
|
|
# Обновляем дерево директорий для данного пакета.
|
|
|
|
|
if (directory_tree[directory_name] is None and
|
|
|
|
|
self.fill_trees):
|
|
|
|
|
package_name = directory_parameters.package
|
|
|
|
|
if package_name in self.packages_file_trees:
|
|
|
|
|
# Если для данного пакета уже есть дерево --
|
|
|
|
|
# накладываем на него текущее.
|
|
|
|
|
self.packages_file_trees[package_name].update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# Если для данного пакета еще нет дерева --
|
|
|
|
|
# копируем для него текущее.
|
|
|
|
|
directory_tree = DirectoryTree(self.base_directory)
|
|
|
|
|
directory_tree.update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree))
|
|
|
|
|
self.packages_file_trees[package_name] = directory_tree
|
|
|
|
|
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
self._update_package_tree(directory_parameters.package,
|
|
|
|
|
directory_tree[directory_name])
|
|
|
|
|
# Перед выходом из директории очищаем текущий уровень
|
|
|
|
|
# дерева.
|
|
|
|
|
directory_tree = {}
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Для того чтобы директория была создана просто добавляем параметр
|
|
|
|
|
# Для того чтобы директория была создана, просто добавляем параметр
|
|
|
|
|
# append = join.
|
|
|
|
|
directory_parameters.set_parameter({'append': 'join'})
|
|
|
|
|
current_target_path = os.path.join(current_target_path,
|
|
|
|
|
directory_name)
|
|
|
|
|
|
|
|
|
|
# * * * МОЖНО ВЫДЕЛИТЬ В ОТДЕЛЬНЫЙ МЕТОД * * *
|
|
|
|
|
# Выполняем наложение шаблона.
|
|
|
|
|
try:
|
|
|
|
|
output = self.template_executor.execute_template(
|
|
|
|
|
current_target_path,
|
|
|
|
|
directory_parameters,
|
|
|
|
|
DIR)
|
|
|
|
|
# Если во время выполнения шаблона был изменен целевой путь,
|
|
|
|
|
# например, из-за ссылки на директорию в source -- обновляем
|
|
|
|
|
# целевой путь.
|
|
|
|
|
if output['target_path'] is not None:
|
|
|
|
|
current_target_path = output['target_path']
|
|
|
|
|
|
|
|
|
|
# Если есть вывод от параметра run -- выводим как info.
|
|
|
|
|
if output['stdout'] is not None:
|
|
|
|
|
self.output.set_info("stdout from template: {}:\n{}\n".format(
|
|
|
|
|
current_directory_path,
|
|
|
|
|
output['stdout']
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
# Если есть ошибки от параметра run -- выводим их как error.
|
|
|
|
|
if output['stderr'] is not None:
|
|
|
|
|
self.output.set_error("stderr from template: {}:\n{}\n".
|
|
|
|
|
format(current_directory_path,
|
|
|
|
|
output['stderr']))
|
|
|
|
|
# Если run выполнен с ошибками -- пропускаем директорию.
|
|
|
|
|
return
|
|
|
|
|
except TemplateExecutorError as error:
|
|
|
|
|
self.output.set_error('Template execution error: {} Template: {}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
current_directory_path))
|
|
|
|
|
current_target_path = self._execute_template(current_target_path,
|
|
|
|
|
directory_parameters, DIR,
|
|
|
|
|
current_directory_path)
|
|
|
|
|
if not current_target_path:
|
|
|
|
|
directory_tree = {}
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.output.set_success('Processing directory: {}'.
|
|
|
|
|
format(current_directory_path))
|
|
|
|
|
|
|
|
|
|
# * * * МОЖНО ВЫДЕЛИТЬ В ОТДЕЛЬНЫЙ МЕТОД * * *
|
|
|
|
|
# Далее обрабатываем файлы шаблонов хранящихся в директории.
|
|
|
|
|
# Список файлов и директорий для дальнейшего обхода получаем из
|
|
|
|
|
# списоков полученных при начальном сканировании директории или,
|
|
|
|
|
# если в данный момент обходим дерево директорий, что можно определить
|
|
|
|
|
# по выключенному флагу fill_trees и по наличию дерева в переменной
|
|
|
|
|
# directory_tree, берем файлы и каталоги для обхода из дерева.
|
|
|
|
|
# Если в данный момент обходим дерево -- берем список файлов и
|
|
|
|
|
# директорий из него.
|
|
|
|
|
if not self.fill_trees and directory_tree:
|
|
|
|
|
tree_files = []
|
|
|
|
|
tree_directories = []
|
|
|
|
|
|
|
|
|
|
for template in directory_tree:
|
|
|
|
|
if template in template_files:
|
|
|
|
|
tree_files.append(template)
|
|
|
|
|
else:
|
|
|
|
|
next_directory_tree =\
|
|
|
|
|
directory_tree.get_directory_tree(template)
|
|
|
|
|
tree_directories.append(next_directory_tree)
|
|
|
|
|
template_directorie, template_file =\
|
|
|
|
|
self._get_files_and_dirs_from_tree(template_files,
|
|
|
|
|
template_directories,
|
|
|
|
|
directory_tree)
|
|
|
|
|
|
|
|
|
|
template_files = tree_files
|
|
|
|
|
template_directories = tree_directories
|
|
|
|
|
# Просто псевдоним, чтобы меньше путаницы было далее.
|
|
|
|
|
template_parameters = directory_parameters
|
|
|
|
|
|
|
|
|
|
# Обрабатываем файлы шаблонов.
|
|
|
|
|
for template_name in template_files:
|
|
|
|
|
# Удаляем все параметры, которые не наследуются и используем
|
|
|
|
|
# полученный контейнер для сбора параметров файлов шаблонов.
|
|
|
|
|
directory_parameters.remove_not_inheritable()
|
|
|
|
|
|
|
|
|
|
template_parameters.remove_not_inheritable()
|
|
|
|
|
template_path = os.path.join(current_directory_path, template_name)
|
|
|
|
|
|
|
|
|
|
# Применяем к файлу шаблона шаблонизатор.
|
|
|
|
|
try:
|
|
|
|
|
self.template_engine.process_template(
|
|
|
|
|
template_name, FILE,
|
|
|
|
|
parameters=directory_parameters)
|
|
|
|
|
except ConditionFailed as error:
|
|
|
|
|
self.output.set_warning('{0}. Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
template_text = self._parse_template(template_parameters,
|
|
|
|
|
template_name,
|
|
|
|
|
FILE, current_directory_path)
|
|
|
|
|
if template_text is False:
|
|
|
|
|
continue
|
|
|
|
|
except Exception as error:
|
|
|
|
|
self.output.set_error('Template error: {0} Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
directory_parameters.print_parameters_for_debug()
|
|
|
|
|
|
|
|
|
|
template_text = self.template_engine.template_text
|
|
|
|
|
template_parameters.print_parameters_for_debug()
|
|
|
|
|
|
|
|
|
|
# Если находимся на стадии заполнения дерева директорий --
|
|
|
|
|
# проверяем параметры package и action с заполнением дерева.
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
tree_for_checker = directory_tree[directory_name]
|
|
|
|
|
else:
|
|
|
|
|
tree_for_checker = None
|
|
|
|
|
|
|
|
|
|
# Проверяем параметры action и package.
|
|
|
|
|
if not self.check_package_and_action(
|
|
|
|
|
directory_parameters,
|
|
|
|
|
template_path,
|
|
|
|
|
directory_tree=tree_for_checker):
|
|
|
|
|
if not self._check_package_and_action(
|
|
|
|
|
template_parameters,
|
|
|
|
|
template_path,
|
|
|
|
|
directory_tree=(directory_tree[directory_name] if
|
|
|
|
|
self.fill_trees else None)):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Если есть параметр merge добавляем в список пакетов для
|
|
|
|
|
# последующей обработки.
|
|
|
|
|
if self.for_package and directory_parameters.merge:
|
|
|
|
|
self.packages_to_merge.extend(directory_parameters.merge)
|
|
|
|
|
|
|
|
|
|
# Если для шаблона задано имя -- меняем его.
|
|
|
|
|
if directory_parameters.name:
|
|
|
|
|
template_name = directory_parameters.name
|
|
|
|
|
# Если есть параметр merge добавляем его содержимое в список
|
|
|
|
|
# пакетов для последующей обработки.
|
|
|
|
|
if self.for_package and template_parameters.merge:
|
|
|
|
|
self.packages_to_merge.extend(template_parameters.merge)
|
|
|
|
|
|
|
|
|
|
# Если для шаблона задан путь -- меняем его.
|
|
|
|
|
if directory_parameters.path:
|
|
|
|
|
target_file_path = join_paths(self.cl_chroot_path,
|
|
|
|
|
directory_parameters.path,
|
|
|
|
|
template_name)
|
|
|
|
|
else:
|
|
|
|
|
target_file_path = join_paths(current_target_path,
|
|
|
|
|
template_name)
|
|
|
|
|
# Корректируем путь к целевому файлу.
|
|
|
|
|
target_file_path = self._make_target_path(current_target_path,
|
|
|
|
|
template_name,
|
|
|
|
|
template_parameters)
|
|
|
|
|
|
|
|
|
|
# Выполняем действия, указанные в шаблоне.
|
|
|
|
|
try:
|
|
|
|
|
output = self.template_executor.execute_template(
|
|
|
|
|
target_file_path = self._execute_template(
|
|
|
|
|
target_file_path,
|
|
|
|
|
directory_parameters,
|
|
|
|
|
FILE,
|
|
|
|
|
template_parameters,
|
|
|
|
|
FILE, template_path,
|
|
|
|
|
template_text=template_text)
|
|
|
|
|
except TemplateExecutorError as error:
|
|
|
|
|
self.output.set_error(
|
|
|
|
|
'Template execution error: {0} Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
if not target_file_path:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Если во время выполнения шаблона был изменен целевой путь,
|
|
|
|
|
# например, из-за ссылки на директорию в source -- обновляем
|
|
|
|
|
# целевой путь.
|
|
|
|
|
if output['target_path'] is not None:
|
|
|
|
|
current_target_path = output['target_path']
|
|
|
|
|
|
|
|
|
|
# Если есть вывод от параметра run -- выводим как info.
|
|
|
|
|
if output['stdout'] is not None:
|
|
|
|
|
self.output.set_info("stdout from template: {}\n{}".format(
|
|
|
|
|
current_directory_path,
|
|
|
|
|
output['stdout']
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
# Если есть ошибки от параметра run -- выводим их как error
|
|
|
|
|
if output['stderr'] is not None:
|
|
|
|
|
self.output.set_error("stderr from template: {}\n{}".
|
|
|
|
|
format(current_directory_path,
|
|
|
|
|
output['stderr']))
|
|
|
|
|
# Если run выполнен с ошибками -- пропускаем директорию.
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.output.set_success('Processed template: {}...'.
|
|
|
|
|
format(template_path))
|
|
|
|
|
|
|
|
|
|
# * * * ПРИДУМАТЬ ОПТИМИЗАЦИЮ * * *
|
|
|
|
|
# Потому что накладывать дерево каждый раз, когда обнаружены файлы
|
|
|
|
|
# какого-то пакета не рационально.
|
|
|
|
|
# Обновляем дерево директорий для данного пакета, если происходит
|
|
|
|
|
# его заполнение.
|
|
|
|
|
self.output.set_info("Let's update tree using current: {}".
|
|
|
|
|
format(directory_tree))
|
|
|
|
|
if (self.fill_trees and directory_tree[directory_name]):
|
|
|
|
|
package_name = directory_parameters.package
|
|
|
|
|
|
|
|
|
|
if package_name in self.packages_file_trees:
|
|
|
|
|
# Если для данного пакета дерево уже есть -- обновляем его.
|
|
|
|
|
self.packages_file_trees[package_name].update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree))
|
|
|
|
|
else:
|
|
|
|
|
# Если нет создаем новое.
|
|
|
|
|
directory_tree = DirectoryTree(self.base_directory)
|
|
|
|
|
directory_tree.update_tree(copy.deepcopy(
|
|
|
|
|
self.directory_tree))
|
|
|
|
|
self.packages_file_trees[package_name] = directory_tree
|
|
|
|
|
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
self._update_package_tree(template_parameters.package,
|
|
|
|
|
directory_tree[directory_name])
|
|
|
|
|
directory_tree[directory_name] = {}
|
|
|
|
|
|
|
|
|
|
# проходимся далее по директориям.
|
|
|
|
|
# Проходимся далее по директориям.
|
|
|
|
|
for directory in template_directories:
|
|
|
|
|
if self.fill_trees:
|
|
|
|
|
self.walk_directory_tree(
|
|
|
|
|
self._walk_directory_tree(
|
|
|
|
|
directory, current_target_path,
|
|
|
|
|
directory_parameters.get_inheritables(),
|
|
|
|
|
directory_tree=directory_tree[directory_name])
|
|
|
|
|
directory_tree[directory_name] = {}
|
|
|
|
|
else:
|
|
|
|
|
if isinstance(directory, DirectoryTree):
|
|
|
|
|
# Если директории берем из дерева -- путь к директории
|
|
|
|
|
# соответствует корню текущего дерева.
|
|
|
|
|
# Если директории взяты из дерева -- путь к директории
|
|
|
|
|
# соответствует корню каждой взятой ветви дерева.
|
|
|
|
|
directory_path = directory.base_directory
|
|
|
|
|
else:
|
|
|
|
|
directory_path = directory
|
|
|
|
|
|
|
|
|
|
self.walk_directory_tree(
|
|
|
|
|
self._walk_directory_tree(
|
|
|
|
|
directory_path,
|
|
|
|
|
current_target_path,
|
|
|
|
|
directory_parameters.get_inheritables())
|
|
|
|
@ -2068,11 +1943,173 @@ class DirectoryProcessor:
|
|
|
|
|
directory_tree = {}
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def check_package_and_action(self, parameters, template_path,
|
|
|
|
|
directory_tree=None):
|
|
|
|
|
def _scan_directory(self, directory_path: str):
|
|
|
|
|
'''Метод для получения и фильтрования списка файлов и директорий,
|
|
|
|
|
содержащихся в директории шаблонов.'''
|
|
|
|
|
template_files = []
|
|
|
|
|
template_directories = []
|
|
|
|
|
|
|
|
|
|
entries = os.scandir(directory_path)
|
|
|
|
|
|
|
|
|
|
for node in entries:
|
|
|
|
|
if not self._check_file_name(node.name):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if node.is_symlink():
|
|
|
|
|
self.output.set_warning(
|
|
|
|
|
'symlink: {0} is ignored in the template directory: {1}'.
|
|
|
|
|
format(node.path, directory_path))
|
|
|
|
|
continue
|
|
|
|
|
elif node.is_dir():
|
|
|
|
|
template_directories.append(node.path)
|
|
|
|
|
elif node.is_file():
|
|
|
|
|
template_files.append(node.name)
|
|
|
|
|
|
|
|
|
|
return template_directories, template_files
|
|
|
|
|
|
|
|
|
|
def _check_file_name(self, filename: str):
|
|
|
|
|
'''Метод для проверки соответствия имени файла содержимому переменной
|
|
|
|
|
main.cl_ignore_files.'''
|
|
|
|
|
for pattern in self.cl_ignore_files:
|
|
|
|
|
if fnmatch.fnmatch(filename, pattern):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def _get_files_and_dirs_from_tree(self, template_files,
|
|
|
|
|
template_directories,
|
|
|
|
|
directory_tree):
|
|
|
|
|
'''Метод для получения списков файлов и директорий из дерева
|
|
|
|
|
директорий.'''
|
|
|
|
|
tree_files = []
|
|
|
|
|
tree_directories = []
|
|
|
|
|
|
|
|
|
|
for template in directory_tree:
|
|
|
|
|
if template in template_files:
|
|
|
|
|
tree_files.append(template)
|
|
|
|
|
else:
|
|
|
|
|
next_directory_tree =\
|
|
|
|
|
directory_tree.get_directory_tree(template)
|
|
|
|
|
tree_directories.append(next_directory_tree)
|
|
|
|
|
|
|
|
|
|
return tree_directories, tree_files
|
|
|
|
|
|
|
|
|
|
def _make_target_path(self, target_path, template_name,
|
|
|
|
|
parameters):
|
|
|
|
|
'''Метод для получения пути к целевому файлу с учетом наличия
|
|
|
|
|
параметров name, path и append = skip.'''
|
|
|
|
|
# Если есть параметр name -- меняем имя шаблона.
|
|
|
|
|
if parameters.name:
|
|
|
|
|
template_name = parameters.name
|
|
|
|
|
|
|
|
|
|
# Если для шаблона задан путь -- меняем путь к директории шаблона.
|
|
|
|
|
if parameters.path:
|
|
|
|
|
target_path = join_paths(self.cl_chroot_path,
|
|
|
|
|
parameters.path)
|
|
|
|
|
|
|
|
|
|
# Если параметр append не равен skip -- добавляем имя шаблона к
|
|
|
|
|
# целевому пути.
|
|
|
|
|
if not parameters.append == 'skip':
|
|
|
|
|
target_path = os.path.join(target_path,
|
|
|
|
|
template_name)
|
|
|
|
|
return target_path
|
|
|
|
|
|
|
|
|
|
def _parse_template(self, parameters,
|
|
|
|
|
template_name,
|
|
|
|
|
template_type,
|
|
|
|
|
template_directory):
|
|
|
|
|
'''Метод для разбора шаблонов, получения значений их параметров и их
|
|
|
|
|
текста после отработки шаблонизитора.'''
|
|
|
|
|
if template_type == DIR:
|
|
|
|
|
template_path = template_directory
|
|
|
|
|
else:
|
|
|
|
|
template_path = join_paths(template_directory, template_name)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
self.template_engine.process_template(template_name,
|
|
|
|
|
template_type,
|
|
|
|
|
parameters=parameters)
|
|
|
|
|
return self.template_engine.template_text
|
|
|
|
|
except ConditionFailed as error:
|
|
|
|
|
self.output.set_warning('{0}. Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
return False
|
|
|
|
|
except Exception as error:
|
|
|
|
|
self.output.set_error('Template error: {0} Template: {1}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def _execute_template(self, target_path,
|
|
|
|
|
parameters,
|
|
|
|
|
template_type,
|
|
|
|
|
template_path,
|
|
|
|
|
template_text=''):
|
|
|
|
|
'''Метод для наложения шаблонов и обработки информации полученной после
|
|
|
|
|
наложения.'''
|
|
|
|
|
try:
|
|
|
|
|
output = self.template_executor.execute_template(
|
|
|
|
|
target_path,
|
|
|
|
|
parameters,
|
|
|
|
|
template_type,
|
|
|
|
|
template_path,
|
|
|
|
|
template_text=template_text)
|
|
|
|
|
# Если во время выполнения шаблона был изменен целевой путь,
|
|
|
|
|
# например, из-за ссылки на директорию в source -- обновляем
|
|
|
|
|
# целевой путь.
|
|
|
|
|
if output['target_path'] is not None:
|
|
|
|
|
target_path = output['target_path']
|
|
|
|
|
|
|
|
|
|
# Если есть вывод от параметра run -- выводим как info.
|
|
|
|
|
if output['stdout'] is not None:
|
|
|
|
|
self.output.set_info("stdout from template: {}:\n{}\n".format(
|
|
|
|
|
template_path,
|
|
|
|
|
output['stdout']))
|
|
|
|
|
|
|
|
|
|
# Если есть ошибки от параметра run -- выводим их как error.
|
|
|
|
|
if output['stderr'] is not None:
|
|
|
|
|
self.output.set_error("stderr from template: {}:\n{}\n".
|
|
|
|
|
format(template_path,
|
|
|
|
|
output['stderr']))
|
|
|
|
|
# Если run выполнен с ошибками -- пропускаем директорию.
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
except TemplateExecutorError as error:
|
|
|
|
|
self.output.set_error('Template execution error: {} Template: {}'.
|
|
|
|
|
format(str(error),
|
|
|
|
|
template_path))
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
self.output.set_success('Processing directory: {}'.
|
|
|
|
|
format(template_path))
|
|
|
|
|
return target_path
|
|
|
|
|
|
|
|
|
|
def _update_package_tree(self, package, current_level_tree):
|
|
|
|
|
'''Метод для обновления деревьев директорий пакетов, необходимых для
|
|
|
|
|
обработки шаблонов пакетов из значения параметра merge.'''
|
|
|
|
|
# Если текущему уровню соответствует заглушка None или он содержит
|
|
|
|
|
# файлы, то есть не пустой -- тогда есть смысл обновлять.
|
|
|
|
|
if current_level_tree is None or current_level_tree:
|
|
|
|
|
if package in self.packages_file_trees:
|
|
|
|
|
# Если для данного пакета уже есть дерево --
|
|
|
|
|
# накладываем на него текущее.
|
|
|
|
|
self.packages_file_trees[package].update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# Если для данного пакета еще нет дерева --
|
|
|
|
|
# копируем для него текущее.
|
|
|
|
|
directory_tree = DirectoryTree(self.base_directory)
|
|
|
|
|
directory_tree.update_tree(
|
|
|
|
|
copy.deepcopy(self.directory_tree))
|
|
|
|
|
self.packages_file_trees[package] = directory_tree
|
|
|
|
|
|
|
|
|
|
def _check_package_and_action(self, parameters, template_path,
|
|
|
|
|
directory_tree=None):
|
|
|
|
|
'''Метод для проверки параметров action и package во время обработки
|
|
|
|
|
каталогов с шаблонами. Если среди аргументов указано также
|
|
|
|
|
дерево каталогов, то'''
|
|
|
|
|
дерево каталогов, то в случае несовпадения значений package для файла
|
|
|
|
|
или директории, им в дереве присваивается значение None.'''
|
|
|
|
|
if parameters.append != 'skip' or parameters.action:
|
|
|
|
|
if not parameters.action:
|
|
|
|
|
self.output.set_warning(
|
|
|
|
|