|
|
@@ -34,7 +34,7 @@ fn repo_resolve(path: &str) -> Option<std::path::PathBuf> {
|
|
|
Some(segs.iter().fold(root, |p, s| p.join(s)))
|
|
|
}
|
|
|
|
|
|
-fn dir_listing(base: &str, name: &str, p: &std::path::Path) -> String {
|
|
|
+fn dir_listing(base: &str, rel: &str, p: &std::path::Path) -> String {
|
|
|
let mut items: Vec<(String, bool, u64)> = Vec::new();
|
|
|
if let Ok(rd) = std::fs::read_dir(p) {
|
|
|
for e in rd.flatten() {
|
|
|
@@ -61,10 +61,12 @@ fn dir_listing(base: &str, name: &str, p: &std::path::Path) -> String {
|
|
|
} else {
|
|
|
format!("{} B", size)
|
|
|
};
|
|
|
+ // child URLs stay relative to this dir's own /repo path
|
|
|
+ let child = if rel.is_empty() { n.to_string() } else { format!("{rel}/{n}") };
|
|
|
let url = if *dir {
|
|
|
- format!("{base}repo/{n}/")
|
|
|
+ format!("{base}/repo/{child}/")
|
|
|
} else {
|
|
|
- format!("{base}repo/{n}")
|
|
|
+ format!("{base}/repo/{child}")
|
|
|
};
|
|
|
format!(
|
|
|
"<tr><td class=\"{cls}\">{n}</td><td class=\"sz\">{sz}</td><td><a href=\"{url}\">open</a></td></tr>"
|
|
|
@@ -77,7 +79,7 @@ fn dir_listing(base: &str, name: &str, p: &std::path::Path) -> String {
|
|
|
<style>body{{font:13px/1.5 system-ui;margin:18px;max-width:720px}}table{{border-collapse:collapse}}td,th{{border-bottom:1px solid #8884;padding:3px 10px;text-align:left}}td.d{{font-weight:600}}td.sz{{opacity:.6}}a{{color:#3b82f6;text-decoration:none}}a:hover{{text-decoration:underline}}.crumb{{margin-bottom:10px;font-size:12px;opacity:.7}}</style>\n\
|
|
|
<div class=\"crumb\">{name}</div>\n\
|
|
|
<table><tr><th>name</th><th>size</th><th></th></tr>{rows}</table>\n",
|
|
|
- name = esc(name),
|
|
|
+ name = esc(rel),
|
|
|
rows = rows.join(""),
|
|
|
)
|
|
|
}
|
|
|
@@ -103,13 +105,13 @@ pub(crate) async fn repo_route(
|
|
|
}
|
|
|
};
|
|
|
if p.is_dir() {
|
|
|
- let name = p
|
|
|
- .components()
|
|
|
- .rev()
|
|
|
- .map(|c| c.as_os_str().to_string_lossy().to_string())
|
|
|
- .collect::<Vec<_>>()
|
|
|
- .join("/");
|
|
|
- return axum::response::Html(dir_listing(&state.base, &name, &p)).into_response();
|
|
|
+ let root = repo_root_ok().unwrap_or_default();
|
|
|
+ let rel = p
|
|
|
+ .strip_prefix(&root)
|
|
|
+ .unwrap_or(&p)
|
|
|
+ .to_string_lossy()
|
|
|
+ .replace(std::path::MAIN_SEPARATOR_STR, "/");
|
|
|
+ return axum::response::Html(dir_listing(&state.base, &rel, &p)).into_response();
|
|
|
}
|
|
|
let text = match std::fs::read_to_string(&p) {
|
|
|
Ok(t) => t,
|
|
|
@@ -174,7 +176,7 @@ pub(crate) fn toml_links(content: &str, recipe: &str, base: &str) -> Vec<serde_j
|
|
|
if let Some(v) = first("docker_image_dir") {
|
|
|
out.push((
|
|
|
v.clone(),
|
|
|
- format!("{base}repo/docker-images/{v}/"),
|
|
|
+ format!("{base}/repo/docker-images/{v}/"),
|
|
|
format!("build dir: docker-images/{v}"),
|
|
|
));
|
|
|
}
|
|
|
@@ -182,14 +184,14 @@ pub(crate) fn toml_links(content: &str, recipe: &str, base: &str) -> Vec<serde_j
|
|
|
if let Some(prof) = first("build_profile") {
|
|
|
out.push((
|
|
|
prof.clone(),
|
|
|
- format!("{base}repo/docker-images/{img}/profiles/{prof}.env"),
|
|
|
+ format!("{base}/repo/docker-images/{img}/profiles/{prof}.env"),
|
|
|
format!("build profile: profiles/{prof}.env"),
|
|
|
));
|
|
|
}
|
|
|
if let Some(script) = first("venv_setup_script") {
|
|
|
out.push((
|
|
|
script.clone(),
|
|
|
- format!("{base}repo/recipes/{recipe}/{script}"),
|
|
|
+ format!("{base}/repo/recipes/{recipe}/{script}"),
|
|
|
format!("venv setup script: recipes/{recipe}/{script}"),
|
|
|
));
|
|
|
}
|
|
|
@@ -198,12 +200,12 @@ pub(crate) fn toml_links(content: &str, recipe: &str, base: &str) -> Vec<serde_j
|
|
|
let (href, title) = if is_builtin {
|
|
|
let file = alias.replace('_', "-") + ".sh";
|
|
|
(
|
|
|
- format!("{base}repo/host-scripts/{file}"),
|
|
|
+ format!("{base}/repo/host-scripts/{file}"),
|
|
|
format!("built-in script: host-scripts/{file}"),
|
|
|
)
|
|
|
} else {
|
|
|
(
|
|
|
- format!("{base}repo/recipes/{recipe}/{alias}"),
|
|
|
+ format!("{base}/repo/recipes/{recipe}/{alias}"),
|
|
|
format!("script: recipes/{recipe}/{alias}"),
|
|
|
)
|
|
|
};
|