Browse Source

Changed order of saving changed CONTENTS files.

master
parent
commit
9d26db03f0
7 changed files with 1651 additions and 186 deletions
  1. +10
    -5
      calculate/templates/template_engine.py
  2. +110
    -84
      calculate/templates/template_processor.py
  3. +64
    -39
      calculate/utils/package.py
  4. +1339
    -0
      output
  5. +2
    -2
      run_templates.py
  6. +123
    -52
      tests/templates/test_directory_processor.py
  7. +3
    -4
      tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS

+ 10
- 5
calculate/templates/template_engine.py View File

@@ -1580,11 +1580,14 @@ class CalculateExtension(Extension):


class TemplateEngine:
def __init__(self, directory_path=None,
datavars_module=Variables(),
appends_set=set(),
chroot_path='/',
for_package=None):
def __init__(self, directory_path: Union[str, None] = None,
datavars_module: Union[Datavars,
NamespaceNode,
Variables] = Variables(),
appends_set: set = set(),
chroot_path: str = '/',
for_package: Union[Package, None] = None,
pkg_autosave: bool = False):
ParametersProcessor._inspect_formats_package()

CalculateExtension._parameters_set =\
@@ -1595,6 +1598,8 @@ class TemplateEngine:
self._datavars_module = datavars_module
self._template_text = ''

self._pkg_autosave: bool = pkg_autosave

self._parameters_object = ParametersContainer()
self.parameters_processor = ParametersProcessor(
chroot_path=chroot_path,


+ 110
- 84
calculate/templates/template_processor.py View File

@@ -3,6 +3,7 @@
from pprint import pprint
from ..utils.package import (
PackageAtomParser,
PackageCreator,
Package,
PackageNotFound,
PackageAtomName,
@@ -42,6 +43,8 @@ from typing import (
List,
Tuple,
Iterator,
NoReturn,
Optional,
Callable
)
from calculate.variables.loader import Datavars
@@ -120,21 +123,21 @@ class CalculateConfigFile:
self._unsaved_changes = False
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 соответствия файла некоторой
контрольной сумме.'''
file_path = self._remove_chroot(file_path)
self._config_dictionary[file_path] = file_md5
self._unsaved_changes = True

def remove_file(self, file_path: str) -> None:
def remove_file(self, file_path: str) -> NoReturn:
'''Метод для удаления файла из config.'''
file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary:
self._config_dictionary.pop(file_path)
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 и некоторой заданной.'''
file_path = self._remove_chroot(file_path)
if file_path in self._config_dictionary:
@@ -142,7 +145,7 @@ class CalculateConfigFile:
else:
return False

def save_changes(self) -> None:
def save_changes(self) -> NoReturn:
'''Метод для записи изменений, внессенных в файл config.'''
if not self._unsaved_changes:
return
@@ -190,10 +193,11 @@ class TemplateWrapper:
template_type: int,
template_path: str,
template_text: str = '',
target_package: Union[Package, None] = None,
target_package: Optional[Package] = None,
chroot_path: str = '/',
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.template_path: str = template_path
self.chroot_path: str = chroot_path
@@ -203,6 +207,8 @@ class TemplateWrapper:
self.package_atom_parser: PackageAtomParser = PackageAtomParser(
chroot_path=self.chroot_path)

self._pkg_autosave: bool = pkg_autosave

# Вспомогательный флаг, включается, если по целевому пути лежит файл,
# для которого не определился никакой пакет.
self.target_without_package: bool = False
@@ -292,7 +298,8 @@ class TemplateWrapper:
self.target_package.package_name !=
self.target_package_name):
self.target_package = Package(self.parameters.package,
chroot_path=self.chroot_path)
chroot_path=self.chroot_path,
autosave=self._pkg_autosave)
return

self._check_type_conflicts()
@@ -306,7 +313,7 @@ class TemplateWrapper:
if self.parameters.append and self.parameters.append == "replace":
self.remove_original = True

def _check_type_conflicts(self) -> None:
def _check_type_conflicts(self) -> NoReturn:
'''Метод для проверки конфликтов типов.'''
if self.parameters.append == 'link':
if self.parameters.force:
@@ -380,7 +387,7 @@ class TemplateWrapper:
raise TemplateTypeConflict("the target file is a directory"
" while the template is a file")

def _check_package_collision(self) -> None:
def _check_package_collision(self) -> NoReturn:
'''Метод для проверки на предмет коллизии, то есть конфликта пакета
шаблона и целевого файла.'''
if self.parameters.package:
@@ -437,12 +444,14 @@ class TemplateWrapper:
if (self.target_package is None or
self.target_package_name != self.target_package.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,
chroot_path=self.chroot_path)
chroot_path=self.chroot_path,
autosave=self._pkg_autosave)
removed = self.source_package.remove_file(self.target_path)

