diff --git a/Makefile b/Makefile index 2a85d23..ae5a7e0 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,8 @@ # Variables -BINARY_NAME := "chase-cli" +BINARY_NAME := chase-rs BINARY := target/release/$(BINARY_NAME) -PATH := /snap/bin:$(PATH) DEBUG_PROJ := 0 RUST_BACKTRACE := 1 -ASSET_DIR := assets -TEST_DATA_DIR := tests/testdata -SHELL := /bin/bash # Default target .DEFAULT_GOAL := help @@ -45,23 +41,13 @@ run: build ## Build and run the binary clean: ## Remove generated and temporary files @echo "Cleaning up..." @cargo clean - @rm -f $(ASSET_DIR)/*.svg && echo "Removed SVG files; might want to run 'make figs' to regenerate them." - -.PHONY: install-snap -install-snap: ## Install a few dependencies using Snapcraft - @echo "Installing the snap package..." - @sudo apt-get update - @sudo apt-get install -y snapd graphviz wget - @sudo snap refresh - @sudo snap install rustup --classic .PHONY: install-deps -install-deps: install-snap ## Install development dependencies +install-deps: ## Install development dependencies @echo "Installing dependencies..." @rustup component add rustfmt clippy @cargo install cargo-tarpaulin @cargo install cargo-audit - @cargo install cargo-careful @cargo install cargo-nextest .PHONY: lint @@ -69,26 +55,11 @@ lint: format ## Run the linters @echo "Linting Rust files..." @DEBUG_PROJ=$(DEBUG_PROJ) cargo clippy -- -D warnings -D clippy::unwrap_used -D clippy::expect_used -.PHONY: publish -publish: ## Publish the package to crates.io (requires CARGO_REGISTRY_TOKEN to be set) - @echo "Publishing the package to Cargo registry..." - @cargo publish --token $(CARGO_REGISTRY_TOKEN) - -.PHONY: bench -bench: ## Run the benchmarks - @echo "Running benchmarks..." - @DEBUG_PROJ=$(DEBUG_PROJ) cargo bench - .PHONY: audit audit: ## Run security audit on Rust dependencies @echo "Running security audit..." @cargo audit -.PHONY: rust-careful -careful: ## Run security checks on Rust code - @echo "Running security checks..." - @cargo careful - .PHONY: docs docs: format ## Generate the documentation @echo "Generating documentation..." @@ -97,12 +68,7 @@ docs: format ## Generate the documentation .PHONY: fix-lint fix-lint: ## Fix the linter warnings @echo "Fixing linter warnings..." - @cargo clippy --fix --allow-dirty --allow-staged --all-targets --workspace --all-features -- -D warnings -D clippy::unwrap_used -D clippy::expect_used - -.PHONY: testdata -testdata: ## Download the datasets used in tests - @echo "Downloading test data..." - @$(SHELL) $(TEST_DATA_DIR)/download_datasets.sh $(TEST_DATA_DIR) + @cargo clippy --fix --allow-dirty --allow-staged --all-targets --workspace .PHONY: nextest nextest: ## Run tests using nextest @@ -110,7 +76,7 @@ nextest: ## Run tests using nextest @DEBUG_PROJ=$(DEBUG_PROJ) RUST_BACKTRACE=$(RUST_BACKTRACE) cargo nextest run .PHONY: setup-hooks -setup-hooks: ## Install Git hooks (pre-commit and pre-push) +setup-hooks: ## Install Git hooks (pre-commit) @echo "Setting up Git hooks..." @if ! command -v pre-commit &> /dev/null; then \ echo "pre-commit not found. Please install it using 'pip install pre-commit'"; \ @@ -124,3 +90,7 @@ setup-hooks: ## Install Git hooks (pre-commit and pre-push) test-hooks: ## Test Git hooks on all files @echo "Testing Git hooks..." @pre-commit run --all-files --show-diff-on-failure + +.PHONY: check +check: format lint test ## Run format, lint, and test + @echo "All checks passed." diff --git a/src/chase/engine.rs b/src/chase/engine.rs index c84c573..a168ab1 100644 --- a/src/chase/engine.rs +++ b/src/chase/engine.rs @@ -5,7 +5,7 @@ use std::collections::{HashMap, HashSet}; use super::atom::Atom; use super::instance::Instance; use super::rule::Rule; -use super::substitution::{unify_atom, Substitution}; +use super::substitution::{Substitution, unify_atom}; use super::term::Term; /// Result of running the chase algorithm. @@ -251,8 +251,8 @@ mod tests { vec![Term::constant("bob"), Term::constant("carol")], ), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // Rule: Parent(X, Y) -> Ancestor(X, Y) let rule1 = RuleBuilder::new() @@ -308,8 +308,8 @@ mod tests { Atom::new("Person", vec![Term::constant("alice")]), Atom::new("Person", vec![Term::constant("bob")]), ] - .into_iter() - .collect(); + .into_iter() + .collect(); let rule = RuleBuilder::new() .when("Person", vec![Term::var("X")]) diff --git a/src/chase/instance.rs b/src/chase/instance.rs index d7e3c1e..e45f645 100644 --- a/src/chase/instance.rs +++ b/src/chase/instance.rs @@ -41,7 +41,7 @@ impl Instance { } /// Iterate over all facts. - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.facts.iter() } @@ -65,7 +65,7 @@ impl fmt::Display for Instance { } impl FromIterator for Instance { - fn from_iter>(iter: T) -> Self { + fn from_iter>(iter: T) -> Self { let mut instance = Instance::new(); for atom in iter { instance.add(atom); @@ -107,13 +107,10 @@ mod tests { "Parent", vec![Term::constant("alice"), Term::constant("bob")], ), - Atom::new( - "Person", - vec![Term::constant("alice")], - ), + Atom::new("Person", vec![Term::constant("alice")]), ] - .into_iter() - .collect(); + .into_iter() + .collect(); assert_eq!(instance.facts_for_predicate("Parent").len(), 1); assert_eq!(instance.facts_for_predicate("Person").len(), 1); diff --git a/src/chase/mod.rs b/src/chase/mod.rs index 9cb5dc1..818f017 100644 --- a/src/chase/mod.rs +++ b/src/chase/mod.rs @@ -9,7 +9,7 @@ pub mod term; mod engine; pub use atom::Atom; -pub use engine::{chase, ChaseResult}; +pub use engine::{ChaseResult, chase}; pub use instance::Instance; pub use rule::Rule; pub use substitution::Substitution; diff --git a/src/chase/substitution.rs b/src/chase/substitution.rs index 2c4a85b..2d8c775 100644 --- a/src/chase/substitution.rs +++ b/src/chase/substitution.rs @@ -56,7 +56,7 @@ impl Substitution { } /// Iterate over all bindings. - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.mapping.iter() } } diff --git a/src/lib.rs b/src/lib.rs index 186b1a4..67f7d0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ pub mod chase; // Re-export main types for convenience -pub use chase::{chase, Atom, ChaseResult, Instance, Rule, Substitution, Term}; +pub use chase::{Atom, ChaseResult, Instance, Rule, Substitution, Term, chase}; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 409c8c7..050457b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,7 +1,7 @@ //! Integration tests for the chase algorithm. use chase_rs::chase::rule::RuleBuilder; -use chase_rs::{chase, Atom, Instance, Term}; +use chase_rs::{Atom, Instance, Term, chase}; #[test] fn test_transitive_closure() { @@ -11,8 +11,8 @@ fn test_transitive_closure() { Atom::new("Edge", vec![Term::constant("b"), Term::constant("c")]), Atom::new("Edge", vec![Term::constant("c"), Term::constant("d")]), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // Edge(X, Y) -> Path(X, Y) let rule1 = RuleBuilder::new() @@ -44,8 +44,8 @@ fn test_existential_rule_generates_nulls() { Atom::new("Employee", vec![Term::constant("bob")]), Atom::new("Employee", vec![Term::constant("carol")]), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // Employee(X) -> WorksIn(X, Y) where Y is existential let rule = RuleBuilder::new() @@ -100,18 +100,21 @@ fn test_multiple_head_atoms() { #[test] fn test_chase_with_constants_in_rules() { let instance: Instance = vec![ - Atom::new("Status", vec![Term::constant("alice"), Term::constant("active")]), - Atom::new("Status", vec![Term::constant("bob"), Term::constant("inactive")]), + Atom::new( + "Status", + vec![Term::constant("alice"), Term::constant("active")], + ), + Atom::new( + "Status", + vec![Term::constant("bob"), Term::constant("inactive")], + ), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // Only active users get access: Status(X, "active") -> HasAccess(X) let rule = RuleBuilder::new() - .when( - "Status", - vec![Term::var("X"), Term::constant("active")], - ) + .when("Status", vec![Term::var("X"), Term::constant("active")]) .then("HasAccess", vec![Term::var("X")]) .build(); @@ -164,8 +167,8 @@ fn test_self_join_rule() { vec![Term::constant("carol"), Term::constant("frank")], ), ] - .into_iter() - .collect(); + .into_iter() + .collect(); // ManagedBy(X, M), ManagedBy(Y, M) -> SameTeam(X, Y) let rule = RuleBuilder::new() diff --git a/tests/property_tests.rs b/tests/property_tests.rs index e69de29..8b13789 100644 --- a/tests/property_tests.rs +++ b/tests/property_tests.rs @@ -0,0 +1 @@ + diff --git a/tests/regression_tests.rs b/tests/regression_tests.rs index e69de29..8b13789 100644 --- a/tests/regression_tests.rs +++ b/tests/regression_tests.rs @@ -0,0 +1 @@ +