From 8b25f9f8e9b0d88b990c56b979e1d26e17bf47b8 Mon Sep 17 00:00:00 2001 From: stubbfelnewpc Date: Wed, 1 Jul 2020 21:19:36 +0200 Subject: [PATCH] add fetch source code --- server/cli/src/main.rs | 5 +- server/lib/src/lib.rs | 12 +-- server/podman/src/lib.rs | 188 ++++++++++++++++++++++++--------------- 3 files changed, 123 insertions(+), 82 deletions(-) diff --git a/server/cli/src/main.rs b/server/cli/src/main.rs index 900d50b..3aa43e9 100644 --- a/server/cli/src/main.rs +++ b/server/cli/src/main.rs @@ -12,9 +12,10 @@ use std::env; use nixideserver_lib::*; fn main() { - let eng = DummyEngine {}; + let _eng = DummyEngine {}; let _podman_eng = PodmanEngine::new(env::current_dir().unwrap()); - let exectuor = NixIdeManageService::new(Box::new(eng)); + //let exectuor = NixIdeManageService::new(Box::new(eng)); + let exectuor = NixIdeManageService::new(Box::new(_podman_eng)); rocket::ignite() .mount( "/api/v1/", diff --git a/server/lib/src/lib.rs b/server/lib/src/lib.rs index 2444a22..f4b39ec 100644 --- a/server/lib/src/lib.rs +++ b/server/lib/src/lib.rs @@ -38,9 +38,9 @@ pub enum IdeState { #[derive(Serialize, Deserialize, Hash, JsonSchema)] pub struct OpenGitParam { - inquirer: String, - clone_url: String, - ref_name: String, + pub inquirer: String, + pub clone_url: String, + pub ref_name: String, } #[derive(Serialize, Deserialize, Hash, JsonSchema)] @@ -52,7 +52,7 @@ pub struct IdeStateResponse { pub trait NixIdeManageServiceEngine { fn fetch_current_ide_state(&self, ide_id: &str) -> Result; - fn start_open(&mut self, ide_id: &str, param: &OpenGitParam) -> Result; + fn start_open(&self, ide_id: &str, param: &OpenGitParam) -> Result; } pub struct NixIdeManageService { @@ -74,7 +74,7 @@ impl NixIdeManageServiceEngine for DummyEngine { Ok(IdeState::OPENING) } - fn start_open(&mut self, _ide_id: &str, _param: &OpenGitParam) -> Result { + fn start_open(&self, _ide_id: &str, _param: &OpenGitParam) -> Result { Ok(IdeState::OPENING) } } @@ -145,7 +145,7 @@ pub fn v1_open_inquirer_git( }; let ide_id = create_ide_id(¶m); - srv.eng.borrow_mut() + srv.eng.borrow() .start_open(&ide_id, ¶m) .map_err(|_| Error {}) .and_then(|starting_result| { diff --git a/server/podman/src/lib.rs b/server/podman/src/lib.rs index 7d692d0..3dbaa6e 100644 --- a/server/podman/src/lib.rs +++ b/server/podman/src/lib.rs @@ -9,8 +9,8 @@ extern crate serde_json; use nixideserver_lib::*; use rocket::http::Status; use std::fs; -use std::io::prelude::*; use std::path::{Path, PathBuf}; +use std::process::Command; // podman create --name test -p 3000:3000 -v $PWD:/nixide -w /nixide docker.io/nixos/nix nix-shell --pure start-ide.nix --run run_ide.sh @@ -27,7 +27,9 @@ pub enum PodmanState { } #[derive(Serialize, Deserialize, Clone)] pub struct PodmanContainer { + ide_id: String, state: PodmanState, + ide_state: IdeState, ide_param: NixIdeServerParam, } @@ -42,7 +44,13 @@ pub struct PodmanEngine { } impl PodmanEngine { - pub fn new(working_folder: PathBuf) -> Self { + pub fn new(working_folder: PathBuf) -> PodmanEngineTraitImpl { + PodmanEngineTraitImpl { + working_folder + } + } + + fn _new(working_folder: PathBuf) -> Self { let list_path = format!("{}/.podman_containers", &working_folder.display()); let list = match read_from_list_file(&list_path) { Ok(p) => p, @@ -58,76 +66,90 @@ impl PodmanEngine { } pub fn save(&self) -> Result<(), std::io::Error> { - let json_string = serde_json::to_string_pretty(&self.list).unwrap();// .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))?; - fs::write(&format!("{}/.podman_containers", &self.working_folder.display()), json_string) + let json_string = serde_json::to_string_pretty(&self.list).unwrap(); // .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))?; + fs::write( + &format!("{}/.podman_containers", &self.working_folder.display()), + json_string, + ) + } + + pub fn reload(trait_impl : &PodmanEngineTraitImpl) -> Result { + Ok( + Self::_new(trait_impl.working_folder.clone()) + ) } } + #[derive(Serialize, Deserialize)] struct PodmanIdeStatus { ide_state: IdeState, } -impl NixIdeManageServiceEngine for PodmanEngine { +pub struct PodmanEngineTraitImpl { + working_folder: PathBuf +} + +impl NixIdeManageServiceEngine for PodmanEngineTraitImpl { fn fetch_current_ide_state(&self, ide_id: &str) -> Result { - let state_file = create_state_file_path(&self.working_folder, ide_id); - let mut file = fs::File::open(state_file) - .map_err(|_| Status::new(500, "could not open state file"))?; - let mut contents = String::new(); - file.read_to_string(&mut contents) - .map_err(|_| Status::NotFound)?; - let ide_state = - read_ide_state(&contents).map_err(|_| Status::new(500, "unexpected json string"))?; - Ok(ide_state) + let eng = PodmanEngine::reload(self) + .map_err(|_| Status::new(500, "internal error : reload engine"))?; + match eng.list.container.iter().find(|i| i.ide_id.eq(ide_id)) { + Some(i) => Ok(i.ide_state.clone()), + _ => Err(Status::NotFound), + } } - fn start_open(&mut self, ide_id: &str, _param: &OpenGitParam) -> Result { - let ide_folder = create_ide_folder_path(&self.working_folder, ide_id); - let state_file = create_state_file_path_from_ide_folder(&ide_folder); - fs::create_dir_all(&ide_folder) - .and_then(|_| { - fs::OpenOptions::new() - .create(true) - .write(true) - .read(true) - .open(state_file) - }) - .and_then(|mut file| { - let mut buffer = String::new(); - match file.read_to_string(&mut buffer) { - Ok(s) if s > 0 => read_ide_state(&buffer) - .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData)), - _ => { - let status = PodmanIdeStatus { - ide_state: IdeState::OPENING, - }; - let listen_port = self - .list - .container - .iter() - .max_by_key(|i| i.ide_param.listen_port) - .and_then(|i| Some(i.ide_param.listen_port + 1)) - .or(Some(3000)) - .unwrap(); - let ide_param = NixIdeServerParam { - listen_address: default_listen_address(), - listen_port: listen_port, - app_folder: default_app_folder(), - project_folder: default_project_folder(), - working_folder: default_working_folder(), - }; + fn start_open(&self, ide_id: &str, param: &OpenGitParam) -> Result { + let mut eng = PodmanEngine::reload(self) + .map_err(|_| Status::new(500, "internal error : reload engine"))?; + match eng.list.container.iter().find(|i| i.ide_id.eq(ide_id)) { + Some(i) => Ok(i.ide_state.clone()), + _ => { + let ide_folder = create_ide_folder_path(&self.working_folder, ide_id); + fs::create_dir_all(&ide_folder) + .map_err(|_| Status::new(500, "internal error : can't create ide folder"))?; + let listen_port = eng + .list + .container + .iter() + .max_by_key(|i| i.ide_param.listen_port) + .and_then(|i| Some(i.ide_param.listen_port + 1)) + .or(Some(3000)) + .unwrap(); + let ide_param = NixIdeServerParam { + listen_address: default_listen_address(), + listen_port, + app_folder: default_app_folder(), + project_folder: default_project_folder(), + working_folder: default_working_folder(), + }; - let container = PodmanContainer { - state: PodmanState::FetchingSource, - ide_param, - }; - self.list.container.push(container); - self.save()?; - file.write(serde_json::to_string_pretty(&status)?.as_bytes())?; - Ok(status.ide_state) + let container = PodmanContainer { + ide_id: ide_id.to_owned(), + ide_state: IdeState::OPENING, + state: PodmanState::FetchingSource, + ide_param, + }; + eng.list.container.push(container); + eng.save() + .map_err(|_| Status::new(500, "internal error: can't save curent state"))?; + + fetch_sources(&format!("{}/repo", ide_folder), param) + .map_err(|_| Status::new(500, "internal error"))?; + match eng.list.container.iter_mut().find(|i| i.ide_id.eq(ide_id)) { + Some(i) => { + i.state = PodmanState::StartingContainer; + eng.save().map_err(|_| { + Status::new(500, "internal error: can't save curent state") + })?; } - } - }) - .map_err(|_| Status::new(500, "internal error")) + _ => {} + }; + + Ok(IdeState::OPENING) + } + } + // println!("foo {:x}", hash); // let out = Command::new("podman") // .arg("create") @@ -188,24 +210,10 @@ fn default_working_folder() -> String { "$PWD".to_owned() } -fn create_state_file_path(working_folder_path: &Path, ide_id: &str) -> String { - let ide_folder = format!("{}/{}", working_folder_path.display(), ide_id); - create_state_file_path_from_ide_folder(&ide_folder) -} - -fn create_state_file_path_from_ide_folder(ide_folder: &str) -> String { - format!("{}/.ide_state", ide_folder) -} - fn create_ide_folder_path(working_folder_path: &Path, ide_id: &str) -> String { format!("{}/{}", working_folder_path.display(), ide_id) } -fn read_ide_state(json_string: &str) -> Result { - let status: PodmanIdeStatus = serde_json::from_str(json_string)?; - Ok(status.ide_state) -} - fn read_from_list_file(path: &str) -> Result { match fs::read_to_string(path) { Ok(json_string) => serde_json::from_str::(&json_string) @@ -213,3 +221,35 @@ fn read_from_list_file(path: &str) -> Result Err(e), } } + +fn fetch_sources(repo_path: &str, param: &OpenGitParam) -> Result<(), std::io::Error> { + Command::new("git") + .arg("clone") + .arg("-n") + .arg(¶m.clone_url) + .arg(repo_path) + .output()?; + + Command::new("git") + .arg("-C") + .arg(repo_path) + .arg("checkout") + .arg(¶m.ref_name) + .output() + .map(|_| ()) +} + +#[test] +fn test_fetch_sources() { + let now = std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap(); + let temp_dir = std::env::temp_dir(); + let repo_path = format!("{}/{}", temp_dir.display(), now.as_secs()); + let git_param = OpenGitParam { + clone_url: "https://github.com/jmesmon/rust-hello-world.git".to_owned(), + inquirer: "stubbfel".to_owned(), + ref_name: "master".to_owned(), + }; + assert_eq!(fetch_sources(&repo_path, &git_param).unwrap(), ()); +}