for file_path, file_info in removed.items():
if file_info['type'] == 'dir':
self.target_package.add_dir(file_path)
@@ -455,14 +464,14 @@ class TemplateWrapper:
file_path,
target_path=file_info['target'],
mtime=file_info['mtime'])
self.source_package.write_contents_file()
else:
self.target_package_name = parameter_package

if (self.target_package is None or
self.target_package_name != self.target_package.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,
rpackage: PackageAtomName
@@ -479,7 +488,7 @@ class TemplateWrapper:
else:
return rpackage

def _check_user_changes(self) -> None:
def _check_user_changes(self) -> NoReturn:
'''Метод для проверки наличия пользовательских изменений в
конфигурационных файлах.'''
# Эта проверка только для файлов.
@@ -604,7 +613,7 @@ class TemplateWrapper:

return new_cfg_path

def remove_from_contents(self) -> None:
def remove_from_contents(self) -> NoReturn:
'''Метод для удаления целевого файла из CONTENTS.'''
if self.target_package is None:
return
@@ -614,13 +623,13 @@ class TemplateWrapper:
elif self.template_type == FILE:
self.target_package.remove_obj(self.target_path)

def clear_dir_contents(self) -> None:
def clear_dir_contents(self) -> NoReturn:
'''Метод для удаления из CONTENTS всего содержимого директории после
применения append = "clear".'''
if self.template_type == DIR and self.target_package is not None:
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.'''
if self.target_package is None:
return
@@ -643,7 +652,7 @@ class TemplateWrapper:
elif self.template_type == FILE:
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 по списку измененных файлов.'''
if self.target_package is None:
return
@@ -666,7 +675,7 @@ class TemplateWrapper:
self.target_package.add_dir(file_path)

@classmethod
def _set_protected(cls, chroot_path: str) -> None:
def _set_protected(cls, chroot_path: str) -> NoReturn:
'''Метод для получения множества защищенных директорий.'''
cls._protected_set = set()
cls._unprotected_set = set()
@@ -689,7 +698,7 @@ class TemplateWrapper:

cls._protected_is_set = True

def save_changes(self) -> None:
def save_changes(self) -> NoReturn:
'''Метод для сохранения изменений внесенных в CONTENTS.'''
if self.target_package:
self.target_package.remove_empty_directories()
@@ -704,7 +713,8 @@ class TemplateExecutor:
cl_config_archive: str = '/var/lib/calculate/config-archive',
cl_config_path: str = '/var/lib/calculate/config',
execute_archive_path: str = '/var/lib/calculate/.execute/',
dbpkg: bool = True):
dbpkg: bool = True,
pkg_autosave: bool = False):
# TODO добавить список измененных файлов.
self.datavars_module: Union[Datavars, Variables] = datavars_module

@@ -718,6 +728,7 @@ class TemplateExecutor:
self.execute_files: OrderedDict = OrderedDict()

self.dbpkg: bool = dbpkg
self._pkg_autosave: bool = pkg_autosave

# Словарь с измененными файлами и статусами их изменений.
self.changed_files: dict = {}
@@ -771,7 +782,7 @@ class TemplateExecutor:
parameters: ParametersContainer, template_type: int,
template_path: str, template_text: str = '',
save_changes: bool = True,
target_package: Union[Package, None] = None) -> dict:
target_package: Optional[Package] = None) -> dict:
'''Метод для запуска выполнения шаблонов.'''
# Словарь с данными о результате работы исполнительного метода.
self.executor_output = {'target_path': None,
@@ -790,7 +801,8 @@ class TemplateExecutor:
target_package=target_package,
chroot_path=self.chroot_path,
config_archive_path=self.cl_config_archive_path,
dbpkg=self.dbpkg)
dbpkg=self.dbpkg,
pkg_autosave=self._pkg_autosave)

except TemplateTypeConflict as error:
raise TemplateExecutorError("type conflict: {}".format(str(error)))
@@ -813,8 +825,8 @@ class TemplateExecutor:
# Если был включен mirror, то после удаления файла завершаем
# выполнение шаблона.
if template_object.parameters.mirror:
if save_changes:
template_object.save_changes()
# if save_changes:
# template_object.save_changes()
return self.executor_output

template_object.target_type = None
@@ -835,8 +847,8 @@ class TemplateExecutor:
template_object)

