Compare commits

..

7 Commits

Author SHA1 Message Date
joeac 52b5da658c rename joeac-build -> shapi 2026-06-08 09:08:13 +01:00
joeac 158044c320 replaces git repo config with routes config 2026-06-08 09:06:08 +01:00
joeac 1277a0733f pull and (TODO) build and (TODO) push 2026-06-01 08:37:23 +01:00
joeac c8cad70d59 adds git2 2026-05-15 15:29:59 +01:00
joeac f849de20bb can configure repositories, hello world response 2026-05-15 15:27:33 +01:00
joeac 2068342144 add anyhow, serde, toml, dirs 2026-05-15 14:39:59 +01:00
joeac e433feddbe installs rocket, hello world endpoint 2026-05-15 14:16:27 +01:00
4 changed files with 2378 additions and 4 deletions
Generated
+2296 -1
View File
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -1,6 +1,13 @@
[package]
name = "joeac-build"
name = "shapi"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.102"
dirs = "6.0.0"
git2 = "0.20.4"
is_executable = "1.0.5"
rocket = "0.5.1"
serde = "1.0.228"
toml = "1.1.2"
+37 -2
View File
@@ -1,3 +1,38 @@
fn main() {
println!("Hello, world!");
use std::path::PathBuf;
use dirs::config_dir;
#[macro_use] extern crate rocket;
mod routes;
use anyhow::Result;
use routes::read_routes;
use rocket::{State, http::Status};
const BIN_NAME: &str = "shapi";
#[launch]
fn rocket() -> _ {
let routes_path: PathBuf = config_dir().unwrap().join(BIN_NAME).join("routes");
let routes = read_routes(&routes_path).expect("Failed to read routes config");
rocket::build().manage(routes).mount("/", routes![index])
}
#[get("/<req_path..>")]
fn index(req_path: PathBuf, routes: &State<Vec<String>>) -> (Status, String) {
match req_path.to_str().map(String::from) {
None => (Status::BadRequest, format!("Failed to convert request path to unicode: {:?}", req_path)),
Some(req_path) => match routes.iter().find(|&route| req_path.eq(route)) {
None => (Status::NotFound, format!("Route not configured: {req_path}")),
Some(route) => match execute_route(route) {
Ok(_) => todo!(),
Err(_) => todo!(),
},
}
}
}
fn execute_route(route: &str) -> Result<()> {
todo!();
}
+37
View File
@@ -0,0 +1,37 @@
use anyhow::anyhow;
use anyhow::Result;
use is_executable::is_executable;
use std::fs::DirEntry;
use std::fs::metadata;
use std::{fs::read_dir, path::PathBuf};
pub fn read_routes(path: &PathBuf) -> Result<Vec<String>> {
read_routes_with_prefix(path, "/")
}
fn read_routes_with_prefix(path: &PathBuf, prefix: &str) -> Result<Vec<String>> {
Ok(
read_dir(path)?
.map(|entry| read_entry_with_prefix(&entry?, path, prefix))
.flatten().flatten().collect())
}
fn read_entry_with_prefix(entry: &DirEntry, dir_path: &PathBuf, prefix: &str) -> Result<Vec<String>> {
let entry_path = entry.path();
let metadata = metadata(&entry_path)?;
if metadata.is_dir() {
let entry_basename = entry_path.file_name()
.ok_or(anyhow!("No basename for file: {:?} in directory: {:?}", entry_path, dir_path))?;
let result = read_routes_with_prefix(&entry_path, &format!("{prefix}{:?}/", entry_basename));
result
} else if metadata.is_file() {
if !is_executable(entry.path()) {
eprintln!("Found {:?} in routes config directory, but cannot configure route as the file is not executable", entry);
return Ok(Vec::new());
}
Ok(vec![format!("{:?}", entry_path)])
} else {
eprintln!("Found {:?} in routes config directory, but cannot configure route as the file is neither a directory nor an ordinary file", entry);
Ok(Vec::new())
}
}