Fix worktree order serialization (#14676)

Fixes an issue in the serialization of workspaces that lead to incorrect
ordering of worktrees and refactors some other parts of the code to use
the new method.

Release Notes:

- N/A
This commit is contained in:
Elliot Thomas 2024-07-18 08:41:29 +01:00 committed by GitHub
parent eb7fe57453
commit 75948e536f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 27 deletions

View file

@ -47,13 +47,6 @@ impl LocalPaths {
}
}
impl From<LocalPaths> for SerializedWorkspaceLocation {
fn from(local_paths: LocalPaths) -> Self {
let order = LocalPathsOrder::default_for_paths(&local_paths);
Self::Local(local_paths, order)
}
}
impl StaticColumnCount for LocalPaths {}
impl Bind for &LocalPaths {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
@ -155,6 +148,63 @@ pub enum SerializedWorkspaceLocation {
DevServer(SerializedDevServerProject),
}
impl SerializedWorkspaceLocation {
/// Create a new `SerializedWorkspaceLocation` from a list of local paths.
///
/// The paths will be sorted and the order will be stored in the `LocalPathsOrder` struct.
///
/// # Examples
///
/// ```
/// use std::path::Path;
/// use zed_workspace::SerializedWorkspaceLocation;
///
/// let location = SerializedWorkspaceLocation::from_local_paths(vec![
/// Path::new("path/to/workspace1"),
/// Path::new("path/to/workspace2"),
/// ]);
/// assert_eq!(location, SerializedWorkspaceLocation::Local(
/// LocalPaths::new(vec![
/// Path::new("path/to/workspace1"),
/// Path::new("path/to/workspace2"),
/// ]),
/// LocalPathsOrder::new(vec![0, 1]),
/// ));
/// ```
///
/// ```
/// use std::path::Path;
/// use zed_workspace::SerializedWorkspaceLocation;
///
/// let location = SerializedWorkspaceLocation::from_local_paths(vec![
/// Path::new("path/to/workspace2"),
/// Path::new("path/to/workspace1"),
/// ]);
///
/// assert_eq!(location, SerializedWorkspaceLocation::Local(
/// LocalPaths::new(vec![
/// Path::new("path/to/workspace1"),
/// Path::new("path/to/workspace2"),
/// ]),
/// LocalPathsOrder::new(vec![1, 0]),
/// ));
/// ```
pub fn from_local_paths<P: AsRef<Path>>(paths: impl IntoIterator<Item = P>) -> Self {
let mut indexed_paths: Vec<_> = paths
.into_iter()
.map(|p| p.as_ref().to_path_buf())
.enumerate()
.collect();
indexed_paths.sort_by(|(_, a), (_, b)| a.cmp(b));
let sorted_paths: Vec<_> = indexed_paths.iter().map(|(_, path)| path.clone()).collect();
let order: Vec<_> = indexed_paths.iter().map(|(index, _)| *index).collect();
Self::Local(LocalPaths::new(sorted_paths), LocalPathsOrder::new(order))
}
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct SerializedWorkspace {
pub(crate) id: WorkspaceId,
@ -454,3 +504,22 @@ impl Column for SerializedItem {
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize_local_paths() {
let paths = vec!["b", "a", "c"];
let serialized = SerializedWorkspaceLocation::from_local_paths(paths);
assert_eq!(
serialized,
SerializedWorkspaceLocation::Local(
LocalPaths::new(vec!["a", "b", "c"]),
LocalPathsOrder::new(vec![1, 0, 2])
)
);
}
}