Skip to main content

strop_engine/editor/git_memory/
file_list.rs

1//! One worker-owned commit catalog: native identity, real buffer text and tree.
2use std::ops::Deref;
3use std::path::Path;
4use std::sync::Arc;
5
6use super::sidebar::Sidebar;
7use ropey::Rope;
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9use strop_git::memory::ChangedFile;
10
11#[derive(Debug, Clone)]
12pub struct PreparedFiles(Arc<FileList>);
13#[derive(Debug)]
14struct FileList {
15    sha: String,
16    files: Vec<ChangedFile>,
17    by_path: Vec<usize>,
18    text: Rope,
19    sidebar: Sidebar,
20}
21impl PreparedFiles {
22    pub fn new(sha: String, files: Vec<ChangedFile>) -> Self {
23        let mut text = format!("commit {}\n\n", sha.get(..10).unwrap_or(&sha));
24        for file in &files {
25            text.push_str(&strop_core::layout::printable_text(
26                file.path.to_string_lossy(),
27            ));
28            text.push('\n');
29        }
30        let mut by_path: Vec<usize> = (0..files.len()).collect();
31        by_path.sort_unstable_by(|&left, &right| files[left].path.cmp(&files[right].path));
32        let sidebar = Sidebar::build(&files);
33        Self(Arc::new(FileList {
34            sha,
35            files,
36            by_path,
37            text: Rope::from_str(&text),
38            sidebar,
39        }))
40    }
41    pub(crate) fn text(&self) -> Rope {
42        self.0.text.clone()
43    }
44    pub fn sidebar(&self) -> &Sidebar {
45        &self.0.sidebar
46    }
47    pub(crate) fn index_of(&self, path: &Path) -> Option<usize> {
48        let index = self
49            .0
50            .by_path
51            .binary_search_by(|&index| self.0.files[index].path.as_path().cmp(path))
52            .ok()?;
53        Some(self.0.by_path[index])
54    }
55}
56impl Deref for PreparedFiles {
57    type Target = [ChangedFile];
58    fn deref(&self) -> &Self::Target {
59        &self.0.files
60    }
61}
62impl<'a> IntoIterator for &'a PreparedFiles {
63    type Item = &'a ChangedFile;
64    type IntoIter = std::slice::Iter<'a, ChangedFile>;
65    fn into_iter(self) -> Self::IntoIter {
66        self.iter()
67    }
68}
69impl Serialize for PreparedFiles {
70    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
71        (&self.0.sha, &self.0.files).serialize(serializer)
72    }
73}
74impl<'de> Deserialize<'de> for PreparedFiles {
75    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
76        let (sha, files) = Deserialize::deserialize(deserializer)?;
77        Ok(Self::new(sha, files))
78    }
79}