update
This commit is contained in:
+148
-18
@@ -234,8 +234,13 @@ class Add_File(Cmdlet):
|
||||
try:
|
||||
candidate_dir = Path(str(path_arg))
|
||||
if candidate_dir.exists() and candidate_dir.is_dir():
|
||||
debug(
|
||||
f"[add-file] Treating -path directory as destination: {candidate_dir}"
|
||||
debug_panel(
|
||||
"add-file destination",
|
||||
[
|
||||
("mode", "local export"),
|
||||
("path", candidate_dir),
|
||||
],
|
||||
border_style="cyan",
|
||||
)
|
||||
location = str(candidate_dir)
|
||||
path_arg = None
|
||||
@@ -350,6 +355,13 @@ class Add_File(Cmdlet):
|
||||
else:
|
||||
items_to_process = [result]
|
||||
|
||||
if result is None and not path_arg and not explicit_path_list_results and not dir_scan_results:
|
||||
try:
|
||||
if ctx.get_stage_context() is not None:
|
||||
return 0
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
total_items = len(items_to_process) if isinstance(items_to_process, list) else 0
|
||||
processed_items = 0
|
||||
try:
|
||||
@@ -580,7 +592,12 @@ class Add_File(Cmdlet):
|
||||
progress.step("resolving source")
|
||||
|
||||
media_path, file_hash, temp_dir_to_cleanup = self._resolve_source(
|
||||
item, path_arg, pipe_obj, config, store_instance=storage_registry
|
||||
item,
|
||||
path_arg,
|
||||
pipe_obj,
|
||||
config,
|
||||
export_destination=(Path(location) if location and not is_storage_backend_location else None),
|
||||
store_instance=storage_registry,
|
||||
)
|
||||
if not media_path and provider_name:
|
||||
media_path, file_hash, temp_dir_to_cleanup = Add_File._download_provider_source(
|
||||
@@ -1103,6 +1120,70 @@ class Add_File(Cmdlet):
|
||||
pass
|
||||
return None, None
|
||||
|
||||
@staticmethod
|
||||
def _download_remote_backend_url(
|
||||
remote_url: str,
|
||||
pipe_obj: models.PipeObject,
|
||||
*,
|
||||
file_hash: Optional[str] = None,
|
||||
output_dir: Optional[Path] = None,
|
||||
) -> Tuple[Optional[Path], Optional[Path]]:
|
||||
"""Best-effort fetch of a remote backend URL.
|
||||
|
||||
Returns (downloaded_path, temp_dir_to_cleanup).
|
||||
When ``output_dir`` is provided, the file is downloaded directly there and no
|
||||
temp cleanup path is returned.
|
||||
"""
|
||||
|
||||
url_text = str(remote_url or "").strip()
|
||||
if not url_text:
|
||||
return None, None
|
||||
if not url_text.lower().startswith(_REMOTE_URL_PREFIXES):
|
||||
return None, None
|
||||
|
||||
tmp_dir: Optional[Path] = None
|
||||
try:
|
||||
download_root = output_dir
|
||||
if download_root is None:
|
||||
tmp_dir = Path(tempfile.mkdtemp(prefix="add-file-src-"))
|
||||
download_root = tmp_dir
|
||||
|
||||
suggested_name = Add_File._build_provider_filename(
|
||||
pipe_obj,
|
||||
fallback_hash=file_hash,
|
||||
source_url=url_text,
|
||||
)
|
||||
pipeline_progress = PipelineProgress(ctx)
|
||||
|
||||
downloaded = _download_direct_file(
|
||||
url_text,
|
||||
download_root,
|
||||
quiet=False,
|
||||
suggested_filename=suggested_name,
|
||||
pipeline_progress=pipeline_progress,
|
||||
)
|
||||
downloaded_path = getattr(downloaded, "path", None)
|
||||
if isinstance(downloaded_path, Path) and downloaded_path.exists():
|
||||
if output_dir is not None:
|
||||
pipe_obj.is_temp = False
|
||||
if isinstance(pipe_obj.extra, dict):
|
||||
pipe_obj.extra["_direct_export_download"] = True
|
||||
else:
|
||||
pipe_obj.extra = {"_direct_export_download": True}
|
||||
return downloaded_path, None
|
||||
|
||||
pipe_obj.is_temp = True
|
||||
return downloaded_path, 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 _build_provider_filename(
|
||||
pipe_obj: models.PipeObject,
|
||||
@@ -1188,6 +1269,7 @@ class Add_File(Cmdlet):
|
||||
pipe_obj: models.PipeObject,
|
||||
config: Dict[str,
|
||||
Any],
|
||||
export_destination: Optional[Path] = None,
|
||||
store_instance: Optional[Any] = None,
|
||||
) -> Tuple[Optional[Path],
|
||||
Optional[str],
|
||||
@@ -1228,12 +1310,30 @@ class Add_File(Cmdlet):
|
||||
pipe_obj.path = str(mp)
|
||||
return mp, str(r_hash), None
|
||||
if isinstance(mp, str) and mp.strip():
|
||||
try:
|
||||
mp_path = Path(str(mp))
|
||||
except Exception:
|
||||
mp_path = None
|
||||
if mp_path is not None and mp_path.exists() and mp_path.is_file():
|
||||
pipe_obj.path = str(mp_path)
|
||||
return mp_path, str(r_hash), None
|
||||
|
||||
dl_path, tmp_dir = Add_File._maybe_download_backend_file(
|
||||
backend, str(r_hash), pipe_obj
|
||||
)
|
||||
if dl_path and dl_path.exists():
|
||||
pipe_obj.path = str(dl_path)
|
||||
return dl_path, str(r_hash), tmp_dir
|
||||
|
||||
dl_path, tmp_dir = Add_File._download_remote_backend_url(
|
||||
str(mp),
|
||||
pipe_obj,
|
||||
file_hash=str(r_hash),
|
||||
output_dir=export_destination,
|
||||
)
|
||||
if dl_path and dl_path.exists():
|
||||
pipe_obj.path = str(dl_path)
|
||||
return dl_path, str(r_hash), tmp_dir
|
||||
except Exception as exc:
|
||||
debug(f"[add-file] _resolve_source backend fetch failed for {r_store}/{r_hash}: {exc}")
|
||||
|
||||
@@ -1657,12 +1757,22 @@ class Add_File(Cmdlet):
|
||||
|
||||
@staticmethod
|
||||
def _emit_pipe_object(pipe_obj: models.PipeObject) -> None:
|
||||
from SYS.result_table import format_result
|
||||
|
||||
log(format_result(pipe_obj, title="Result"), file=sys.stderr)
|
||||
ctx.emit(pipe_obj.to_dict())
|
||||
payload = pipe_obj.to_dict()
|
||||
ctx.emit(payload)
|
||||
ctx.set_current_stage_table(None)
|
||||
|
||||
stage_ctx = ctx.get_stage_context()
|
||||
is_last = (stage_ctx is None) or bool(getattr(stage_ctx, "is_last_stage", False))
|
||||
if not is_last:
|
||||
return
|
||||
|
||||
try:
|
||||
from ._shared import display_and_persist_items
|
||||
|
||||
display_and_persist_items([payload], title="Result", subject=payload)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _emit_storage_result(
|
||||
payload: Dict[str,
|
||||
@@ -1925,7 +2035,24 @@ class Add_File(Cmdlet):
|
||||
log(f"❌ Invalid destination path '{location}': {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
log(f"Exporting to local path: {destination_root}", file=sys.stderr)
|
||||
direct_export_download = False
|
||||
try:
|
||||
if isinstance(pipe_obj.extra, dict):
|
||||
direct_export_download = bool(pipe_obj.extra.pop("_direct_export_download", False))
|
||||
except Exception:
|
||||
direct_export_download = False
|
||||
|
||||
try:
|
||||
debug_panel(
|
||||
"add-file export",
|
||||
[
|
||||
("destination", destination_root),
|
||||
("source", media_path),
|
||||
],
|
||||
border_style="green",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
result = None
|
||||
tags, url, title, f_hash = Add_File._prepare_metadata(result, media_path, pipe_obj, config)
|
||||
@@ -1961,18 +2088,21 @@ class Add_File(Cmdlet):
|
||||
destination_root.mkdir(parents=True, exist_ok=True)
|
||||
target_path = destination_root / new_name
|
||||
|
||||
if target_path.exists():
|
||||
target_path = unique_path(target_path)
|
||||
if direct_export_download:
|
||||
target_path = media_path
|
||||
else:
|
||||
if target_path.exists():
|
||||
target_path = unique_path(target_path)
|
||||
|
||||
# COPY Operation (Safe Export)
|
||||
try:
|
||||
shutil.copy2(str(media_path), target_path)
|
||||
except Exception as exc:
|
||||
log(f"❌ Failed to export file: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
# COPY Operation (Safe Export)
|
||||
try:
|
||||
shutil.copy2(str(media_path), target_path)
|
||||
except Exception as exc:
|
||||
log(f"❌ Failed to export file: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Copy Sidecars
|
||||
Add_File._copy_sidecars(media_path, target_path)
|
||||
# Copy Sidecars
|
||||
Add_File._copy_sidecars(media_path, target_path)
|
||||
|
||||
# Ensure hash for exported copy
|
||||
if not f_hash:
|
||||
|
||||
Reference in New Issue
Block a user