# Сохраняем изменения в CONTENTS внесенные согласно шаблону.
if save_changes:
template_object.save_changes()
# if save_changes:
# template_object.save_changes()

# Возвращаем целевой путь, если он был изменен, или
# None если не был изменен.
@@ -851,7 +863,7 @@ class TemplateExecutor:

return self.executor_output

def save_changes(self) -> None:
def save_changes(self) -> NoReturn:
'''Метод для сохранения чего-нибудь после выполнения всех шаблонов.'''
# Пока сохраняем только получившееся содержимое config-файла.
self.calculate_config_file.save_changes()
@@ -879,7 +891,7 @@ class TemplateExecutor:
template_object.add_to_contents()

def _append_remove_directory(self, template_object: TemplateWrapper
) -> None:
) -> NoReturn:
'''Метод описывающий действия для append = "remove", если шаблон --
директория. Удаляет директорию со всем содержимым, если она есть.'''
if template_object.target_type is not None:
@@ -901,11 +913,11 @@ class TemplateExecutor:
template_object.remove_from_contents()

def _append_skip_directory(self,
template_object: TemplateWrapper) -> None:
template_object: TemplateWrapper) -> NoReturn:
pass

def _append_clear_directory(self,
template_object: TemplateWrapper) -> None:
template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия для append = "clear", если шаблон --
директория. Удаляет все содержимое директории, если она есть.'''
if template_object.target_type is not None:
@@ -935,7 +947,8 @@ class TemplateExecutor:
if self.dbpkg:
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", если шаблон --
директория. Создает ссылку на директорию, если она есть.'''
self._link_directory(template_object.parameters.source,
@@ -959,8 +972,8 @@ class TemplateExecutor:
if self.dbpkg:
template_object.add_to_contents()

def _append_replace_directory(self,
template_object: TemplateWrapper) -> None:
def _append_replace_directory(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия для append = "replace", если шаблон --
директория. Очищает директорию или создает, если ее нет.'''
if template_object.target_type is None:
@@ -992,7 +1005,7 @@ class TemplateExecutor:

def _append_join_file(self, template_object: TemplateWrapper,
join_before: bool = False, replace: bool = False
) -> None:
) -> NoReturn:
'''Метод описывающий действия при append = "join", если шаблон -- файл.
Объединяет шаблон с целевым файлом.'''
output_path = template_object.output_path
@@ -1206,8 +1219,8 @@ class TemplateExecutor:
self.calculate_config_file.remove_file(template_object.target_path)

def _copy_from_source(self, template_object: TemplateWrapper,
chown: Union[dict, None] = None,
chmod: Union[int, None] = None) -> str:
chown: Optional[dict] = None,
chmod: Optional[int] = None) -> str:
'''Метод для копирования файла, указанного в source.'''
output_path = template_object.output_path
source_path = template_object.input_path
@@ -1248,29 +1261,32 @@ class TemplateExecutor:
chown = self.file_default_parameters.get('chown', False)
return chown

def _append_after_file(self, template_object: TemplateWrapper) -> None:
def _append_after_file(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод описывающий действия при append = "after", если шаблон --
файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся
в конец файла и в конец каждой секции файла.'''
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", если шаблон --
файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся
в начало файла и в начало каждой секции файла.'''
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". Пока никаких
действий.'''
pass

def _append_replace_file(self, template_object: TemplateWrapper) -> None:
def _append_replace_file(self, template_object: TemplateWrapper
) -> NoReturn:
'''Метод описывающий действия при append = "replace", если шаблон --
файл. Очищает файл и затем накладывает на него шаблон.'''
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", если шаблон --
файл. Удаляет файл.'''
if template_object.target_type is not None:
@@ -1286,7 +1302,7 @@ class TemplateExecutor:
if self.dbpkg:
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", если шаблон --
файл. Очищает файл.'''
if template_object.target_type is not None:
@@ -1308,7 +1324,7 @@ class TemplateExecutor:
if self.dbpkg:
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", если шаблон --
файл. Создает ссылку на файл, указанный в параметре source.'''
input_path = template_object.input_path
@@ -1390,7 +1406,7 @@ class TemplateExecutor:
return hashlib.md5(source_path.encode()).hexdigest()

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:
@@ -1447,7 +1463,7 @@ class TemplateExecutor:
'Failed to create directory: {}, reason: {}'.
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.isdir(target_path):
@@ -1471,7 +1487,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path,
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.isdir(target_path):
@@ -1492,7 +1508,7 @@ class TemplateExecutor:
error_message))

def _link_directory(self, source: str, target_path: str,
force: bool = False) -> None:
force: bool = False) -> NoReturn:
'''Метод для создания по целевому пути ссылки на директорию
расположенную на пути, указанному в source.'''
try:
@@ -1502,7 +1518,7 @@ class TemplateExecutor:
"failed to create symlink: {0} -> {1}, reason: {2}".
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.isfile(target_path):
@@ -1533,7 +1549,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path,
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.isfile(target_path):
@@ -1552,7 +1568,7 @@ class TemplateExecutor:
"reason: {1}").format(target_path,
error_message))

def _link_file(self, source: str, target_path: str) -> None:
def _link_file(self, source: str, target_path: str) -> NoReturn:
'''Метод для создания по целевому пути ссылки на файл расположенный на
пути, указанному в source.'''
try:
@@ -1562,7 +1578,7 @@ class TemplateExecutor:
"failed to create symlink to the file: {0} -> {1}, reason: {2}".
format(target_path, source, str(error)))

def _run_template(self, template_object: TemplateWrapper) -> None:
def _run_template(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод для сохранения текста шаблонов, который должен быть исполнен
интерпретатором указанным в run прямо во время обработки шаблонов.'''
text_to_run = template_object.template_text
@@ -1600,7 +1616,7 @@ class TemplateExecutor:
" interpreter '{}', reason: {}").
format(interpreter, str(error)))

