add go bench client
This commit is contained in:
179
backend/migrate_file_organization.py
Normal file
179
backend/migrate_file_organization.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Migrate existing uploads to organized structure
|
||||
Moves files from uploads/ to uploads/{hostname}/images or uploads/{hostname}/files
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from app.db.session import SessionLocal
|
||||
from app.core.config import settings
|
||||
from app.models.device import Device
|
||||
from app.models.document import Document
|
||||
from app.utils.file_organizer import (
|
||||
sanitize_hostname,
|
||||
is_image_file,
|
||||
ensure_device_directories
|
||||
)
|
||||
|
||||
|
||||
def migrate_files(dry_run: bool = True):
|
||||
"""
|
||||
Migrate existing files to organized structure
|
||||
|
||||
Args:
|
||||
dry_run: If True, only print what would be done
|
||||
"""
|
||||
db: Session = SessionLocal()
|
||||
|
||||
try:
|
||||
# Get all documents
|
||||
documents = db.query(Document).all()
|
||||
|
||||
print(f"Found {len(documents)} documents to migrate")
|
||||
print(f"Mode: {'DRY RUN' if dry_run else 'ACTUAL MIGRATION'}")
|
||||
print("-" * 80)
|
||||
|
||||
migrated_count = 0
|
||||
error_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
for doc in documents:
|
||||
# Get device
|
||||
device = db.query(Device).filter(Device.id == doc.device_id).first()
|
||||
|
||||
if not device:
|
||||
print(f"❌ Document {doc.id}: Device {doc.device_id} not found - SKIPPING")
|
||||
error_count += 1
|
||||
continue
|
||||
|
||||
# Check if file exists
|
||||
if not os.path.exists(doc.stored_path):
|
||||
print(f"⚠️ Document {doc.id}: File not found at {doc.stored_path} - SKIPPING")
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# Determine if image
|
||||
is_image = is_image_file(doc.filename, doc.mime_type)
|
||||
file_type = "image" if is_image else "file"
|
||||
|
||||
# Get new path
|
||||
sanitized_hostname = sanitize_hostname(device.hostname)
|
||||
subdir = "images" if is_image else "files"
|
||||
filename = os.path.basename(doc.stored_path)
|
||||
|
||||
new_path = os.path.join(
|
||||
settings.UPLOAD_DIR,
|
||||
sanitized_hostname,
|
||||
subdir,
|
||||
filename
|
||||
)
|
||||
|
||||
# Check if already in correct location
|
||||
if doc.stored_path == new_path:
|
||||
print(f"✓ Document {doc.id}: Already in correct location")
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
print(f"📄 Document {doc.id} ({file_type}):")
|
||||
print(f" Device: {device.hostname} (ID: {device.id})")
|
||||
print(f" From: {doc.stored_path}")
|
||||
print(f" To: {new_path}")
|
||||
|
||||
if not dry_run:
|
||||
try:
|
||||
# Create target directory
|
||||
os.makedirs(os.path.dirname(new_path), exist_ok=True)
|
||||
|
||||
# Move file
|
||||
shutil.move(doc.stored_path, new_path)
|
||||
|
||||
# Update database
|
||||
doc.stored_path = new_path
|
||||
db.add(doc)
|
||||
|
||||
print(f" ✅ Migrated successfully")
|
||||
migrated_count += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Error: {e}")
|
||||
error_count += 1
|
||||
else:
|
||||
print(f" [DRY RUN - would migrate]")
|
||||
migrated_count += 1
|
||||
|
||||
print()
|
||||
|
||||
if not dry_run:
|
||||
db.commit()
|
||||
print("Database updated")
|
||||
|
||||
print("-" * 80)
|
||||
print(f"Summary:")
|
||||
print(f" Migrated: {migrated_count}")
|
||||
print(f" Skipped: {skipped_count}")
|
||||
print(f" Errors: {error_count}")
|
||||
print(f" Total: {len(documents)}")
|
||||
|
||||
if dry_run:
|
||||
print()
|
||||
print("This was a DRY RUN. To actually migrate files, run:")
|
||||
print(" python backend/migrate_file_organization.py --execute")
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def cleanup_empty_directories(base_dir: str):
|
||||
"""Remove empty directories after migration"""
|
||||
for root, dirs, files in os.walk(base_dir, topdown=False):
|
||||
for dir_name in dirs:
|
||||
dir_path = os.path.join(root, dir_name)
|
||||
try:
|
||||
if not os.listdir(dir_path): # Directory is empty
|
||||
os.rmdir(dir_path)
|
||||
print(f"Removed empty directory: {dir_path}")
|
||||
except Exception as e:
|
||||
print(f"Could not remove {dir_path}: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Migrate uploads to organized structure")
|
||||
parser.add_argument(
|
||||
"--execute",
|
||||
action="store_true",
|
||||
help="Actually perform the migration (default is dry-run)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cleanup",
|
||||
action="store_true",
|
||||
help="Clean up empty directories after migration"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print("=" * 80)
|
||||
print("File Organization Migration")
|
||||
print("=" * 80)
|
||||
print()
|
||||
|
||||
migrate_files(dry_run=not args.execute)
|
||||
|
||||
if args.execute and args.cleanup:
|
||||
print()
|
||||
print("=" * 80)
|
||||
print("Cleaning up empty directories")
|
||||
print("=" * 80)
|
||||
cleanup_empty_directories(settings.UPLOAD_DIR)
|
||||
|
||||
print()
|
||||
print("Done!")
|
||||
Reference in New Issue
Block a user