mirror of
https://github.com/dandavison/delta.git
synced 2024-10-04 03:47:53 +03:00
Merge beb5c87ea2
into 0dd38d43f7
This commit is contained in:
commit
2e00a4b722
@ -79,9 +79,12 @@ pub struct Opt {
|
||||
#[arg(
|
||||
long = "blame-timestamp-format",
|
||||
default_value = "%Y-%m-%d %H:%M:%S %z",
|
||||
value_name = "FMT"
|
||||
value_name = "FMT_IN"
|
||||
)]
|
||||
/// Format of `git blame` timestamp in raw git output received by delta.
|
||||
/// Expected formatting of the timestamp in raw `git blame` output read by delta.
|
||||
///
|
||||
/// Must follow the format given to the git `--date=format:...` option, i.e. the
|
||||
/// `strftime` conventions. Spelled out days or months are not supported.
|
||||
pub blame_timestamp_format: String,
|
||||
|
||||
#[arg(long = "blame-timestamp-output-format", value_name = "FMT")]
|
||||
|
@ -187,11 +187,30 @@ impl<'a> StateMachine<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
// The parsed time stamp, or if that fails the raw input string.
|
||||
pub(crate) enum BlameTime<'a> {
|
||||
Time(DateTime<FixedOffset>),
|
||||
RawString(&'a str),
|
||||
}
|
||||
|
||||
impl<'a> BlameTime<'a> {
|
||||
fn format(&self, format_str: &Option<String>) -> String {
|
||||
match self {
|
||||
Self::Time(datetime) => match format_str {
|
||||
Some(time_format) => datetime.format(time_format).to_string(),
|
||||
None => chrono_humanize::HumanTime::from(*datetime).to_string(),
|
||||
},
|
||||
Self::RawString(s) => s.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlameLine<'a> {
|
||||
pub commit: &'a str,
|
||||
pub author: &'a str,
|
||||
pub time: DateTime<FixedOffset>,
|
||||
pub time: BlameTime<'a>,
|
||||
pub line_number: usize,
|
||||
pub code: &'a str,
|
||||
}
|
||||
@ -210,11 +229,11 @@ lazy_static! {
|
||||
[\ ]
|
||||
\( # open ( which the previous file name may not contain in case a name does (which is more likely)
|
||||
(
|
||||
[^\ ].*[^\ ] # author name
|
||||
[^\ ].*?[^\ ] # author name (non-greedy via '?' so the following timestamp is matched)
|
||||
)
|
||||
[\ ]+
|
||||
( # timestamp
|
||||
[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\ [-+][0-9]{4}
|
||||
( # timestamp, a general regex to capture input which will be parsed by strftime
|
||||
(?:[0-9]+[\ :\+-T]+)*[0-9]+ # numbers and possible separatores, then a final number
|
||||
)
|
||||
[\ ]+
|
||||
(
|
||||
@ -237,7 +256,10 @@ pub fn parse_git_blame_line<'a>(line: &'a str, timestamp_format: &str) -> Option
|
||||
let author = caps.get(2).unwrap().as_str();
|
||||
let timestamp = caps.get(3).unwrap().as_str();
|
||||
|
||||
let time = DateTime::parse_from_str(timestamp, timestamp_format).ok()?;
|
||||
let time = match DateTime::parse_from_str(timestamp, timestamp_format) {
|
||||
Ok(datetime) => BlameTime::Time(datetime),
|
||||
Err(_) => BlameTime::RawString(timestamp),
|
||||
};
|
||||
|
||||
let line_number = caps.get(4).unwrap().as_str().parse::<usize>().ok()?;
|
||||
|
||||
@ -272,12 +294,9 @@ pub fn format_blame_metadata(
|
||||
let width = placeholder.width.unwrap_or(15);
|
||||
|
||||
let field = match placeholder.placeholder {
|
||||
Some(Placeholder::Str("timestamp")) => {
|
||||
Some(Cow::from(match &config.blame_timestamp_output_format {
|
||||
Some(time_format) => blame.time.format(time_format).to_string(),
|
||||
None => chrono_humanize::HumanTime::from(blame.time).to_string(),
|
||||
}))
|
||||
}
|
||||
Some(Placeholder::Str("timestamp")) => Some(Cow::from(
|
||||
blame.time.format(&config.blame_timestamp_output_format),
|
||||
)),
|
||||
Some(Placeholder::Str("author")) => Some(Cow::from(blame.author)),
|
||||
Some(Placeholder::Str("commit")) => Some(delta::format_raw_line(blame.commit, config)),
|
||||
None => None,
|
||||
@ -405,6 +424,9 @@ mod tests {
|
||||
assert!(caps.is_some());
|
||||
assert!(parse_git_blame_line(line, "%Y-%m-%d %H:%M:%S %z").is_some());
|
||||
}
|
||||
|
||||
let strange_date = "1234 (Author Name-Here 19-01-0500 18-08+2022T41 1) --date=format:'%d-%m%z %M-%H+%YT%S'";
|
||||
assert!(parse_git_blame_line(strange_date, "%d-%m%z %M-%H+%YT%S").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -456,6 +478,23 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blame_timestamp_regex() {
|
||||
// Not supported: rfc2822, the weekday start (plus possible localisation) can't be separated from the author
|
||||
for timestamp_fmt in &[
|
||||
"1234 (Author Name-Here 2021-08-22 18:20:19 -0700 1) default blame (iso)",
|
||||
"1234 (Author Name-Here 2022-01-19T23:49:50+01:00 1) iso strict",
|
||||
"1234 (Author Name-Here 2022-01-19 1) short",
|
||||
"1234 (Author Name-Here 123456789 1) unix",
|
||||
"1234 (Author Name-Here 123456789 +0100 1) raw",
|
||||
"1234 (Author Name-Here 19-01-0500 18-08+2022T41 1) --date=format:'%d-%m%z %M-%H+%YT%S'"
|
||||
] {
|
||||
let caps = BLAME_LINE_REGEX.captures(timestamp_fmt);
|
||||
assert!(caps.is_some());
|
||||
assert!(caps.unwrap().get(3).is_some())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_color_assignment() {
|
||||
let mut writer = Cursor::new(vec![0; 512]);
|
||||
@ -551,7 +590,7 @@ mod tests {
|
||||
BlameLine {
|
||||
commit: "",
|
||||
author: "",
|
||||
time,
|
||||
time: BlameTime::Time(time),
|
||||
line_number: 0,
|
||||
code: "",
|
||||
}
|
||||
@ -568,7 +607,7 @@ mod tests {
|
||||
BlameLine {
|
||||
commit: "",
|
||||
author,
|
||||
time: chrono::DateTime::default(),
|
||||
time: BlameTime::Time(chrono::DateTime::default()),
|
||||
line_number: 0,
|
||||
code: "",
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user