def _exec_template(self, template_object: TemplateWrapper) -> None:
def _exec_template(self, template_object: TemplateWrapper) -> NoReturn:
'''Метод для сохранения текста шаблонов, который должен быть исполнен
интерпретатором указанным в exec после выполнения всех прочих шаблонов.
'''
@@ -1685,7 +1701,8 @@ class TemplateExecutor:
" interpreter '{}', reason: {}").
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:
if os.path.exists(target_path):
@@ -1703,7 +1720,7 @@ class TemplateExecutor:
chown_value['gid']),
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]:
chmod_value = chmod_value[0]
@@ -1724,7 +1741,7 @@ class TemplateExecutor:
'Can not chmod directory: {0}, reason: {1}'.
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:
if os.path.exists(target_path):
@@ -1742,7 +1759,7 @@ class TemplateExecutor:
chown_value['gid']),
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:
if not os.path.exists(target_path):
@@ -1764,7 +1781,7 @@ class TemplateExecutor:
format(target_path, str(error)))

def _use_chmod_x_mask(self, chmod: Tuple[int, int],
current_mode: Union[int, None] = None) -> int:
current_mode: Optional[int] = None) -> int:
'''Метод для наложения X-маски, необходимой для получения значения
chmod, c учетом возможности наличия в нем значения "X".'''
if not chmod[1]:
@@ -1862,7 +1879,7 @@ class TemplateExecutor:
else:
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:
@@ -1872,7 +1889,7 @@ class TemplateExecutor:
return hasattr(error, 'errno') and error.errno == errno.EACCES and\
'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. Нужно для того,
чтобы знать о возможности применения chown, chmod и т.д.'''
# Инициализируем объект для проверки примонтированных файловых систем.
@@ -1892,7 +1909,7 @@ class DirectoryTree:
self.base_directory = base_directory
self._tree = {}

def update_tree(self, tree: dict) -> None:
def update_tree(self, tree: dict) -> NoReturn:
'''Метод, инициирующий наложение заданного дерева каталогов на данный
экземпляр дерева.'''
self._update(self._tree, tree)
@@ -1908,7 +1925,7 @@ class DirectoryTree:
original_tree[parent] = child
return original_tree

def show_tree(self) -> None:
def show_tree(self) -> NoReturn:
pprint(self._tree)

def get_directory_tree(self, directory: str) -> "DirectoryTree":
@@ -1927,7 +1944,7 @@ class DirectoryTree:
else:
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

def __iter__(self) -> Iterator[str]:
@@ -1948,8 +1965,9 @@ class DirectoryProcessor:
def __init__(self, action: str,
datavars_module: Union[Datavars, Variables] = Variables(),
install: Union[str, PackageAtomName] = '',
output_module: IOModule = IOModule(), dbpkg: bool = True,
namespace: NamespaceNode = None, **groups: dict):
output_module: IOModule = IOModule(),
dbpkg: bool = True, pkg_autosave: bool = True,
namespace: Optional[NamespaceNode] = None, **groups: dict):
if isinstance(action, list):
self.action = action
else:
@@ -1958,6 +1976,7 @@ class DirectoryProcessor:
self.output: IOModule = output_module
self.datavars_module: Variables = datavars_module
self._namespace: NamespaceNode = namespace
self._pkg_autosave: bool = pkg_autosave

# Корневая директория.
self.cl_chroot_path: str
@@ -2013,7 +2032,8 @@ class DirectoryProcessor:
cl_config_archive=self.cl_config_archive,
cl_config_path=self.cl_config_path,
execute_archive_path=self.cl_exec_dir_path,
dbpkg=dbpkg)
dbpkg=dbpkg,
pkg_autosave=self._pkg_autosave)

# Разбираем atom имена пакетов, указанных для групп пакетов.
if groups:
@@ -2111,7 +2131,7 @@ class DirectoryProcessor:
return path_to_add

def _add_package_to_group(self, group_name: str,
package_atom: str) -> None:
package_atom: str) -> NoReturn:
try:
groups_namespace = self.datavars_module.main.cl.groups
except (VariableNotFoundError, AttributeError):
@@ -2192,7 +2212,7 @@ class DirectoryProcessor:
return -1
return -2

def _make_current_template_var(self) -> None:
def _make_current_template_var(self) -> NoReturn:
var_path = ['main', 'cl']
namespace = self.datavars_module

@@ -2213,7 +2233,7 @@ class DirectoryProcessor:
else:
namespace['current_template'] = ""

def process_template_directories(self) -> None:
def process_template_directories(self) -> NoReturn:
'''Метод для обхода шаблонов, содержащихся в каталогах из
main.cl_template.path.'''
# Режим заполнения очередей директорий пакетов, необходимых для более
@@ -2225,7 +2245,8 @@ class DirectoryProcessor:
package = self.for_package
else:
package = Package(self.for_package,
chroot_path=self.cl_chroot_path)
chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
else:
package = None

@@ -2277,14 +2298,15 @@ class DirectoryProcessor:
self._run_exec_files()

self.template_executor.save_changes()
PackageCreator.save_all()
return self.template_executor.changed_files

def _run_template_from_base_directory(
self, template_names: List[str],
base_directory: str,
package: Union[Package, None] = None,
directory_tree: Union[dict, None] = None
) -> None:
package: Optional[Package] = None,
directory_tree: Optional[dict] = None
) -> NoReturn:
'''Метод для запуска шаблонов файлов находящихся в базовой директории.
'''
self.template_engine.change_directory(base_directory)
@@ -2335,7 +2357,8 @@ class DirectoryProcessor:
parameters)
if parameters.package:
template_package = Package(parameters.package,
chroot_path=self.cl_chroot_path)
chroot_path=self.cl_chroot_path,
autosave=self._pkg_autosave)
else:
template_package = package

@@ -2355,7 +2378,7 @@ class DirectoryProcessor:
template_text=template_text,
package=template_package)

def _execute_handlers(self) -> None:
def _execute_handlers(self) -> NoReturn:
'''Метод для запуска обработчиков добавленных в очередь обработчиков
с помощью параметра notify.'''
self.output.set_info('Processing handlers...')
@@ -2421,7 +2444,7 @@ class DirectoryProcessor:
FILE, handler_path,
template_text=handler_text)

def _merge_packages(self) -> None:
def _merge_packages(self) -> NoReturn:
'''Метод для выполнения шаблонов относящихся к пакетам, указанным во
всех встреченных значениях параметра merge.'''
not_merged_packages = []
@@ -2461,7 +2484,8 @@ class DirectoryProcessor:
continue

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]:
directory_tree = self.packages_file_trees[self.for_package].\
@@ -2485,7 +2509,7 @@ class DirectoryProcessor:
else:
self.output.set_success('All packages are merged.')

def _run_exec_files(self) -> None:
def _run_exec_files(self) -> NoReturn:
'''Метод для выполнения скриптов, полученных в результате обработки
шаблонов с параметром exec.'''
for exec_file_path, exec_info in\
@@ -2512,7 +2536,7 @@ class DirectoryProcessor:
current_target_path: str,
directory_parameters: ParametersContainer,
directory_tree: Union[dict, DirectoryTree] = {},
package: Union[Package, None] = None) -> None:
package: Optional[Package] = None) -> NoReturn:
'''Метод для рекурсивного обхода директорий с шаблонами, а также, при
необходимости, заполнения деревьев директорий шаблонов, с помощью
которых далее выполняются шаблоны пакетов из merge.'''
@@ -2603,7 +2627,8 @@ class DirectoryProcessor:
if (package is None or
package.package_name != 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:
# Если .calculate_directory отсутствует -- создаем директорию,
# используя унаследованные параметры и имя самой директории.
@@ -2714,7 +2739,8 @@ class DirectoryProcessor:
if (template_package is None or
package.package_name != 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.format:
@@ -2873,7 +2899,7 @@ class DirectoryProcessor:
template_type: int,
template_path: str,
template_text: str = '',
package: Union[Package, None] = None
package: Optional[Package] = None
) -> Union[bool, str]:
'''Метод для наложения шаблонов и обработки информации полученной после
наложения.'''
@@ -2952,7 +2978,7 @@ class DirectoryProcessor:

def _check_package_and_action(self, parameters: ParametersContainer,
template_path: str,
directory_tree: Union[dict, None] = None
directory_tree: Optional[dict] = None
) -> bool:
'''Метод для проверки параметров action и package во время обработки
каталогов с шаблонами. Если среди аргументов указано также


