Files
galaxy/crates/repo_metadata/src/file_tree_update.rs
T

124 lines
4.2 KiB
Rust

//! Serializable incremental file tree update types.
//!
//! These types mirror the protobuf schema for `RepoMetadataUpdate` 1:1,
//! making encode/decode between Rust and proto trivial. They are produced
//! by the server after processing watcher events and consumed by the client
//! to update its [`RemoteRepoMetadataModel`](crate::remote_model::RemoteRepoMetadataModel).
use galaxy_util::standardized_path::StandardizedPath;
use crate::entry::{DirectoryEntry, Entry, FileMetadata};
use crate::standing_queries::StandingQueryResultsDelta;
/// Describes how a file-tree entry update should be interpreted by consumers.
#[derive(Debug, Clone)]
pub enum MetadataUpdateType {
/// The updated entry was replaced without a precise metadata delta.
/// Consumers should refresh any derived state conservatively.
FullReplace,
/// The updated entry includes a precise incremental metadata delta.
IncrementalUpdate(RepoMetadataUpdate),
}
/// Mirrors `RepoMetadataUpdate` proto.
///
/// A batch of incremental changes for a single repository. Removals are
/// processed before additions so that "move" semantics (remove old + add new)
/// work correctly.
#[derive(Debug, Clone)]
pub struct RepoMetadataUpdate {
/// Which repository this update targets.
pub repo_path: StandardizedPath,
/// Paths to remove from the tree.
pub remove_entries: Vec<StandardizedPath>,
/// Subtree patches to add or replace in the tree.
pub update_entries: Vec<FileTreeEntryUpdate>,
/// Standing query changes synchronized with this tree change.
pub standing_results_delta: StandingQueryResultsDelta,
}
/// Mirrors `FileTreeEntry` proto.
///
/// Describes a subtree patch rooted at a specific parent directory.
/// Applying this inserts the described nodes under `parent_path_to_replace`.
///
/// Parent→child relationships are not included because they are derived
/// implicitly: each node's parent is determined by its path, and
/// `insert_child_state` registers the child in `parent_to_child_map`
/// during application.
#[derive(Debug, Clone)]
pub struct FileTreeEntryUpdate {
/// The parent directory whose subtree is being patched.
pub parent_path_to_replace: StandardizedPath,
/// Metadata for each node in the subtree.
/// Directories must appear before their children (depth-first pre-order)
/// so that parent entries exist when child entries are inserted.
pub subtree_metadata: Vec<RepoNodeMetadata>,
}
/// Mirrors `RepoNodeMetadata` proto.
#[derive(Debug, Clone)]
pub enum RepoNodeMetadata {
Directory(DirectoryNodeMetadata),
File(FileNodeMetadata),
}
/// Mirrors `DirectoryNodeMetadata` proto.
#[derive(Debug, Clone)]
pub struct DirectoryNodeMetadata {
pub path: StandardizedPath,
pub ignored: bool,
pub loaded: bool,
}
/// Mirrors `FileNodeMetadata` proto.
#[derive(Debug, Clone)]
pub struct FileNodeMetadata {
pub path: StandardizedPath,
pub extension: Option<String>,
pub ignored: bool,
}
/// Flattens a recursive [`Entry`] into a `Vec<RepoNodeMetadata>` in
/// depth-first pre-order (directories before their children).
pub fn flatten_entry_metadata(entry: &Entry) -> Vec<RepoNodeMetadata> {
let mut metadata = Vec::new();
collect_metadata(entry, &mut metadata);
metadata
}
fn collect_metadata(entry: &Entry, metadata: &mut Vec<RepoNodeMetadata>) {
match entry {
Entry::File(file) => {
metadata.push(file_metadata_to_node(file));
}
Entry::Directory(dir) => {
collect_directory_metadata(dir, metadata);
}
}
}
fn collect_directory_metadata(dir: &DirectoryEntry, metadata: &mut Vec<RepoNodeMetadata>) {
// Emit metadata for the directory itself before its children.
metadata.push(RepoNodeMetadata::Directory(DirectoryNodeMetadata {
path: dir.path.clone(),
ignored: dir.ignored,
loaded: dir.loaded,
}));
for child in &dir.children {
collect_metadata(child, metadata);
}
}
fn file_metadata_to_node(file: &FileMetadata) -> RepoNodeMetadata {
RepoNodeMetadata::File(FileNodeMetadata {
path: file.path.clone(),
extension: file.extension.clone(),
ignored: file.ignored,
})
}
#[cfg(test)]
#[path = "file_tree_update_tests.rs"]
mod tests;