Test Gitea Runner functionality
This commit is contained in:
247
markbase-fskit/src/fskit/filesystem.rs
Normal file
247
markbase-fskit/src/fskit/filesystem.rs
Normal file
@@ -0,0 +1,247 @@
|
||||
use objc2_foundation::NSString;
|
||||
use objc2_fs_kit::{
|
||||
FSFileSystem, FSVolume, FSItem,
|
||||
FSVolumeOperations, FSVolumeReadWriteOperations,
|
||||
};
|
||||
use rusqlite::Connection;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct MarkBaseFS {
|
||||
sqlite: Mutex<Connection>,
|
||||
user_id: String,
|
||||
}
|
||||
|
||||
impl MarkBaseFS {
|
||||
pub fn new(user_id: &str, db_path: &str) -> Self {
|
||||
let conn = Connection::open(db_path)
|
||||
.expect("Failed to open SQLite database");
|
||||
|
||||
Self {
|
||||
sqlite: Mutex::new(conn),
|
||||
user_id: user_id.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_node(&self, node_id: &str) -> Option<FileNodeData> {
|
||||
let conn = self.sqlite.lock().unwrap();
|
||||
|
||||
conn.query_row(
|
||||
"SELECT node_id, label, node_type, file_size, aliases_json
|
||||
FROM file_nodes WHERE node_id = ?",
|
||||
[node_id],
|
||||
|row| {
|
||||
Ok(FileNodeData {
|
||||
node_id: row.get::<_, String>(0)?,
|
||||
label: row.get::<_, String>(1)?,
|
||||
node_type: row.get::<_, String>(2)?,
|
||||
file_size: row.get::<_, Option<i64>>(3)?,
|
||||
aliases_json: row.get::<_, String>(4)?,
|
||||
})
|
||||
},
|
||||
).ok()
|
||||
}
|
||||
|
||||
pub fn query_children(&self, parent_id: &str) -> Vec<FileNodeData> {
|
||||
let conn = self.sqlite.lock().unwrap();
|
||||
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT node_id, label, node_type, file_size, aliases_json
|
||||
FROM file_nodes WHERE parent_id = ?
|
||||
ORDER BY sort_order, label"
|
||||
).unwrap();
|
||||
|
||||
stmt.query_map([parent_id], |row| {
|
||||
Ok(FileNodeData {
|
||||
node_id: row.get::<_, String>(0)?,
|
||||
label: row.get::<_, String>(1)?,
|
||||
node_type: row.get::<_, String>(2)?,
|
||||
file_size: row.get::<_, Option<i64>>(3)?,
|
||||
aliases_json: row.get::<_, String>(4)?,
|
||||
})
|
||||
}).unwrap()
|
||||
.filter_map(|r| r.ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn read_file(&self, node_id: &str) -> Option<Vec<u8>> {
|
||||
let conn = self.sqlite.lock().unwrap();
|
||||
|
||||
let aliases_json: String = conn.query_row(
|
||||
"SELECT aliases_json FROM file_nodes WHERE node_id = ?",
|
||||
[node_id],
|
||||
|row| row.get(0),
|
||||
).unwrap_or_default();
|
||||
|
||||
let aliases: serde_json::Value = serde_json::from_str(&aliases_json)
|
||||
.unwrap_or(serde_json::json!({}));
|
||||
|
||||
let file_path = aliases["path"].as_str().unwrap_or_default();
|
||||
|
||||
if file_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
std::fs::read(file_path).ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileNodeData {
|
||||
pub node_id: String,
|
||||
pub label: String,
|
||||
pub node_type: String,
|
||||
pub file_size: Option<i64>,
|
||||
pub aliases_json: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_markbase_fs_creation() {
|
||||
let fs = MarkBaseFS::new("test", "data/users/test.sqlite");
|
||||
assert_eq!(fs.user_id, "test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_node_data() {
|
||||
let node = FileNodeData {
|
||||
node_id: "test123".to_string(),
|
||||
label: "test.txt".to_string(),
|
||||
node_type: "file".to_string(),
|
||||
file_size: Some(1024),
|
||||
aliases_json: "{}".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(node.node_id, "test123");
|
||||
assert_eq!(node.label, "test.txt");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod warren_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_warren_database_connection() {
|
||||
let fs = MarkBaseFS::new("warren", "data/users/warren.sqlite");
|
||||
assert_eq!(fs.user_id, "warren");
|
||||
|
||||
let conn = fs.sqlite.lock().unwrap();
|
||||
let count: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM file_nodes",
|
||||
[],
|
||||
|row| row.get(0)
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(count, 12659);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_warren_query_root() {
|
||||
let fs = MarkBaseFS::new("warren", "data/users/warren.sqlite");
|
||||
|
||||
let root_id: String = {
|
||||
let conn = fs.sqlite.lock().unwrap();
|
||||
conn.query_row(
|
||||
"SELECT node_id FROM file_nodes WHERE parent_id IS NULL LIMIT 1",
|
||||
[],
|
||||
|row| row.get(0)
|
||||
).unwrap()
|
||||
};
|
||||
|
||||
let root = fs.query_node(&root_id);
|
||||
assert!(root.is_some());
|
||||
|
||||
let root_node = root.unwrap();
|
||||
assert_eq!(root_node.node_type, "folder");
|
||||
println!("Root node: {} - {}", root_node.node_id, root_node.label);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_warren_query_children() {
|
||||
let fs = MarkBaseFS::new("warren", "data/users/warren.sqlite");
|
||||
|
||||
let root_id: String = {
|
||||
let conn = fs.sqlite.lock().unwrap();
|
||||
conn.query_row(
|
||||
"SELECT node_id FROM file_nodes WHERE parent_id IS NULL LIMIT 1",
|
||||
[],
|
||||
|row| row.get(0)
|
||||
).unwrap()
|
||||
};
|
||||
|
||||
let children = fs.query_children(&root_id);
|
||||
|
||||
assert!(children.len() > 0);
|
||||
|
||||
let folders = children.iter().filter(|c| c.node_type == "folder").count();
|
||||
let files = children.iter().filter(|c| c.node_type == "file").count();
|
||||
|
||||
println!("Root children: {} folders, {} files", folders, files);
|
||||
|
||||
assert!(folders > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_warren_read_text_file() {
|
||||
let fs = MarkBaseFS::new("warren", "data/users/warren.sqlite");
|
||||
|
||||
let result = {
|
||||
let conn = fs.sqlite.lock().unwrap();
|
||||
conn.query_row(
|
||||
"SELECT node_id, aliases_json FROM file_nodes
|
||||
WHERE node_type = 'file'
|
||||
AND aliases_json IS NOT NULL
|
||||
AND file_size < 1000
|
||||
LIMIT 1",
|
||||
[],
|
||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
|
||||
).ok()
|
||||
};
|
||||
|
||||
if let Some((node_id, aliases_json)) = result {
|
||||
let aliases: serde_json::Value = serde_json::from_str(&aliases_json).unwrap();
|
||||
let path = aliases["path"].as_str().unwrap_or_default();
|
||||
|
||||
if !path.is_empty() && std::path::Path::new(path).exists() {
|
||||
let content = fs.read_file(&node_id);
|
||||
assert!(content.is_some());
|
||||
|
||||
let data = content.unwrap();
|
||||
assert!(data.len() > 0);
|
||||
|
||||
if let Ok(text) = String::from_utf8(data.clone()) {
|
||||
println!("File content preview: {}", text.chars().take(100).collect::<String>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_warren_statfs() {
|
||||
let conn = Connection::open("data/users/warren.sqlite").unwrap();
|
||||
|
||||
let total_nodes: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM file_nodes",
|
||||
[],
|
||||
|row| row.get(0)
|
||||
).unwrap();
|
||||
|
||||
let total_size: i64 = conn.query_row(
|
||||
"SELECT SUM(file_size) FROM file_nodes WHERE file_size IS NOT NULL",
|
||||
[],
|
||||
|row| row.get(0)
|
||||
).unwrap_or(0);
|
||||
|
||||
println!("Total nodes: {}", total_nodes);
|
||||
println!("Total size: {} bytes ({:.2} GB)",
|
||||
total_size,
|
||||
total_size as f64 / 1_073_741_824.0
|
||||
);
|
||||
|
||||
assert_eq!(total_nodes, 12659);
|
||||
assert!(total_size > 0);
|
||||
}
|
||||
}
|
||||
5
markbase-fskit/src/fskit/mod.rs
Normal file
5
markbase-fskit/src/fskit/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod filesystem;
|
||||
pub mod volume;
|
||||
|
||||
pub use filesystem::{MarkBaseFS, FileNodeData};
|
||||
pub use volume::MarkBaseVolume;
|
||||
2
markbase-fskit/src/fskit/operations.rs
Normal file
2
markbase-fskit/src/fskit/operations.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub use super::filesystem::MarkBaseFS;
|
||||
pub use super::volume::MarkBaseVolume;
|
||||
68
markbase-fskit/src/fskit/volume.rs
Normal file
68
markbase-fskit/src/fskit/volume.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use rusqlite::Connection;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct MarkBaseVolume {
|
||||
sqlite: Mutex<Connection>,
|
||||
user_id: String,
|
||||
root_id: String,
|
||||
}
|
||||
|
||||
impl MarkBaseVolume {
|
||||
pub fn new(conn: Connection, user_id: String) -> Self {
|
||||
let root_id = Self::find_root_node(&conn, &user_id);
|
||||
|
||||
Self {
|
||||
sqlite: Mutex::new(conn),
|
||||
user_id,
|
||||
root_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_root_node(conn: &Connection, user_id: &str) -> String {
|
||||
conn.query_row(
|
||||
"SELECT node_id FROM file_nodes
|
||||
WHERE parent_id IS NULL
|
||||
LIMIT 1",
|
||||
[],
|
||||
|row| row.get::<_, String>(0),
|
||||
).unwrap_or_else(|_| "root".to_string())
|
||||
}
|
||||
|
||||
pub fn get_root_id(&self) -> &str {
|
||||
&self.root_id
|
||||
}
|
||||
|
||||
pub fn get_user_id(&self) -> &str {
|
||||
&self.user_id
|
||||
}
|
||||
|
||||
pub fn statfs(&self) -> (i64, i64) {
|
||||
let conn = self.sqlite.lock().unwrap();
|
||||
|
||||
let total_nodes: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM file_nodes",
|
||||
[],
|
||||
|row| row.get(0),
|
||||
).unwrap_or(0);
|
||||
|
||||
let total_size: i64 = conn.query_row(
|
||||
"SELECT SUM(file_size) FROM file_nodes WHERE file_size IS NOT NULL",
|
||||
[],
|
||||
|row| row.get(0),
|
||||
).unwrap_or(0);
|
||||
|
||||
(total_nodes, total_size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_volume_creation() {
|
||||
let conn = Connection::open("data/users/test.sqlite").unwrap();
|
||||
let vol = MarkBaseVolume::new(conn, "test".to_string());
|
||||
assert_eq!(vol.get_user_id(), "test");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user