Files

176 lines
6.1 KiB
Python

"""
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)