aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bin/tosin-admin.rs58
-rw-r--r--src/urls.rs10
-rw-r--r--tests/tutorial/mod.rs39
3 files changed, 91 insertions, 16 deletions
diff --git a/src/bin/tosin-admin.rs b/src/bin/tosin-admin.rs
index a1f03fb..3eb57a1 100644
--- a/src/bin/tosin-admin.rs
+++ b/src/bin/tosin-admin.rs
@@ -1,5 +1,31 @@
+use std::env::set_current_dir;
+use std::fs;
+use std::io::Write as _;
+use std::process::Command;
+
use structopt::StructOpt;
+const TOSIN_DEPENDENCY: &str = concat!(r#"tosin = { path = ""#, env!("CARGO_MANIFEST_DIR"), r#"" }"#);
+const PROJECT_MAIN: &str = r#"
+use tosin::Settings;
+use tosin::contrib::admin;
+use tosin::urls::{UrlMap, url_map};
+
+fn urls() -> UrlMap {
+ url_map! {
+ "admin" / ..admin::site::urls(),
+ }
+}
+
+fn settings() -> Settings {
+ Settings {
+ ..Settings::default()
+ }
+}
+
+tosin::main!(urls(), settings());
+"#;
+
#[derive(StructOpt, Debug)]
enum Opt {
/// Start a new project/site (can contain multiple apps)
@@ -10,5 +36,35 @@ enum Opt {
fn main() {
let opts = Opt::from_args();
- dbg!(opts);
+ match opts {
+ Opt::StartProject { name } => {
+ match name {
+ Some(name) => {
+ // there's a name, so we're creating a project.
+ // TODO make this all more robust
+ let cargo_new = Command::new("cargo")
+ .args(&["new", "--bin", &name])
+ .status()
+ .unwrap();
+ if !cargo_new.success() {
+ panic!("cargo new failed");
+ }
+
+ set_current_dir(name).unwrap();
+
+ let mut cargo_toml = fs::OpenOptions::new()
+ .append(true)
+ .open("Cargo.toml")
+ .unwrap();
+ writeln!(cargo_toml, "{}", TOSIN_DEPENDENCY).unwrap();
+ drop(cargo_toml);
+
+ fs::write("src/main.rs", PROJECT_MAIN).unwrap();
+ }
+ None => {
+ todo!("absorb existing Rust project maybe??")
+ }
+ }
+ }
+ }
}
diff --git a/src/urls.rs b/src/urls.rs
index 80eba9e..2668835 100644
--- a/src/urls.rs
+++ b/src/urls.rs
@@ -1,6 +1,8 @@
use crate::http::Response;
pub use crate::url_map;
+pub use warp::path as warp_path;
+
pub type UrlMap = warp::filters::BoxedFilter<(Response,)>;
#[doc(hidden)]
@@ -40,20 +42,20 @@ macro_rules! __url_map_inner {
($chain:ident @rest) => { $chain };
(@one => $view:expr) => {
- ::warp::path::end().map($view)
+ $crate::urls::warp_path::end().map($view)
};
(@one $head:tt $(/ $tail:tt)* => $view:expr) => {
- ::warp::path!($head $(/ $tail)*).map($view)
+ $crate::urls::warp_path!($head $(/ $tail)*).map($view)
};
(@one $head:tt $(/ $tail:tt)* $child:expr) => {
- ::warp::path!($head $(/ $tail)*).and($child)
+ $crate::urls::warp_path!($head $(/ $tail)*).and($child)
};
}
#[macro_export]
macro_rules! url_map {
($($body:tt)*) => {{
- use ::warp::Filter;
+ use $crate::http::Filter;
$crate::__url_map_inner!(@root $($body)*)
.boxed()
}};
diff --git a/tests/tutorial/mod.rs b/tests/tutorial/mod.rs
index 576d3af..54f9c9f 100644
--- a/tests/tutorial/mod.rs
+++ b/tests/tutorial/mod.rs
@@ -1,8 +1,12 @@
use std::env::set_current_dir;
use std::fs;
-use std::io::Read;
+use std::io::{BufRead, BufReader};
use std::path::Path;
-use std::process::Command;
+use std::process::{Command, Stdio};
+use std::thread::sleep;
+use std::time::Duration;
+
+use rand::prelude::*;
trait ExitStatusExt {
fn check(self);
@@ -18,13 +22,13 @@ const CARGO: &str = env!("CARGO");
const PROJECT_DIR: &str = env!("CARGO_MANIFEST_DIR");
const TOSIN_ADMIN: &str = env!("CARGO_BIN_EXE_tosin-admin");
-fn get(url: &'static str) -> (hyper::StatusCode, String) {
+fn get(url: &str) -> (hyper::StatusCode, String) {
let get = async {
- use hyper::{Client, Uri};
+ use hyper::Client;
let client = Client::new();
- let res = client.get(Uri::from_static(url)).await.unwrap();
+ let res = client.get(url.parse().unwrap()).await.unwrap();
let status = res.status();
@@ -44,6 +48,11 @@ pub fn step1(dest: &str) {
// tosin-admin start-project {dest}
set_current_dir(PROJECT_DIR).unwrap();
set_current_dir("target").unwrap();
+ if fs::metadata("tests").is_err() {
+ fs::create_dir("tests").unwrap();
+ }
+ set_current_dir("tests").unwrap();
+ fs::write("Cargo.toml", "[workspace]\nmembers = ['tutorial1']").unwrap();
if fs::metadata(dest).is_ok() {
fs::remove_dir_all(dest).unwrap();
}
@@ -59,20 +68,28 @@ pub fn step1(dest: &str) {
assert!(fs::read_to_string("src/main.rs").unwrap().contains("tosin::main!"));
// cargo run run-server
+ let port = thread_rng().gen_range(8081u16..9000u16);
let mut server = Command::new(CARGO)
- .args(&["run", "run-server", "8069"])
+ .args(&["run", "run-server", &format!("{}", port)])
+ .stdout(Stdio::piped())
.spawn()
.unwrap();
- let server_poke = get("http://127.0.0.1:8069");
+ let mut server_output = String::new();
+ let server_stdout = server.stdout.take().unwrap();
+ let mut server_stdout = BufReader::new(server_stdout);
+ server_stdout.read_line(&mut server_output).unwrap();
+ assert!(server_output.contains(&format!("http://127.0.0.1:{}", port)));
+ sleep(Duration::from_secs_f32(0.5));
+ let server_poke = get(&format!("http://127.0.0.1:{}/", port));
assert_eq!(server_poke.0, hyper::StatusCode::NOT_FOUND);
+ if let Ok(Some(exit_status)) = server.try_wait() {
+ exit_status.check();
+ }
server.kill().unwrap();
- let mut server_stdout = String::new();
- server.stdout.unwrap().read_to_string(&mut server_stdout).unwrap();
- assert!(server_stdout.contains("http://127.0.0.1:8069"));
// could `cargo run start-app polls` or `tosin-admin start-app polls` so
// flip a coin i guess
- if rand::random() {
+ if random() {
let mut cmd = Command::new(CARGO);
cmd.arg("run");
cmd