1use clap::Args;
2use reqwest::StatusCode;
3use std::{error::Error, ffi::OsString, fs, io::stdout, path, time::Duration};
4
5use crate::cmd::init;
6use crate::cmd::run;
7use crate::config;
8
9use crate::{
10 categories::Category,
11 github,
12 net::{self, kill_port},
13};
14
15#[derive(Args, Debug)]
16pub struct CheckOptions {
17 #[arg(long, default_value_t = false)]
18 skip_git: bool,
19 #[arg(long, default_value_t = 3000)]
20 port: u16,
21}
22
23#[derive(Debug)]
24pub enum OsedaCheckError {
25 MissingConfig(String),
26 BadConfig(String),
27 BadGitCredentials(String),
28 DirectoryNameMismatch(String),
29 CouldNotPingLocalPresentation(String),
30}
31
32impl std::error::Error for OsedaCheckError {}
33
34impl std::fmt::Display for OsedaCheckError {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 Self::MissingConfig(msg) => write!(f, "Missing config file {}", msg),
38 Self::BadConfig(msg) => write!(f, "Bad config file {}", msg),
39 Self::BadGitCredentials(msg) => write!(f, "Missing git credentials {}", msg),
40 Self::DirectoryNameMismatch(msg) => {
41 write!(f, "Project name does not match directory {}", msg)
42 }
43 Self::CouldNotPingLocalPresentation(msg) => {
44 write!(f, "Could not ping localhost after project was ran {}", msg)
45 }
46 }
47 }
48}
49
50pub fn check(opts: CheckOptions) -> Result<(), OsedaCheckError> {
51 match verify_project(opts.skip_git, opts.port) {
54 OsedaProjectStatus::DeployReady => return Ok(()),
55 OsedaProjectStatus::NotDeploymentReady(err) => return Err(err),
56 }
57}
58
59pub enum OsedaProjectStatus {
60 DeployReady,
61 NotDeploymentReady(OsedaCheckError),
62}
63
64pub fn verify_project(skip_git: bool, port_num: u16) -> OsedaProjectStatus {
65 let conf = match config::read_and_validate_config(skip_git) {
68 Ok(conf) => conf,
69 Err(err) => return OsedaProjectStatus::NotDeploymentReady(err),
70 };
71
72 let run_handle = std::thread::spawn(move || run::run());
73
74 std::thread::sleep(Duration::from_millis(5000));
75
76 let addr = format!("http://localhost:{}", port_num);
77 let status = match net::get_status(&addr) {
78 Ok(status) => status,
79 Err(_) => {
80 return OsedaProjectStatus::NotDeploymentReady(
81 OsedaCheckError::CouldNotPingLocalPresentation(
82 "Could not ping presentation".to_owned(),
83 ),
84 );
85 }
86 };
87
88 if status != StatusCode::OK {
89 return OsedaProjectStatus::NotDeploymentReady(
90 OsedaCheckError::CouldNotPingLocalPresentation(
91 "Presentation returned non 200 error status code".to_owned(),
92 ),
93 );
94 }
95
96 println!("Project returned status code {:?}", status);
97
98 if kill_port(port_num).is_err() {
106 println!("Warning: could not kill process on port, project could still be running");
107 } else {
108 println!("Project process sucessfully terminated");
109 }
110
111 return OsedaProjectStatus::DeployReady;
112}