A review against the Python client, which shares this client's config
and login cache, found the transfers holding whole files in memory and
several commands answering differently from their Python counterparts.
- Stream uploads and downloads instead of buffering the whole file, so
memory no longer scales with file size times concurrency. Uploads
still declare a Content-Length rather than going out chunked.
- Write a download beside its destination and move it into place once
complete, and refuse a destination that cannot be written, so a
failed transfer leaves what was already there untouched.
- Report the server's own error detail instead of the bare status.
- List locked sub-folders in `ls --json --recursive` using the given
password and skip only those that cannot be unlocked, instead of
failing the whole listing.
- Name each folder's laboratory in JSON output and sort its entries,
matching the Python client's schema and order.
- Ask the server who is logged in for `whoami`, rather than trusting
the cached name.
- Collapse repeated separators and refuse `..` in remote paths.
- Fall back to the API when a laboratory is missing from the cache, so
a newly added one no longer needs a fresh login.
- Verify the login cache digest on read, as the Python client does.
- Accept `-e` as the short form of `--exclude`.
- Satisfy clippy and rustfmt across the crate.
The reply to a refresh carries a new refresh token and the provider
stops honouring the one that was sent. Only the access half was read,
so the cache kept re-sending a token the server had already retired.
- deserialize the refresh half and write it back to the cache, as an
Option so a provider that does not rotate leaves the stored one be
- bound the refresh request on its own: the caller holds a lock that
spans processes while it runs, so a provider that goes quiet would
stall every other request on the machine
- give config create/update one rule for what a remote URL is, and
store it without the trailing slash, matching the Python client so
the two can share config.ini; this drops the validators crate and
77 transitive dependencies with it
- join the base URL and the API's relative download path with the
separator neither of them carries, as download.rs already does
Match the Python client for read-only commands by falling back to
anonymous API requests when no valid login cache is available.
Keep mutating commands login-only while letting ls, labs, metadata,
and file-metadata resolve laboratories and folders without a cached
token.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cache parsed auth state per remote and validate it with on-disk
file metadata so repeated authenticated API calls can skip
redundant open/read/JSON parse work within one process.
Centralize cache load, persist, and removal helpers in the cache
module, reuse them from login, logout, and whoami, and update
the refresh path to persist structured cache data directly.
Add targeted cache tests for memory reuse, invalidation after
external writes, persist updates, and cache removal.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move token refresh checks into the shared Rust connection/API path so long-running authenticated operations stop reusing stale access tokens. This covers recursive download and upload traversal, recursive ls via the shared APIs, and direct authenticated commands such as cp, mv, rm, and chacl.
Also surface HTTP failures earlier in the affected API methods instead of failing later during response parsing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Phase 5: Replace all Box<dyn Error> return types with anyhow::Result<T>
throughout the codebase. Replace string-based Err("msg".into()) and
format!().into() patterns with bail!() and anyhow!() macros. Fix
dirs::home_dir().unwrap() in settings.rs to use a fallback path instead
of panicking when HOME is unset. Remove stray use std::error::Error
imports no longer needed.
Phase 6: Add From<&User> for CacheUser in models/user.rs and
From<&Laboratory>/From<&Laboratories> for CacheLaboratory/CacheLabsWrapper
in models/laboratory.rs. Simplify commands/login.rs to use .into()
conversions, removing the redundant to_cache_user() and to_cache_labs()
helper functions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>