CharlesChen0823cleanup (#11835)1a358e22 years agoHistory
1324 lines · 48.0 KB · Rust
RawDownload
pub mod model; use std::path::Path; use anyhow::{anyhow, bail, Context, Result};use client::DevServerProjectId;use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};use gpui::{point, size, Axis, Bounds, WindowBounds}; use sqlez::{    bindable::{Bind, Column, StaticColumnCount},    statement::Statement,}; use util::ResultExt;use uuid::Uuid; use crate::WorkspaceId; use model::{    GroupId, LocalPaths, PaneId, SerializedItem, SerializedPane, SerializedPaneGroup,    SerializedWorkspace,}; use self::model::{DockStructure, SerializedDevServerProject, SerializedWorkspaceLocation}; #[derive(Copy, Clone, Debug, PartialEq)]pub(crate) struct SerializedAxis(pub(crate) gpui::Axis);impl sqlez::bindable::StaticColumnCount for SerializedAxis {}impl sqlez::bindable::Bind for SerializedAxis {    fn bind(        &self,        statement: &sqlez::statement::Statement,        start_index: i32,    ) -> anyhow::Result<i32> {        match self.0 {            gpui::Axis::Horizontal => "Horizontal",            gpui::Axis::Vertical => "Vertical",        }        .bind(statement, start_index)    }} impl sqlez::bindable::Column for SerializedAxis {    fn column(        statement: &mut sqlez::statement::Statement,        start_index: i32,    ) -> anyhow::Result<(Self, i32)> {        String::column(statement, start_index).and_then(|(axis_text, next_index)| {            Ok((                match axis_text.as_str() {                    "Horizontal" => Self(Axis::Horizontal),                    "Vertical" => Self(Axis::Vertical),                    _ => anyhow::bail!("Stored serialized item kind is incorrect"),                },                next_index,            ))        })    }} #[derive(Copy, Clone, Debug, PartialEq, Default)]pub(crate) struct SerializedWindowBounds(pub(crate) WindowBounds); impl StaticColumnCount for SerializedWindowBounds {    fn column_count() -> usize {        5    }} impl Bind for SerializedWindowBounds {    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {        match self.0 {            WindowBounds::Windowed(bounds) => {                let next_index = statement.bind(&"Windowed", start_index)?;                statement.bind(                    &(                        SerializedDevicePixels(bounds.origin.x),                        SerializedDevicePixels(bounds.origin.y),                        SerializedDevicePixels(bounds.size.width),                        SerializedDevicePixels(bounds.size.height),                    ),                    next_index,                )            }            WindowBounds::Maximized(bounds) => {                let next_index = statement.bind(&"Maximized", start_index)?;                statement.bind(                    &(                        SerializedDevicePixels(bounds.origin.x),                        SerializedDevicePixels(bounds.origin.y),                        SerializedDevicePixels(bounds.size.width),                        SerializedDevicePixels(bounds.size.height),                    ),                    next_index,                )            }            WindowBounds::Fullscreen(bounds) => {                let next_index = statement.bind(&"FullScreen", start_index)?;                statement.bind(                    &(                        SerializedDevicePixels(bounds.origin.x),                        SerializedDevicePixels(bounds.origin.y),                        SerializedDevicePixels(bounds.size.width),                        SerializedDevicePixels(bounds.size.height),                    ),                    next_index,                )            }        }    }} impl Column for SerializedWindowBounds {    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {        let (window_state, next_index) = String::column(statement, start_index)?;        let status = match window_state.as_str() {            "Windowed" | "Fixed" => {                let ((x, y, width, height), _) = Column::column(statement, next_index)?;                let x: i32 = x;                let y: i32 = y;                let width: i32 = width;                let height: i32 = height;                SerializedWindowBounds(WindowBounds::Windowed(Bounds {                    origin: point(x.into(), y.into()),                    size: size(width.into(), height.into()),                }))            }            "Maximized" => {                let ((x, y, width, height), _) = Column::column(statement, next_index)?;                let x: i32 = x;                let y: i32 = y;                let width: i32 = width;                let height: i32 = height;                SerializedWindowBounds(WindowBounds::Maximized(Bounds {                    origin: point(x.into(), y.into()),                    size: size(width.into(), height.into()),                }))            }            "FullScreen" => {                let ((x, y, width, height), _) = Column::column(statement, next_index)?;                let x: i32 = x;                let y: i32 = y;                let width: i32 = width;                let height: i32 = height;                SerializedWindowBounds(WindowBounds::Fullscreen(Bounds {                    origin: point(x.into(), y.into()),                    size: size(width.into(), height.into()),                }))            }            _ => bail!("Window State did not have a valid string"),        };         Ok((status, next_index + 4))    }} #[derive(Clone, Debug, PartialEq)]struct SerializedDevicePixels(gpui::DevicePixels);impl sqlez::bindable::StaticColumnCount for SerializedDevicePixels {} impl sqlez::bindable::Bind for SerializedDevicePixels {    fn bind(        &self,        statement: &sqlez::statement::Statement,        start_index: i32,    ) -> anyhow::Result<i32> {        let this: i32 = self.0.into();        this.bind(statement, start_index)    }} define_connection! {    // Current schema shape using pseudo-rust syntax:    //    // workspaces(    //   workspace_id: usize, // Primary key for workspaces    //   local_paths: Bincode<Vec<PathBuf>>,    //   dock_visible: bool, // Deprecated    //   dock_anchor: DockAnchor, // Deprecated    //   dock_pane: Option<usize>, // Deprecated    //   left_sidebar_open: boolean,    //   timestamp: String, // UTC YYYY-MM-DD HH:MM:SS    //   window_state: String, // WindowBounds Discriminant    //   window_x: Option<f32>, // WindowBounds::Fixed RectF x    //   window_y: Option<f32>, // WindowBounds::Fixed RectF y    //   window_width: Option<f32>, // WindowBounds::Fixed RectF width    //   window_height: Option<f32>, // WindowBounds::Fixed RectF height    //   display: Option<Uuid>, // Display id    //   fullscreen: Option<bool>, // Is the window fullscreen?    //   centered_layout: Option<bool>, // Is the Centered Layout mode activated?    // )    //    // pane_groups(    //   group_id: usize, // Primary key for pane_groups    //   workspace_id: usize, // References workspaces table    //   parent_group_id: Option<usize>, // None indicates that this is the root node    //   position: Optiopn<usize>, // None indicates that this is the root node    //   axis: Option<Axis>, // 'Vertical', 'Horizontal'    //   flexes: Option<Vec<f32>>, // A JSON array of floats    // )    //    // panes(    //     pane_id: usize, // Primary key for panes    //     workspace_id: usize, // References workspaces table    //     active: bool,    // )    //    // center_panes(    //     pane_id: usize, // Primary key for center_panes    //     parent_group_id: Option<usize>, // References pane_groups. If none, this is the root    //     position: Option<usize>, // None indicates this is the root    // )    //    // CREATE TABLE items(    //     item_id: usize, // This is the item's view id, so this is not unique    //     workspace_id: usize, // References workspaces table    //     pane_id: usize, // References panes table    //     kind: String, // Indicates which view this connects to. This is the key in the item_deserializers global    //     position: usize, // Position of the item in the parent pane. This is equivalent to panes' position column    //     active: bool, // Indicates if this item is the active one in the pane    //     preview: bool // Indicates if this item is a preview item    // )    pub static ref DB: WorkspaceDb<()> =    &[sql!(        CREATE TABLE workspaces(            workspace_id INTEGER PRIMARY KEY,            workspace_location BLOB UNIQUE,            dock_visible INTEGER, // Deprecated. Preserving so users can downgrade Zed.            dock_anchor TEXT, // Deprecated. Preserving so users can downgrade Zed.            dock_pane INTEGER, // Deprecated.  Preserving so users can downgrade Zed.            left_sidebar_open INTEGER, // Boolean            timestamp TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,            FOREIGN KEY(dock_pane) REFERENCES panes(pane_id)        ) STRICT;         CREATE TABLE pane_groups(            group_id INTEGER PRIMARY KEY,            workspace_id INTEGER NOT NULL,            parent_group_id INTEGER, // NULL indicates that this is a root node            position INTEGER, // NULL indicates that this is a root node            axis TEXT NOT NULL, // Enum: 'Vertical' / 'Horizontal'            FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)            ON DELETE CASCADE            ON UPDATE CASCADE,            FOREIGN KEY(parent_group_id) REFERENCES pane_groups(group_id) ON DELETE CASCADE        ) STRICT;         CREATE TABLE panes(            pane_id INTEGER PRIMARY KEY,            workspace_id INTEGER NOT NULL,            active INTEGER NOT NULL, // Boolean            FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)            ON DELETE CASCADE            ON UPDATE CASCADE        ) STRICT;         CREATE TABLE center_panes(            pane_id INTEGER PRIMARY KEY,            parent_group_id INTEGER, // NULL means that this is a root pane            position INTEGER, // NULL means that this is a root pane            FOREIGN KEY(pane_id) REFERENCES panes(pane_id)            ON DELETE CASCADE,            FOREIGN KEY(parent_group_id) REFERENCES pane_groups(group_id) ON DELETE CASCADE        ) STRICT;         CREATE TABLE items(            item_id INTEGER NOT NULL, // This is the item's view id, so this is not unique            workspace_id INTEGER NOT NULL,            pane_id INTEGER NOT NULL,            kind TEXT NOT NULL,            position INTEGER NOT NULL,            active INTEGER NOT NULL,            FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)            ON DELETE CASCADE            ON UPDATE CASCADE,            FOREIGN KEY(pane_id) REFERENCES panes(pane_id)            ON DELETE CASCADE,            PRIMARY KEY(item_id, workspace_id)        ) STRICT;    ),    sql!(        ALTER TABLE workspaces ADD COLUMN window_state TEXT;        ALTER TABLE workspaces ADD COLUMN window_x REAL;        ALTER TABLE workspaces ADD COLUMN window_y REAL;        ALTER TABLE workspaces ADD COLUMN window_width REAL;        ALTER TABLE workspaces ADD COLUMN window_height REAL;        ALTER TABLE workspaces ADD COLUMN display BLOB;    ),    // Drop foreign key constraint from workspaces.dock_pane to panes table.    sql!(        CREATE TABLE workspaces_2(            workspace_id INTEGER PRIMARY KEY,            workspace_location BLOB UNIQUE,            dock_visible INTEGER, // Deprecated. Preserving so users can downgrade Zed.            dock_anchor TEXT, // Deprecated. Preserving so users can downgrade Zed.            dock_pane INTEGER, // Deprecated.  Preserving so users can downgrade Zed.            left_sidebar_open INTEGER, // Boolean            timestamp TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,            window_state TEXT,            window_x REAL,            window_y REAL,            window_width REAL,            window_height REAL,            display BLOB        ) STRICT;        INSERT INTO workspaces_2 SELECT * FROM workspaces;        DROP TABLE workspaces;        ALTER TABLE workspaces_2 RENAME TO workspaces;    ),    // Add panels related information    sql!(        ALTER TABLE workspaces ADD COLUMN left_dock_visible INTEGER; //bool        ALTER TABLE workspaces ADD COLUMN left_dock_active_panel TEXT;        ALTER TABLE workspaces ADD COLUMN right_dock_visible INTEGER; //bool        ALTER TABLE workspaces ADD COLUMN right_dock_active_panel TEXT;        ALTER TABLE workspaces ADD COLUMN bottom_dock_visible INTEGER; //bool        ALTER TABLE workspaces ADD COLUMN bottom_dock_active_panel TEXT;    ),    // Add panel zoom persistence    sql!(        ALTER TABLE workspaces ADD COLUMN left_dock_zoom INTEGER; //bool        ALTER TABLE workspaces ADD COLUMN right_dock_zoom INTEGER; //bool        ALTER TABLE workspaces ADD COLUMN bottom_dock_zoom INTEGER; //bool    ),    // Add pane group flex data    sql!(        ALTER TABLE pane_groups ADD COLUMN flexes TEXT;    ),    // Add fullscreen field to workspace    // Deprecated, `WindowBounds` holds the fullscreen state now.    // Preserving so users can downgrade Zed.    sql!(        ALTER TABLE workspaces ADD COLUMN fullscreen INTEGER; //bool    ),    // Add preview field to items    sql!(        ALTER TABLE items ADD COLUMN preview INTEGER; //bool    ),    // Add centered_layout field to workspace    sql!(        ALTER TABLE workspaces ADD COLUMN centered_layout INTEGER; //bool    ),    sql!(        CREATE TABLE remote_projects (            remote_project_id INTEGER NOT NULL UNIQUE,            path TEXT,            dev_server_name TEXT        );        ALTER TABLE workspaces ADD COLUMN remote_project_id INTEGER;        ALTER TABLE workspaces RENAME COLUMN workspace_location TO local_paths;    ),    sql!(        DROP TABLE remote_projects;        CREATE TABLE dev_server_projects (            id INTEGER NOT NULL UNIQUE,            path TEXT,            dev_server_name TEXT        );        ALTER TABLE workspaces DROP COLUMN remote_project_id;        ALTER TABLE workspaces ADD COLUMN dev_server_project_id INTEGER;    ),    ];} impl WorkspaceDb {    /// Returns a serialized workspace for the given worktree_roots. If the passed array    /// is empty, the most recent workspace is returned instead. If no workspace for the    /// passed roots is stored, returns none.    pub(crate) fn workspace_for_roots<P: AsRef<Path>>(        &self,        worktree_roots: &[P],    ) -> Option<SerializedWorkspace> {        let local_paths = LocalPaths::new(worktree_roots);         // Note that we re-assign the workspace_id here in case it's empty        // and we've grabbed the most recent workspace        let (            workspace_id,            local_paths,            dev_server_project_id,            window_bounds,            display,            centered_layout,            docks,        ): (            WorkspaceId,            Option<LocalPaths>,            Option<u64>,            Option<SerializedWindowBounds>,            Option<Uuid>,            Option<bool>,            DockStructure,        ) = self            .select_row_bound(sql! {                SELECT                    workspace_id,                    local_paths,                    dev_server_project_id,                    window_state,                    window_x,                    window_y,                    window_width,                    window_height,                    display,                    centered_layout,                    left_dock_visible,                    left_dock_active_panel,                    left_dock_zoom,                    right_dock_visible,                    right_dock_active_panel,                    right_dock_zoom,                    bottom_dock_visible,                    bottom_dock_active_panel,                    bottom_dock_zoom                FROM workspaces                WHERE local_paths = ?            })            .and_then(|mut prepared_statement| (prepared_statement)(&local_paths))            .context("No workspaces found")            .warn_on_err()            .flatten()?;         let location = if let Some(dev_server_project_id) = dev_server_project_id {            let dev_server_project: SerializedDevServerProject = self                .select_row_bound(sql! {                    SELECT id, path, dev_server_name                    FROM dev_server_projects                    WHERE id = ?                })                .and_then(|mut prepared_statement| (prepared_statement)(dev_server_project_id))                .context("No remote project found")                .warn_on_err()                .flatten()?;            SerializedWorkspaceLocation::DevServer(dev_server_project)        } else if let Some(local_paths) = local_paths {            SerializedWorkspaceLocation::Local(local_paths)        } else {            return None;        };         Some(SerializedWorkspace {            id: workspace_id,            location,            center_group: self                .get_center_pane_group(workspace_id)                .context("Getting center group")                .log_err()?,            window_bounds,            centered_layout: centered_layout.unwrap_or(false),            display,            docks,        })    }     /// Saves a workspace using the worktree roots. Will garbage collect any workspaces    /// that used this workspace previously    pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {        self.write(move |conn| {            conn.with_savepoint("update_worktrees", || {                // Clear out panes and pane_groups                conn.exec_bound(sql!(                    DELETE FROM pane_groups WHERE workspace_id = ?1;                    DELETE FROM panes WHERE workspace_id = ?1;))?(workspace.id)                .context("Clearing old panes")?;                 match workspace.location {                    SerializedWorkspaceLocation::Local(local_paths) => {                        conn.exec_bound(sql!(                            DELETE FROM workspaces WHERE local_paths = ? AND workspace_id != ?                        ))?((&local_paths, workspace.id))                        .context("clearing out old locations")?;                         // Upsert                        conn.exec_bound(sql!(                            INSERT INTO workspaces(                                workspace_id,                                local_paths,                                left_dock_visible,                                left_dock_active_panel,                                left_dock_zoom,                                right_dock_visible,                                right_dock_active_panel,                                right_dock_zoom,                                bottom_dock_visible,                                bottom_dock_active_panel,                                bottom_dock_zoom,                                timestamp                            )                            VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, CURRENT_TIMESTAMP)                            ON CONFLICT DO                            UPDATE SET                                local_paths = ?2,                                left_dock_visible = ?3,                                left_dock_active_panel = ?4,                                left_dock_zoom = ?5,                                right_dock_visible = ?6,                                right_dock_active_panel = ?7,                                right_dock_zoom = ?8,                                bottom_dock_visible = ?9,

Lines 1–500 of 1324.