This commit is contained in:
2026-01-04 02:23:50 -08:00
parent 3acf21a673
commit 8545367e28
6 changed files with 2925 additions and 94 deletions

View File

@@ -5,6 +5,7 @@ from pathlib import Path
from copy import deepcopy
import sys
import shutil
import tempfile
import re
from SYS import models
@@ -501,7 +502,7 @@ class Add_File(Cmdlet):
temp_dir_to_cleanup: Optional[Path] = None
delete_after_item = delete_after
try:
media_path, file_hash = self._resolve_source(
media_path, file_hash, temp_dir_to_cleanup = self._resolve_source(
item, path_arg, pipe_obj, config
)
debug(
@@ -901,6 +902,38 @@ class Add_File(Cmdlet):
except Exception:
continue
@staticmethod
def _maybe_download_backend_file(
backend: Any,
file_hash: str,
pipe_obj: models.PipeObject,
) -> Tuple[Optional[Path], Optional[Path]]:
"""Best-effort fetch of a backend file when get_file returns a URL.
Returns (downloaded_path, temp_dir_to_cleanup).
"""
downloader = getattr(backend, "download_to_temp", None)
if not callable(downloader):
return None, None
tmp_dir: Optional[Path] = None
try:
tmp_dir = Path(tempfile.mkdtemp(prefix="add-file-src-"))
downloaded = downloader(str(file_hash), temp_root=tmp_dir)
if isinstance(downloaded, Path) and downloaded.exists():
pipe_obj.is_temp = True
return downloaded, tmp_dir
except Exception:
pass
if tmp_dir is not None:
try:
shutil.rmtree(tmp_dir, ignore_errors=True)
except Exception:
pass
return None, None
@staticmethod
def _resolve_source(
result: Any,
@@ -909,10 +942,11 @@ class Add_File(Cmdlet):
config: Dict[str,
Any],
) -> Tuple[Optional[Path],
Optional[str]]:
Optional[str],
Optional[Path]]:
"""Resolve the source file path from args or pipeline result.
Returns (media_path, file_hash).
Returns (media_path, file_hash, temp_dir_to_cleanup).
"""
# PRIORITY 1a: Try hash+path from directory scan result (has 'path' and 'hash' keys)
if isinstance(result, dict):
@@ -931,7 +965,7 @@ class Add_File(Cmdlet):
f"[add-file] Using path+hash from directory scan: {media_path}"
)
pipe_obj.path = str(media_path)
return media_path, str(result_hash)
return media_path, str(result_hash), None
except Exception as exc:
debug(f"[add-file] Failed to use directory scan result: {exc}")
@@ -950,7 +984,17 @@ class Add_File(Cmdlet):
media_path = backend.get_file(result_hash)
if isinstance(media_path, Path) and media_path.exists():
pipe_obj.path = str(media_path)
return media_path, str(result_hash)
return media_path, str(result_hash), None
if isinstance(media_path, str) and media_path.strip():
downloaded, tmp_dir = Add_File._maybe_download_backend_file(
backend,
str(result_hash),
pipe_obj,
)
if isinstance(downloaded, Path) and downloaded.exists():
pipe_obj.path = str(downloaded)
return downloaded, str(result_hash), tmp_dir
except Exception as exc:
debug(f"[add-file] Failed to retrieve via hash+store: {exc}")
@@ -959,7 +1003,7 @@ class Add_File(Cmdlet):
media_path = Path(path_arg)
pipe_obj.path = str(media_path)
debug(f"[add-file] Using explicit path argument: {media_path}")
return media_path, None
return media_path, None, None
# PRIORITY 3: Try from pipe_obj.path (check file first before URL)
pipe_path = getattr(pipe_obj, "path", None)
@@ -976,8 +1020,8 @@ class Add_File(Cmdlet):
"add-file ingests local files only. Use download-file first.",
file=sys.stderr,
)
return None, None
return Path(pipe_path_str), None
return None, None, None
return Path(pipe_path_str), None, None
# Try from result (if it's a string path or URL)
if isinstance(result, str):
@@ -993,10 +1037,10 @@ class Add_File(Cmdlet):
"add-file ingests local files only. Use download-file first.",
file=sys.stderr,
)
return None, None
return None, None, None
media_path = Path(result)
pipe_obj.path = str(media_path)
return media_path, None
return media_path, None, None
# Try from result if it's a list (pipeline emits multiple results)
if isinstance(result, list) and result:
@@ -1014,10 +1058,10 @@ class Add_File(Cmdlet):
"add-file ingests local files only. Use download-file first.",
file=sys.stderr,
)
return None, None
return None, None, None
media_path = Path(first_item)
pipe_obj.path = str(media_path)
return media_path, None
return media_path, None, None
# If the first item is a dict, interpret it as a PipeObject-style result
if isinstance(first_item, dict):
@@ -1037,9 +1081,9 @@ class Add_File(Cmdlet):
try:
media_path = Path(path_candidate)
pipe_obj.path = str(media_path)
return media_path, first_item.get("hash")
return media_path, first_item.get("hash"), None
except Exception:
return None, first_item.get("hash")
return None, first_item.get("hash"), None
# If first item is a PipeObject object
try:
@@ -1052,7 +1096,7 @@ class Add_File(Cmdlet):
debug(f"Resolved path from PipeObject: {path_candidate}")
media_path = Path(path_candidate)
pipe_obj.path = str(media_path)
return media_path, getattr(first_item, "hash", None)
return media_path, getattr(first_item, "hash", None), None
except Exception:
pass
@@ -1060,7 +1104,7 @@ class Add_File(Cmdlet):
f"No resolution path matched. pipe_obj.path={pipe_path}, result type={type(result).__name__}"
)
log("File path could not be resolved")
return None, None
return None, None, None
@staticmethod
def _scan_directory_for_files(directory: Path) -> List[Dict[str, Any]]:
@@ -1778,6 +1822,12 @@ class Add_File(Cmdlet):
store = Store(config)
backend = store[backend_name]
hydrus_like_backend = False
try:
hydrus_like_backend = str(type(backend).__name__ or "").lower().startswith("hydrus")
except Exception:
hydrus_like_backend = False
# Prepare metadata from pipe_obj and sidecars
tags, url, title, f_hash = Add_File._prepare_metadata(
result, media_path, pipe_obj, config
@@ -1870,6 +1920,11 @@ class Add_File(Cmdlet):
log(f"[add-file] FlorenceVision tagging error: {exc}", file=sys.stderr)
return 1
upload_tags = tags
if hydrus_like_backend and upload_tags:
upload_tags = []
debug("[add-file] Deferring tag application until after Hydrus upload")
debug(
f"[add-file] Storing into backend '{backend_name}' path='{media_path}' title='{title}'"
)
@@ -1879,7 +1934,7 @@ class Add_File(Cmdlet):
file_identifier = backend.add_file(
media_path,
title=title,
tag=tags,
tag=upload_tags,
url=[] if (defer_url_association and url) else url,
)
debug(
@@ -1921,6 +1976,17 @@ class Add_File(Cmdlet):
(f_hash or file_identifier or "unknown")
)
if hydrus_like_backend and tags:
try:
adder = getattr(backend, "add_tag", None)
if callable(adder):
debug(
f"[add-file] Applying {len(tags)} tag(s) post-upload to Hydrus"
)
adder(resolved_hash, list(tags))
except Exception as exc:
log(f"[add-file] Hydrus post-upload tagging failed: {exc}", file=sys.stderr)
# If we have url(s), ensure they get associated with the destination file.
# This mirrors `add-url` behavior but avoids emitting extra pipeline noise.
if url: