Changed order of saving changed CONTENTS files.

master
Иванов Денис 3 years ago
parent 1afbff8b1c
commit 9d26db03f0

@ -1580,11 +1580,14 @@ class CalculateExtension(Extension):
class TemplateEngine: class TemplateEngine:
def __init__(self, directory_path=None, def __init__(self, directory_path: Union[str, None] = None,
datavars_module=Variables(), datavars_module: Union[Datavars,
appends_set=set(), NamespaceNode,
chroot_path='/', Variables] = Variables(),
for_package=None): appends_set: set = set(),
chroot_path: str = '/',
for_package: Union[Package, None] = None,
pkg_autosave: bool = False):
ParametersProcessor._inspect_formats_package() ParametersProcessor._inspect_formats_package()
CalculateExtension._parameters_set =\ CalculateExtension._parameters_set =\
@ -1595,6 +1598,8 @@ class TemplateEngine:
self._datavars_module = datavars_module self._datavars_module = datavars_module
self._template_text = '' self._template_text = ''
self._pkg_autosave: bool = pkg_autosave
self._parameters_object = ParametersContainer() self._parameters_object = ParametersContainer()
self.parameters_processor = ParametersProcessor( self.parameters_processor = ParametersProcessor(
chroot_path=chroot_path, chroot_path=chroot_path,

@ -3,6 +3,7 @@
from pprint import pprint from pprint import pprint
from ..utils.package import ( from ..utils.package import (
PackageAtomParser, PackageAtomParser,
PackageCreator,
Package, Package,
PackageNotFound, PackageNotFound,
PackageAtomName, PackageAtomName,
@ -42,6 +43,8 @@ from typing import (
List, List,
Tuple, Tuple,
Iterator, Iterator,
NoReturn,
Optional,
Callable Callable
) )
from calculate.variables.loader import Datavars from calculate.variables.loader import Datavars
@ -120,21 +123,21 @@ class CalculateConfigFile:
self._unsaved_changes = False self._unsaved_changes = False
return config_dictionary return config_dictionary
def set_files_md5(self, file_path: str, file_md5: str) -> None: def set_files_md5(self, file_path: str, file_md5: str) -> NoReturn:
'''Метод для установки в config соответствия файла некоторой '''Метод для установки в config соответствия файла некоторой
контрольной сумме.''' контрольной сумме.'''
file_path = self._remove_chroot(file_path) file_path = self._remove_chroot(file_path)
self._config_dictionary[file_path] = file_md5 self._config_dictionary[file_path] = file_md5
self._unsaved_changes = True self._unsaved_changes = True
def remove_file(self, file_path: str) -> None: def remove_file(self, file_path: str) -> NoReturn:
'''Метод для удаления файла из config.''' '''Метод для удаления файла из config.'''
file_path = self._remove_chroot(file_path) file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary: if file_path in self._config_dictionary:
self._config_dictionary.pop(file_path) self._config_dictionary.pop(file_path)
self._unsaved_changes = True self._unsaved_changes = True
def compare_md5(self, file_path: str, file_md5: str) -> None: def compare_md5(self, file_path: str, file_md5: str) -> NoReturn:
'''Метод для сравнения хэш-суммы из config и некоторой заданной.''' '''Метод для сравнения хэш-суммы из config и некоторой заданной.'''
file_path = self._remove_chroot(file_path) file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary: if file_path in self._config_dictionary:
@ -142,7 +145,7 @@ class CalculateConfigFile:
else: else:
return False return False
def save_changes(self) -> None: def save_changes(self) -> NoReturn:
'''Метод для записи изменений, внессенных в файл config.''' '''Метод для записи изменений, внессенных в файл config.'''
if not self._unsaved_changes: if not self._unsaved_changes:
return return
@ -190,10 +193,11 @@ class TemplateWrapper:
template_type: int, template_type: int,
template_path: str, template_path: str,
template_text: str = '', template_text: str = '',
target_package: Union[Package, None] = None, target_package: Optional[Package] = None,
chroot_path: str = '/', chroot_path: str = '/',
config_archive_path: str = '/var/lib/calculate/config-archive', config_archive_path: str = '/var/lib/calculate/config-archive',
dbpkg: bool = True): dbpkg: bool = True,
pkg_autosave: bool = False):
self.target_path: str = target_file_path self.target_path: str = target_file_path
self.template_path: str = template_path self.template_path: str = template_path
self.chroot_path: str = chroot_path self.chroot_path: str = chroot_path
@ -203,6 +207,8 @@ class TemplateWrapper:
self.package_atom_parser: PackageAtomParser = PackageAtomParser( self.package_atom_parser: PackageAtomParser = PackageAtomParser(
chroot_path=self.chroot_path) chroot_path=self.chroot_path)
self._pkg_autosave: bool = pkg_autosave
# Вспомогательный флаг, включается, если по целевому пути лежит файл, # Вспомогательный флаг, включается, если по целевому пути лежит файл,
# для которого не определился никакой пакет. # для которого не определился никакой пакет.
self.target_without_package: bool = False self.target_without_package: bool = False
@ -292,7 +298,8 @@ class TemplateWrapper:
self.target_package.package_name != self.target_package.package_name !=
self.target_package_name): self.target_package_name):
self.target_package = Package(self.parameters.package, self.target_package = Package(self.parameters.package,
chroot_path=self.chroot_path) chroot_path=self.chroot_path,
autosave=self._pkg_autosave)
return return
self._check_type_conflicts() self._check_type_conflicts()
@ -306,7 +313,7 @@ class TemplateWrapper:
if self.parameters.append and self.parameters.append == "replace": if self.parameters.append and self.parameters.append == "replace":
self.remove_original = True self.remove_original = True
def _check_type_conflicts(self) -> None: def _check_type_conflicts(self) -> NoReturn:
'''Метод для проверки конфликтов типов.''' '''Метод для проверки конфликтов типов.'''
if self.parameters.append == 'link': if self.parameters.append == 'link':
if self.parameters.force: if self.parameters.force:
@ -380,7 +387,7 @@ class TemplateWrapper:
raise TemplateTypeConflict("the target file is a directory" raise TemplateTypeConflict("the target file is a directory"
" while the template is a file") " while the template is a file")
def _check_package_collision(self) -> None: def _check_package_collision(self) -> NoReturn:
'''Метод для проверки на предмет коллизии, то есть конфликта пакета '''Метод для проверки на предмет коллизии, то есть конфликта пакета
шаблона и целевого файла.''' шаблона и целевого файла.'''
if self.parameters.package: if self.parameters.package:
@ -437,12 +444,14 @@ class TemplateWrapper:
if (self.target_package is None or if (self.target_package is None or
self.target_package_name != self.target_package.package_name): self.target_package_name != self.target_package.package_name):
self.target_package = Package(self.target_package_name, self.target_package = Package(self.target_package_name,
chroot_path=self.chroot_path) chroot_path=self.chroot_path,
autosave=True)
# Теперь перемещаем файл в пакет со старшей версией. # Теперь перемещаем файл в пакет со старшей версией.
self.source_package = Package(file_package, self.source_package = Package(file_package,
chroot_path=self.chroot_path) chroot_path=self.chroot_path,
autosave=self._pkg_autosave)
removed = self.source_package.remove_file(self.target_path) removed = self.source_package.remove_file(self.target_path)
for file_path, file_info in removed.items(): for file_path, file_info in removed.items():
if file_info['type'] == 'dir': if file_info['type'] == 'dir':
self.target_package.add_dir(file_path) self.target_package.add_dir(file_path)
@ -455,14 +464,14 @@ class TemplateWrapper:
file_path, file_path,
target_path=file_info['target'], target_path=file_info['target'],
mtime=file_info['mtime']) mtime=file_info['mtime'])
self.source_package.write_contents_file()
else: else:
self.target_package_name = parameter_package self.target_package_name = parameter_package
if (self.target_package is None or if (self.target_package is None or
self.target_package_name != self.target_package.package_name): self.target_package_name != self.target_package.package_name):
self.target_package = Package(self.target_package_name, self.target_package = Package(self.target_package_name,
chroot_path=self.chroot_path) chroot_path=self.chroot_path,
autosave=self._pkg_autosave)
def _compare_packages(self, lpackage: PackageAtomName, def _compare_packages(self, lpackage: PackageAtomName,
rpackage: PackageAtomName rpackage: PackageAtomName
@ -479,7 +488,7 @@ class TemplateWrapper:
else: else:
return rpackage return rpackage
def _check_user_changes(self) -> None: def _check_user_changes(self) -> NoReturn:
'''Метод для проверки наличия пользовательских изменений в '''Метод для проверки наличия пользовательских изменений в
конфигурационных файлах.''' конфигурационных файлах.'''
# Эта проверка только для файлов. # Эта проверка только для файлов.
@ -604,7 +613,7 @@ class TemplateWrapper:
return new_cfg_path return new_cfg_path
def remove_from_contents(self) -> None: def remove_from_contents(self) -> NoReturn:
'''Метод для удаления целевого файла из CONTENTS.''' '''Метод для удаления целевого файла из CONTENTS.'''
if self.target_package is None: if self.target_package is None:
return return
@ -614,13 +623,13 @@ class TemplateWrapper:
elif self.template_type == FILE: elif self.template_type == FILE:
self.target_package.remove_obj(self.target_path) self.target_package.remove_obj(self.target_path)
def clear_dir_contents(self) -> None: def clear_dir_contents(self) -> NoReturn:
'''Метод для удаления из CONTENTS всего содержимого директории после '''Метод для удаления из CONTENTS всего содержимого директории после
применения append = "clear".''' применения append = "clear".'''
if self.template_type == DIR and self.target_package is not None: if self.template_type == DIR and self.target_package is not None:
self.target_package.clear_dir(self.target_path) self.target_package.clear_dir(self.target_path)
def add_to_contents(self, file_md5: Union[str, None] = None) -> None: def add_to_contents(self, file_md5: Optional[str] = None) -> NoReturn:
'''Метод для добавления целевого файла в CONTENTS.''' '''Метод для добавления целевого файла в CONTENTS.'''
if self.target_package is None: if self.target_package is None:
return return
@ -643,7 +652,7 @@ class TemplateWrapper:
elif self.template_type == FILE: elif self.template_type == FILE:
self.target_package.add_obj(source_path, file_md5=file_md5) self.target_package.add_obj(source_path, file_md5=file_md5)
def update_contents_from_list(self, changed_list: dict) -> None: def update_contents_from_list(self, changed_list: dict) -> NoReturn:
'''Метод для изменения CONTENTS по списку измененных файлов.''' '''Метод для изменения CONTENTS по списку измененных файлов.'''
if self.target_package is None: if self.target_package is None:
return return
@ -666,7 +675,7 @@ class TemplateWrapper:
self.target_package.add_dir(file_path) self.target_package.add_dir(file_path)
@classmethod @classmethod
def _set_protected(cls, chroot_path: str) -> None: def _set_protected(cls, chroot_path: str) -> NoReturn:
'''Метод для получения множества защищенных директорий.''' '''Метод для получения множества защищенных директорий.'''
cls._protected_set = set() cls._protected_set = set()
cls._unprotected_set = set() cls._unprotected_set = set()
@ -689,7 +698,7 @@ class TemplateWrapper:
cls._protected_is_set = True cls._protected_is_set = True
def save_changes(self) -> None: def save_changes(self) -> NoReturn:
'''Метод для сохранения изменений внесенных в CONTENTS.''' '''Метод для сохранения изменений внесенных в CONTENTS.'''
if self.target_package: if self.target_package:
self.target_package.remove_empty_directories() self.target_package.remove_empty_directories()
@ -704,7 +713,8 @@ class TemplateExecutor:
cl_config_archive: str = '/var/lib/calculate/config-archive', cl_config_archive: str = '/var/lib/calculate/config-archive',
cl_config_path: str = '/var/lib/calculate/config', cl_config_path: str = '/var/lib/calculate/config',
execute_archive_path: str = '/var/lib/calculate/.execute/', execute_archive_path: str = '/var/lib/calculate/.execute/',
dbpkg: bool = True): dbpkg: bool = True,
pkg_autosave: bool = False):
# TODO добавить список измененных файлов. # TODO добавить список измененных файлов.
self.datavars_module: Union[Datavars, Variables] = datavars_module self.datavars_module: Union[Datavars, Variables] = datavars_module
@ -718,6 +728,7 @@ class TemplateExecutor:
self.execute_files: OrderedDict = OrderedDict() self.execute_files: OrderedDict = OrderedDict()
self.dbpkg: bool = dbpkg self.dbpkg: bool = dbpkg
self._pkg_autosave: bool = pkg_autosave
# Словарь с измененными файлами и статусами их изменений. # Словарь с измененными файлами и статусами их изменений.
self.changed_files: dict = {} self.changed_files: dict = {}
@ -771,7 +782,7 @@ class TemplateExecutor:
parameters: ParametersContainer, template_type: int, parameters: ParametersContainer, template_type: int,
template_path: str, template_text: str = '', template_path: str, template_text: str = '',
save_changes: bool = True, save_changes: bool = True,
target_package: Union[Package, None] = None) -> dict: target_package: Optional[Package] = None) -> dict:
'''Метод для запуска выполнения шаблонов.''' '''Метод для запуска выполнения шаблонов.'''
# Словарь с данными о результате работы исполнительного метода. # Словарь с данными о результате работы исполнительного метода.
self.executor_output = {'target_path': None, self.executor_output = {'target_path': None,
@ -790,7 +801,8 @@ class TemplateExecutor:
target_package=target_package, target_package=target_package,
chroot_path=self.chroot_path, chroot_path=self.chroot_path,
config_archive_path=self.cl_config_archive_path, config_archive_path=self.cl_config_archive_path,
dbpkg=self.dbpkg) dbpkg=self.dbpkg,
pkg_autosave=self._pkg_autosave)
except TemplateTypeConflict as error: except TemplateTypeConflict as error:
raise TemplateExecutorError("type conflict: {}".format(str(error))) raise TemplateExecutorError("type conflict: {}".format(str(error)))
@ -813,8 +825,8 @@ class TemplateExecutor:
# Если был включен mirror, то после удаления файла завершаем # Если был включен mirror, то после удаления файла завершаем
# выполнение шаблона. # выполнение шаблона.
if template_object.parameters.mirror: if template_object.parameters.mirror:
if save_changes: # if save_changes:
template_object.save_changes() # template_object.save_changes()
return self.executor_output return self.executor_output
template_object.target_type = None template_object.target_type = None
@ -835,8 +847,8 @@ class TemplateExecutor:
template_object) template_object)
# Сохраняем изменения в CONTENTS внесенные согласно шаблону. # Сохраняем изменения в CONTENTS внесенные согласно шаблону.
if save_changes: # if save_changes:
template_object.save_changes() # template_object.save_changes()
# Возвращаем целевой путь, если он был изменен, или # Возвращаем целевой путь, если он был изменен, или
# None если не был изменен. # None если не был изменен.
@ -851,7 +863,7 @@ class TemplateExecutor:
return self.executor_output return self.executor_output
def save_changes(self) -> None: def save_changes(self) -> NoReturn:
'''Метод для сохранения чего-нибудь после выполнения всех шаблонов.''' '''Метод для сохранения чего-нибудь после выполнения всех шаблонов.'''
# Пока сохраняем только получившееся содержимое config-файла. # Пока сохраняем только получившееся содержимое config-файла.
self.calculate_config_file.save_changes() self.calculate_config_file.save_changes()
@ -879,7 +891,7 @@ class TemplateExecutor:
template_object.add_to_contents() template_object.add_to_contents()
def _append_remove_directory(self, template_object: TemplateWrapper def _append_remove_directory(self, template_object: TemplateWrapper
) -> None: ) -> NoReturn:
'''Метод описывающий действия для append = "remove", если шаблон -- '''Метод описывающий действия для append = "remove", если шаблон --
директория. Удаляет директорию со всем содержимым, если она есть.''' директория. Удаляет директорию со всем содержимым, если она есть.'''
if template_object.target_type is not None: if template_object.target_type is not None:
@ -901,11 +913,11 @@ class TemplateExecutor:
template_object.remove_from_contents() template_object.remove_from_contents()
def _append_skip_directory(self, def _append_skip_directory(self,
template_object: TemplateWrapper) -> None: template_object: TemplateWrapper) -> NoReturn:
pass pass
def _append_clear_directory(self, def _append_clear_directory(self,
template_object: TemplateWrapper) -> None: template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия для append = "clear", если шаблон -- '''Метод описывающий действия для append = "clear", если шаблон --
директория. Удаляет все содержимое директории, если она есть.''' директория. Удаляет все содержимое директории, если она есть.'''
if template_object.target_type is not None: if template_object.target_type is not None:
@ -935,7 +947,8 @@ class TemplateExecutor:
if self.dbpkg: if self.dbpkg:
template_object.clear_dir_contents() template_object.clear_dir_contents()
def _append_link_directory(self, template_object: TemplateWrapper) -> None: def _append_link_directory(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия для append = "link", если шаблон -- '''Метод описывающий действия для append = "link", если шаблон --
директория. Создает ссылку на директорию, если она есть.''' директория. Создает ссылку на директорию, если она есть.'''
self._link_directory(template_object.parameters.source, self._link_directory(template_object.parameters.source,
@ -959,8 +972,8 @@ class TemplateExecutor:
if self.dbpkg: if self.dbpkg:
template_object.add_to_contents() template_object.add_to_contents()
def _append_replace_directory(self, def _append_replace_directory(self, template_object: TemplateWrapper
template_object: TemplateWrapper) -> None: ) -> NoReturn:
'''Метод описывающий действия для append = "replace", если шаблон -- '''Метод описывающий действия для append = "replace", если шаблон --
директория. Очищает директорию или создает, если ее нет.''' директория. Очищает директорию или создает, если ее нет.'''
if template_object.target_type is None: if template_object.target_type is None:
@ -992,7 +1005,7 @@ class TemplateExecutor:
def _append_join_file(self, template_object: TemplateWrapper, def _append_join_file(self, template_object: TemplateWrapper,
join_before: bool = False, replace: bool = False join_before: bool = False, replace: bool = False
) -> None: ) -> NoReturn:
'''Метод описывающий действия при append = "join", если шаблон -- файл. '''Метод описывающий действия при append = "join", если шаблон -- файл.
Объединяет шаблон с целевым файлом.''' Объединяет шаблон с целевым файлом.'''
output_path = template_object.output_path output_path = template_object.output_path
@ -1206,8 +1219,8 @@ class TemplateExecutor:
self.calculate_config_file.remove_file(template_object.target_path) self.calculate_config_file.remove_file(template_object.target_path)
def _copy_from_source(self, template_object: TemplateWrapper, def _copy_from_source(self, template_object: TemplateWrapper,
chown: Union[dict, None] = None, chown: Optional[dict] = None,
chmod: Union[int, None] = None) -> str: chmod: Optional[int] = None) -> str:
'''Метод для копирования файла, указанного в source.''' '''Метод для копирования файла, указанного в source.'''
output_path = template_object.output_path output_path = template_object.output_path
source_path = template_object.input_path source_path = template_object.input_path
@ -1248,29 +1261,32 @@ class TemplateExecutor:
chown = self.file_default_parameters.get('chown', False) chown = self.file_default_parameters.get('chown', False)
return chown return chown
def _append_after_file(self, template_object: TemplateWrapper) -> None: def _append_after_file(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия при append = "after", если шаблон -- '''Метод описывающий действия при append = "after", если шаблон --
файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся
в конец файла и в конец каждой секции файла.''' в конец файла и в конец каждой секции файла.'''
self._append_join_file(template_object, join_before=False) self._append_join_file(template_object, join_before=False)
def _append_before_file(self, template_object: TemplateWrapper) -> None: def _append_before_file(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия при append = "after", если шаблон -- '''Метод описывающий действия при append = "after", если шаблон --
файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся
в начало файла и в начало каждой секции файла.''' в начало файла и в начало каждой секции файла.'''
self._append_join_file(template_object, join_before=True) self._append_join_file(template_object, join_before=True)
def _append_skip_file(self, template_object: TemplateWrapper) -> None: def _append_skip_file(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия при append = "skip". Пока никаких '''Метод описывающий действия при append = "skip". Пока никаких
действий.''' действий.'''
pass pass
def _append_replace_file(self, template_object: TemplateWrapper) -> None: def _append_replace_file(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия при append = "replace", если шаблон -- '''Метод описывающий действия при append = "replace", если шаблон --
файл. Очищает файл и затем накладывает на него шаблон.''' файл. Очищает файл и затем накладывает на него шаблон.'''
self._append_join_file(template_object, replace=True) self._append_join_file(template_object, replace=True)
def _append_remove_file(self, template_object: TemplateWrapper) -> None: def _append_remove_file(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия при append = "remove", если шаблон -- '''Метод описывающий действия при append = "remove", если шаблон --
файл. Удаляет файл.''' файл. Удаляет файл.'''
if template_object.target_type is not None: if template_object.target_type is not None:
@ -1286,7 +1302,7 @@ class TemplateExecutor:
if self.dbpkg: if self.dbpkg:
template_object.remove_from_contents() template_object.remove_from_contents()
def _append_clear_file(self, template_object: TemplateWrapper) -> None: def _append_clear_file(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия при append = "clear", если шаблон -- '''Метод описывающий действия при append = "clear", если шаблон --
файл. Очищает файл.''' файл. Очищает файл.'''
if template_object.target_type is not None: if template_object.target_type is not None:
@ -1308,7 +1324,7 @@ class TemplateExecutor:
if self.dbpkg: if self.dbpkg:
template_object.add_to_contents() template_object.add_to_contents()
def _append_link_file(self, template_object: TemplateWrapper) -> None: def _append_link_file(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия при append = "link", если шаблон -- '''Метод описывающий действия при append = "link", если шаблон --
файл. Создает ссылку на файл, указанный в параметре source.''' файл. Создает ссылку на файл, указанный в параметре source.'''
input_path = template_object.input_path input_path = template_object.input_path
@ -1390,7 +1406,7 @@ class TemplateExecutor:
return hashlib.md5(source_path.encode()).hexdigest() return hashlib.md5(source_path.encode()).hexdigest()
def _create_directory(self, template_object: TemplateWrapper, def _create_directory(self, template_object: TemplateWrapper,
path_to_create: Union[str, None] = None) -> None: path_to_create: Optional[str] = None) -> NoReturn:
'''Метод для создания директории и, при необходимости, изменения '''Метод для создания директории и, при необходимости, изменения
владельца и доступа все директорий на пути к целевой.''' владельца и доступа все директорий на пути к целевой.'''
if path_to_create is None: if path_to_create is None:
@ -1447,7 +1463,7 @@ class TemplateExecutor:
'Failed to create directory: {}, reason: {}'. 'Failed to create directory: {}, reason: {}'.
format(create_path, str(error))) format(create_path, str(error)))
def _remove_directory(self, target_path: str) -> None: def _remove_directory(self, target_path: str) -> NoReturn:
'''Метод для удаления директории.''' '''Метод для удаления директории.'''
if os.path.exists(target_path): if os.path.exists(target_path):
if os.path.isdir(target_path): if os.path.isdir(target_path):
@ -1471,7 +1487,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path, "reason: {1}").format(target_path,
error_message)) error_message))
def _clear_directory(self, target_path: str) -> None: def _clear_directory(self, target_path: str) -> NoReturn:
'''Метод для очистки содержимого целевой директории.''' '''Метод для очистки содержимого целевой директории.'''
if os.path.exists(target_path): if os.path.exists(target_path):
if os.path.isdir(target_path): if os.path.isdir(target_path):
@ -1492,7 +1508,7 @@ class TemplateExecutor:
error_message)) error_message))
def _link_directory(self, source: str, target_path: str, def _link_directory(self, source: str, target_path: str,
force: bool = False) -> None: force: bool = False) -> NoReturn:
'''Метод для создания по целевому пути ссылки на директорию '''Метод для создания по целевому пути ссылки на директорию
расположенную на пути, указанному в source.''' расположенную на пути, указанному в source.'''
try: try:
@ -1502,7 +1518,7 @@ class TemplateExecutor:
"failed to create symlink: {0} -> {1}, reason: {2}". "failed to create symlink: {0} -> {1}, reason: {2}".
format(target_path, source, str(error))) format(target_path, source, str(error)))
def _remove_file(self, target_path: str) -> None: def _remove_file(self, target_path: str) -> NoReturn:
'''Метод для удаления файлов.''' '''Метод для удаления файлов.'''
if os.path.exists(target_path): if os.path.exists(target_path):
if os.path.isfile(target_path): if os.path.isfile(target_path):
@ -1533,7 +1549,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path, "reason: {1}").format(target_path,
error_message)) error_message))
def _clear_file(self, target_path: str) -> None: def _clear_file(self, target_path: str) -> NoReturn:
'''Метод для очистки файлов.''' '''Метод для очистки файлов.'''
if os.path.exists(target_path): if os.path.exists(target_path):
if os.path.isfile(target_path): if os.path.isfile(target_path):
@ -1552,7 +1568,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path, "reason: {1}").format(target_path,
error_message)) error_message))
def _link_file(self, source: str, target_path: str) -> None: def _link_file(self, source: str, target_path: str) -> NoReturn:
'''Метод для создания по целевому пути ссылки на файл расположенный на '''Метод для создания по целевому пути ссылки на файл расположенный на
пути, указанному в source.''' пути, указанному в source.'''
try: try:
@ -1562,7 +1578,7 @@ class TemplateExecutor:
"failed to create symlink to the file: {0} -> {1}, reason: {2}". "failed to create symlink to the file: {0} -> {1}, reason: {2}".
format(target_path, source, str(error))) format(target_path, source, str(error)))
def _run_template(self, template_object: TemplateWrapper) -> None: def _run_template(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод для сохранения текста шаблонов, который должен быть исполнен '''Метод для сохранения текста шаблонов, который должен быть исполнен
интерпретатором указанным в run прямо во время обработки шаблонов.''' интерпретатором указанным в run прямо во время обработки шаблонов.'''
text_to_run = template_object.template_text text_to_run = template_object.template_text
@ -1600,7 +1616,7 @@ class TemplateExecutor:
" interpreter '{}', reason: {}"). " interpreter '{}', reason: {}").
format(interpreter, str(error))) format(interpreter, str(error)))
def _exec_template(self, template_object: TemplateWrapper) -> None: def _exec_template(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод для сохранения текста шаблонов, который должен быть исполнен '''Метод для сохранения текста шаблонов, который должен быть исполнен
интерпретатором указанным в exec после выполнения всех прочих шаблонов. интерпретатором указанным в exec после выполнения всех прочих шаблонов.
''' '''
@ -1685,7 +1701,8 @@ class TemplateExecutor:
" interpreter '{}', reason: {}"). " interpreter '{}', reason: {}").
format(interpreter, str(error))) format(interpreter, str(error)))
def _chown_directory(self, target_path: str, chown_value: dict) -> None: def _chown_directory(self, target_path: str, chown_value: dict
) -> NoReturn:
"""Метод для смены владельца директории.""" """Метод для смены владельца директории."""
try: try:
if os.path.exists(target_path): if os.path.exists(target_path):
@ -1703,7 +1720,7 @@ class TemplateExecutor:
chown_value['gid']), chown_value['gid']),
str(error))) str(error)))
def _chmod_directory(self, target_path: str, chmod_value: int) -> None: def _chmod_directory(self, target_path: str, chmod_value: int) -> NoReturn:
'''Метод для смены прав доступа к директории.''' '''Метод для смены прав доступа к директории.'''
if isinstance(chmod_value, tuple) and not chmod_value[1]: if isinstance(chmod_value, tuple) and not chmod_value[1]:
chmod_value = chmod_value[0] chmod_value = chmod_value[0]
@ -1724,7 +1741,7 @@ class TemplateExecutor:
'Can not chmod directory: {0}, reason: {1}'. 'Can not chmod directory: {0}, reason: {1}'.
format(target_path, str(error))) format(target_path, str(error)))
def _chown_file(self, target_path: str, chown_value: dict) -> None: def _chown_file(self, target_path: str, chown_value: dict) -> NoReturn:
'''Метод для смены владельца файла.''' '''Метод для смены владельца файла.'''
try: try:
if os.path.exists(target_path): if os.path.exists(target_path):
@ -1742,7 +1759,7 @@ class TemplateExecutor:
chown_value['gid']), chown_value['gid']),
str(error))) str(error)))
def _chmod_file(self, target_path: str, chmod_value: int) -> None: def _chmod_file(self, target_path: str, chmod_value: int) -> NoReturn:
'''Метод для смены прав доступа к директории.''' '''Метод для смены прав доступа к директории.'''
try: try:
if not os.path.exists(target_path): if not os.path.exists(target_path):
@ -1764,7 +1781,7 @@ class TemplateExecutor:
format(target_path, str(error))) format(target_path, str(error)))
def _use_chmod_x_mask(self, chmod: Tuple[int, int], def _use_chmod_x_mask(self, chmod: Tuple[int, int],
current_mode: Union[int, None] = None) -> int: current_mode: Optional[int] = None) -> int:
'''Метод для наложения X-маски, необходимой для получения значения '''Метод для наложения X-маски, необходимой для получения значения
chmod, c учетом возможности наличия в нем значения "X".''' chmod, c учетом возможности наличия в нем значения "X".'''
if not chmod[1]: if not chmod[1]:
@ -1862,7 +1879,7 @@ class TemplateExecutor:
else: else:
return str(gid) return str(gid)
def _check_os_error(self, error: Exception, path_to_check: str) -> True: def _check_os_error(self, error: Exception, path_to_check: str) -> bool:
'''Метод для проверки причины, по которой не удалось изменить владельца '''Метод для проверки причины, по которой не удалось изменить владельца
или права доступа файла.''' или права доступа файла.'''
if hasattr(error, 'errno') and error.errno == errno.EPERM: if hasattr(error, 'errno') and error.errno == errno.EPERM:
@ -1872,7 +1889,7 @@ class TemplateExecutor:
return hasattr(error, 'errno') and error.errno == errno.EACCES and\ return hasattr(error, 'errno') and error.errno == errno.EACCES and\
'var/calculate/remote' in path_to_check 'var/calculate/remote' in path_to_check
def _is_vfat(self, path_to_check: str): def _is_vfat(self, path_to_check: str) -> bool:
'''Метод, проверяющий является ли файловая система vfat. Нужно для того, '''Метод, проверяющий является ли файловая система vfat. Нужно для того,
чтобы знать о возможности применения chown, chmod и т.д.''' чтобы знать о возможности применения chown, chmod и т.д.'''
# Инициализируем объект для проверки примонтированных файловых систем. # Инициализируем объект для проверки примонтированных файловых систем.
@ -1892,7 +1909,7 @@ class DirectoryTree:
self.base_directory = base_directory self.base_directory = base_directory
self._tree = {} self._tree = {}
def update_tree(self, tree: dict) -> None: def update_tree(self, tree: dict) -> NoReturn:
'''Метод, инициирующий наложение заданного дерева каталогов на данный '''Метод, инициирующий наложение заданного дерева каталогов на данный
экземпляр дерева.''' экземпляр дерева.'''
self._update(self._tree, tree) self._update(self._tree, tree)
@ -1908,7 +1925,7 @@ class DirectoryTree:
original_tree[parent] = child original_tree[parent] = child
return original_tree return original_tree
def show_tree(self) -> None: def show_tree(self) -> NoReturn:
pprint(self._tree) pprint(self._tree)
def get_directory_tree(self, directory: str) -> "DirectoryTree": def get_directory_tree(self, directory: str) -> "DirectoryTree":
@ -1927,7 +1944,7 @@ class DirectoryTree:
else: else:
return None return None
def __setitem__(self, name: str, value: Union[None, dict]) -> None: def __setitem__(self, name: str, value: Union[None, dict]) -> NoReturn:
self._tree[name] = value self._tree[name] = value
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]:
@ -1948,8 +1965,9 @@ class DirectoryProcessor:
def __init__(self, action: str, def __init__(self, action: str,
datavars_module: Union[Datavars, Variables] = Variables(), datavars_module: Union[Datavars, Variables] = Variables(),
install: Union[str, PackageAtomName] = '', install: Union[str, PackageAtomName] = '',
output_module: IOModule = IOModule(), dbpkg: bool = True, output_module: IOModule = IOModule(),
namespace: NamespaceNode = None, **groups: dict): dbpkg: bool = True, pkg_autosave: bool = True,
namespace: Optional[NamespaceNode] = None, **groups: dict):
if isinstance(action, list): if isinstance(action, list):
self.action = action self.action = action
else: else:
@ -1958,6 +1976,7 @@ class DirectoryProcessor:
self.output: IOModule = output_module self.output: IOModule = output_module
self.datavars_module: Variables = datavars_module self.datavars_module: Variables = datavars_module
self._namespace: NamespaceNode = namespace self._namespace: NamespaceNode = namespace
self._pkg_autosave: bool = pkg_autosave
# Корневая директория. # Корневая директория.
self.cl_chroot_path: str self.cl_chroot_path: str
@ -2013,7 +2032,8 @@ class DirectoryProcessor:
cl_config_archive=self.cl_config_archive, cl_config_archive=self.cl_config_archive,
cl_config_path=self.cl_config_path, cl_config_path=self.cl_config_path,
execute_archive_path=self.cl_exec_dir_path, execute_archive_path=self.cl_exec_dir_path,
dbpkg=dbpkg) dbpkg=dbpkg,
pkg_autosave=self._pkg_autosave)
# Разбираем atom имена пакетов, указанных для групп пакетов. # Разбираем atom имена пакетов, указанных для групп пакетов.
if groups: if groups:
@ -2111,7 +2131,7 @@ class DirectoryProcessor:
return path_to_add return path_to_add
def _add_package_to_group(self, group_name: str, def _add_package_to_group(self, group_name: str,
package_atom: str) -> None: package_atom: str) -> NoReturn:
try: try:
groups_namespace = self.datavars_module.main.cl.groups groups_namespace = self.datavars_module.main.cl.groups
except (VariableNotFoundError, AttributeError): except (VariableNotFoundError, AttributeError):
@ -2192,7 +2212,7 @@ class DirectoryProcessor:
return -1 return -1
return -2 return -2
def _make_current_template_var(self) -> None: def _make_current_template_var(self) -> NoReturn:
var_path = ['main', 'cl'] var_path = ['main', 'cl']
namespace = self.datavars_module namespace = self.datavars_module
@ -2213,7 +2233,7 @@ class DirectoryProcessor:
else: else:
namespace['current_template'] = "" namespace['current_template'] = ""
def process_template_directories(self) -> None: def process_template_directories(self) -> NoReturn:
'''Метод для обхода шаблонов, содержащихся в каталогах из '''Метод для обхода шаблонов, содержащихся в каталогах из
main.cl_template.path.''' main.cl_template.path.'''
# Режим заполнения очередей директорий пакетов, необходимых для более # Режим заполнения очередей директорий пакетов, необходимых для более
@ -2225,7 +2245,8 @@ class DirectoryProcessor:
package = self.for_package package = self.for_package
else: else:
package = Package(self.for_package, package = Package(self.for_package,
chroot_path=self.cl_chroot_path) chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
else: else:
package = None package = None
@ -2277,14 +2298,15 @@ class DirectoryProcessor:
self._run_exec_files() self._run_exec_files()
self.template_executor.save_changes() self.template_executor.save_changes()
PackageCreator.save_all()
return self.template_executor.changed_files return self.template_executor.changed_files
def _run_template_from_base_directory( def _run_template_from_base_directory(
self, template_names: List[str], self, template_names: List[str],
base_directory: str, base_directory: str,
package: Union[Package, None] = None, package: Optional[Package] = None,
directory_tree: Union[dict, None] = None directory_tree: Optional[dict] = None
) -> None: ) -> NoReturn:
'''Метод для запуска шаблонов файлов находящихся в базовой директории. '''Метод для запуска шаблонов файлов находящихся в базовой директории.
''' '''
self.template_engine.change_directory(base_directory) self.template_engine.change_directory(base_directory)
@ -2335,7 +2357,8 @@ class DirectoryProcessor:
parameters) parameters)
if parameters.package: if parameters.package:
template_package = Package(parameters.package, template_package = Package(parameters.package,
chroot_path=self.cl_chroot_path) chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
else: else:
template_package = package template_package = package
@ -2355,7 +2378,7 @@ class DirectoryProcessor:
template_text=template_text, template_text=template_text,
package=template_package) package=template_package)
def _execute_handlers(self) -> None: def _execute_handlers(self) -> NoReturn:
'''Метод для запуска обработчиков добавленных в очередь обработчиков '''Метод для запуска обработчиков добавленных в очередь обработчиков
с помощью параметра notify.''' с помощью параметра notify.'''
self.output.set_info('Processing handlers...') self.output.set_info('Processing handlers...')
@ -2421,7 +2444,7 @@ class DirectoryProcessor:
FILE, handler_path, FILE, handler_path,
template_text=handler_text) template_text=handler_text)
def _merge_packages(self) -> None: def _merge_packages(self) -> NoReturn:
'''Метод для выполнения шаблонов относящихся к пакетам, указанным во '''Метод для выполнения шаблонов относящихся к пакетам, указанным во
всех встреченных значениях параметра merge.''' всех встреченных значениях параметра merge.'''
not_merged_packages = [] not_merged_packages = []
@ -2461,7 +2484,8 @@ class DirectoryProcessor:
continue continue
package = Package(self.for_package, package = Package(self.for_package,
chroot_path=self.cl_chroot_path) chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
for directory_name in self.packages_file_trees[self.for_package]: for directory_name in self.packages_file_trees[self.for_package]:
directory_tree = self.packages_file_trees[self.for_package].\ directory_tree = self.packages_file_trees[self.for_package].\
@ -2485,7 +2509,7 @@ class DirectoryProcessor:
else: else:
self.output.set_success('All packages are merged.') self.output.set_success('All packages are merged.')
def _run_exec_files(self) -> None: def _run_exec_files(self) -> NoReturn:
'''Метод для выполнения скриптов, полученных в результате обработки '''Метод для выполнения скриптов, полученных в результате обработки
шаблонов с параметром exec.''' шаблонов с параметром exec.'''
for exec_file_path, exec_info in\ for exec_file_path, exec_info in\
@ -2512,7 +2536,7 @@ class DirectoryProcessor:
current_target_path: str, current_target_path: str,
directory_parameters: ParametersContainer, directory_parameters: ParametersContainer,
directory_tree: Union[dict, DirectoryTree] = {}, directory_tree: Union[dict, DirectoryTree] = {},
package: Union[Package, None] = None) -> None: package: Optional[Package] = None) -> NoReturn:
'''Метод для рекурсивного обхода директорий с шаблонами, а также, при '''Метод для рекурсивного обхода директорий с шаблонами, а также, при
необходимости, заполнения деревьев директорий шаблонов, с помощью необходимости, заполнения деревьев директорий шаблонов, с помощью
которых далее выполняются шаблоны пакетов из merge.''' которых далее выполняются шаблоны пакетов из merge.'''
@ -2603,7 +2627,8 @@ class DirectoryProcessor:
if (package is None or if (package is None or
package.package_name != directory_parameters.package): package.package_name != directory_parameters.package):
package = Package(directory_parameters.package, package = Package(directory_parameters.package,
chroot_path=self.cl_chroot_path) chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
else: else:
# Если .calculate_directory отсутствует -- создаем директорию, # Если .calculate_directory отсутствует -- создаем директорию,
# используя унаследованные параметры и имя самой директории. # используя унаследованные параметры и имя самой директории.
@ -2714,7 +2739,8 @@ class DirectoryProcessor:
if (template_package is None or if (template_package is None or
package.package_name != template_parameters.package): package.package_name != template_parameters.package):
template_package = Package(template_parameters.package, template_package = Package(template_parameters.package,
chroot_path=self.cl_chroot_path) chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
if not template_parameters.run and not template_parameters.exec: if not template_parameters.run and not template_parameters.exec:
if not template_parameters.format: if not template_parameters.format:
@ -2873,7 +2899,7 @@ class DirectoryProcessor:
template_type: int, template_type: int,
template_path: str, template_path: str,
template_text: str = '', template_text: str = '',
package: Union[Package, None] = None package: Optional[Package] = None
) -> Union[bool, str]: ) -> Union[bool, str]:
'''Метод для наложения шаблонов и обработки информации полученной после '''Метод для наложения шаблонов и обработки информации полученной после
наложения.''' наложения.'''
@ -2952,7 +2978,7 @@ class DirectoryProcessor:
def _check_package_and_action(self, parameters: ParametersContainer, def _check_package_and_action(self, parameters: ParametersContainer,
template_path: str, template_path: str,
directory_tree: Union[dict, None] = None directory_tree: Optional[dict] = None
) -> bool: ) -> bool:
'''Метод для проверки параметров action и package во время обработки '''Метод для проверки параметров action и package во время обработки
каталогов с шаблонами. Если среди аргументов указано также каталогов с шаблонами. Если среди аргументов указано также

@ -7,6 +7,9 @@ from collections import OrderedDict
from .files import read_file, read_link, join_paths, FilesError from .files import read_file, read_link, join_paths, FilesError
from typing import ( from typing import (
Generator, Generator,
NoReturn,
Optional,
Dict,
Tuple, Tuple,
Union, Union,
List, List,
@ -55,6 +58,34 @@ class PackageNotFound(Exception):
pass pass
class PackageCreator(type):
_instances: Dict["PackageAtomName", "Package"] = {}
def __call__(cls, *args, **kwargs):
autosave = False
if 'autosave' in kwargs:
autosave = kwargs['autosave']
if not autosave or isinstance(args[0], str):
return super().__call__(*args, **kwargs)
if args[0] not in cls._instances:
cls._instances[args[0]] = super().__call__(*args, **kwargs)
return cls._instances[args[0]]
@classmethod
def save_all(cls) -> NoReturn:
for atom, pkg in cls._instances.items():
pkg.remove_empty_directories()
pkg.write_contents_file()
@classmethod
def clear_instances(cls) -> NoReturn:
"""Метод для очистки текущего кэша пакетный объектов.
Необходим при тестировании."""
cls._instances.clear()
class Version: class Version:
_suffix_order = {'alpha': 0, 'beta': 1, 'pre': 2, _suffix_order = {'alpha': 0, 'beta': 1, 'pre': 2,
'rc': 3, 'no': 4, 'p': 5} 'rc': 3, 'no': 4, 'p': 5}
@ -316,34 +347,19 @@ class ContentsParser(metaclass=Singleton):
@staticmethod @staticmethod
def _parse_dir(parts: List[str]) -> Tuple[str, dict]: def _parse_dir(parts: List[str]) -> Tuple[str, dict]:
try: return parts[1], {'type': 'dir'}
return parts[1], {'type': 'dir'}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
@staticmethod @staticmethod
def _parse_obj(parts: List[str]) -> Tuple[str, dict]: def _parse_obj(parts: List[str]) -> Tuple[str, dict]:
try: return parts[1], {'type': 'obj',
return parts[1], {'type': 'obj', 'md5': parts[2].strip(),
'md5': parts[2].strip(), 'mtime': parts[3].strip()}
'mtime': parts[3].strip()}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
@staticmethod @staticmethod
def _parse_sym(parts: List[str]) -> Tuple[str, dict]: def _parse_sym(parts: List[str]) -> Tuple[str, dict]:
try: return parts[1], {'type': 'sym',
return parts[1], {'type': 'sym', 'target': parts[3].strip(),
'target': parts[3].strip(), 'mtime': parts[4].strip()}
'mtime': parts[4].strip()}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
def render(self, contents_dictionary: OrderedDict) -> str: def render(self, contents_dictionary: OrderedDict) -> str:
lines = [] lines = []
@ -669,7 +685,7 @@ class PackageAtomParser:
return atom_dictionary return atom_dictionary
def _check_slot_value(self, pkg_path: str, def _check_slot_value(self, pkg_path: str,
atom_dictionary: dict) -> None: atom_dictionary: dict) -> NoReturn:
'''Метод для проверки полученного из параметра package значения slot. '''Метод для проверки полученного из параметра package значения slot.
''' '''
if atom_dictionary['slot']: if atom_dictionary['slot']:
@ -682,7 +698,7 @@ class PackageAtomParser:
errno=NOTEXIST) errno=NOTEXIST)
def _check_use_flags_value(self, pkg_path: str, def _check_use_flags_value(self, pkg_path: str,
atom_dictionary: dict) -> None: atom_dictionary: dict) -> NoReturn:
'''Метод для проверки полученных из параметра package значений '''Метод для проверки полученных из параметра package значений
use-флагов.''' use-флагов.'''
if atom_dictionary['use_flags']: if atom_dictionary['use_flags']:
@ -725,7 +741,7 @@ class PackageAtomParser:
yield path yield path
def _check_version(self, atom_dictionary: dict, pkg_version: Version def _check_version(self, atom_dictionary: dict, pkg_version: Version
) -> None: ) -> NoReturn:
condition = atom_dictionary['condition'] condition = atom_dictionary['condition']
if condition == '=': if condition == '=':
@ -831,13 +847,14 @@ class PackageAtomParser:
return atom_dict return atom_dict
class Package: class Package(metaclass=PackageCreator):
'''Класс для работы с принадлежностью файлов пакетам.''' '''Класс для работы с принадлежностью файлов пакетам.'''
re_cfg = re.compile(r'/\._cfg\d{4}_') re_cfg = re.compile(r'/\._cfg\d{4}_')
def __init__(self, package_atom: Union[str, PackageAtomName], def __init__(self, package_atom: Union[str, PackageAtomName],
pkg_path: str = '/var/db/pkg', pkg_path: str = '/var/db/pkg',
chroot_path: str = '/'): chroot_path: str = '/',
autosave: bool = False):
self.chroot_path: str = chroot_path self.chroot_path: str = chroot_path
self.contents_file_path = self._get_contents_path(package_atom) self.contents_file_path = self._get_contents_path(package_atom)
@ -855,6 +872,8 @@ class Package:
self.contents_dictionary = OrderedDict() self.contents_dictionary = OrderedDict()
self.read_contents_file() self.read_contents_file()
self.autosave: bool = autosave
def _get_contents_path(self, package_atom: Union[str, PackageAtomName] def _get_contents_path(self, package_atom: Union[str, PackageAtomName]
) -> str: ) -> str:
'''Метод для получения из ATOM-названия или готового объекта '''Метод для получения из ATOM-названия или готового объекта
@ -886,7 +905,7 @@ class Package:
else: else:
return file_name return file_name
def read_contents_file(self): def read_contents_file(self) -> bool:
'''Метод для чтения файла CONTENTS.''' '''Метод для чтения файла CONTENTS.'''
try: try:
contents_text = read_file(self.contents_file_path) contents_text = read_file(self.contents_file_path)
@ -899,18 +918,18 @@ class Package:
else: else:
return False return False
def write_contents_file(self): def write_contents_file(self) -> NoReturn:
'''Метод для записи файла CONTENTS.''' '''Метод для записи файла CONTENTS.'''
with open(self.contents_file_path, 'w') as contents_file: with open(self.contents_file_path, 'w') as contents_file:
contents_text = self.render_contents_file() contents_text = self.render_contents_file()
contents_file.write(contents_text) contents_file.write(contents_text)
def render_contents_file(self): def render_contents_file(self) -> str:
'''Метод для получения текста файла CONTENTS.''' '''Метод для получения текста файла CONTENTS.'''
return self.parser.render(self.contents_dictionary) return self.parser.render(self.contents_dictionary)
@property @property
def files(self): def files(self) -> List[str]:
'''Метод для получения списка путей файлов, имеющихся в CONTENTS-файле '''Метод для получения списка путей файлов, имеющихся в CONTENTS-файле
пакета.''' пакета.'''
return list(self.contents_dictionary.keys()) return list(self.contents_dictionary.keys())
@ -923,7 +942,7 @@ class Package:
return self.contents_dictionary[file_path]['type'] return self.contents_dictionary[file_path]['type']
return None return None
def sort_contents_dictionary(self) -> None: def sort_contents_dictionary(self) -> NoReturn:
'''Метод для сортировки словаря, полученного в результате разбора и '''Метод для сортировки словаря, полученного в результате разбора и
изменения CONTENTS-файла.''' изменения CONTENTS-файла.'''
tree = {} tree = {}
@ -960,7 +979,7 @@ class Package:
if level[part]: if level[part]:
yield from self._make_paths(part_path, level[part]) yield from self._make_paths(part_path, level[part])
def add_dir(self, file_name: str) -> None: def add_dir(self, file_name: str) -> NoReturn:
'''Метод для добавления в CONTENTS директорий.''' '''Метод для добавления в CONTENTS директорий.'''
file_name = self.remove_chroot_path(file_name) file_name = self.remove_chroot_path(file_name)
@ -971,8 +990,8 @@ class Package:
contents_item = OrderedDict({'type': 'dir'}) contents_item = OrderedDict({'type': 'dir'})
self.contents_dictionary[file_name] = contents_item self.contents_dictionary[file_name] = contents_item
def add_sym(self, file_name: str, target_path: Union[str, None] = None, def add_sym(self, file_name: str, target_path: Optional[str] = None,
mtime: Union[str, None] = None) -> None: mtime: Optional[str] = None) -> NoReturn:
'''Метод для добавления в CONTENTS символьных ссылок.''' '''Метод для добавления в CONTENTS символьных ссылок.'''
real_path = file_name real_path = file_name
@ -997,8 +1016,8 @@ class Package:
self.contents_dictionary[file_name] = contents_item self.contents_dictionary[file_name] = contents_item
def add_obj(self, file_name: str, file_md5: Union[str, None] = None, def add_obj(self, file_name: str, file_md5: Optional[str] = None,
mtime: Union[str, None] = None) -> None: mtime: Optional[str] = None) -> NoReturn:
'''Метод для добавления в CONTENTS обычных файлов как obj.''' '''Метод для добавления в CONTENTS обычных файлов как obj.'''
real_path = file_name real_path = file_name
file_name = self.remove_chroot_path(file_name) file_name = self.remove_chroot_path(file_name)
@ -1023,7 +1042,7 @@ class Package:
'mtime': mtime}) 'mtime': mtime})
self.contents_dictionary[file_name] = contents_item self.contents_dictionary[file_name] = contents_item
def add_file(self, file_name: str) -> None: def add_file(self, file_name: str) -> NoReturn:
'''Метод для добавления в CONTENTS файла любого типа.''' '''Метод для добавления в CONTENTS файла любого типа.'''
if file_name != '/': if file_name != '/':
real_path = file_name real_path = file_name
@ -1071,6 +1090,7 @@ class Package:
file_path = self.remove_chroot_path(file_path) file_path = self.remove_chroot_path(file_path)
file_path = self.remove_cfg_prefix(file_path) file_path = self.remove_cfg_prefix(file_path)
removed = OrderedDict() removed = OrderedDict()
print(f"REMOVE {file_path} FROM PACKAGE {self.package_name}")
if file_path not in self.contents_dictionary: if file_path not in self.contents_dictionary:
return return
@ -1099,7 +1119,7 @@ class Package:
self.contents_dictionary.pop(file_path)}) self.contents_dictionary.pop(file_path)})
return removed return removed
def remove_empty_directories(self): def remove_empty_directories(self) -> OrderedDict:
'''Метод для удаления из CONTENTS директорий, которые после удаления '''Метод для удаления из CONTENTS директорий, которые после удаления
тех или иных файлов больше не находятся на пути к тем файлам, которые тех или иных файлов больше не находятся на пути к тем файлам, которые
по-прежнему принадлежат пакету.''' по-прежнему принадлежат пакету.'''
@ -1176,3 +1196,8 @@ class Package:
def __repr__(self) -> str: def __repr__(self) -> str:
return '<Package: {}/{}>'.format(self.package_name.category, return '<Package: {}/{}>'.format(self.package_name.category,
self.package_name.fullname) self.package_name.fullname)
def __del__(self) -> NoReturn:
if self.autosave and os.path.exists(self.contents_file_path):
self.remove_empty_directories()
self.write_contents_file()

1339
output

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@ def main():
parser = argparse.ArgumentParser('Run templates.') parser = argparse.ArgumentParser('Run templates.')
parser.add_argument('-a', '--action', action='append', type=str, nargs='+', parser.add_argument('-a', '--action', action='append', type=str, nargs='+',
help="action parameter value.") help="action parameter value.")
parser.add_argument('-p', '--install', type=str, parser.add_argument('-i', '--install', type=str,
help="atom name of a target package.") help="atom name of a target package.")
parser.add_argument('--dbpkg', action='store_true', parser.add_argument('--dbpkg', action='store_true',
help=("flag for switching template engine's mode from" help=("flag for switching template engine's mode from"
@ -32,7 +32,7 @@ def main():
elif args.install.strip().casefold() == 'all': elif args.install.strip().casefold() == 'all':
package = None package = None
else: else:
package = args.package package = args.install
group_packages = {} group_packages = {}
if args.build is not None: if args.build is not None:

@ -2,11 +2,12 @@ import os
import pytest import pytest
import shutil import shutil
import hashlib import hashlib
from pprint import pprint
from stat import ST_MODE from stat import ST_MODE
from calculate.templates.template_processor import DirectoryProcessor,\ from calculate.templates.template_processor import DirectoryProcessor,\
TemplateWrapper TemplateWrapper
from calculate.utils.package import PackageAtomName, Version, Package,\ from calculate.utils.package import PackageAtomName, Version, Package,\
NonePackage NonePackage, PackageCreator
from calculate.utils.files import join_paths from calculate.utils.files import join_paths
from calculate.utils.io_module import IOModule from calculate.utils.io_module import IOModule
from calculate.templates.template_engine import Variables from calculate.templates.template_engine import Variables
@ -111,6 +112,7 @@ class TestDirectoryProcessor:
shutil.copytree(os.path.join(CHROOT_PATH, 'var.backup'), shutil.copytree(os.path.join(CHROOT_PATH, 'var.backup'),
os.path.join(CHROOT_PATH, 'var'), os.path.join(CHROOT_PATH, 'var'),
symlinks=True) symlinks=True)
PackageCreator.clear_instances()
def test_if_templates_consist_only_one_directory_with_a_single_calculate_directory_file_with_the_append_skip_parameter__the_directory_processor_does_nothing(self): def test_if_templates_consist_only_one_directory_with_a_single_calculate_directory_file_with_the_append_skip_parameter__the_directory_processor_does_nothing(self):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
@ -146,7 +148,8 @@ class TestDirectoryProcessor:
+ ";\n};\n")) + ";\n};\n"))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_0'))
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/file_0' in test_package assert '/etc/file_0' in test_package
with open(join_paths(CHROOT_PATH, '/etc/file_0'), 'r') as output_file: with open(join_paths(CHROOT_PATH, '/etc/file_0'), 'r') as output_file:
output_file_text = output_file.read() output_file_text = output_file.read()
@ -208,7 +211,8 @@ class TestDirectoryProcessor:
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2/file_0'))
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/dir_2' in test_package assert '/etc/dir_2' in test_package
assert '/etc/dir_2/file_0' in test_package assert '/etc/dir_2/file_0' in test_package
with open(join_paths(CHROOT_PATH, with open(join_paths(CHROOT_PATH,
@ -256,7 +260,8 @@ class TestDirectoryProcessor:
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4/file_0'))
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/dir_4' in test_package assert '/etc/dir_4' in test_package
assert '/etc/dir_4/file_0' in test_package assert '/etc/dir_4/file_0' in test_package
with open(join_paths(CHROOT_PATH, with open(join_paths(CHROOT_PATH,
@ -269,7 +274,8 @@ class TestDirectoryProcessor:
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_5/dir_6')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_5/dir_6'))
assert os.path.exists(join_paths(CHROOT_PATH, assert os.path.exists(join_paths(CHROOT_PATH,
'/etc/dir_5/dir_6/file_0')) '/etc/dir_5/dir_6/file_0'))
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/dir_5' in test_package assert '/etc/dir_5' in test_package
assert '/etc/dir_5/dir_6' in test_package assert '/etc/dir_5/dir_6' in test_package
assert '/etc/dir_5/dir_6/file_0' in test_package assert '/etc/dir_5/dir_6/file_0' in test_package
@ -309,7 +315,8 @@ class TestDirectoryProcessor:
+ datavars.ns.variable_2 + datavars.ns.variable_2
+ ";\n};\n")) + ";\n};\n"))
test_package = Package(new_package_name, chroot_path=CHROOT_PATH) test_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_1')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_1'))
with open(join_paths(CHROOT_PATH, '/etc/file_1'), 'r') as output_file: with open(join_paths(CHROOT_PATH, '/etc/file_1'), 'r') as output_file:
@ -350,7 +357,8 @@ class TestDirectoryProcessor:
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6/file_0'))
test_package = Package(new_package_name, chroot_path=CHROOT_PATH) test_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/dir_6' in test_package assert '/etc/dir_6' in test_package
assert '/etc/dir_6/file_0' in test_package assert '/etc/dir_6/file_0' in test_package
with open(join_paths(CHROOT_PATH, with open(join_paths(CHROOT_PATH,
@ -391,7 +399,8 @@ class TestDirectoryProcessor:
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_2')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_2'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_2')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_2'))
test_package = Package(new_package_name, chroot_path=CHROOT_PATH) test_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/file_2' in test_package assert '/etc/file_2' in test_package
with open(join_paths(CHROOT_PATH, with open(join_paths(CHROOT_PATH,
'/etc/._cfg0000_file_2'), 'r') as output_file: '/etc/._cfg0000_file_2'), 'r') as output_file:
@ -431,7 +440,8 @@ class TestDirectoryProcessor:
assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_3')) assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_3'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_3')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_3'))
test_package = Package(new_package_name, chroot_path=CHROOT_PATH) test_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/file_3' in test_package assert '/etc/file_3' in test_package
with open(join_paths(CHROOT_PATH, with open(join_paths(CHROOT_PATH,
'/etc/._cfg0000_file_3'), 'r') as output_file: '/etc/._cfg0000_file_3'), 'r') as output_file:
@ -501,7 +511,8 @@ class TestDirectoryProcessor:
assert not os.path.exists(join_paths(CHROOT_PATH, assert not os.path.exists(join_paths(CHROOT_PATH,
'/etc/dir_7/._cfg0001_file_0')) '/etc/dir_7/._cfg0001_file_0'))
test_package = Package(new_package_name, chroot_path=CHROOT_PATH) test_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert '/etc/file_4' in test_package assert '/etc/file_4' in test_package
assert '/etc/file_5' in test_package assert '/etc/file_5' in test_package
assert '/etc/dir_7/file_0' in test_package assert '/etc/dir_7/file_0' in test_package
@ -597,8 +608,10 @@ class TestDirectoryProcessor:
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9/file_0'))
@ -652,7 +665,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install', directory_processor = DirectoryProcessor('install',
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
new_package = Package(new_package_name, chroot_path=CHROOT_PATH) new_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, assert os.path.exists(join_paths(CHROOT_PATH,
'/etc/dir_12')) '/etc/dir_12'))
@ -672,8 +686,10 @@ class TestDirectoryProcessor:
install=other_package_name) install=other_package_name)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13/file_0'))
@ -698,8 +714,10 @@ class TestDirectoryProcessor:
install=other_package_name) install=other_package_name)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15/file_0'))
@ -726,7 +744,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install', directory_processor = DirectoryProcessor('install',
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
# Для разнообразия один из шаблонов удаляет файл, а не создает. # Для разнообразия один из шаблонов удаляет файл, а не создает.
assert not os.path.exists(join_paths(CHROOT_PATH, assert not os.path.exists(join_paths(CHROOT_PATH,
@ -753,7 +772,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install', directory_processor = DirectoryProcessor('install',
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
# Для разнообразия один из шаблонов удаляет файл, а не создает. # Для разнообразия один из шаблонов удаляет файл, а не создает.
# Но в данном случае он ничего не сделает. # Но в данном случае он ничего не сделает.
@ -786,9 +806,12 @@ class TestDirectoryProcessor:
install=other_package_name) install=other_package_name)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH) other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21/file_0'))
@ -829,9 +852,12 @@ class TestDirectoryProcessor:
install='test-category/other-package') install='test-category/other-package')
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH) other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24/file_0'))
@ -872,8 +898,10 @@ class TestDirectoryProcessor:
install='test-category/other-package') install='test-category/other-package')
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
other_package = Package(other_package_name, chroot_path=CHROOT_PATH) autosave=True)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)
print('DIRECTORY TREE:') print('DIRECTORY TREE:')
for key in directory_processor.packages_file_trees.keys(): for key in directory_processor.packages_file_trees.keys():
@ -914,7 +942,8 @@ class TestDirectoryProcessor:
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_10')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_10'))
assert '/etc/file_10' in test_package assert '/etc/file_10' in test_package
@ -929,7 +958,8 @@ class TestDirectoryProcessor:
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_11')) assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_11'))
assert '/etc/file_11' not in test_package assert '/etc/file_11' not in test_package
@ -943,7 +973,8 @@ class TestDirectoryProcessor:
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29/file_0'))
@ -964,7 +995,8 @@ class TestDirectoryProcessor:
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert not os.path.exists(join_paths(CHROOT_PATH, assert not os.path.exists(join_paths(CHROOT_PATH,
'/etc/dir_30')) '/etc/dir_30'))
@ -1064,7 +1096,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor(['install', 'update'], directory_processor = DirectoryProcessor(['install', 'update'],
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_32')) 'etc/dir_32'))
@ -1094,7 +1127,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor(['install', 'update'], directory_processor = DirectoryProcessor(['install', 'update'],
datavars_module=datavars) datavars_module=datavars)
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, assert os.path.exists(join_paths(CHROOT_PATH,
'etc/dir_35')) 'etc/dir_35'))
@ -1118,7 +1152,8 @@ class TestDirectoryProcessor:
install='test-category/test-package' install='test-category/test-package'
) )
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH) test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
# Тестируем handler_0 -- это просто обработчик-скрипт. # Тестируем handler_0 -- это просто обработчик-скрипт.
assert os.path.exists(join_paths(CHROOT_PATH, assert os.path.exists(join_paths(CHROOT_PATH,
@ -1324,8 +1359,10 @@ class TestDirectoryProcessor:
+ ";\n};\n")) + ";\n};\n"))
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH) test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH,
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH) autosave=True)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57/file_0'))
@ -1344,11 +1381,30 @@ class TestDirectoryProcessor:
'install', 'install',
datavars_module=datavars) datavars_module=datavars)
output_text = "options {\n parameter-0 yes;\n};\n" # output_text = "options {\n parameter-0 yes;\n};\n"
header = ('#' + '-' * 79 + '\n' +
'# Modified by Calculate Utilities 4.0\n' +
'# Processed template files:\n' +
'# ' + '{0}' + '\n' +
'#' + '-' * 79 + '\n')
header = header.format('\n# '.
join([join_paths(
CHROOT_PATH,
'templates_40/install/dir_58/file_0')]))
output_text = '{0}{1}'.format(header,
("options {\n parameter-0 yes;"
+ "\n parameter-1 "
+ datavars.ns.variable_1
+ ";\n parameter-2 "
+ datavars.ns.variable_2
+ ";\n};\n"))
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH) test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH,
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH) autosave=True)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58/file_0'))
@ -1357,11 +1413,9 @@ class TestDirectoryProcessor:
output = output.read() output = output.read()
assert output_text == output assert output_text == output
assert '/etc/dir_58' not in test_package_1 assert '/etc/dir_58' in test_package_1
assert '/etc/dir_58/file_0' not in test_package_1 assert '/etc/dir_58/file_0' in test_package_1
assert '/etc/dir_58/file_0' not in test_package_0
assert '/etc/dir_58' in test_package_0
assert '/etc/dir_58/file_0' in test_package_0
def test_solving_collisions_for_the_same_packages_from_different_slots_but_slot_was_set_in_the_for_package_parameter(self): def test_solving_collisions_for_the_same_packages_from_different_slots_but_slot_was_set_in_the_for_package_parameter(self):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
@ -1372,11 +1426,30 @@ class TestDirectoryProcessor:
install='test-category/test-package:1' install='test-category/test-package:1'
) )
output_text = "options {\n parameter-0 yes;\n};\n" # output_text = "options {\n parameter-0 yes;\n};\n"
header = ('#' + '-' * 79 + '\n' +
'# Modified by Calculate Utilities 4.0\n' +
'# Processed template files:\n' +
'# ' + '{0}' + '\n' +
'#' + '-' * 79 + '\n')
header = header.format('\n# '.
join([join_paths(
CHROOT_PATH,
'templates_41/install/dir_59/file_0')]))
output_text = '{0}{1}'.format(header,
("options {\n parameter-0 yes;"
+ "\n parameter-1 "
+ datavars.ns.variable_1
+ ";\n parameter-2 "
+ datavars.ns.variable_2
+ ";\n};\n"))
directory_processor.process_template_directories() directory_processor.process_template_directories()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH) test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH,
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH) autosave=True)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59'))
assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59/file_0')) assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59/file_0'))
@ -1385,11 +1458,9 @@ class TestDirectoryProcessor:
output = output.read() output = output.read()
assert output_text == output assert output_text == output
assert '/etc/dir_59' not in test_package_1 assert '/etc/dir_59' in test_package_1
assert '/etc/dir_59/file_0' not in test_package_1 assert '/etc/dir_59/file_0' in test_package_1
assert '/etc/dir_59/file_0' not in test_package_0
assert '/etc/dir_59' in test_package_0
assert '/etc/dir_59/file_0' in test_package_0
def test_copy_file_using_source(self): def test_copy_file_using_source(self):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH, datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,

@ -1,11 +1,10 @@
dir /etc dir /etc
dir /etc/dir
dir /etc/terminfo dir /etc/terminfo
obj /etc/terminfo/info.json 7a374d90a202b969ee338ac4334fb14b 1591354184 obj /etc/terminfo/info.json 7a374d90a202b969ee338ac4334fb14b 1591354184
obj /etc/dir/deleted.json 11e3a79fe51cce828d973dba8702adaa 1591356795 dir /etc/dir
dir /etc/dir/subdir dir /etc/dir/subdir
obj /etc/dir/subdir/config.json 506649cf099878124deda2c2452c3693 1591605050 obj /etc/dir/subdir/file 62c2ba07fc6dc7c9b5b2cad1d03ef52e 1602168237
obj /etc/dir/subdir/file 84bcceb2c8e6de79849ea5f3304f2411 1591343236 obj /etc/dir/deleted.json 0b87fea7f5b65cac5012baa2bf647e72 1602168237
obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1602168237 obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1602168237
dir /etc/dir/dir_1 dir /etc/dir/dir_1
obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1602168237 obj /etc/dir/dir_1/config.json 506649cf099878124deda2c2452c3693 1602168237

Loading…
Cancel
Save