fn spawn_commit_history_search_thread()

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(&current_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");
        }
    });
}