fix: give each 404 copy that matches what was actually missing
commit
49e8543fix: give each 404 copy that matches what was actually missing
not_found() always said No such repository, even for a missing file, directory, commit, or check run inside a repository that resolved just fine, which read as though the whole repository had vanished. It now takes a reason string, and every call site reports what it was actually looking for.
Assisted-by: Claude:claude-sonnet-5
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
crates/git-ents-server/src/web/mod.rs
@@ -96,7 +96,7 @@
return route(state, &repo, &rel, rest, query, host, session).await;
}
- not_found().into_response()
+ not_found("No such repository.").into_response()
}
/// Resolve the leading path segments to a repository: the shortest valid prefix
@@ -198,12 +198,12 @@
}
let Some((repo, rel, rest)) = resolve_repo(&state.data_dir, &segments) else {
- return not_found().into_response();
+ return not_found("No such repository.").into_response();
};
match rest {
["settings"] => save_settings(state, &repo, &rel, cookie, body).await,
["comment"] => save_comment(state, &repo, &rel, cookie, body).await,
- _ => not_found().into_response(),
+ _ => not_found("No such page.").into_response(),
}
}
@@ -537,7 +537,7 @@
)
.await
.into_response(),
- _ => not_found().into_response(),
+ _ => not_found("No such page.").into_response(),
}
}
@@ -763,8 +763,9 @@
)
}
-/// A `404` page.
-fn not_found() -> (StatusCode, Markup) {
+/// A `404` page reporting `reason`, e.g. "No such file." or "No such commit.",
+/// so a missing sub-resource does not read as a missing repository.
+fn not_found(reason: &str) -> (StatusCode, Markup) {
(
StatusCode::NOT_FOUND,
page(
@@ -772,7 +773,7 @@
html! {
div.blankslate {
h2 { "404" }
- p { "No such repository." }
+ p { (reason) }
a.btn href="/" { "Back to repositories" }
}
},
crates/git-ents-server/src/web/pages.rs
@@ -295,7 +295,7 @@
) -> Response {
let rel = &meta.rel;
let Some(selected) = browse_path(sub) else {
- return not_found().into_response();
+ return not_found("No such file or directory.").into_response();
};
// Classify the selection so the right pane shows a file and the tree expands
@@ -314,7 +314,7 @@
.rsplit_once('/')
.map_or(String::new(), |(d, _)| d.to_owned()),
_ if selected.is_empty() => String::new(),
- _ => return not_found().into_response(),
+ _ => return not_found("No such file or directory.").into_response(),
};
// Expand every ancestor directory of the selection (and the selection itself
@@ -496,7 +496,7 @@
) -> Response {
let rel = &meta.rel;
let Some(dir) = browse_path(sub) else {
- return not_found().into_response();
+ return not_found("No such directory.").into_response();
};
let spec = if dir.is_empty() {
"HEAD".to_owned()
@@ -505,7 +505,7 @@
};
let entries = list_tree(repo, &spec).await;
if entries.is_empty() && !dir.is_empty() {
- return not_found().into_response();
+ return not_found("No such directory.").into_response();
}
let name = meta.name();
repo_shell(
@@ -563,7 +563,7 @@
) -> Response {
let rel = &meta.rel;
let Some(path) = browse_path(sub).filter(|p| !p.is_empty()) else {
- return not_found().into_response();
+ return not_found("No such file.").into_response();
};
let spec = format!("HEAD:{path}");
if git_output(repo, &["cat-file", "-t", &spec])
@@ -571,12 +571,12 @@
.as_deref()
!= Some("blob\n")
{
- return not_found().into_response();
+ return not_found("No such file.").into_response();
}
let Some((bytes, truncated)) =
git_output_capped(repo, &["cat-file", "-p", &spec], MAX_RENDER_BYTES).await
else {
- return not_found().into_response();
+ return not_found("No such file.").into_response();
};
let name = path.rsplit('/').next().unwrap_or(&path);
let displayable = !truncated && !is_binary(&bytes);
@@ -814,7 +814,7 @@
auth: Option<&super::Auth>,
) -> Response {
if sha.is_empty() || sha.len() > 64 || !sha.bytes().all(|b| b.is_ascii_hexdigit()) {
- return not_found().into_response();
+ return not_found("No such commit.").into_response();
}
let Some(info) = git_output(
repo,
@@ -822,14 +822,14 @@
)
.await
else {
- return not_found().into_response();
+ return not_found("No such commit.").into_response();
};
let mut parts = info.split('\u{0}');
let Some(oid) = parts
.next()
.and_then(|h| ObjectId::from_hex(h.trim().as_bytes()).ok())
else {
- return not_found().into_response();
+ return not_found("No such commit.").into_response();
};
let author = parts.next().unwrap_or_default().to_owned();
let when = parts.next().and_then(parse_iso);
@@ -1076,10 +1076,10 @@
auth: Option<&super::Auth>,
) -> Response {
let Some(commit_oid) = ObjectId::from_hex(commit.as_bytes()).ok() else {
- return not_found().into_response();
+ return not_found("No such check run.").into_response();
};
let Some(outcome) = latest_outcome(repo, commit_oid, name).await else {
- return not_found().into_response();
+ return not_found("No such check run.").into_response();
};
let short_commit = commit.get(..8).unwrap_or(commit);
let rel = &meta.rel;
@@ -1140,7 +1140,7 @@
live_runs: &git_effect::engine::LiveRegistry,
) -> Response {
let Some(commit_oid) = ObjectId::from_hex(commit.as_bytes()).ok() else {
- return not_found().into_response();
+ return not_found("No such check run.").into_response();
};
let key = (repo.to_owned(), commit_oid, name.to_owned());
let recording = git_effect::engine::live_snapshot(live_runs, &key);
@@ -1169,10 +1169,10 @@
live_runs: &git_effect::engine::LiveRegistry,
) -> Response {
let Some(commit_oid) = ObjectId::from_hex(commit.as_bytes()).ok() else {
- return not_found().into_response();
+ return not_found("No such check run.").into_response();
};
let Some(outcome) = latest_outcome(repo, commit_oid, name).await else {
- return not_found().into_response();
+ return not_found("No such check run.").into_response();
};
let live = super::render::is_in_progress(outcome.status)
.then(|| {
@@ -1181,7 +1181,7 @@
})
.flatten();
let Some(recording) = live.or(outcome.recording) else {
- return not_found().into_response();
+ return not_found("No recording available for this check run.").into_response();
};
let short_commit = commit.get(..8).unwrap_or(commit);
let filename = format!(