display lossy commit msg when containing invalid utf8 (closes #150)

This commit is contained in:
Stephan Dilly 2020-06-24 10:11:27 +02:00
parent 6b52b60280
commit fab5b6ea47
7 changed files with 70 additions and 8 deletions

View file

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- clearer help headers ([#131](https://github.com/extrawurst/gitui/issues/131))
- diisplay non-utf8 commit messages at least partially ([#150](https://github.com/extrawurst/gitui/issues/150))
## [0.7.0] - 2020-06-15

5
Cargo.lock generated
View file

@ -45,6 +45,7 @@ version = "0.7.0"
dependencies = [
"crossbeam-channel",
"git2",
"invalidstring",
"log",
"rayon-core",
"scopetime",
@ -367,6 +368,10 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "invalidstring"
version = "0.1.0"
[[package]]
name = "iovec"
version = "0.1.4"

View file

@ -12,12 +12,13 @@ categories = ["concurrency","asynchronous"]
keywords = ["git"]
[dependencies]
scopetime = { path = "../scopetime", version = "0.1" }
git2 = { version = "0.13.6", default-features = false }
rayon-core = "1.7"
crossbeam-channel = "0.4"
log = "0.4"
scopetime = { path = "../scopetime", version = "0.1" }
thiserror = "1.0"
[dev-dependencies]
tempfile = "3.1"
tempfile = "3.1"
invalidstring = { path = "../invalidstring", version = "0.1" }

View file

@ -2,6 +2,7 @@ use super::utils::repo;
use crate::error::Result;
use git2::{Commit, Error, Oid};
use scopetime::scope_time;
use std::borrow::Cow;
/// identifies a single commit
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -81,14 +82,13 @@ pub fn get_commits_info(
}
fn get_message(c: &Commit, message_length_limit: usize) -> String {
if let Some(msg) = c.message() {
limit_str(msg, message_length_limit)
} else {
String::from("<unknown>")
}
limit_str(
String::from_utf8_lossy(c.message_bytes()),
message_length_limit,
)
}
fn limit_str(s: &str, limit: usize) -> String {
fn limit_str(s: Cow<'_, str>, limit: usize) -> String {
if let Some(first) = s.lines().next() {
first.chars().take(limit).collect::<String>()
} else {
@ -103,6 +103,7 @@ mod tests {
use crate::error::Result;
use crate::sync::{
commit, stage_add_file, tests::repo_init_empty,
utils::get_head_repo,
};
use std::{fs::File, io::Write, path::Path};
@ -130,4 +131,31 @@ mod tests {
Ok(())
}
#[test]
fn test_invalid_utf8() -> Result<()> {
let file_path = Path::new("foo");
let (_td, repo) = repo_init_empty().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();
File::create(&root.join(file_path))?.write_all(b"a")?;
stage_add_file(repo_path, file_path).unwrap();
let msg = invalidstring::invalid_utf8("test msg");
commit(repo_path, msg.as_str()).unwrap();
let res = get_commits_info(
repo_path,
&vec![get_head_repo(&repo).unwrap().into()],
50,
)
.unwrap();
assert_eq!(res.len(), 1);
dbg!(&res[0].message);
assert_eq!(res[0].message.starts_with("test msg"), true);
Ok(())
}
}

14
invalidstring/Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "invalidstring"
version = "0.1.0"
authors = ["Stephan Dilly <dilly.stephan@gmail.com>"]
edition = "2018"
description = "just for testing invalid string data"
homepage = "https://github.com/extrawurst/gitui"
repository = "https://github.com/extrawurst/gitui"
readme = "README.md"
license = "MIT"
categories = ["testing","utf8"]
keywords = ["string"]
[dependencies]

5
invalidstring/README.md Normal file
View file

@ -0,0 +1,5 @@
# invalidstring
*just for testing invalid string data*
This crate is part of the [gitui](http://gitui.org) project. We need this to be a seperate crate so that `asyncgit` can remain forbidding `unsafe`.

8
invalidstring/src/lib.rs Normal file
View file

@ -0,0 +1,8 @@
/// uses unsafe to postfix the string with invalid utf8 data
pub fn invalid_utf8(prefix: &str) -> String {
let bytes = b"\xc3\x73";
unsafe {
format!("{}{}", prefix, std::str::from_utf8_unchecked(bytes))
}
}