pub mod ast;
pub mod attempts;
pub mod bug_reporter;
pub(crate) mod changeset;
pub(crate) mod class_mapping;
pub mod git;
pub mod lang_profile;
pub mod line_based;
pub(crate) mod matching;
pub mod merge;
pub(crate) mod merge_3dm;
pub(crate) mod merge_result;
pub(crate) mod merged_text;
pub(crate) mod merged_tree;
#[cfg(feature = "dev")]
pub mod minimize;
pub(crate) mod multimap;
pub mod newline;
pub(crate) mod parsed_merge;
pub(crate) mod pcs;
pub mod settings;
pub(crate) mod signature;
pub mod solve;
pub(crate) mod structured;
pub mod supported_langs;
#[cfg(test)]
pub(crate) mod test_utils;
pub(crate) mod tree_builder;
pub(crate) mod tree_matcher;
pub mod utils;
pub(crate) mod visualizer;
use core::fmt::Write;
use std::{path::Path, time::Instant};
use itertools::Itertools;
use lang_profile::LangProfile;
use log::debug;
use merge_result::MergeResult;
use parsed_merge::{PARSED_MERGE_DIFF2_DETECTED, ParsedMerge};
use pcs::Revision;
use settings::DisplaySettings;
use structured::structured_merge;
use supported_langs::SUPPORTED_LANGUAGES;
pub const ENABLING_ENV_VAR: &str = "mergiraf";
pub const EXIT_SUCCESS: i32 = 0;
pub const EXIT_MERGE_HAS_CONFLICTS: i32 = 1;
pub const EXIT_SOLVE_FAILED: i32 = 1;
pub const EXIT_SOLVE_HAS_CONFLICTS: i32 = 2;
pub use merge::line_merge_and_structured_resolution;
#[cfg(feature = "dev")]
pub use minimize::minimize;
fn resolve_merge<'a>(
parsed_merge: &ParsedMerge<'a>,
settings: &DisplaySettings<'a>,
lang_profile: &LangProfile,
debug_dir: Option<&Path>,
) -> Result<MergeResult, String> {
let start = Instant::now();
let base_rev = parsed_merge.reconstruct_revision(Revision::Base);
let left_rev = parsed_merge.reconstruct_revision(Revision::Left);
let right_rev = parsed_merge.reconstruct_revision(Revision::Right);
debug!(
"re-constructing revisions from parsed merge took {:?}",
start.elapsed()
);
structured_merge(
&base_rev,
&left_rev,
&right_rev,
Some(parsed_merge),
settings,
lang_profile,
debug_dir,
)
}
fn fxhasher() -> rustc_hash::FxHasher {
use std::hash::BuildHasher;
rustc_hash::FxBuildHasher.build_hasher()
}
pub fn languages(gitattributes: bool) -> String {
let mut res = String::new();
for lang_profile in &*SUPPORTED_LANGUAGES {
let extensions = lang_profile.extensions;
let file_names = lang_profile.file_names;
if gitattributes {
for extension in extensions {
let _ = writeln!(res, "*.{extension} merge=mergiraf");
}
for file_name in file_names {
let _ = writeln!(res, "{file_name} merge=mergiraf");
}
} else {
let _ = writeln!(
res,
"{lang_profile} ({}{}{})",
extensions
.iter()
.format_with(", ", |ext, f| f(&format_args!("*.{ext}"))),
if extensions.is_empty() || file_names.is_empty() {
""
} else {
", "
},
file_names.iter().format(", "),
);
}
}
res
}
#[cfg(test)]
mod test {
use crate::structured::ZDIFF3_DETECTED;
use super::*;
#[test]
fn zdiff() {
let contents = "\
<<<<<<< LEFT
if foo {
left()
||||||| BASE
=======
if bar {
right()
>>>>>>> RIGHT
}
";
let settings = DisplaySettings::default();
let parsed = ParsedMerge::parse(contents, &settings).unwrap();
let result = resolve_merge(&parsed, &settings, LangProfile::rust(), None);
assert_eq!(result, Err(ZDIFF3_DETECTED.to_string()));
}
#[test]
fn languages_plain() {
let plain_text = languages(false);
assert!(plain_text.contains("Rust (*.rs)"));
assert!(plain_text.contains("go.mod (go.mod)"));
}
#[test]
fn languages_gitattributes() {
let gitattributes_config = languages(true);
assert!(gitattributes_config.contains("*.rs merge=mergiraf"));
assert!(gitattributes_config.contains("go.mod merge=mergiraf"));
}
}