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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions crates/db/src/models/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,31 @@ impl Workspace {
Ok(result.rows_affected() > 0)
}

/// Compare-and-set name update: only sets `name` if it still equals
/// `expected_old` (NULL-safe via SQLite `IS`). Returns `true` if a row was
/// updated (the name was unchanged since the caller snapshotted it), `false`
/// if it changed concurrently. Lets the async generated-title write avoid
/// clobbering a manual rename (or an MCP-provided name) that landed in the
/// meantime. `expected_old` must be the pre-spawn workspace-row snapshot
/// name, NOT a value re-derived from the prompt (they can differ).
pub async fn update_name_if_unchanged(
pool: &SqlitePool,
workspace_id: Uuid,
new_name: &str,
expected_old: Option<&str>,
) -> Result<bool, WorkspaceError> {
let result = sqlx::query!(
"UPDATE workspaces SET name = $1, updated_at = datetime('now', 'subsec') WHERE id = $2 AND name IS $3",
new_name,
workspace_id,
expected_old,
)
.execute(pool)
.await?;

Ok(result.rows_affected() > 0)
}

/// Find workspace by path using container-ref path containment.
/// Used by clients that may open a repo subfolder rather than the workspace root.
pub async fn resolve_container_ref_by_prefix(
Expand Down
Loading
Loading