This commit is contained in:
parent
38e21a8c56
commit
5c7b9f583c
6 changed files with 206 additions and 7 deletions
113
Cargo.lock
generated
113
Cargo.lock
generated
|
@ -50,6 +50,12 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
|
@ -61,12 +67,40 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.147"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
|
@ -89,6 +123,8 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"redb",
|
"redb",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_yaml",
|
||||||
|
"toml",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -186,6 +222,12 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.171"
|
version = "1.0.171"
|
||||||
|
@ -206,6 +248,28 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_yaml"
|
||||||
|
version = "0.9.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd5f51e3fdb5b9cdd1577e1cb7a733474191b1aca6a72c2e50913241632c1180"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
"unsafe-libyaml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.26"
|
version = "2.0.26"
|
||||||
|
@ -243,12 +307,52 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unsafe-libyaml"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
@ -330,3 +434,12 @@ name = "windows_x86_64_msvc"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
|
@ -12,4 +12,6 @@ dirs = "5.0.1"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
redb = "1.0.5"
|
redb = "1.0.5"
|
||||||
serde = { version = "1.0.171", features = ["derive"] }
|
serde = { version = "1.0.171", features = ["derive"] }
|
||||||
|
serde_yaml = "0.9.24"
|
||||||
|
toml = "0.7.6"
|
||||||
uuid = { version = "1.4.1", features = ["v4", "v8", "fast-rng"] }
|
uuid = { version = "1.4.1", features = ["v4", "v8", "fast-rng"] }
|
||||||
|
|
|
@ -13,6 +13,8 @@ namespaces:
|
||||||
|
|
||||||
event-location:
|
event-location:
|
||||||
description:
|
description:
|
||||||
|
type: integer
|
||||||
|
|
||||||
event-location:
|
event-location:
|
||||||
description:
|
description:
|
||||||
|
type: integer
|
||||||
|
|
82
src/db.rs
82
src/db.rs
|
@ -1,20 +1,92 @@
|
||||||
use std::path::Path;
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use redb::ReadableTable;
|
use redb::ReadableTable;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::db_keys::{metadata_by_id, nodes_by_id};
|
use crate::{
|
||||||
|
apps::meta::{self, AppMetadata},
|
||||||
|
db_keys::{installed_apps, metadata_by_id, nodes_by_id},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct PanoramaDb {
|
pub struct PanoramaDb {
|
||||||
redb_db: redb::Database,
|
redb_db: redb::Database,
|
||||||
|
app_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PanoramaDb {
|
impl PanoramaDb {
|
||||||
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
|
pub fn open(
|
||||||
let redb_db = redb::Database::create(path)?;
|
db_path: impl AsRef<Path>,
|
||||||
|
app_path: impl AsRef<Path>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let redb_db = redb::Database::create(db_path)?;
|
||||||
|
let app_path = app_path.as_ref().to_path_buf();
|
||||||
|
let mut panorama = Self { redb_db, app_path };
|
||||||
|
|
||||||
Ok(Self { redb_db })
|
panorama.app_init()?;
|
||||||
|
|
||||||
|
Ok(panorama)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn app_init(&mut self) -> Result<()> {
|
||||||
|
// Get list of on-disk apps
|
||||||
|
let on_disk_apps = {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
for entry in fs::read_dir(&self.app_path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let path = entry.path();
|
||||||
|
if !path.is_dir() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let meta_file = path.join("meta.yml");
|
||||||
|
if !path.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let meta_content = fs::read_to_string(&meta_file)?;
|
||||||
|
let parsed_toml: AppMetadata = serde_yaml::from_str(&meta_content)?;
|
||||||
|
|
||||||
|
set.insert(parsed_toml.name);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
};
|
||||||
|
println!("On-disk apps: {on_disk_apps:?}");
|
||||||
|
|
||||||
|
// Get list of installed apps (in the database)
|
||||||
|
let installed_apps = {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
let tx = self.redb_db.begin_read()?;
|
||||||
|
let table = tx.open_table(*installed_apps());
|
||||||
|
if let Ok(installed_apps_table) = table {
|
||||||
|
for entry in installed_apps_table.iter()? {
|
||||||
|
let (key, value) = entry?;
|
||||||
|
let key = key.value();
|
||||||
|
let value = value.value();
|
||||||
|
set.insert(key.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
};
|
||||||
|
println!("Installed apps: {installed_apps:?}");
|
||||||
|
|
||||||
|
// Add new apps to database
|
||||||
|
let new_apps = on_disk_apps
|
||||||
|
.difference(&installed_apps)
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
println!("New apps: {new_apps:?}");
|
||||||
|
|
||||||
|
// Remove existing apps
|
||||||
|
let deleted_apps = installed_apps
|
||||||
|
.difference(&on_disk_apps)
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
println!("Deleted apps: {deleted_apps:?}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check(&mut self) -> Result<()> {
|
pub fn check(&mut self) -> Result<()> {
|
||||||
|
|
|
@ -2,7 +2,8 @@ use once_cell::sync::OnceCell;
|
||||||
use redb::TableDefinition;
|
use redb::TableDefinition;
|
||||||
|
|
||||||
macro_rules! table_def {
|
macro_rules! table_def {
|
||||||
($str:ident, $key:ty, $val:ty) => {
|
($(#[$meta:meta])* $str:ident, $key:ty, $val:ty) => {
|
||||||
|
$(#[$meta])*
|
||||||
pub fn $str() -> &'static TableDefinition<'static, $key, $val> {
|
pub fn $str() -> &'static TableDefinition<'static, $key, $val> {
|
||||||
static INSTANCE: OnceCell<TableDefinition<'static, $key, $val>> =
|
static INSTANCE: OnceCell<TableDefinition<'static, $key, $val>> =
|
||||||
OnceCell::new();
|
OnceCell::new();
|
||||||
|
@ -19,3 +20,12 @@ table_def!(
|
||||||
(&'static str, &'static str, &'static str),
|
(&'static str, &'static str, &'static str),
|
||||||
()
|
()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
table_def!(
|
||||||
|
/// Table of installed apps
|
||||||
|
///
|
||||||
|
/// Maps "name" to (path installed from, json config)
|
||||||
|
installed_apps,
|
||||||
|
&'static str,
|
||||||
|
(&'static str, &'static str)
|
||||||
|
);
|
||||||
|
|
|
@ -9,7 +9,7 @@ fn main() -> Result<()> {
|
||||||
fs::create_dir_all(&panorama_data_dir)?;
|
fs::create_dir_all(&panorama_data_dir)?;
|
||||||
let database_file_path = panorama_data_dir.join("data.redb");
|
let database_file_path = panorama_data_dir.join("data.redb");
|
||||||
|
|
||||||
let database = PanoramaDb::open(database_file_path)?;
|
let database = PanoramaDb::open(database_file_path, "./apps")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let write = database.begin_write()?;
|
let write = database.begin_write()?;
|
||||||
|
|
Loading…
Reference in a new issue