""" Converter from version 0.0 to version 1.0 ========================================= This module converts backups from version 0.0 (old format without version info) to version 1.0 (current format with version info). The old version backup has a simple directory structure with .md files for markdown content, .mdmeta files for markdown metadata, and .meta files for path metadata. The current version backup has a more complex structure with tree/ and template/ directories, .json files for markdown content, .json.meta files for path metadata, and a webhook.json file. For all old version markdowns, they are considered to be using the default template with no other settings, and their content is converted from plain text to {"markdown": content_in_md}. For all old version paths, they are considered to have no settings. """ import os import json import shutil from datetime import datetime import logging import tempfile from misc.backup_converters import register_converter logger = logging.getLogger(__name__) def convert_v0_to_v1(backup_dir: str) -> str: """ Convert a backup from version 0.0 to version 1.0. Args: backup_dir (str): Path to the backup directory Returns: str: The new version ("1.0") """ logger.info(f"Converting backup from version 0.0 to 1.0: {backup_dir}") temp_dir = tempfile.mkdtemp() new_backup_dir = os.path.join(temp_dir, "new_backup") os.makedirs(new_backup_dir) try: tree_dir = os.path.join(new_backup_dir, 'tree') template_dir = os.path.join(new_backup_dir, 'template') os.makedirs(tree_dir) os.makedirs(template_dir) with open(os.path.join(new_backup_dir, 'webhook.json'), 'w') as f: json.dump([], f) with open(os.path.join(new_backup_dir, 'version.json'), 'w') as f: json.dump({"version": "1.0"}, f) root_dir = os.path.join(backup_dir, 'Root') if os.path.exists(root_dir) and os.path.isdir(root_dir): source_dir = root_dir else: source_dir = backup_dir convert_directory(source_dir, tree_dir) for item in os.listdir(new_backup_dir): src = os.path.join(new_backup_dir, item) dst = os.path.join(backup_dir, item) if os.path.isdir(src): if os.path.exists(dst): shutil.rmtree(dst) shutil.copytree(src, dst) else: shutil.copy2(src, dst) shutil.rmtree(temp_dir) return "1.0" except Exception as e: logger.error(f"Error converting backup: {e}") shutil.rmtree(temp_dir) raise def convert_directory(old_dir: str, new_dir: str): """ Recursively convert a directory from the old backup format to the new format. This function processes a directory from the old backup format and converts it to the new format. It creates a .json.meta file for the directory with metadata from the .meta file (if it exists), processes all markdown files (.md) in the directory, converting them to .json files with the new format, and recursively processes all subdirectories. For markdown files, the function: 1. Reads the content from the .md file 2. Converts the content to the new format {"markdown": content_in_md} 3. Reads metadata from the .mdmeta file (if it exists) 4. Creates a new .json file with the content and metadata For directories, the function: 1. Reads metadata from the .meta file (if it exists) 2. Creates a new .json.meta file with the metadata 3. Recursively processes all subdirectories Args: old_dir (str): Path to the old directory new_dir (str): Path to the new directory where the converted files will be stored """ order = '' meta_file_path = os.path.join(old_dir, '.meta') if os.path.exists(meta_file_path): with open(meta_file_path, 'r') as f: for line in f: try: if line.startswith('order:'): order = line.strip().split(': ', 1)[1] except (ValueError, IndexError): continue path_meta = { 'name': os.path.basename(old_dir), 'order': order, 'backup_id': 0 } with open(os.path.join(new_dir, '.json.meta'), 'w') as f: json.dump(path_meta, f, default=str, indent=2) for file_name in os.listdir(old_dir): old_file_path = os.path.join(old_dir, file_name) if file_name.endswith('.md'): md_title = file_name[:-3] with open(old_file_path, 'r', encoding='utf-8') as f: content = f.read() new_content = json.dumps({'markdown': content}) created_at = datetime.now() order = '' shortcut = '' mdmeta_path = old_file_path + 'meta' if os.path.exists(mdmeta_path): with open(mdmeta_path, 'r') as f: for line in f: try: key, value = line.strip().split(': ', 1) if key == 'created_at': created_at = value elif key == 'order': order = value elif key == 'shortcut': shortcut = value except ValueError: continue md_data = { 'title': md_title, 'content': new_content, 'created_at': created_at, 'order': order, 'shortcut': shortcut, 'backup_id': 0 } with open(os.path.join(new_dir, f'{md_title}.json'), 'w') as f: json.dump(md_data, f, default=str, indent=2) elif os.path.isdir(old_file_path) and not file_name.startswith('.'): new_subdir = os.path.join(new_dir, file_name) os.makedirs(new_subdir, exist_ok=True) convert_directory(old_file_path, new_subdir) register_converter("0.0", "1.0", convert_v0_to_v1)