Update analysis and plan files to enhance duplicate handling and reporting

- Updated `analysis.json` with a new generation timestamp.
- Modified `plan.json` to include a new plan ID and created timestamp, and changed operation types from "no-op" to "quarantine" for specific files needing manual review.
- Enhanced the README.md to document the new `--analysis` option for generating execution plans, which now includes a human-readable summary and duplicate handling strategies.
- Introduced a new `duplicate_resolve.py` module to manage duplicate file resolution strategies.
- Improved the execution engine to support quarantine operations and added rollback functionality for quarantined files.

These changes improve the functionality of the Video Library Manager by providing better duplicate management and clearer reporting capabilities.
This commit is contained in:
windyboy
2026-02-10 18:07:38 +08:00
parent dcd87754cf
commit 79f5ddf1f5
14 changed files with 882 additions and 456 deletions
+42 -18
View File
@@ -151,30 +151,42 @@ def _generate_inventory_json(
def generate_completeness_report(
analysis: list[SeasonCompleteness],
format: str,
library_root: Path
library_root: Path,
plan_summary: str | None = None,
) -> str:
"""Generate completeness report showing series with episode gaps.
Args:
analysis: List of SeasonCompleteness objects with detected gaps
format: Output format ("text" or "json")
library_root: Root of the library (included in report metadata)
plan_summary: Optional plan content summary to prepend (when --plan was used)
Returns:
Formatted report as string
Raises:
ValueError: If format is not "text" or "json"
"""
if format not in ["text", "json"]:
raise ValueError(f"Invalid format: {format}. Must be 'text' or 'json'")
generation_timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
if format == "json":
return _generate_completeness_json(analysis, generation_timestamp, library_root)
else: # text
return _generate_completeness_text(analysis, generation_timestamp, library_root)
body = _generate_completeness_json(analysis, generation_timestamp, library_root)
else:
body = _generate_completeness_text(analysis, generation_timestamp, library_root)
if plan_summary:
if format == "text":
section = "计划内容总结\n" + "-" * 40 + "\n" + plan_summary + "\n\n"
return section + body
else:
data = json.loads(body)
data["plan_summary"] = plan_summary
return json.dumps(data, indent=2, ensure_ascii=False)
return body
def _generate_completeness_text(
@@ -264,30 +276,42 @@ def _generate_completeness_json(
def generate_duplicate_report(
duplicates: list[DuplicateGroup],
format: str,
library_root: Path
library_root: Path,
plan_summary: str | None = None,
) -> str:
"""Generate duplicate report showing duplicate files with quality comparisons.
Args:
duplicates: List of DuplicateGroup objects with duplicate files
format: Output format ("text" or "json")
library_root: Root of the library (included in report metadata)
plan_summary: Optional plan content summary to prepend (when --plan was used)
Returns:
Formatted report as string
Raises:
ValueError: If format is not "text" or "json"
"""
if format not in ["text", "json"]:
raise ValueError(f"Invalid format: {format}. Must be 'text' or 'json'")
generation_timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")
if format == "json":
return _generate_duplicate_json(duplicates, generation_timestamp, library_root)
else: # text
return _generate_duplicate_text(duplicates, generation_timestamp, library_root)
body = _generate_duplicate_json(duplicates, generation_timestamp, library_root)
else:
body = _generate_duplicate_text(duplicates, generation_timestamp, library_root)
if plan_summary:
if format == "text":
section = "计划内容总结\n" + "-" * 40 + "\n" + plan_summary + "\n\n"
return section + body
else:
data = json.loads(body)
data["plan_summary"] = plan_summary
return json.dumps(data, indent=2, ensure_ascii=False)
return body
def _generate_duplicate_text(