+ 64
- 39
calculate/utils/package.py View File

@@ -7,6 +7,9 @@ from collections import OrderedDict
from .files import read_file, read_link, join_paths, FilesError
from typing import (
Generator,
NoReturn,
Optional,
Dict,
Tuple,
Union,
List,
@@ -55,6 +58,34 @@ class PackageNotFound(Exception):
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:
_suffix_order = {'alpha': 0, 'beta': 1, 'pre': 2,
'rc': 3, 'no': 4, 'p': 5}
@@ -316,34 +347,19 @@ class ContentsParser(metaclass=Singleton):

@staticmethod
def _parse_dir(parts: List[str]) -> Tuple[str, dict]:
try:
return parts[1], {'type': 'dir'}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
return parts[1], {'type': 'dir'}

@staticmethod
def _parse_obj(parts: List[str]) -> Tuple[str, dict]:
try:
return parts[1], {'type': 'obj',
'md5': parts[2].strip(),
'mtime': parts[3].strip()}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
return parts[1], {'type': 'obj',
'md5': parts[2].strip(),
'mtime': parts[3].strip()}

@staticmethod
def _parse_sym(parts: List[str]) -> Tuple[str, dict]:
try:
return parts[1], {'type': 'sym',
'target': parts[3].strip(),
'mtime': parts[4].strip()}
except Exception as error:
print(str(error))
print("parts:", parts)
raise
return parts[1], {'type': 'sym',
'target': parts[3].strip(),
'mtime': parts[4].strip()}

def render(self, contents_dictionary: OrderedDict) -> str:
lines = []
@@ -669,7 +685,7 @@ class PackageAtomParser:
return atom_dictionary

def _check_slot_value(self, pkg_path: str,
atom_dictionary: dict) -> None:
atom_dictionary: dict) -> NoReturn:
'''Метод для проверки полученного из параметра package значения slot.
'''
if atom_dictionary['slot']:
@@ -682,7 +698,7 @@ class PackageAtomParser:
errno=NOTEXIST)

