fix(build): render Nextcloud login page via askama, not include_str!(OUT_DIR)

The SvelteKit migration gated build.rs's static-dist/OUT_DIR generation
behind OXICLOUD_RUST_ASSETS=1 (early return), but login_v2_handler.rs
still embedded the page with
`include_str!(concat!(env!("OUT_DIR"), "/nextcloud-login.html"))`. With
OXICLOUD_RUST_ASSETS unset (the default), that file is never written to
OUT_DIR, so a clean `cargo build` failed to compile. (#489)

Migrate the page off include_str! to an askama template
(templates/nextcloud/login.html), mirroring the existing
DrivePickerTemplate in the same handler. This drops the only
compile-time dependency on the legacy build.rs pipeline, so the
OXICLOUD_RUST_ASSETS=1 CI workaround is no longer needed and is removed
from ci.yml, load-smoke.yml and load-nightly.yml.

Also fix the second failure on #489: with OXICLOUD_RUST_ASSETS=1 the
release pipeline panicked in copy_dir_recursive because `static/locales`
is now a symlink to frontend/static/locales. entry.file_type() reports
the link itself (not its target), so the symlinked directory was routed
to fs::copy and failed with "the source path is neither a regular file
nor a symlink to a regular file". Classify entries with fs::metadata,
which follows symlinks, so symlinked directories are traversed.

static/nextcloud-login.html is removed (its content moved into the
template; no other consumer) and dropped from build.rs HTML_INCLUDE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNCEMN6fC2xSmxqCVbstkd
This commit is contained in:
Claude
2026-06-19 17:13:49 +00:00
parent ddfc481616
commit 6023bca2e8
6 changed files with 38 additions and 31 deletions
+9 -3
View File
@@ -25,7 +25,6 @@ const HTML_INCLUDE: &[&str] = &[
"profile.html",
"admin.html",
"device-verify.html",
"nextcloud-login.html",
"share.html",
];
@@ -1239,14 +1238,21 @@ fn fnv_hash(data: &[u8]) -> String {
format!("{h:016x}")
}
/// Recursively copy a directory tree.
/// Recursively copy a directory tree, following symlinks.
///
/// `fs::metadata` (not `entry.file_type()`) is used to classify each entry so
/// that symlinked directories are traversed into rather than handed to
/// `fs::copy`. `static/locales` is a symlink to `frontend/static/locales`;
/// `entry.file_type()` reports the link itself, so the old code routed it to
/// the `fs::copy` branch and failed with "the source path is neither a regular
/// file nor a symlink to a regular file".
fn copy_dir_recursive(src: &Path, dst: &Path) -> io::Result<()> {
fs::create_dir_all(dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let src_path = entry.path();
let dst_path = dst.join(entry.file_name());
if entry.file_type()?.is_dir() {
if fs::metadata(&src_path)?.is_dir() {
copy_dir_recursive(&src_path, &dst_path)?;
} else {
fs::copy(&src_path, &dst_path)?;