add: backup version converter/ backup logic 1.0
This commit is contained in:
172
misc/backup_converters/__init__.py
Normal file
172
misc/backup_converters/__init__.py
Normal file
@@ -0,0 +1,172 @@
|
||||
"""
|
||||
Backup Conversion System
|
||||
========================
|
||||
|
||||
This module provides functionality for converting backups between different versions.
|
||||
Each version converter is implemented in a separate file and registered with the system.
|
||||
|
||||
Usage:
|
||||
------
|
||||
To convert a backup from one version to another:
|
||||
|
||||
```python
|
||||
from misc.backup_converters import convert_backup
|
||||
|
||||
# Convert a backup from version 1.0 to the latest version
|
||||
convert_backup(backup_dir, target_version=None) # None means latest version
|
||||
```
|
||||
|
||||
Adding a New Converter:
|
||||
----------------------
|
||||
1. Create a new file in the backup_converters directory, e.g., v1_to_v2.py
|
||||
2. Implement a function that takes a backup directory and converts it to the target version
|
||||
3. Register the converter in this file using the register_converter function
|
||||
|
||||
Example:
|
||||
```python
|
||||
# In v1_to_v2.py
|
||||
from misc.backup_converters import register_converter
|
||||
|
||||
def convert_v1_to_v2(backup_dir):
|
||||
# Conversion logic here
|
||||
return new_version
|
||||
|
||||
register_converter("1.0", "2.0", convert_v1_to_v2)
|
||||
```
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, Callable, Tuple, Optional, List
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CURRENT_VERSION = "1.0"
|
||||
|
||||
_converters: Dict[Tuple[str, str], Callable[[str], str]] = {}
|
||||
|
||||
def register_converter(from_version: str, to_version: str, converter: Callable[[str], str]):
|
||||
"""
|
||||
Register a converter function for a specific version transition.
|
||||
|
||||
Args:
|
||||
from_version (str): The source version
|
||||
to_version (str): The target version
|
||||
converter (callable): A function that takes a backup directory path and returns the new version
|
||||
"""
|
||||
_converters[(from_version, to_version)] = converter
|
||||
logger.info(f"Registered converter from version {from_version} to {to_version}")
|
||||
|
||||
def get_backup_version(backup_dir: str) -> str:
|
||||
"""
|
||||
Get the version of a backup.
|
||||
|
||||
Args:
|
||||
backup_dir (str): Path to the backup directory
|
||||
|
||||
Returns:
|
||||
str: The version of the backup, or "0.0" if no version is found
|
||||
"""
|
||||
version_file = os.path.join(backup_dir, "version.json")
|
||||
if os.path.exists(version_file):
|
||||
try:
|
||||
with open(version_file, 'r') as f:
|
||||
version_data = json.load(f)
|
||||
return version_data.get("version", "0.0")
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading version file: {e}")
|
||||
return "0.0"
|
||||
|
||||
def set_backup_version(backup_dir: str, version: str):
|
||||
"""
|
||||
Set the version of a backup.
|
||||
|
||||
Args:
|
||||
backup_dir (str): Path to the backup directory
|
||||
version (str): The version to set
|
||||
"""
|
||||
version_file = os.path.join(backup_dir, "version.json")
|
||||
try:
|
||||
with open(version_file, 'w') as f:
|
||||
json.dump({"version": version}, f)
|
||||
except Exception as e:
|
||||
logger.error(f"Error writing version file: {e}")
|
||||
|
||||
def find_conversion_path(from_version: str, to_version: str) -> Optional[List[Tuple[str, str]]]:
|
||||
"""
|
||||
Find a path of converters to go from one version to another.
|
||||
|
||||
Args:
|
||||
from_version (str): The source version
|
||||
to_version (str): The target version
|
||||
|
||||
Returns:
|
||||
list: A list of (from, to) version pairs representing the conversion path,
|
||||
or None if no path is found
|
||||
"""
|
||||
if from_version == to_version:
|
||||
return []
|
||||
|
||||
if (from_version, to_version) in _converters:
|
||||
return [(from_version, to_version)]
|
||||
|
||||
queue = [(from_version, [])]
|
||||
visited = {from_version}
|
||||
|
||||
while queue:
|
||||
current, path = queue.pop(0)
|
||||
|
||||
for (src, dst), _ in _converters.items():
|
||||
if src == current and dst not in visited:
|
||||
new_path = path + [(src, dst)]
|
||||
if dst == to_version:
|
||||
return new_path
|
||||
visited.add(dst)
|
||||
queue.append((dst, new_path))
|
||||
|
||||
return None
|
||||
|
||||
def convert_backup(backup_dir: str, target_version: Optional[str] = None) -> str:
|
||||
"""
|
||||
Convert a backup to the target version.
|
||||
|
||||
Args:
|
||||
backup_dir (str): Path to the backup directory
|
||||
target_version (str, optional): The target version. If None, converts to the latest version.
|
||||
|
||||
Returns:
|
||||
str: The new version of the backup
|
||||
|
||||
Raises:
|
||||
ValueError: If no conversion path is found
|
||||
"""
|
||||
if target_version is None:
|
||||
target_version = CURRENT_VERSION
|
||||
|
||||
current_version = get_backup_version(backup_dir)
|
||||
if current_version == target_version:
|
||||
return current_version
|
||||
|
||||
path = find_conversion_path(current_version, target_version)
|
||||
if not path:
|
||||
raise ValueError(f"No conversion path found from version {current_version} to {target_version}")
|
||||
|
||||
for from_ver, to_ver in path:
|
||||
converter = _converters.get((from_ver, to_ver))
|
||||
if converter:
|
||||
logger.info(f"Converting backup from version {from_ver} to {to_ver}")
|
||||
new_version = converter(backup_dir)
|
||||
set_backup_version(backup_dir, new_version)
|
||||
else:
|
||||
raise ValueError(f"Converter not found for {from_ver} to {to_ver}")
|
||||
|
||||
return target_version
|
||||
|
||||
import pkgutil
|
||||
import importlib
|
||||
|
||||
for _, name, is_pkg in pkgutil.iter_modules([os.path.dirname(__file__)]):
|
||||
if not is_pkg and name != "__init__":
|
||||
importlib.import_module(f"misc.backup_converters.{name}")
|
||||
Reference in New Issue
Block a user