Flat-file DB

This commit is contained in:
southerntofu 2020-04-30 22:11:06 +02:00
parent d2118316d3
commit ec55a274c3
5 changed files with 188 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

Binary file not shown.

Binary file not shown.

178
src/db.rs Normal file
View File

@ -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
}
}
}

View File

@ -2,6 +2,7 @@ use std::env;
use std::collections::HashMap;
mod log;
mod db;
fn main() {
@ -12,5 +13,13 @@ fn main() {
test.insert("$i18n_task".to_string(), "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
}