251 lines · 8.9 KB · Rust
RawDownload
use gix_diff::tree::recorder::Location;pub use gix_diff::*; ///pub mod options {    ///    pub mod init {        /// The error returned when instantiating [diff options](crate::diff::Options).        #[derive(Debug, thiserror::Error)]        #[cfg_attr(feature = "blob-diff", expect(missing_docs))]        pub enum Error {            #[cfg(feature = "blob-diff")]            #[error(transparent)]            RewritesConfiguration(#[from] crate::diff::new_rewrites::Error),        }    }} /// General diff-related options for configuring rename-tracking and blob diffs.#[derive(Debug, Copy, Clone)]pub struct Options {    location: Option<Location>,    #[cfg(feature = "blob-diff")]    rewrites: Option<gix_diff::Rewrites>,} impl Default for Options {    fn default() -> Self {        Options {            location: Some(Location::Path),            #[cfg(feature = "blob-diff")]            rewrites: None,        }    }} #[cfg(feature = "blob-diff")]impl From<Options> for gix_diff::tree_with_rewrites::Options {    fn from(opts: Options) -> Self {        gix_diff::tree_with_rewrites::Options {            location: opts.location,            #[cfg(feature = "blob-diff")]            rewrites: opts.rewrites,        }    }} /// Lifecycleimpl Options {    #[cfg(feature = "blob-diff")]    pub(crate) fn from_configuration(config: &crate::config::Cache) -> Result<Self, options::init::Error> {        Ok(Options {            location: Some(Location::Path),            rewrites: {                let (rewrites, is_configured) = config.diff_renames()?;                if is_configured {                    rewrites                } else {                    Some(Default::default())                }            },        })    }} /// Settersimpl Options {    /// Do not keep track of filepaths at all, which will leave all `location` fields empty.    pub fn no_locations(&mut self) -> &mut Self {        self.location = None;        self    }     /// Keep track of file-names, which makes `location` fields usable with the filename of the changed item.    pub fn track_filename(&mut self) -> &mut Self {        self.location = Some(Location::FileName);        self    }     /// Keep track of the entire path of a change, relative to the repository. (default).    ///    /// This makes the `location` field fully usable.    pub fn track_path(&mut self) -> &mut Self {        self.location = Some(Location::Path);        self    }     /// Provide `None` to disable rewrite tracking entirely, or pass `Some(<configuration>)` to control to    /// what extent rename and copy tracking is performed.    ///    /// Note that by default, the git configuration determines rewrite tracking and git defaults are used    /// if nothing is configured, which turns rename tracking with 50% similarity on, while not tracking copies at all.    #[cfg(feature = "blob-diff")]    pub fn track_rewrites(&mut self, renames: Option<gix_diff::Rewrites>) -> &mut Self {        self.rewrites = renames;        self    }} /// Builderimpl Options {    /// Provide `None` to disable rewrite tracking entirely, or pass `Some(<configuration>)` to control to    /// what extent rename and copy tracking is performed.    ///    /// Note that by default, the git configuration determines rewrite tracking and git defaults are used    /// if nothing is configured, which turns rename tracking with 50% similarity on, while not tracking copies at all.    #[cfg(feature = "blob-diff")]    pub fn with_rewrites(mut self, renames: Option<gix_diff::Rewrites>) -> Self {        self.rewrites = renames;        self    }} ///pub mod rename {    /// Determine how to do rename tracking.    #[derive(Debug, Copy, Clone, Eq, PartialEq)]    pub enum Tracking {        /// Do not track renames at all, the fastest option.        Disabled,        /// Track renames.        Renames,        /// Track renames and copies.        ///        /// This is the most expensive option.        RenamesAndCopies,    }} ///#[cfg(feature = "blob-diff")]pub(crate) mod utils {    use gix_diff::{Rewrites, rewrites::Copies};     use crate::{        Repository,        config::{cache::util::ApplyLeniency, tree::Diff},        diff::rename::Tracking,    };     ///    pub mod new_rewrites {        /// The error returned by [`new_rewrites()`](super::new_rewrites()).        #[derive(Debug, thiserror::Error)]        #[expect(missing_docs)]        pub enum Error {            #[error(transparent)]            ConfigDiffRenames(#[from] crate::config::key::GenericError),            #[error(transparent)]            ConfigDiffRenameLimit(#[from] crate::config::unsigned_integer::Error),        }    }     ///    pub mod resource_cache {        /// The error returned by [`resource_cache()`](super::resource_cache()).        #[derive(Debug, thiserror::Error)]        #[expect(missing_docs)]        pub enum Error {            #[error(transparent)]            DiffAlgorithm(#[from] crate::config::diff::algorithm::Error),            #[error(transparent)]            WorktreeFilterOptions(#[from] crate::filter::pipeline::options::Error),            #[error(transparent)]            DiffDrivers(#[from] crate::config::diff::drivers::Error),            #[error(transparent)]            DiffPipelineOptions(#[from] crate::config::diff::pipeline_options::Error),            #[error(transparent)]            CommandContext(#[from] crate::config::command_context::Error),        }    }     /// Create an instance by reading all relevant information from the `config`uration, while being `lenient` or not.    /// Returns `Ok((None, false))` if nothing is configured, or `Ok((None, true))` if it's configured and disabled.    ///    /// Note that missing values will be defaulted similar to what git does.    pub fn new_rewrites(        config: &gix_config::File,        lenient: bool,    ) -> Result<(Option<Rewrites>, bool), new_rewrites::Error> {        new_rewrites_inner(config, lenient, &Diff::RENAMES, &Diff::RENAME_LIMIT)    }     pub(crate) fn new_rewrites_inner(        config: &gix_config::File,        lenient: bool,        renames: &'static crate::config::tree::diff::Renames,        rename_limit: &'static crate::config::tree::keys::UnsignedInteger,    ) -> Result<(Option<Rewrites>, bool), new_rewrites::Error> {        let copies = match renames            .try_into_renames(config.boolean(renames))            .with_leniency(lenient)?        {            Some(renames) => match renames {                Tracking::Disabled => return Ok((None, true)),                Tracking::Renames => None,                Tracking::RenamesAndCopies => Some(Copies::default()),            },            None => return Ok((None, false)),        };         let default = Rewrites::default();        Ok((            Rewrites {                copies,                limit: rename_limit                    .try_into_usize(config.integer(rename_limit))                    .with_leniency(lenient)?                    .unwrap_or(default.limit),                ..default            }            .into(),            true,        ))    }     /// Return a low-level utility to efficiently prepare a blob-level diff operation between two resources,    /// and cache these diffable versions so that matrix-like MxN diffs are efficient.    ///    /// `repo` is used to obtain the needed configuration values.    /// `mode` determines how the diffable files will look like, and also how fast, in average, these conversions are.    /// `attr_stack` is for accessing `.gitattributes` for knowing how to apply filters. Know that it's typically adjusted based on the    /// `roots` - if there are no worktree roots, `.gitattributes` are also not usually read from worktrees.    /// `roots` provide information about where to get diffable data from, so source and destination can either be sourced from    /// a worktree, or from the object database, or both.    pub fn resource_cache(        repo: &Repository,        mode: gix_diff::blob::pipeline::Mode,        attr_stack: gix_worktree::Stack,        roots: gix_diff::blob::pipeline::WorktreeRoots,    ) -> Result<gix_diff::blob::Platform, resource_cache::Error> {        let diff_algo = repo.config.diff_algorithm()?;        let diff_cache = gix_diff::blob::Platform::new(            gix_diff::blob::platform::Options {                algorithm: Some(diff_algo),                skip_internal_diff_if_external_is_configured: false,            },            gix_diff::blob::Pipeline::new(                roots,                gix_filter::Pipeline::new(repo.command_context()?, crate::filter::Pipeline::options(repo)?),                repo.config.diff_drivers()?,                repo.config.diff_pipeline_options()?,            ),            mode,            attr_stack,        );        Ok(diff_cache)    }}#[cfg(feature = "blob-diff")]pub use utils::{new_rewrites, resource_cache};