Skip to content

Commit

Permalink
feat: Add property capability
Browse files Browse the repository at this point in the history
  • Loading branch information
jcs090218 committed Jun 10, 2024
1 parent 33c0a26 commit 4221a4f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ chrono = "0.4.38"
clap = "4.5.4"
dunce = "1.0.4"
ignore = "0.4.22"
java-properties = "2.0.0"
path-slash = "0.2.1"
rpassword = "7.3.1"
serde = { version = "1.0.203", features = ["derive"] }
Expand Down
62 changes: 42 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,34 @@ use clap::{arg, Arg, ArgMatches, Command};
use dunce;
use fmt::Layer;
use rpassword;
use server::properties::Properties;
use server::Server;
use std::env::current_dir;
use std::io;
use std::io::Write;
use std::str::FromStr;
use tracing::Level;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{fmt, layer::SubscriberExt};

const DOT_COGRU: &str = "./.cogru";
const PROP_FILE: &str = "./Cogru.properties";

const LOG_LEVEL: Level = Level::DEBUG; // Default is `DEBUG`
const DEFAULT_HOST: &str = "127.0.0.1";
const DEFAULT_PORT: &str = "8786";

/// Setup logger rotator.
///
/// https://docs.rs/tracing-appender/0.2.3/tracing_appender/non_blocking/struct.WorkerGuard.html
pub fn setup_logger() -> WorkerGuard {
pub fn setup_logger(prop: &Properties) -> WorkerGuard {
println!("Setup logger :::");
let file_appender = tracing_appender::rolling::hourly(DOT_COGRU, "example.log");
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);

let prop_log_level = prop.get_or_default("cogru.LogLevel", "DEBUG");
let level = Level::from_str(&prop_log_level).unwrap();

let subscriber = tracing_subscriber::fmt()
.with_max_level(LOG_LEVEL)
.with_max_level(level)
.finish()
.with(Layer::new().with_writer(non_blocking));

Expand All @@ -68,12 +74,14 @@ pub fn setup_logger() -> WorkerGuard {
///
/// * `port` - port to start.
/// * `password` - password to enter the session.
async fn start_server(port: u16, working_dir: &str, password: Option<String>) {
let _guard = setup_logger();

async fn start_server(prop: &Properties, port: u16, working_dir: &str, password: Option<String>) {
println!("Start room server :::");
let host = prop.get_or_default("cogru.Host", DEFAULT_HOST);

println!("host: {}", host);

let room = Room::new(working_dir, password);
let mut server = Server::new("127.0.0.1", port, room);
let mut server = Server::new(&host, port, room);
let _ = server.start().await;
}

Expand Down Expand Up @@ -105,10 +113,9 @@ fn get_workspace(matches: &ArgMatches) -> String {
.to_string()
}

/// Program Entry
#[tokio::main]
async fn main() {
let matches = Command::new("Cogru")
/// Setup CLI.
fn setup_cli() -> ArgMatches {
Command::new("Cogru")
.version("0.1.0")
.about("cogru - Where the collaboration start!?")
.arg(
Expand All @@ -121,7 +128,7 @@ async fn main() {
arg!(--port <VALUE>)
.required(false)
.help("Port number")
.default_value("8786"),
.default_value(DEFAULT_PORT),
)
.arg(
Arg::new("no_password")
Expand All @@ -132,7 +139,16 @@ async fn main() {
.help("Don't require password to enter the room")
.default_value("false"),
)
.get_matches();
.get_matches()
}

/// Program Entry
#[tokio::main]
async fn main() {
let prop = Properties::new(&PROP_FILE);
let prop_port = prop.get_or_default("cogru.Port", DEFAULT_PORT);

let matches = setup_cli();

let current_dir = get_workspace(&matches);
let mut current_dir = to_slash(&current_dir);
Expand All @@ -141,11 +157,14 @@ async fn main() {
current_dir = format!("{}/", current_dir);
}

let port = matches
.get_one::<String>("port")
.unwrap()
.parse::<u16>()
.unwrap();
let mut port = matches.get_one::<String>("port").unwrap();

if port == DEFAULT_PORT {
port = &prop_port;
}

// Convert to u16
let port = port.parse::<u16>().unwrap();

let no_password = matches.get_flag("no_password");

Expand All @@ -155,6 +174,9 @@ async fn main() {
Some(get_password().expect("Confirm password doesn't match"))
};

// Setup logger
let _guard = setup_logger(&prop);

// Start the server
start_server(port, &current_dir, password).await;
start_server(&prop, port, &current_dir, password).await;
}
1 change: 1 addition & 0 deletions src/server.rs → src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pub mod properties;
use crate::channel::*;
use crate::client::*;
use crate::connection::*;
Expand Down
77 changes: 77 additions & 0 deletions src/server/properties.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Copyright (c) 2024 Cogru Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use java_properties::read;
use java_properties::write;
use java_properties::PropertiesIter;
use java_properties::PropertiesWriter;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::net::ToSocketAddrs;
use std::path::Path;

pub struct Properties {
data: HashMap<String, String>,
read: bool,
}

impl Properties {
pub fn new(path: &str) -> Self {
let mut prop = Self {
data: HashMap::new(),
read: false,
};
prop.read(path);
prop
}

fn read(&mut self, path: &str) {
if !Path::new(path).exists() {
return;
}

let f = File::open(path).unwrap();

let _ = PropertiesIter::new(BufReader::new(f)).read_into(|k, v| {
self.data.insert(k, v);
});

self.read = true;
}

/// Return property value.
///
/// # Arguments
///
/// * `key` - The key used to find value.
pub fn get(&self, key: &str) -> Option<&String> {
self.data.get(key)
}

/// Return property value or the default value when null.
///
/// # Arguments
///
/// * `key` - The key used to find value.
/// * `default_value` - The fallback value.
pub fn get_or_default(&self, key: &str, default_value: &str) -> String {
let data = self.get(key);
if data.is_none() {
return default_value.to_string();
}
data.unwrap().clone()
}
}

0 comments on commit 4221a4f

Please sign in to comment.