in focus/operations/src/selection.rs [528:585]
fn spawn_commit_history_search_thread(tx: SkimItemSender, sparse_repo_path: PathBuf) {
fn inner(tx: SkimItemSender, sparse_repo_path: PathBuf) -> Result<()> {
let repo = git2::Repository::open(sparse_repo_path)?;
let head_commit = get_head_commit(&repo)?;
let head_tree = head_commit.tree().context("Getting HEAD tree")?;
let user_email = repo
.config()
.context("Getting config")?
.get_string("user.email")
.context("Reading user.email")?;
let mut seen_items = HashSet::new();
let mut commit = Some(head_commit);
while let Some(current_commit) = commit {
let parent_commit = match current_commit.parent(0) {
Ok(commit) => Some(commit),
Err(err) if err.code() == git2::ErrorCode::NotFound => None,
Err(err) => bail!("Failed to get parent commit: {err}"),
};
let parent_tree = match &parent_commit {
Some(parent_commit) => Some(parent_commit.tree()?),
None => None,
};
if current_commit.author().email_bytes() == user_email.as_bytes() {
let changed_paths = get_changed_paths_between_trees(
&repo,
parent_tree.as_ref(),
Some(¤t_commit.tree()?),
)?;
let mut items = changed_paths
.into_iter()
.filter_map(|path| {
let path = path.parent()?;
suggest_skim_item_from_path(SkimSource::CommitHistory, &head_tree, path)
})
.collect::<Vec<_>>();
items.sort();
for item in items {
if seen_items.insert(item.clone()) {
tx.send(Arc::new(item))?;
}
}
}
commit = parent_commit;
}
Ok(())
}
thread::spawn(move || {
if let Err(err) = inner(tx, sparse_repo_path) {
info!(?err, "Error while querying Phabricator");
}
});
}