blob: 0ab7d7e79290a607b73c25b0f5e8f108c4952371 [file] [log] [blame]
use std::path::Path;
use bstr::{ByteSlice, ByteVec};
use gix_filter::{eol, eol::AttributesDigest};
#[test]
fn with_binary_attribute_is_never_converted() {
let mut buf = Vec::new();
let changed = eol::convert_to_git(
b"hi\r\nho",
AttributesDigest::Binary,
&mut buf,
&mut no_call,
Default::default(),
)
.expect("no error");
assert!(!changed, "the user marked it as binary so it's never being touched");
}
#[test]
fn no_crlf_means_no_work() -> crate::Result {
let mut buf = Vec::new();
let changed = eol::convert_to_git(
b"hi",
AttributesDigest::TextCrlf,
&mut buf,
&mut no_call,
Default::default(),
)
.expect("no error");
assert!(!changed);
let changed = eol::convert_to_git(
b"hi",
AttributesDigest::TextAutoCrlf,
&mut buf,
&mut no_object_in_index,
Default::default(),
)
.expect("no error");
assert!(!changed, "in auto-mode, the object is queried in the index as well.");
Ok(())
}
#[test]
fn detected_as_binary() -> crate::Result {
let mut buf = Vec::new();
let changed = eol::convert_to_git(
b"hi\0zero makes it binary",
AttributesDigest::TextAuto,
&mut buf,
&mut no_call,
Default::default(),
)
.expect("no error");
assert!(
!changed,
"in auto-mode, we have a heuristic to see if the buffer is binary"
);
Ok(())
}
#[test]
fn fast_conversion_by_stripping_cr() -> crate::Result {
let mut buf = Vec::new();
let changed = eol::convert_to_git(
b"a\r\nb\r\nc",
AttributesDigest::TextCrlf,
&mut buf,
&mut no_call,
Default::default(),
)
.expect("no error");
assert!(changed);
assert_eq!(buf.as_bstr(), "a\nb\nc", "here carriage returns can just be stripped");
Ok(())
}
#[test]
fn slower_conversion_due_to_lone_cr() -> crate::Result {
let mut buf = Vec::new();
let changed = eol::convert_to_git(
b"\r\ra\r\nb\r\nc",
AttributesDigest::TextCrlf,
&mut buf,
&mut no_call,
Default::default(),
)
.expect("no error");
assert!(changed);
assert_eq!(
buf.as_bstr(),
"\r\ra\nb\nc",
"here carriage returns cannot be stripped but must be handled in pairs"
);
Ok(())
}
#[test]
fn crlf_in_index_prevents_conversion_to_lf() -> crate::Result {
let mut buf = Vec::new();
let mut called = false;
let changed = eol::convert_to_git(
b"elligible\n",
AttributesDigest::TextAutoInput,
&mut buf,
&mut |buf| {
called = true;
buf.clear();
buf.push_str("with CRLF\r\n");
Ok(Some(()))
},
Default::default(),
)
.expect("no error");
assert!(called, "in auto mode, the index is queried as well");
assert!(
!changed,
"we saw the CRLF is present in the index, so it's unsafe to make changes"
);
Ok(())
}
#[test]
fn round_trip_check() -> crate::Result {
let mut buf = Vec::new();
for (input, expected) in [
(&b"lone-nl\nhi\r\nho"[..], "LF would be replaced by CRLF in 'hello.txt'"),
// despite trying, I was unable to get into the other branch
(b"lone-cr\nhi\r\nho", "LF would be replaced by CRLF in 'hello.txt'"),
] {
let err = eol::convert_to_git(
input,
AttributesDigest::TextCrlf,
&mut buf,
&mut no_call,
eol::convert_to_git::Options {
round_trip_check: Some(gix_filter::eol::convert_to_git::RoundTripCheck::Fail {
rela_path: Path::new("hello.txt"),
}),
config: Default::default(),
},
)
.unwrap_err();
assert_eq!(err.to_string(), expected);
let changed = eol::convert_to_git(
input,
AttributesDigest::TextCrlf,
&mut buf,
&mut no_call,
eol::convert_to_git::Options {
round_trip_check: Some(gix_filter::eol::convert_to_git::RoundTripCheck::Warn {
rela_path: Path::new("hello.txt"),
}),
config: Default::default(),
},
)?;
assert!(
changed,
"in warn mode, we will get a result even though it won't round-trip"
)
}
Ok(())
}
#[allow(clippy::ptr_arg)]
fn no_call(_buf: &mut Vec<u8>) -> Result<Option<()>, Box<dyn std::error::Error + Send + Sync>> {
unreachable!("index function will not be called")
}
#[allow(clippy::ptr_arg)]
fn no_object_in_index(_buf: &mut Vec<u8>) -> Result<Option<()>, Box<dyn std::error::Error + Send + Sync>> {
Ok(None)
}