6
0
Fork 0
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

96 linhas
3.7 KiB

Esse arquivo contém caracteres Unicode ambíguos!

Este arquivo contém caracteres ambíguos Unicode que podem ser confundidos com outros no seu idioma atual. Se o seu caso de uso for intencional e legítimo, você pode ignorar com segurança este aviso. Use o botão Escapar para destacar esses caracteres.

# vim: fileencoding=utf-8
#
from .base_format import Format
from calculate.utils.files import Process
from calculate.templates.format.base_format import FormatError
from ..template_engine import ParametersContainer, Variables
from ...variables.datavars import NamespaceNode
from ...variables.loader import Datavars
from typing import Union
from os import path
class PatchFormat(Format):
FORMAT = 'patch'
EXECUTABLE = True
def __init__(self, patch_text: str,
template_path: str,
parameters: ParametersContainer,
datavars: Union[Datavars, NamespaceNode, Variables]):
self._patch_text = patch_text
self._cwd_path = '/'
self._last_level = 0
# Измененные файлы.
self.changed_files = dict()
# Предупреждения.
self._warnings: list = []
def execute_format(self, target_path, chroot_path='/'):
'''Метод для запуска работы формата.'''
self._cwd_path = target_path
if not path.isdir(self._cwd_path):
# Если target_path -- путь к файлу, запускаем все процессы из
# директории, в которой этот файл находится.
self._cwd_path = path.dirname(self._cwd_path)
if not path.exists(self._cwd_path):
raise FormatError('root path does not exist', executable=True)
if self._patch_text:
self._patch_document()
return self.changed_files
else:
raise FormatError('empty patch file', executable=True)
def _patch_document(self):
'''Метод, производящий наложение патча путем запуска процесса patch.'''
# Сначала определяем на каком уровне накладываем патч.
# Для этого запускаем утилиту patch с --dry-run и смотрим результат
# выполнения.
for level in range(0, 4):
patch_dry_run = Process('patch', '--dry-run',
'-p{}'.format(level),
cwd=self._cwd_path)
patch_dry_run.write(self._patch_text)
if patch_dry_run.success():
break
patch_dry_run = Process('patch', '-R', '--dry-run',
'-p{}'.format(level),
cwd=self._cwd_path)
patch_dry_run.write(self._patch_text)
if patch_dry_run.success():
return ''
else:
raise FormatError('correction failed', executable=True)
self._last_level = level
patch_run = Process('patch', '-p{}'.format(level),
cwd=self._cwd_path)
patch_run.write(self._patch_text)
if patch_run.success():
for line in patch_run.read_lines():
if line.startswith('patching file'):
changed_file_path = path.join(self._cwd_path,
line[13:].strip())
if path.exists(changed_file_path):
self.changed_files.update({changed_file_path:
'C'})
else:
self.changed_files.update({changed_file_path:
'D'})
return patch_run.read()
else:
return ''
def __bool__(self):
return bool(self._patch_text)
@property
def warnings(self):
return self._warnings