diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index 7d8bd8eb1b..5ffff0921f 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -78,10 +78,10 @@ CREATE TABLE "worktree_entries" ( "id" INTEGER NOT NULL, "is_dir" BOOL NOT NULL, "path" VARCHAR NOT NULL, + "canonical_path" TEXT, "inode" INTEGER NOT NULL, "mtime_seconds" INTEGER NOT NULL, "mtime_nanos" INTEGER NOT NULL, - "is_symlink" BOOL NOT NULL, "is_external" BOOL NOT NULL, "is_ignored" BOOL NOT NULL, "is_deleted" BOOL NOT NULL, diff --git a/crates/collab/migrations/20241019184824_adjust_symlink_data.sql b/crates/collab/migrations/20241019184824_adjust_symlink_data.sql new file mode 100644 index 0000000000..a38dd21cde --- /dev/null +++ b/crates/collab/migrations/20241019184824_adjust_symlink_data.sql @@ -0,0 +1,2 @@ +ALTER TABLE worktree_entries ADD COLUMN canonical_path text; +ALTER TABLE worktree_entries ALTER COLUMN is_symlink SET DEFAULT false; diff --git a/crates/collab/src/db/queries/projects.rs b/crates/collab/src/db/queries/projects.rs index f4eabf4979..b04d88242e 100644 --- a/crates/collab/src/db/queries/projects.rs +++ b/crates/collab/src/db/queries/projects.rs @@ -317,7 +317,7 @@ impl Database { inode: ActiveValue::set(entry.inode as i64), mtime_seconds: ActiveValue::set(mtime.seconds as i64), mtime_nanos: ActiveValue::set(mtime.nanos as i32), - is_symlink: ActiveValue::set(entry.is_symlink), + canonical_path: ActiveValue::set(entry.canonical_path.clone()), is_ignored: ActiveValue::set(entry.is_ignored), is_external: ActiveValue::set(entry.is_external), git_status: ActiveValue::set(entry.git_status.map(|status| status as i64)), @@ -338,7 +338,7 @@ impl Database { worktree_entry::Column::Inode, worktree_entry::Column::MtimeSeconds, worktree_entry::Column::MtimeNanos, - worktree_entry::Column::IsSymlink, + worktree_entry::Column::CanonicalPath, worktree_entry::Column::IsIgnored, worktree_entry::Column::GitStatus, worktree_entry::Column::ScanId, @@ -735,7 +735,7 @@ impl Database { seconds: db_entry.mtime_seconds as u64, nanos: db_entry.mtime_nanos as u32, }), - is_symlink: db_entry.is_symlink, + canonical_path: db_entry.canonical_path, is_ignored: db_entry.is_ignored, is_external: db_entry.is_external, git_status: db_entry.git_status.map(|status| status as i32), diff --git a/crates/collab/src/db/queries/rooms.rs b/crates/collab/src/db/queries/rooms.rs index a0bb9fed69..9235b8550b 100644 --- a/crates/collab/src/db/queries/rooms.rs +++ b/crates/collab/src/db/queries/rooms.rs @@ -659,7 +659,7 @@ impl Database { seconds: db_entry.mtime_seconds as u64, nanos: db_entry.mtime_nanos as u32, }), - is_symlink: db_entry.is_symlink, + canonical_path: db_entry.canonical_path, is_ignored: db_entry.is_ignored, is_external: db_entry.is_external, git_status: db_entry.git_status.map(|status| status as i32), diff --git a/crates/collab/src/db/tables/worktree_entry.rs b/crates/collab/src/db/tables/worktree_entry.rs index d60d2c336b..d148c63a7f 100644 --- a/crates/collab/src/db/tables/worktree_entry.rs +++ b/crates/collab/src/db/tables/worktree_entry.rs @@ -16,12 +16,12 @@ pub struct Model { pub mtime_seconds: i64, pub mtime_nanos: i32, pub git_status: Option, - pub is_symlink: bool, pub is_ignored: bool, pub is_external: bool, pub is_deleted: bool, pub scan_id: i64, pub is_fifo: bool, + pub canonical_path: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ba3841b4e2..f7fef4707c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6282,11 +6282,9 @@ impl Editor { let project_path = buffer.read(cx).project_path(cx)?; let project = self.project.as_ref()?.read(cx); let entry = project.entry_for_path(&project_path, cx)?; - let abs_path = project.absolute_path(&project_path, cx)?; - let parent = if entry.is_symlink { - abs_path.canonicalize().ok()? - } else { - abs_path + let parent = match &entry.canonical_path { + Some(canonical_path) => canonical_path.to_path_buf(), + None => project.absolute_path(&project_path, cx)?, } .parent()? .to_path_buf(); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a7ec02c06c..aca5cc7bee 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -91,7 +91,6 @@ struct EditState { entry_id: ProjectEntryId, is_new_entry: bool, is_dir: bool, - is_symlink: bool, depth: usize, processing_filename: Option, } @@ -987,7 +986,6 @@ impl ProjectPanel { is_new_entry: true, is_dir, processing_filename: None, - is_symlink: false, depth: 0, }); self.filename_editor.update(cx, |editor, cx| { @@ -1027,7 +1025,6 @@ impl ProjectPanel { is_new_entry: false, is_dir: entry.is_dir(), processing_filename: None, - is_symlink: entry.is_symlink, depth: 0, }); let file_name = entry @@ -1533,16 +1530,15 @@ impl ProjectPanel { fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext) { if let Some((worktree, entry)) = self.selected_sub_entry(cx) { - let abs_path = worktree.abs_path().join(&entry.path); + let abs_path = match &entry.canonical_path { + Some(canonical_path) => Some(canonical_path.to_path_buf()), + None => worktree.absolutize(&entry.path).ok(), + }; + let working_directory = if entry.is_dir() { - Some(abs_path) + abs_path } else { - if entry.is_symlink { - abs_path.canonicalize().ok() - } else { - Some(abs_path) - } - .and_then(|path| Some(path.parent()?.to_path_buf())) + abs_path.and_then(|path| Some(path.parent()?.to_path_buf())) }; if let Some(working_directory) = working_directory { cx.dispatch_action(workspace::OpenTerminal { working_directory }.boxed_clone()) @@ -1830,7 +1826,6 @@ impl ProjectPanel { .unwrap_or_default(); if let Some(edit_state) = &mut self.edit_state { if edit_state.entry_id == entry.id { - edit_state.is_symlink = entry.is_symlink; edit_state.depth = depth; } } @@ -1861,7 +1856,6 @@ impl ProjectPanel { is_private: false, git_status: entry.git_status, canonical_path: entry.canonical_path.clone(), - is_symlink: entry.is_symlink, char_bag: entry.char_bag, is_fifo: entry.is_fifo, }); @@ -1920,7 +1914,7 @@ impl ProjectPanel { let width_estimate = item_width_estimate( depth, path.to_string_lossy().chars().count(), - entry.is_symlink, + entry.canonical_path.is_some(), ); match max_width_item.as_mut() { diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index 09891de6fe..226b2474b2 100644 --- a/crates/proto/proto/zed.proto +++ b/crates/proto/proto/zed.proto @@ -1867,12 +1867,13 @@ message Entry { string path = 3; uint64 inode = 4; Timestamp mtime = 5; - bool is_symlink = 6; bool is_ignored = 7; bool is_external = 8; + reserved 6; optional GitStatus git_status = 9; bool is_fifo = 10; optional uint64 size = 11; + optional string canonical_path = 12; } message RepositoryEntry { diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index c205f2a8e5..f7e9dba965 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1739,11 +1739,9 @@ impl Pane { .worktree_for_entry(entry, cx)? .read(cx); let entry = worktree.entry_for_id(entry)?; - let abs_path = worktree.absolutize(&entry.path).ok()?; - if entry.is_symlink { - abs_path.canonicalize().ok() - } else { - Some(abs_path) + match &entry.canonical_path { + Some(canonical_path) => Some(canonical_path.to_path_buf()), + None => worktree.absolutize(&entry.path).ok(), } } diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 3a5ba2c276..abf1f744a3 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -3203,7 +3203,6 @@ pub struct Entry { pub mtime: Option, pub canonical_path: Option>, - pub is_symlink: bool, /// Whether this entry is ignored by Git. /// /// We only scan ignored entries once the directory is expanded and @@ -3280,7 +3279,6 @@ impl Entry { mtime: Some(metadata.mtime), size: metadata.len, canonical_path, - is_symlink: metadata.is_symlink, is_ignored: false, is_external: false, is_private: false, @@ -5249,12 +5247,15 @@ impl<'a> From<&'a Entry> for proto::Entry { path: entry.path.to_string_lossy().into(), inode: entry.inode, mtime: entry.mtime.map(|time| time.into()), - is_symlink: entry.is_symlink, is_ignored: entry.is_ignored, is_external: entry.is_external, git_status: entry.git_status.map(git_status_to_proto), is_fifo: entry.is_fifo, size: Some(entry.size), + canonical_path: entry + .canonical_path + .as_ref() + .map(|path| path.to_string_lossy().to_string()), } } } @@ -5277,12 +5278,13 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry { inode: entry.inode, mtime: entry.mtime.map(|time| time.into()), size: entry.size.unwrap_or(0), - canonical_path: None, + canonical_path: entry + .canonical_path + .map(|path_string| Box::from(Path::new(&path_string))), is_ignored: entry.is_ignored, is_external: entry.is_external, git_status: git_status_from_proto(entry.git_status), is_private: false, - is_symlink: entry.is_symlink, char_bag, is_fifo: entry.is_fifo, })