rebecca-core 0.3.0

Core planning, safety, scanning, and history models for Rebecca.
Documentation
use std::path::PathBuf;

use serde::{Deserialize, Serialize};

mod catalog;
mod context;
mod definitions;
mod discovery;
mod policy;

pub(crate) use self::catalog::project_artifact_policy_matches_selectors;
pub use self::catalog::{
    all_project_artifact_definitions, project_artifact_definition_for_dir_name,
    project_artifact_definitions, project_artifact_matches_selectors,
    validate_project_artifact_selectors,
};
pub use self::discovery::{
    discover_project_artifacts, discover_project_artifacts_with_diagnostics,
    recently_modified_reason,
};
pub use self::policy::{
    ProjectArtifactPolicy, ProjectArtifactRanking, all_project_artifact_policies,
    policy_for_rule_id,
};

use crate::model::DEFAULT_PROJECT_ARTIFACT_MAX_DEPTH;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProjectArtifactDefinition {
    pub directory_name: &'static str,
    pub rule_id: &'static str,
    pub restore_hint: &'static str,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProjectArtifactContextMatch {
    pub matched_context: String,
    pub project_root: PathBuf,
    pub project_anchor: PathBuf,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectArtifactCandidate {
    pub definition: ProjectArtifactDefinition,
    pub policy: &'static ProjectArtifactPolicy,
    pub path: PathBuf,
    pub context: ProjectArtifactContextMatch,
    pub modified_at_unix_seconds: Option<u64>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ProjectArtifactDiscoveryReport {
    pub candidates: Vec<ProjectArtifactCandidate>,
    pub diagnostics: Vec<ProjectArtifactDiscoveryDiagnostic>,
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ProjectArtifactDiscoveryDiagnostic {
    pub kind: ProjectArtifactDiscoveryDiagnosticKind,
    pub path: PathBuf,
    pub detail: String,
}

impl ProjectArtifactDiscoveryDiagnostic {
    pub fn new(
        kind: ProjectArtifactDiscoveryDiagnosticKind,
        path: PathBuf,
        detail: impl Into<String>,
    ) -> Self {
        Self {
            kind,
            path,
            detail: detail.into(),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum ProjectArtifactDiscoveryDiagnosticKind {
    RootMissing,
    RootMetadataReadSkipped,
    RootNotDirectory,
    ReparsePointSkipped,
    DirectoryReadSkipped,
    DirectoryEntryReadSkipped,
    MetadataReadSkipped,
}

impl ProjectArtifactDiscoveryDiagnosticKind {
    pub fn label(self) -> &'static str {
        match self {
            Self::RootMissing => "root-missing",
            Self::RootMetadataReadSkipped => "root-metadata-read-skipped",
            Self::RootNotDirectory => "root-not-directory",
            Self::ReparsePointSkipped => "reparse-point-skipped",
            Self::DirectoryReadSkipped => "directory-read-skipped",
            Self::DirectoryEntryReadSkipped => "directory-entry-read-skipped",
            Self::MetadataReadSkipped => "metadata-read-skipped",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectArtifactScanOptions {
    pub roots: Vec<PathBuf>,
    pub max_depth: usize,
}

impl ProjectArtifactScanOptions {
    pub fn new(roots: Vec<PathBuf>) -> Self {
        Self {
            roots,
            max_depth: DEFAULT_PROJECT_ARTIFACT_MAX_DEPTH,
        }
    }

    pub fn with_max_depth(mut self, max_depth: usize) -> Self {
        self.max_depth = max_depth;
        self
    }
}