(Query(query): Query<ListFilesQuery>)
| 2932 | } |
| 2933 | |
| 2934 | async fn list_files(Query(query): Query<ListFilesQuery>) -> Result<Json<Vec<FileInfo>>> { |
| 2935 | let root = project_root()?; |
| 2936 | let path = resolve_input_path(&query.path, &root)?; |
| 2937 | let mut files = Vec::new(); |
| 2938 | |
| 2939 | if path.is_dir() { |
| 2940 | if let Ok(entries) = std::fs::read_dir(&path) { |
| 2941 | for entry in entries.flatten() { |
| 2942 | let path_buf = entry.path(); |
| 2943 | if !is_within_root(&path_buf, &root) { |
| 2944 | continue; |
| 2945 | } |
| 2946 | let file_type = if path_buf.is_dir() { |
| 2947 | "directory" |
| 2948 | } else { |
| 2949 | "file" |
| 2950 | }; |
| 2951 | let size = if path_buf.is_file() { |
| 2952 | std::fs::metadata(&path_buf).ok().map(|m| m.len()) |
| 2953 | } else { |
| 2954 | None |
| 2955 | }; |
| 2956 | let modified = std::fs::metadata(&path_buf).ok().and_then(|m| { |
| 2957 | m.modified().ok().map(|t| { |
| 2958 | t.duration_since(std::time::UNIX_EPOCH) |
| 2959 | .unwrap_or_default() |
| 2960 | .as_millis() as i64 |
| 2961 | }) |
| 2962 | }); |
| 2963 | |
| 2964 | files.push(FileInfo { |
| 2965 | name: entry.file_name().to_string_lossy().to_string(), |
| 2966 | path: path_buf.to_string_lossy().to_string(), |
| 2967 | file_type: file_type.to_string(), |
| 2968 | size, |
| 2969 | modified, |
| 2970 | }); |
| 2971 | } |
| 2972 | } |
| 2973 | } |
| 2974 | |
| 2975 | Ok(Json(files)) |
| 2976 | } |
| 2977 | |
| 2978 | async fn read_file(Query(query): Query<ListFilesQuery>) -> Result<Json<serde_json::Value>> { |
| 2979 | let root = project_root()?; |
nothing calls this directly
no test coverage detected