Skip invalid app records when listing library apps
This commit is contained in:
@@ -724,10 +724,17 @@ impl ArtifactLibraryStore {
|
||||
let Some(app_id) = path.file_name().and_then(|value| value.to_str()) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(app) = self.get_app(app_id)? {
|
||||
if app.manifest.visibility != AppVisibility::Archived {
|
||||
match self.get_app(app_id) {
|
||||
Ok(Some(app)) if app.manifest.visibility != AppVisibility::Archived => {
|
||||
apps.push(app);
|
||||
}
|
||||
Ok(Some(_)) | Ok(None) => {}
|
||||
Err(error) => {
|
||||
eprintln!(
|
||||
"artifact library: skipping unreadable app `{}` while listing apps: {}",
|
||||
app_id, error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
apps.sort_by(|left, right| {
|
||||
@@ -2016,4 +2023,61 @@ mod tests {
|
||||
std::env::remove_var("CLAW_WORKER_DEFAULT_CWD");
|
||||
let _ = std::fs::remove_dir_all(&state_root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_apps_skips_invalid_app_directories() {
|
||||
let _lock = test_env_lock();
|
||||
let state_root =
|
||||
std::env::temp_dir().join(format!("artifact-lib-list-{}", super::now_secs()));
|
||||
let workspace = state_root.join("workspace");
|
||||
let _ = std::fs::remove_dir_all(&state_root);
|
||||
std::fs::create_dir_all(&workspace).expect("workspace should exist");
|
||||
std::env::set_var("CLAW_WORKER_STATE_ROOT", &state_root);
|
||||
std::env::set_var("CLAW_WORKER_DEFAULT_CWD", &workspace);
|
||||
|
||||
let source = workspace.join("dashboard.html");
|
||||
std::fs::write(&source, "<!doctype html><body>one</body>").expect("html source should write");
|
||||
let store = ArtifactLibraryStore::new();
|
||||
let feed = store
|
||||
.record_turn(
|
||||
"turn-3",
|
||||
vec![FeedFileInput {
|
||||
title: "dashboard.html".to_string(),
|
||||
file_name: "dashboard.html".to_string(),
|
||||
source_kind: FeedItemSourceKind::Generated,
|
||||
source_turn_id: Some("turn-3".to_string()),
|
||||
source_file_id: Some("generated-3".to_string()),
|
||||
source_files: vec!["dashboard.html".to_string()],
|
||||
change_kind: Some(FeedItemChangeKind::Created),
|
||||
media_type: Some("text/html".to_string()),
|
||||
source_path: Some(source),
|
||||
preview_text: Some("Initial dashboard".to_string()),
|
||||
deleted: false,
|
||||
}],
|
||||
)
|
||||
.expect("turn should record");
|
||||
let packaged = store
|
||||
.package_feed_item(AppPackageRequest {
|
||||
feed_item_id: feed[0].feed_item_id.clone(),
|
||||
requested_app_id: Some("dash".to_string()),
|
||||
title: Some("Dash".to_string()),
|
||||
description: None,
|
||||
})
|
||||
.expect("packaging should succeed")
|
||||
.expect("app should package");
|
||||
|
||||
let broken_dir = super::library_apps_dir()
|
||||
.expect("library apps dir")
|
||||
.join("broken-app");
|
||||
std::fs::create_dir_all(&broken_dir).expect("create broken dir");
|
||||
std::fs::write(broken_dir.join("manifest.json"), "{not-json").expect("write broken manifest");
|
||||
|
||||
let apps = store.list_apps().expect("listing should skip broken app");
|
||||
assert_eq!(apps.len(), 1);
|
||||
assert_eq!(apps[0].manifest.app_id, packaged.app.manifest.app_id);
|
||||
|
||||
std::env::remove_var("CLAW_WORKER_STATE_ROOT");
|
||||
std::env::remove_var("CLAW_WORKER_DEFAULT_CWD");
|
||||
let _ = std::fs::remove_dir_all(&state_root);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user