def _check_use_flags_value(self, pkg_path: str,
atom_dictionary: dict) -> None:
atom_dictionary: dict) -> NoReturn:
'''Метод для проверки полученных из параметра package значений
use-флагов.'''
if atom_dictionary['use_flags']:
@@ -725,7 +741,7 @@ class PackageAtomParser:
yield path

def _check_version(self, atom_dictionary: dict, pkg_version: Version
) -> None:
) -> NoReturn:
condition = atom_dictionary['condition']

if condition == '=':
@@ -831,13 +847,14 @@ class PackageAtomParser:
return atom_dict


class Package:
class Package(metaclass=PackageCreator):
'''Класс для работы с принадлежностью файлов пакетам.'''
re_cfg = re.compile(r'/\._cfg\d{4}_')

def __init__(self, package_atom: Union[str, PackageAtomName],
pkg_path: str = '/var/db/pkg',
chroot_path: str = '/'):
chroot_path: str = '/',
autosave: bool = False):
self.chroot_path: str = chroot_path

self.contents_file_path = self._get_contents_path(package_atom)
@@ -855,6 +872,8 @@ class Package:
self.contents_dictionary = OrderedDict()
self.read_contents_file()

self.autosave: bool = autosave

def _get_contents_path(self, package_atom: Union[str, PackageAtomName]
) -> str:
'''Метод для получения из ATOM-названия или готового объекта
@@ -886,7 +905,7 @@ class Package:
else:
return file_name

def read_contents_file(self):
def read_contents_file(self) -> bool:
'''Метод для чтения файла CONTENTS.'''
try:
contents_text = read_file(self.contents_file_path)
@@ -899,18 +918,18 @@ class Package:
else:
return False

def write_contents_file(self):
def write_contents_file(self) -> NoReturn:
'''Метод для записи файла CONTENTS.'''
with open(self.contents_file_path, 'w') as contents_file:
contents_text = self.render_contents_file()
contents_file.write(contents_text)

def render_contents_file(self):
def render_contents_file(self) -> str:
'''Метод для получения текста файла CONTENTS.'''
return self.parser.render(self.contents_dictionary)

@property
def files(self):
def files(self) -> List[str]:
'''Метод для получения списка путей файлов, имеющихся в CONTENTS-файле
пакета.'''
return list(self.contents_dictionary.keys())
@@ -923,7 +942,7 @@ class Package:
return self.contents_dictionary[file_path]['type']
return None

def sort_contents_dictionary(self) -> None:
def sort_contents_dictionary(self) -> NoReturn:
'''Метод для сортировки словаря, полученного в результате разбора и
изменения CONTENTS-файла.'''
tree = {}
@@ -960,7 +979,7 @@ class Package:
if 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 директорий.'''
file_name = self.remove_chroot_path(file_name)

