2021-07-27 18:07:08 +00:00
|
|
|
//! fragment attached with git versioning information
|
2021-07-28 13:20:09 +00:00
|
|
|
use crate::raw::RawFragment;
|
|
|
|
use hashbrown::HashMap;
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)]
|
|
|
|
pub(crate) enum LocalizationState {
|
|
|
|
UpToDate,
|
|
|
|
NotFound,
|
|
|
|
Outdated,
|
|
|
|
Unused,
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
pub(crate) const ALL_LOCALIZATION_STATES: [Option<LocalizationState>; 5] = [
|
|
|
|
Some(LocalizationState::UpToDate),
|
|
|
|
Some(LocalizationState::NotFound),
|
|
|
|
Some(LocalizationState::Outdated),
|
|
|
|
Some(LocalizationState::Unused),
|
|
|
|
None,
|
|
|
|
];
|
|
|
|
|
2021-07-29 19:26:37 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2021-07-28 13:20:09 +00:00
|
|
|
pub(crate) struct LocalizationEntryState {
|
|
|
|
pub(crate) key_line: Option<usize>,
|
|
|
|
pub(crate) chuck_line_range: Option<(usize, usize)>,
|
|
|
|
pub(crate) commit_id: Option<git2::Oid>,
|
|
|
|
pub(crate) state: Option<LocalizationState>,
|
|
|
|
}
|
2021-07-27 18:07:08 +00:00
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
impl LocalizationState {
|
|
|
|
pub(crate) fn print(this: &Option<Self>) -> String {
|
|
|
|
match this {
|
|
|
|
Some(LocalizationState::UpToDate) => "UpToDate",
|
|
|
|
Some(LocalizationState::NotFound) => "NotFound",
|
|
|
|
Some(LocalizationState::Outdated) => "Outdated",
|
|
|
|
Some(LocalizationState::Unused) => "Unused",
|
|
|
|
None => "Unknown",
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
2021-07-28 13:20:09 +00:00
|
|
|
.to_owned()
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
impl LocalizationEntryState {
|
|
|
|
fn new(key_line: Option<usize>) -> LocalizationEntryState {
|
|
|
|
LocalizationEntryState {
|
|
|
|
key_line,
|
|
|
|
chuck_line_range: None,
|
|
|
|
commit_id: None,
|
|
|
|
state: None,
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-28 13:20:09 +00:00
|
|
|
}
|
2021-07-27 18:07:08 +00:00
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
/// Returns the Git blob associated with the given reference and path
|
|
|
|
pub(crate) fn read_file_from_path<'a>(
|
2021-07-27 18:07:08 +00:00
|
|
|
repo: &'a git2::Repository,
|
2021-07-28 13:20:09 +00:00
|
|
|
reference: &git2::Reference,
|
2021-07-27 18:07:08 +00:00
|
|
|
path: &std::path::Path,
|
2021-07-28 13:20:09 +00:00
|
|
|
) -> git2::Blob<'a> {
|
|
|
|
let tree = reference
|
|
|
|
.peel_to_tree()
|
|
|
|
.expect("Impossible to peel HEAD to a tree object");
|
|
|
|
tree.get_path(path)
|
|
|
|
.unwrap_or_else(|_| {
|
|
|
|
panic!(
|
|
|
|
"Impossible to find the file {:?} in reference {:?}",
|
|
|
|
path,
|
|
|
|
reference.name()
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.to_object(repo)
|
|
|
|
.unwrap()
|
|
|
|
.peel_to_blob()
|
|
|
|
.expect("Impossible to fetch the Git object")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Extend a Fragment with historical git data
|
|
|
|
/// The actual translation gets dropped
|
|
|
|
/// TODO: transform vector_map too
|
|
|
|
pub(crate) fn transform_fragment<'a>(
|
|
|
|
repo: &'a git2::Repository,
|
|
|
|
fragment: (&Path, RawFragment<String>),
|
2021-07-27 18:07:08 +00:00
|
|
|
file_blob: &git2::Blob,
|
2021-07-28 13:20:09 +00:00
|
|
|
) -> RawFragment<LocalizationEntryState> {
|
|
|
|
let (path, fragment) = fragment;
|
|
|
|
// Find key start lines by searching all lines which have `:` in them (as they
|
|
|
|
// are probably keys) and getting the first part of such line trimming
|
|
|
|
// whitespace and quotes. Quite buggy heuristic
|
2021-07-27 18:07:08 +00:00
|
|
|
let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file");
|
2021-07-28 13:20:09 +00:00
|
|
|
// we only need the key part of the file to process
|
|
|
|
let file_content_keys = file_content.lines().enumerate().filter_map(|(no, line)| {
|
|
|
|
line.split_once(':').map(|(key, _)| {
|
|
|
|
let mut key = key.trim().chars();
|
|
|
|
key.next();
|
|
|
|
key.next_back();
|
|
|
|
(no, key.as_str())
|
|
|
|
})
|
|
|
|
});
|
|
|
|
//speed up the search by sorting all keys!
|
|
|
|
let mut file_content_keys_sorted = file_content_keys.into_iter().collect::<Vec<_>>();
|
|
|
|
file_content_keys_sorted.sort_by_key(|(_, key)| *key);
|
|
|
|
|
|
|
|
let mut result = RawFragment::<LocalizationEntryState> {
|
|
|
|
string_map: HashMap::new(),
|
|
|
|
vector_map: HashMap::new(),
|
|
|
|
};
|
|
|
|
|
|
|
|
for (original_key, _) in fragment.string_map {
|
|
|
|
let line_nb = file_content_keys_sorted
|
|
|
|
.binary_search_by_key(&original_key.as_str(), |(_, key)| *key)
|
|
|
|
.map_or_else(
|
|
|
|
|_| {
|
|
|
|
eprintln!(
|
|
|
|
"Key {} does not have a git line in it's state!",
|
|
|
|
original_key
|
|
|
|
);
|
|
|
|
None
|
|
|
|
},
|
|
|
|
|id| Some(file_content_keys_sorted[id].0),
|
|
|
|
);
|
|
|
|
|
|
|
|
result
|
|
|
|
.string_map
|
|
|
|
.insert(original_key, LocalizationEntryState::new(line_nb));
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
// Find commit for each keys, THIS PART IS SLOW (2s/4s)
|
|
|
|
for e in repo
|
|
|
|
.blame_file(path, None)
|
2021-07-27 18:07:08 +00:00
|
|
|
.expect("Impossible to generate the Git blame")
|
|
|
|
.iter()
|
2021-07-28 13:20:09 +00:00
|
|
|
{
|
|
|
|
for (_, state) in result.string_map.iter_mut() {
|
|
|
|
if let Some(line) = state.key_line {
|
|
|
|
let range = (
|
|
|
|
e.final_start_line(),
|
|
|
|
e.final_start_line() + e.lines_in_hunk(),
|
|
|
|
);
|
|
|
|
if line + 1 >= range.0 && line + 1 < range.1 {
|
|
|
|
state.chuck_line_range = Some(range);
|
|
|
|
state.commit_id = state.commit_id.map_or_else(
|
|
|
|
|| Some(e.final_commit_id()),
|
|
|
|
|existing_commit| match repo
|
|
|
|
.graph_descendant_of(e.final_commit_id(), existing_commit)
|
|
|
|
{
|
|
|
|
Ok(true) => Some(e.final_commit_id()),
|
|
|
|
Ok(false) => Some(existing_commit),
|
|
|
|
Err(err) => panic!("{}", err),
|
2021-07-27 18:07:08 +00:00
|
|
|
},
|
2021-07-28 13:20:09 +00:00
|
|
|
);
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-28 13:20:09 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-27 18:07:08 +00:00
|
|
|
|
2021-07-28 13:20:09 +00:00
|
|
|
result
|
2021-07-27 18:07:08 +00:00
|
|
|
}
|