backup per defecte
covertir arregla extensions incorrectes
This commit is contained in:
@@ -71,7 +71,7 @@ python main.py --ruta ~/Comics --limpiar
|
|||||||
# Limpiar basura sin preguntar (modo automático)
|
# Limpiar basura sin preguntar (modo automático)
|
||||||
python main.py --ruta ~/Comics --limpiar --no-preguntar
|
python main.py --ruta ~/Comics --limpiar --no-preguntar
|
||||||
|
|
||||||
# Limpiar y convertir todo a CBZ (pide confirmación para la limpieza)
|
# Limpiar, renumerar, uniformizar imágenes y convertir a CBZ (pide confirmación en cada paso)
|
||||||
python main.py --ruta ~/Comics --estandarizar
|
python main.py --ruta ~/Comics --estandarizar
|
||||||
|
|
||||||
# Convertir todo a CBZ sin confirmación
|
# Convertir todo a CBZ sin confirmación
|
||||||
|
|||||||
+31
-7
@@ -7,6 +7,7 @@ import shutil
|
|||||||
import rarfile
|
import rarfile
|
||||||
|
|
||||||
from core.archive import detect_real_format, extract_archive, repack_as_cbz, ArchiveError, list_archive_names
|
from core.archive import detect_real_format, extract_archive, repack_as_cbz, ArchiveError, list_archive_names
|
||||||
|
from core.backup import move_to_backup
|
||||||
from core.collision import CollisionPolicy, resolve_collision
|
from core.collision import CollisionPolicy, resolve_collision
|
||||||
from core.result import ComicResult, StepResult
|
from core.result import ComicResult, StepResult
|
||||||
from processors.validator import validate_archive
|
from processors.validator import validate_archive
|
||||||
@@ -69,12 +70,16 @@ class Pipeline:
|
|||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def _needs_extraction(self, step_results: list, real_format: str) -> bool:
|
def _needs_extraction(self, step_results: list, real_format: str, path: str) -> bool:
|
||||||
for step in self.steps:
|
for step in self.steps:
|
||||||
if step in ("normalize_pages", "normalize_images", "convert_images"):
|
if step in ("normalize_pages", "normalize_images", "convert_images"):
|
||||||
return True
|
return True
|
||||||
if step == "convert" and needs_conversion(real_format, self.desired_format):
|
if step == "convert":
|
||||||
return True
|
if needs_conversion(real_format, self.desired_format):
|
||||||
|
return True
|
||||||
|
ext = os.path.splitext(path)[1].lower().lstrip(".")
|
||||||
|
if ext != self.desired_format:
|
||||||
|
return True
|
||||||
if step == "clean":
|
if step == "clean":
|
||||||
trash = next((r for r in step_results if r.step == "check_trash"), None)
|
trash = next((r for r in step_results if r.step == "check_trash"), None)
|
||||||
if trash and trash.warnings:
|
if trash and trash.warnings:
|
||||||
@@ -108,7 +113,7 @@ class Pipeline:
|
|||||||
]
|
]
|
||||||
|
|
||||||
# 4. Pre-flight: si ningún step necesita extracción, salir sin tocar el archivo
|
# 4. Pre-flight: si ningún step necesita extracción, salir sin tocar el archivo
|
||||||
if not self._needs_extraction(step_results, real_format):
|
if not self._needs_extraction(step_results, real_format, path):
|
||||||
return ComicResult(original_path=path, final_path=path, steps=step_results)
|
return ComicResult(original_path=path, final_path=path, steps=step_results)
|
||||||
|
|
||||||
# 5. Extraer una sola vez
|
# 5. Extraer una sola vez
|
||||||
@@ -167,6 +172,18 @@ class Pipeline:
|
|||||||
preview = self._compute_preview("convert", temp_dir, step_results)
|
preview = self._compute_preview("convert", temp_dir, step_results)
|
||||||
if confirm_fn is None or confirm_fn("convert", preview):
|
if confirm_fn is None or confirm_fn("convert", preview):
|
||||||
conv_result = conversion_step_result(real_format, self.desired_format)
|
conv_result = conversion_step_result(real_format, self.desired_format)
|
||||||
|
# Extensión incorrecta aunque el formato real ya sea correcto
|
||||||
|
file_ext = os.path.splitext(path)[1].lower().lstrip(".")
|
||||||
|
if (
|
||||||
|
not conv_result.errors
|
||||||
|
and not conv_result.changed
|
||||||
|
and file_ext != self.desired_format
|
||||||
|
):
|
||||||
|
conv_result = StepResult(
|
||||||
|
step="convert",
|
||||||
|
changed=True,
|
||||||
|
details=[f"Extensión incorrecta corregida: .{file_ext} → .{self.desired_format}"],
|
||||||
|
)
|
||||||
step_results.append(conv_result)
|
step_results.append(conv_result)
|
||||||
if conv_result.errors:
|
if conv_result.errors:
|
||||||
return ComicResult(
|
return ComicResult(
|
||||||
@@ -176,9 +193,13 @@ class Pipeline:
|
|||||||
any_changed = True
|
any_changed = True
|
||||||
|
|
||||||
# 7. Reempaquetar si hubo cambios o conversión de formato
|
# 7. Reempaquetar si hubo cambios o conversión de formato
|
||||||
|
ext = os.path.splitext(path)[1].lower().lstrip(".")
|
||||||
needs_repack = any_changed or (
|
needs_repack = any_changed or (
|
||||||
"convert" in self.steps
|
"convert" in self.steps
|
||||||
and needs_conversion(real_format, self.desired_format)
|
and (
|
||||||
|
needs_conversion(real_format, self.desired_format)
|
||||||
|
or ext != self.desired_format
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if not needs_repack:
|
if not needs_repack:
|
||||||
@@ -192,9 +213,12 @@ class Pipeline:
|
|||||||
if not self.dry_run:
|
if not self.dry_run:
|
||||||
safe_target = resolve_collision(target_path, self.collision_policy)
|
safe_target = resolve_collision(target_path, self.collision_policy)
|
||||||
repack_as_cbz(temp_dir, safe_target)
|
repack_as_cbz(temp_dir, safe_target)
|
||||||
# Eliminar original si el nombre cambió
|
# Eliminar o mover a backup el original si el nombre cambió
|
||||||
if safe_target != path and os.path.exists(path):
|
if safe_target != path and os.path.exists(path):
|
||||||
os.remove(path)
|
if self.collision_policy == CollisionPolicy.BACKUP:
|
||||||
|
move_to_backup(path)
|
||||||
|
else:
|
||||||
|
os.remove(path)
|
||||||
else:
|
else:
|
||||||
safe_target = target_path
|
safe_target = target_path
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import argparse
|
|||||||
from core.scanner import find_comic_files
|
from core.scanner import find_comic_files
|
||||||
from core.pipeline import Pipeline
|
from core.pipeline import Pipeline
|
||||||
from core.summary import SummaryCollector
|
from core.summary import SummaryCollector
|
||||||
|
from core.collision import CollisionPolicy
|
||||||
|
|
||||||
_COL_W = 30
|
_COL_W = 30
|
||||||
_SEP = "─" * 44
|
_SEP = "─" * 44
|
||||||
@@ -70,6 +71,12 @@ def parse_args():
|
|||||||
parser.add_argument("--formato-imagen", choices=["jpg", "png", "webp"], default="png")
|
parser.add_argument("--formato-imagen", choices=["jpg", "png", "webp"], default="png")
|
||||||
|
|
||||||
parser.add_argument("--no-preguntar", action="store_true")
|
parser.add_argument("--no-preguntar", action="store_true")
|
||||||
|
parser.add_argument(
|
||||||
|
"--al-modificar",
|
||||||
|
choices=["backup", "borrar"],
|
||||||
|
default="backup",
|
||||||
|
dest="al_modificar",
|
||||||
|
)
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@@ -110,10 +117,12 @@ def main():
|
|||||||
|
|
||||||
if steps:
|
if steps:
|
||||||
confirm_fn = None if args.no_preguntar else make_confirm_fn(args)
|
confirm_fn = None if args.no_preguntar else make_confirm_fn(args)
|
||||||
|
collision = CollisionPolicy.BACKUP if args.al_modificar == "backup" else CollisionPolicy.ABORT
|
||||||
pipeline = Pipeline(
|
pipeline = Pipeline(
|
||||||
steps=steps,
|
steps=steps,
|
||||||
desired_format=args.formato,
|
desired_format=args.formato,
|
||||||
desired_image_format="." + args.formato_imagen,
|
desired_image_format="." + args.formato_imagen,
|
||||||
|
collision_policy=collision,
|
||||||
)
|
)
|
||||||
collector = SummaryCollector()
|
collector = SummaryCollector()
|
||||||
for f in comic_files:
|
for f in comic_files:
|
||||||
|
|||||||
Reference in New Issue
Block a user