diff --git a/Cargo.lock b/Cargo.lock index f90361c..33f324c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -656,6 +656,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "is_executable" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baabb8b4867b26294d818bf3f651a454b6901431711abb96e296245888d6e8c4" +dependencies = [ + "windows-sys 0.60.2", +] + [[package]] name = "itoa" version = "1.0.18" @@ -679,6 +688,7 @@ dependencies = [ "anyhow", "dirs", "git2", + "is_executable", "rocket", "serde", "toml 1.1.2+spec-1.1.0", @@ -1860,6 +1870,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1893,13 +1912,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -1912,6 +1948,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -1924,6 +1966,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -1936,12 +1984,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -1954,6 +2014,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -1966,6 +2032,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -1978,6 +2050,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -1990,6 +2068,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.7.15" diff --git a/Cargo.toml b/Cargo.toml index a5d02cc..2416a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" 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" diff --git a/src/build.rs b/src/build.rs deleted file mode 100644 index 7f83869..0000000 --- a/src/build.rs +++ /dev/null @@ -1,52 +0,0 @@ -use anyhow::{Error, Result}; -use git2::BranchType; - -use crate::config::RepoConfig; - -pub fn pull_or_clone_and_build_and_push(repo: &RepoConfig) -> Result<(), BuildError> { - let git_repo = pull_or_clone(repo)?; - build(&git_repo)?; - push(&git_repo)?; - - Ok(()) -} - -fn pull_or_clone(repo: &RepoConfig) -> Result { - match git2::Repository::open(&repo.local_git_repo) { - Ok(git_repo) => { - pull(&git_repo).map_err(|err| BuildError::FailedToPull(err))?; - Ok(git_repo) - }, - - Err(open_err) => match git2::Repository::clone(&repo.remote_git_repo, &repo.local_git_repo) { - Ok(git_repo) => Ok(git_repo), - Err(clone_err) => Err(BuildError::FailedToOpenOrClone(open_err.into(), clone_err.into())), - } - } -} - -fn pull(git_repo: &git2::Repository) -> Result<()> { - let mut origin = git_repo.find_remote("origin")?; - let (main_branch, main_branch_name) = git_repo.find_branch("main", BranchType::Local).map(|b| (b, "main")) - .or_else(|_| git_repo.find_branch("master", BranchType::Local).map(|b| (b, "master")))?; - let upstream_main_branch = main_branch.upstream()?; - - git_repo.set_head(main_branch_name)?; - origin.fetch(&[main_branch_name], None, None)?; - let upstream_commit = git_repo.reference_to_annotated_commit(&upstream_main_branch.into_reference())?; - git_repo.merge(&[&upstream_commit], None, None)?; - Ok(()) -} - -fn build(git_repo: &git2::Repository) -> Result<(), BuildError> { - todo!() -} - -fn push(git_repo: &git2::Repository) -> Result<(), BuildError> { - todo!() -} - -pub enum BuildError { - FailedToOpenOrClone(Error, Error), - FailedToPull(Error), -} diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index 5d17bfc..0000000 --- a/src/config.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::path::PathBuf; - -use anyhow::Context; -use serde::Deserialize; - -pub fn read_config(path: &PathBuf) -> anyhow::Result { - let toml = std::fs::read(path) - .with_context(|| format!("Failed to read config file at {:#?}", path))?; - let config = toml::from_slice(&toml) - .with_context(|| format!("Failed to parse config file at {:#?}", path))?; - Ok(config) -} - -#[derive(Debug, Default, Deserialize)] -pub struct Config { - pub repositories: Vec, -} - -#[derive(Debug, Deserialize)] -pub struct RepoConfig { - pub remote_git_repo: String, - pub local_git_repo: String, - pub remote_package_repo: String, -} diff --git a/src/main.rs b/src/main.rs index 42cfaae..5dd5db5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,47 +4,35 @@ use dirs::config_dir; #[macro_use] extern crate rocket; -mod build; -mod config; +mod routes; -use config::read_config; +use anyhow::Result; +use routes::read_routes; use rocket::{State, http::Status}; -use crate::{build::{BuildError, pull_or_clone_and_build_and_push}, config::Config}; - const BIN_NAME: &str = "build-joeac"; #[launch] fn rocket() -> _ { - let config_path: PathBuf = config_dir().unwrap() - .join(BIN_NAME).join(BIN_NAME).with_added_extension("toml"); - let config = read_config(&config_path).inspect_err(|err| - eprintln!("Failed to read config. Error: {}\nProceeding with defaults", err)) - .unwrap_or(Config::default()); - - rocket::build().manage(config).mount("/", routes![index]) + 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("/")] -fn index(remote_git_repo: PathBuf, config: &State) -> (Status, String) { - match remote_git_repo.to_str() { - None => (Status::BadRequest, format!("Failed to convert request path to unicode: {:?}", remote_git_repo)), - Some(remote_git_repo) => match config.repositories.iter().find(|repo| repo.remote_git_repo.eq(remote_git_repo)) { - None => (Status::NotFound, format!("Remote git repository not configured: {remote_git_repo}")), - Some(repo) => match pull_or_clone_and_build_and_push(repo) { - Err(BuildError::FailedToOpenOrClone(open_err, clone_err)) => ( - Status::InternalServerError, - format!( - "Failed to open or clone git repository. Error opening: {:#?}\n\nError cloning: {:#?}", - open_err, - clone_err) - ), - Err(BuildError::FailedToPull(err)) => ( - Status::InternalServerError, - format!("Failed to pull git repository. Error: {:#?}", err), - ), - Ok(()) => (Status::Ok, String::from("Pulled, built and pushed image")), - } +#[get("/")] +fn index(req_path: PathBuf, routes: &State>) -> (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!(); +} diff --git a/src/routes.rs b/src/routes.rs new file mode 100644 index 0000000..9a1e401 --- /dev/null +++ b/src/routes.rs @@ -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> { + read_routes_with_prefix(path, "/") +} + +fn read_routes_with_prefix(path: &PathBuf, prefix: &str) -> Result> { + 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> { + 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()) + } +}