@@ -971,8 +990,8 @@ class Package:
contents_item = OrderedDict({'type': 'dir'})
self.contents_dictionary[file_name] = contents_item

def add_sym(self, file_name: str, target_path: Union[str, None] = None,
mtime: Union[str, None] = None) -> None:
def add_sym(self, file_name: str, target_path: Optional[str] = None,
mtime: Optional[str] = None) -> NoReturn:
'''Метод для добавления в CONTENTS символьных ссылок.'''
real_path = file_name

@@ -997,8 +1016,8 @@ class Package:

self.contents_dictionary[file_name] = contents_item

def add_obj(self, file_name: str, file_md5: Union[str, None] = None,
mtime: Union[str, None] = None) -> None:
def add_obj(self, file_name: str, file_md5: Optional[str] = None,
mtime: Optional[str] = None) -> NoReturn:
'''Метод для добавления в CONTENTS обычных файлов как obj.'''
real_path = file_name
file_name = self.remove_chroot_path(file_name)
@@ -1023,7 +1042,7 @@ class Package:
'mtime': mtime})
self.contents_dictionary[file_name] = contents_item

def add_file(self, file_name: str) -> None:
def add_file(self, file_name: str) -> NoReturn:
'''Метод для добавления в CONTENTS файла любого типа.'''
if file_name != '/':
real_path = file_name
@@ -1071,6 +1090,7 @@ class Package:
file_path = self.remove_chroot_path(file_path)
file_path = self.remove_cfg_prefix(file_path)
removed = OrderedDict()
print(f"REMOVE {file_path} FROM PACKAGE {self.package_name}")

if file_path not in self.contents_dictionary:
return
@@ -1099,7 +1119,7 @@ class Package:
self.contents_dictionary.pop(file_path)})
return removed

def remove_empty_directories(self):
def remove_empty_directories(self) -> OrderedDict:
'''Метод для удаления из CONTENTS директорий, которые после удаления
тех или иных файлов больше не находятся на пути к тем файлам, которые
по-прежнему принадлежат пакету.'''
@@ -1176,3 +1196,8 @@ class Package:
def __repr__(self) -> str:
return '<Package: {}/{}>'.format(self.package_name.category,
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
- 0
output
File diff suppressed because it is too large
View File


+ 2
- 2
run_templates.py View File

@@ -11,7 +11,7 @@ def main():
parser = argparse.ArgumentParser('Run templates.')
parser.add_argument('-a', '--action', action='append', type=str, nargs='+',
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.")
parser.add_argument('--dbpkg', action='store_true',
help=("flag for switching template engine's mode from"
@@ -32,7 +32,7 @@ def main():
elif args.install.strip().casefold() == 'all':
package = None
else:
package = args.package
package = args.install

group_packages = {}
if args.build is not None:


+ 123
- 52
tests/templates/test_directory_processor.py View File

@@ -2,11 +2,12 @@ import os
import pytest
import shutil
import hashlib
from pprint import pprint
from stat import ST_MODE
from calculate.templates.template_processor import DirectoryProcessor,\
TemplateWrapper
from calculate.utils.package import PackageAtomName, Version, Package,\
NonePackage
NonePackage, PackageCreator
from calculate.utils.files import join_paths
from calculate.utils.io_module import IOModule
from calculate.templates.template_engine import Variables
@@ -111,6 +112,7 @@ class TestDirectoryProcessor:
shutil.copytree(os.path.join(CHROOT_PATH, 'var.backup'),
os.path.join(CHROOT_PATH, 'var'),
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):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
@@ -146,7 +148,8 @@ class TestDirectoryProcessor:
+ ";\n};\n"))

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
with open(join_paths(CHROOT_PATH, '/etc/file_0'), 'r') as output_file:
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/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/file_0' in test_package
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/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/file_0' in test_package
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/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/dir_6' in test_package
assert '/etc/dir_5/dir_6/file_0' in test_package
@@ -309,7 +315,8 @@ class TestDirectoryProcessor:
+ datavars.ns.variable_2
+ ";\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'))
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/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/file_0' in test_package
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/._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
with open(join_paths(CHROOT_PATH,
'/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 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
with open(join_paths(CHROOT_PATH,
'/etc/._cfg0000_file_3'), 'r') as output_file:
@@ -501,7 +511,8 @@ class TestDirectoryProcessor:
assert not os.path.exists(join_paths(CHROOT_PATH,
'/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_5' in test_package
assert '/etc/dir_7/file_0' in test_package
@@ -597,8 +608,10 @@ class TestDirectoryProcessor:
datavars_module=datavars)
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, 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/file_0'))
@@ -652,7 +665,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install',
datavars_module=datavars)
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,
'/etc/dir_12'))
@@ -672,8 +686,10 @@ class TestDirectoryProcessor:
install=other_package_name)
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, 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/file_0'))
@@ -698,8 +714,10 @@ class TestDirectoryProcessor:
install=other_package_name)
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, 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/file_0'))
@@ -726,7 +744,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install',
datavars_module=datavars)
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,
@@ -753,7 +772,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor('install',
datavars_module=datavars)
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)
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
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/file_0'))
@@ -829,9 +852,12 @@ class TestDirectoryProcessor:
install='test-category/other-package')
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
new_package = Package(new_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
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/file_0'))
@@ -872,8 +898,10 @@ class TestDirectoryProcessor:
install='test-category/other-package')
directory_processor.process_template_directories()

