Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ name: Rust

on:
push:
branches: [ "main" ]
branches: [ "main", "dev" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "dev" ]

env:
CARGO_TERM_COLOR: always

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Install system packages
run: sudo apt-get install libglib2.0-dev libgtk-3-dev libsoup-3.0
- name: Build
run: cargo build --verbose
run: cargo build --release --features "desktop"
- name: Run tests
run: cargo test --verbose
2 changes: 2 additions & 0 deletions extern/backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ sha2 = { version = "0.10.8" }
uuid = { version = "1.15.1", features = ["v4"] }
bincode = { version = "1.1.3" }
tokio = { version = "1.43.0", features = ["sync"] }
fuzzy-matcher = "0.3.7"
walkdir = "2.5.0"
Binary file not shown.
Binary file not shown.
9 changes: 7 additions & 2 deletions extern/backend/nodes/bundled_node/meta.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
name = "bundled_node"
description = "A bundled node"
author = "Author"
date = "2025-03-05T19:02:06.992970322Z"
impls = [[{ deps = [] }, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"]]
date = "2025-03-10T12:33:26.326778746Z"

[[versions]]
version = "0.0.1"

[versions.env]
deps = []
Binary file not shown.
Binary file not shown.
Binary file not shown.
24 changes: 22 additions & 2 deletions extern/backend/nodes/complex_bundled_node/meta.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
name = "complex_bundled_node"
description = "A complex bundled node"
author = "Author"
date = "2025-03-05T19:02:06.992988239Z"
impls = [[{ deps = [{ name = "serde", versions = ["1.0"], lib = true }] }, "347d4e7d76b463a7b8415486415c698bf2c792ee6384f96eca96e1d45a2f3986"]]
date = "2025-03-10T12:33:26.326848257Z"

[[versions]]
version = "0.0.1"

[[versions.env.deps]]
name = "serde"
versions = ["1.0"]
lib = true

[[versions]]
version = "0.0.2"

[[versions.env.deps]]
name = "serde"
versions = ["1.0"]
lib = true

[[versions.env.deps]]
name = "torch"
versions = ["2.0"]
lib = true
Binary file not shown.
Binary file not shown.
9 changes: 7 additions & 2 deletions extern/backend/nodes/test_code_node/meta.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
name = "test_code_node"
description = "A simple code node"
author = "Author"
date = "2025-03-05T17:47:07.471655003Z"
impls = [[{ deps = [] }, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"]]
date = "2025-03-10T12:33:26.326772004Z"

[[versions]]
version = "0.0.1"

[versions.env]
deps = []
Binary file not shown.
10 changes: 10 additions & 0 deletions extern/backend/nodes/test_delete_invalid_version/meta.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "test_delete_invalid_version"
description = "A node with a single version"
author = "Author"
date = "2025-03-10T18:11:02.512933191Z"

[[versions]]
version = "1.0.0"

[versions.env]
deps = []
Binary file not shown.
10 changes: 10 additions & 0 deletions extern/backend/nodes/test_delete_version/meta.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "test_delete_version"
description = "A node with multiple versions"
author = "Author"
date = "2025-03-10T18:11:02.512959856Z"

[[versions]]
version = "2.0.0"

[versions.env]
deps = []
4 changes: 2 additions & 2 deletions extern/backend/src/modules/nms.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod create;
pub mod delete;
pub mod modify;
pub mod query;
pub mod save;

fn check_name(name: String) -> bool {
name.chars()
Expand Down
52 changes: 0 additions & 52 deletions extern/backend/src/modules/nms/create.rs

This file was deleted.

69 changes: 69 additions & 0 deletions extern/backend/src/modules/nms/delete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

use crate::utils::prelude::*;

pub fn delete_node(name: String, version: Option<String>) -> Result<(), String> {
let node_path = Path::new("nodes/").join(&name);
let meta_path = node_path.join("meta.toml");

if !node_path.exists() {
return Err(format!("Node '{}' does not exist.", name));
}

if !meta_path.exists() {
fs::remove_dir_all(&node_path).map_err(|e| e.to_string())?;
return Ok(());
}

let meta_content = std::fs::read_to_string(&meta_path).map_err(|e| e.to_string())?;
let mut meta: Metadata = toml::from_str(&meta_content).map_err(|e| e.to_string())?;

if let Some(ver) = version {
let version_index = meta.versions.iter().position(|v| v.version == ver);
if let Some(index) = version_index {
let env_hash = meta.versions[index].env.hash();
let bin_path = node_path.join(&env_hash).join(format!("{}.bin", ver));

if bin_path.exists() {
fs::remove_file(&bin_path).map_err(|e| e.to_string())?;
}

// Remove empty environment folder
let env_path = node_path.join(&env_hash);
if env_path
.read_dir()
.map_err(|e| e.to_string())?
.next()
.is_none()
{
fs::remove_dir(&env_path).map_err(|e| e.to_string())?;
}

meta.versions.remove(index);
} else {
return Err(format!("Version '{}' not found for node '{}'.", ver, name));
}
} else {
// Delete the entire node
fs::remove_dir_all(&node_path).map_err(|e| e.to_string())?;
return Ok(());
}

if meta.versions.is_empty() {
fs::remove_dir_all(&node_path).map_err(|e| e.to_string())?;
} else {
let meta_toml = toml::to_string(&meta).map_err(|e| e.to_string())?;
let tmp_meta_path = node_path.join("meta.toml.tmp");

let mut tmp_meta_file = File::create(&tmp_meta_path).map_err(|e| e.to_string())?;
tmp_meta_file
.write_all(meta_toml.as_bytes())
.map_err(|e| e.to_string())?;

fs::rename(&tmp_meta_path, &meta_path).map_err(|e| e.to_string())?;
}

Ok(())
}
Empty file.
48 changes: 48 additions & 0 deletions extern/backend/src/modules/nms/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::path::Path;

use crate::utils::prelude::{save::*, *};
use walkdir::WalkDir;

pub fn get_all_nodes() -> Result<NodeContainer, String> {
let nodes_dir = Path::new("nodes");
if !nodes_dir.exists() {
return Ok(NodeContainer::default());
}

let mut nc = NodeContainer::default();

for entry in WalkDir::new(nodes_dir)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.path().extension().is_some_and(|ext| ext == "bin"))
{
let path = entry.path();
let data =
std::fs::read(path).map_err(|e| format!("Failed to read {}: {}", path.display(), e))?;

let save_node: SaveNode = bincode::deserialize(&data)
.map_err(|e| format!("Failed to deserialize {}: {}", path.display(), e))?;

let node = Node::from(save_node);
nc.push_context(StrongNode::from(node));
}

Ok(nc)
}

/// This function searches through all available Nodes and returns a NodeContainer containing all Nodes available for the inferred environment.
pub fn query(query_filter: Vec<QueryFilter>) -> NodeContainer {
let all_nodes = get_all_nodes().expect("Error walking directory!");

all_nodes
.iter()
.filter(|node| {
query_filter.iter().all(|filter| {
filter
.clone()
.is_ok(node.context.try_lock().unwrap().to_owned())
})
})
.cloned()
.collect()
}
109 changes: 109 additions & 0 deletions extern/backend/src/modules/nms/save.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::nms::check_name;
use crate::utils::prelude::{save::*, *};
use anyhow::Result;
use std::fs::{self, create_dir, create_dir_all, File};
use std::io::Write;
use std::path::Path;
use toml;

// #[cfg(feature = "desktop")]
pub fn save_node(node: Node) -> Result<(), String> {
let name = node.name.clone();

if !check_name(name.clone()) {
return Err(format!(
"Node name {} is not allowed! Please only use letters, dashes and underscores.",
name
));
}

let node_path = Path::new("nodes/").join(&name);
if !node_path.exists() {
create_dir_all(&node_path).map_err(|e| e.to_string())?;
}

let meta_path = node_path.join("meta.toml");
let mut meta: Metadata = if meta_path.exists() {
let meta_content = std::fs::read_to_string(&meta_path).map_err(|e| e.to_string())?;
toml::from_str(&meta_content).map_err(|e| e.to_string())?
} else {
Metadata::from(node.clone())
};

let new_version = Version {
version: node.version.version.clone(),
env: node.clone().get_full_env(),
};

let existing_index = meta
.versions
.iter()
.position(|v| v.version == new_version.version);

if let Some(index) = existing_index {
let existing_env_hash = meta.versions[index].env.hash();
let new_env_hash = new_version.env.hash();

if existing_env_hash != new_env_hash {
// Remove old binary
let old_bin_path = node_path
.join(&existing_env_hash)
.join(format!("{}.bin", new_version.version));
if old_bin_path.exists() {
fs::remove_file(&old_bin_path).map_err(|e| e.to_string())?;
}

// Remove empty env folder
let old_env_path = node_path.join(&existing_env_hash);
if old_env_path.exists()
&& old_env_path
.read_dir()
.map_err(|e| e.to_string())?
.next()
.is_none()
{
fs::remove_dir(&old_env_path).map_err(|e| e.to_string())?;
}

// Update the existing entry
meta.versions[index] = new_version.clone();
}
} else {
meta.versions.push(new_version.clone());
}

let meta_toml = toml::to_string(&meta).map_err(|e| e.to_string())?;
let tmp_meta_path = node_path.join("meta.toml.tmp");

let mut tmp_meta_file = File::create(&tmp_meta_path).map_err(|e| e.to_string())?;
tmp_meta_file
.write_all(meta_toml.as_bytes())
.map_err(|e| e.to_string())?;

// Atomically replace the old meta file
fs::rename(&tmp_meta_path, &meta_path).map_err(|e| e.to_string())?;

let env_hash = new_version.env.hash();
let env_path = node_path.join(&env_hash);
if !env_path.exists() {
create_dir(&env_path).map_err(|e| e.to_string())?;
}

let bin_path = env_path.join(format!("{}.bin", new_version.version));

let node_bin = bincode::serialize(&SaveNode::from(node)).map_err(|e| e.to_string())?;
let mut node_file = File::create(&bin_path).map_err(|e| e.to_string())?;
node_file.write_all(&node_bin).map_err(|e| e.to_string())?;

// Remove empty node folder if necessary
if node_path
.read_dir()
.map_err(|e| e.to_string())?
.next()
.is_none()
{
fs::remove_dir(&node_path).map_err(|e| e.to_string())?;
}

Ok(())
}
Loading
Loading