Skip to content

Commit 7c21398

Browse files
authored
Merge pull request #9439 from gitbutlerapp/workspace-rules
Playing with a Workspace Rules idea
2 parents 59868be + 74e7e22 commit 7c21398

File tree

14 files changed

+469
-2
lines changed

14 files changed

+469
-2
lines changed

Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ but-hunk-assignment = { path = "crates/but-hunk-assignment" }
7676
but-hunk-dependency = { path = "crates/but-hunk-dependency" }
7777
but-db = { path = "crates/but-db" }
7878
but-graph = { path = "crates/but-graph" }
79+
but-rules = { path = "crates/but-rules" }
7980
but-action = { path = "crates/but-action" }
8081
but-status = { path = "crates/but-status" }
8182
but-tools = { path = "crates/but-tools" }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- This file should undo anything in `up.sql`
2+
DROP TABLE IF EXISTS `workspace_rules`;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Your SQL goes here
2+
CREATE TABLE `workspace_rules`(
3+
`id` TEXT NOT NULL PRIMARY KEY,
4+
`created_at` TIMESTAMP NOT NULL,
5+
`enabled` BOOL NOT NULL,
6+
`trigger` TEXT NOT NULL,
7+
`filters` TEXT NOT NULL,
8+
`action` TEXT NOT NULL
9+
);

crates/but-db/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ mod claude_code_sessions;
1717
pub use claude_code_sessions::ClaudeCodeSession;
1818
mod file_write_locks;
1919
pub use file_write_locks::FileWriteLock;
20+
mod workspace_rules;
21+
pub use workspace_rules::WorkspaceRule;
2022

2123
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
2224
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations");

crates/but-db/src/schema.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,14 @@ diesel::table! {
5151
owner -> Text,
5252
}
5353
}
54+
55+
diesel::table! {
56+
workspace_rules (id) {
57+
id -> Text,
58+
created_at -> Timestamp,
59+
enabled -> Bool,
60+
trigger -> Text,
61+
filters -> Text,
62+
action -> Text,
63+
}
64+
}

crates/but-db/src/workspace_rules.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl};
2+
3+
use crate::DbHandle;
4+
use crate::schema::workspace_rules::dsl::workspace_rules;
5+
6+
use diesel::prelude::{Insertable, Queryable, Selectable};
7+
use serde::{Deserialize, Serialize};
8+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Queryable, Selectable, Insertable)]
9+
#[diesel(table_name = crate::schema::workspace_rules)]
10+
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
11+
pub struct WorkspaceRule {
12+
pub id: String,
13+
pub created_at: chrono::NaiveDateTime,
14+
pub enabled: bool,
15+
pub trigger: String,
16+
pub filters: String,
17+
pub action: String,
18+
}
19+
20+
impl DbHandle {
21+
pub fn workspace_rules(&mut self) -> WorkspaceRulesHandle {
22+
WorkspaceRulesHandle { db: self }
23+
}
24+
}
25+
26+
pub struct WorkspaceRulesHandle<'a> {
27+
db: &'a mut DbHandle,
28+
}
29+
30+
impl WorkspaceRulesHandle<'_> {
31+
pub fn insert(&mut self, rule: WorkspaceRule) -> Result<(), diesel::result::Error> {
32+
diesel::insert_into(workspace_rules)
33+
.values(rule)
34+
.execute(&mut self.db.conn)?;
35+
Ok(())
36+
}
37+
38+
pub fn update(&mut self, id: &str, rule: WorkspaceRule) -> Result<(), diesel::result::Error> {
39+
diesel::update(workspace_rules.filter(crate::schema::workspace_rules::id.eq(id)))
40+
.set((
41+
crate::schema::workspace_rules::enabled.eq(rule.enabled),
42+
crate::schema::workspace_rules::trigger.eq(rule.trigger),
43+
crate::schema::workspace_rules::filters.eq(rule.filters),
44+
crate::schema::workspace_rules::action.eq(rule.action),
45+
))
46+
.execute(&mut self.db.conn)?;
47+
Ok(())
48+
}
49+
50+
pub fn delete(&mut self, id: &str) -> Result<(), diesel::result::Error> {
51+
diesel::delete(workspace_rules.filter(crate::schema::workspace_rules::id.eq(id)))
52+
.execute(&mut self.db.conn)?;
53+
Ok(())
54+
}
55+
56+
pub fn list(&mut self) -> Result<Vec<WorkspaceRule>, diesel::result::Error> {
57+
let rules = workspace_rules.load::<WorkspaceRule>(&mut self.db.conn)?;
58+
Ok(rules)
59+
}
60+
61+
pub fn get(&mut self, id: &str) -> Result<Option<WorkspaceRule>, diesel::result::Error> {
62+
let rule = workspace_rules
63+
.filter(crate::schema::workspace_rules::id.eq(id))
64+
.first::<WorkspaceRule>(&mut self.db.conn)
65+
.optional()?;
66+
Ok(rule)
67+
}
68+
}

crates/but-rules/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "but-rules"
3+
version = "0.0.0"
4+
edition = "2024"
5+
authors = ["GitButler <[email protected]>"]
6+
publish = false
7+
8+
9+
[lib]
10+
doctest = false
11+
12+
[dependencies]
13+
anyhow = "1.0.98"
14+
itertools.workspace = true
15+
serde.workspace = true
16+
regex = "1.11.1"
17+
chrono = { version = "0.4.41", features = [] }
18+
serde_regex = "1.1.0"
19+
serde_json = "1.0.138"
20+
gitbutler-command-context.workspace = true
21+
but-db.workspace = true
22+
uuid.workspace = true

crates/but-rules/src/db.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use anyhow::Result;
2+
use gitbutler_command_context::CommandContext;
3+
4+
impl TryFrom<but_db::WorkspaceRule> for crate::WorkspaceRule {
5+
type Error = anyhow::Error;
6+
fn try_from(value: but_db::WorkspaceRule) -> Result<Self, Self::Error> {
7+
Ok(crate::WorkspaceRule {
8+
id: value.id,
9+
created_at: value.created_at,
10+
enabled: value.enabled,
11+
trigger: serde_json::from_str(&value.trigger)?,
12+
filters: serde_json::from_str(&value.filters)?,
13+
action: serde_json::from_str(&value.action)?,
14+
})
15+
}
16+
}
17+
18+
impl TryFrom<crate::WorkspaceRule> for but_db::WorkspaceRule {
19+
type Error = anyhow::Error;
20+
fn try_from(value: crate::WorkspaceRule) -> Result<Self, Self::Error> {
21+
Ok(but_db::WorkspaceRule {
22+
id: value.id,
23+
created_at: value.created_at,
24+
enabled: value.enabled,
25+
trigger: serde_json::to_string(&value.trigger)?,
26+
filters: serde_json::to_string(&value.filters)?,
27+
action: serde_json::to_string(&value.action)?,
28+
})
29+
}
30+
}
31+
32+
pub fn workspace_rules(ctx: &mut CommandContext) -> Result<Vec<crate::WorkspaceRule>> {
33+
let rules = ctx
34+
.db()?
35+
.workspace_rules()
36+
.list()?
37+
.into_iter()
38+
.map(|r| r.try_into())
39+
.collect::<Result<Vec<crate::WorkspaceRule>>>()?;
40+
Ok(rules)
41+
}

0 commit comments

Comments
 (0)