"""Class for warehouses without Version Control System."""
from __future__ import annotations
from os import makedirs, remove, rename, scandir
from os.path import exists, join, isdir, dirname, normpath, isabs, relpath
from shutil import rmtree, copy
from chrysalio.lib.utils import copy_content
from .utils import INFOS_DIR, file_check_move
from .utils import thumbnail_remove, thumbnail_move
from .i18n import _
# =============================================================================
[docs]
class VcsNone():
"""Class to manage warehouses without VCS.
:param str root:
Absolute path to the warehouse directory.
:param str source: (optional)
Absolute path to the source directory to initialize the warehouse.
"""
engine = 'none'
# -------------------------------------------------------------------------
def __init__(self, root: str, source: str | None = None):
"""Constructor method."""
self.root = root
self._source = source
# -------------------------------------------------------------------------
[docs]
def init(self):
"""Possibly create the root directory.
:rtype: None
"""
makedirs(self.root, exist_ok=True)
# -------------------------------------------------------------------------
[docs]
@classmethod
def is_dirty(cls) -> bool:
"""Return ``False``.
:rtype: bool
"""
return False
# -------------------------------------------------------------------------
[docs]
def clone(self):
"""Call meth:`init`.
:rtype: None
"""
self.init()
if self._source and exists(self._source) \
and not tuple(scandir(self.root)):
copy_content(self._source, self.root)
# -------------------------------------------------------------------------
[docs]
def pull(self):
"""Do a clone if source exists and root directory is empty.
:rtype: None
"""
if self._source and exists(self._source) \
and len(tuple(scandir(self.root))) < 2:
copy_content(self._source, self.root)
# -------------------------------------------------------------------------
[docs]
def add(self, path=None):
"""Do nothing.
:rtype: None
"""
# -------------------------------------------------------------------------
[docs]
def remove(self, directory: str, filename: str) -> str | None:
"""Remove a file or a directory in path ``directory``.
:param str directory:
Relative or absolute path to the directory containing the file.
:param str filename:
Name of the file to remove.
:rtype: :class:`pyramid.i18n.TranslationString` or ``None``
:return:
Error message or ``None`` if it succeeds.
"""
if isabs(directory):
directory = relpath(directory, self.root)
abs_file = normpath(join(self.root, directory, filename))
if not abs_file.startswith(self.root) or abs_file == self.root:
return _('git remove: incorrect path')
# Remove information file
is_dir = isdir(abs_file)
abs_path = join(self.root, INFOS_DIR, directory, f'{filename}.xml')
if exists(abs_path):
remove(abs_path)
abs_path = join(self.root, INFOS_DIR, directory, filename)
if is_dir and isdir(abs_path):
rmtree(abs_path)
abs_path = normpath(dirname(abs_path))
if exists(abs_path):
while abs_path != self.root and not tuple(scandir(abs_path)):
rmtree(abs_path)
abs_path = dirname(abs_path)
# Remove the file
if is_dir:
rmtree(abs_file)
elif exists(abs_file):
remove(abs_file)
# Remove thumbnails
thumbnail_remove(self.root, directory, filename)
return None
# -------------------------------------------------------------------------
[docs]
def move(
self,
file1: tuple[str, str],
file2: tuple[str, str],
copy_only: bool = False) -> str | None:
"""Move or copy a file.
:param tuple file1:
A tuple such as ``(directory1, name1)``.
:param tuple file2:
A tuple such as ``(directory2, name2)``.
:param bool copy_only: (default=False)
If ``True``, copy instead of moving the file.
:rtype: :class:`pyramid.i18n.TranslationString` or ``None``
:return:
Error message or ``None`` if it succeeds.
"""
# Prepare files
abs_path1, abs_path2, error = file_check_move(self, file1, self, file2)
if abs_path1 is None:
return error
# Move/copy file
is_dir = isdir(abs_path1)
action = copy_content if copy_only and is_dir else \
copy if copy_only else rename
makedirs(dirname(abs_path2), exist_ok=True)
action(abs_path1, abs_path2)
# Move/copy information file
abs_path1 = join(
self.root, INFOS_DIR, file1[0], '{0}.xml'.format(file1[1]))
abs_path2 = join(
self.root, INFOS_DIR, file2[0], '{0}.xml'.format(file2[1]))
if exists(abs_path1):
makedirs(dirname(abs_path2), exist_ok=True)
action = copy if copy_only else rename
action(abs_path1, abs_path2)
abs_path1 = join(self.root, INFOS_DIR, file1[0], file1[1])
abs_path2 = join(self.root, INFOS_DIR, file2[0], file2[1])
if is_dir and isdir(abs_path1):
if exists(abs_path2):
rmtree(abs_path2)
action = copy_content if copy_only else rename
action(abs_path1, abs_path2)
# Move thumbnails
thumbnail_move(self.root, file1, self.root, file2, copy_only)
return None
# -------------------------------------------------------------------------
[docs]
def copy(self, file1, file2):
"""Copy a file.
:param tuple file1:
A tuple such as ``(old_directory, old_name)``.
:param tuple file2:
A tuple such as ``(new_directory, new_name)``.
:rtype: :class:`pyramid.i18n.TranslationString` or ``None``
:return:
Error message or ``None`` if it succeeds.
"""
return self.move(file1, file2, True)
# -------------------------------------------------------------------------
[docs]
def commit(self, message, name, email=None):
"""Do nothing.
:rtype: None
"""
# -------------------------------------------------------------------------
[docs]
def log(self, directory, filename, limit=20):
"""Do nothing.
:rtype: None
"""