test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH,
autosave=True)
other_package = Package(other_package_name, chroot_path=CHROOT_PATH,
autosave=True)

print('DIRECTORY TREE:')
for key in directory_processor.packages_file_trees.keys():
@@ -914,7 +942,8 @@ class TestDirectoryProcessor:
datavars_module=datavars)
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 '/etc/file_10' in test_package

@@ -929,7 +958,8 @@ class TestDirectoryProcessor:
datavars_module=datavars)
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 '/etc/file_11' not in test_package

@@ -943,7 +973,8 @@ class TestDirectoryProcessor:
datavars_module=datavars)
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/file_0'))
@@ -964,7 +995,8 @@ class TestDirectoryProcessor:
datavars_module=datavars)
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/dir_30'))
@@ -1064,7 +1096,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor(['install', 'update'],
datavars_module=datavars)
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_32'))
@@ -1094,7 +1127,8 @@ class TestDirectoryProcessor:
directory_processor = DirectoryProcessor(['install', 'update'],
datavars_module=datavars)
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_35'))
@@ -1118,7 +1152,8 @@ class TestDirectoryProcessor:
install='test-category/test-package'
)
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 -- это просто обработчик-скрипт.
assert os.path.exists(join_paths(CHROOT_PATH,
@@ -1324,8 +1359,10 @@ class TestDirectoryProcessor:
+ ";\n};\n"))

directory_processor.process_template_directories()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)
test_package_0 = Package(test_package_name_0, 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/file_0'))
@@ -1344,11 +1381,30 @@ class TestDirectoryProcessor:
'install',
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()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)
test_package_0 = Package(test_package_name_0, 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/file_0'))
@@ -1357,11 +1413,9 @@ class TestDirectoryProcessor:
output = output.read()
assert output_text == output

assert '/etc/dir_58' not in test_package_1
assert '/etc/dir_58/file_0' not in test_package_1

assert '/etc/dir_58' in test_package_0
assert '/etc/dir_58/file_0' in test_package_0
assert '/etc/dir_58' 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

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,
@@ -1372,11 +1426,30 @@ class TestDirectoryProcessor:
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()
test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)
test_package_0 = Package(test_package_name_0, 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/file_0'))
@@ -1385,11 +1458,9 @@ class TestDirectoryProcessor:
output = output.read()
assert output_text == output

assert '/etc/dir_59' not in test_package_1
assert '/etc/dir_59/file_0' not in test_package_1

assert '/etc/dir_59' in test_package_0
assert '/etc/dir_59/file_0' in test_package_0
assert '/etc/dir_59' 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

def test_copy_file_using_source(self):
datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,


+ 3
- 4
tests/templates/testfiles/test_wrapper_root/var/db/pkg/test-category/test-package-1.0/CONTENTS View File

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

Loading…
Cancel
Save