Flat-file DB
This commit is contained in:
parent
d2118316d3
commit
ec55a274c3
|
@ -0,0 +1 @@
|
||||||
|
/target
|
BIN
src/.db.rs.swp
BIN
src/.db.rs.swp
Binary file not shown.
BIN
src/.main.rs.swp
BIN
src/.main.rs.swp
Binary file not shown.
|
@ -0,0 +1,178 @@
|
||||||
|
use std::path::{PathBuf, Path};
|
||||||
|
use std::fs;
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
//use crate::log;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Entry {
|
||||||
|
base_dir: PathBuf,
|
||||||
|
pub name: OsString
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Task {
|
||||||
|
name: OsString,
|
||||||
|
bin: PathBuf,
|
||||||
|
source: Option<String>,
|
||||||
|
dvcs: Option<String>,
|
||||||
|
config: HashMap<String, String>,
|
||||||
|
branch: Option<String>,
|
||||||
|
host: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Task {
|
||||||
|
pub fn new(base_dir: PathBuf, name: OsString) -> Task {
|
||||||
|
let t = Entry::new(base_dir, name.clone());
|
||||||
|
Task {
|
||||||
|
name: name.clone(),
|
||||||
|
bin: PathBuf::from(name.clone()),
|
||||||
|
source: t.source(),
|
||||||
|
dvcs: t.dvcs(),
|
||||||
|
config: HashMap::new(),
|
||||||
|
branch: t.branch(),
|
||||||
|
host: t.host(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
pub fn new(base_dir: PathBuf, name: OsString) -> Entry {
|
||||||
|
Entry {
|
||||||
|
base_dir,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_setting(&self, setting: &str) -> Option<String> {
|
||||||
|
let mut path = self.base_dir.clone();
|
||||||
|
path.push(&self.name);
|
||||||
|
path.set_extension(setting);
|
||||||
|
read_or_none(&path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source(&self) -> Option<String> {
|
||||||
|
self.read_setting("source")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dvcs(&self) -> Option<String> {
|
||||||
|
self.read_setting("dvcs")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn branch(&self) -> Option<String> {
|
||||||
|
self.read_setting("branch")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn host(&self) -> Option<String> {
|
||||||
|
self.read_setting("branch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Database {
|
||||||
|
base_dir: PathBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Database {
|
||||||
|
pub fn from_folder(p: &str) -> Database {
|
||||||
|
let path = PathBuf::from(&p);
|
||||||
|
if !path.is_dir() {
|
||||||
|
panic!("Folder {} not found", &p);
|
||||||
|
}
|
||||||
|
Database {
|
||||||
|
base_dir: path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tasks(&self) -> Vec<Task> {
|
||||||
|
// If database doesn't exist, simply return an empty vec
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for file in list_files(&self.base_dir) {
|
||||||
|
if is_executable(&file) {
|
||||||
|
res.push(
|
||||||
|
Task::new(self.base_dir.clone(), file.file_name().expect("WTF").to_os_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
println!("{:?}", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn task(&self, name: &str) -> Option<Task> {
|
||||||
|
let mut path = self.base_dir.clone();
|
||||||
|
path.push(name);
|
||||||
|
if !path.is_file() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(
|
||||||
|
Task::new(self.base_dir.clone(), path.file_name().expect("WTF").to_os_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads the file and strips whitespace (newline including)
|
||||||
|
/// Useful for file-based key-value store
|
||||||
|
fn read_or_none(path: &Path) -> Option<String> {
|
||||||
|
if !path.is_file() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match fs::read_to_string(path) {
|
||||||
|
Ok(content) => {
|
||||||
|
// Remove trailing space/newlines
|
||||||
|
Some(content.trim().to_string())
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("IO ERROR: {}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_files(path: &Path) -> Vec<PathBuf> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
match fs::read_dir(path) {
|
||||||
|
Ok(files) => {
|
||||||
|
for r in files {
|
||||||
|
match r {
|
||||||
|
Ok(entry) => {
|
||||||
|
let file = entry.path();
|
||||||
|
if file.is_file() {
|
||||||
|
res.push(file);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("IOERROR: {}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("IOERROR: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If the file doesn't exist or fails, return false
|
||||||
|
fn is_executable(path: &Path) -> bool {
|
||||||
|
match fs::metadata(path) {
|
||||||
|
Ok(stat) => {
|
||||||
|
let mode = stat.mode();
|
||||||
|
// Check user exec permission)
|
||||||
|
if (mode & 0o100) == 0o100 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("IO Error: {}", e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ use std::env;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod log;
|
mod log;
|
||||||
|
mod db;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
|
@ -12,5 +13,13 @@ fn main() {
|
||||||
test.insert("$i18n_task".to_string(), "test");
|
test.insert("$i18n_task".to_string(), "test");
|
||||||
log::info("process", Some(&test));
|
log::info("process", Some(&test));
|
||||||
|
|
||||||
|
let db = db::Database::from_folder(&base_dir);
|
||||||
|
let truc = db.tasks();
|
||||||
|
println!("{:?}", truc);
|
||||||
|
|
||||||
|
for task in truc {
|
||||||
|
println!("{:#?}", task);
|
||||||
|
}
|
||||||
|
|
||||||
//let log_level = env::var("LOG").unwrap_or
|
//let log_level = env::var("LOG").unwrap_or
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue