Update commit index in a transaction
Diff
src/database/indexer.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
src/database/schema/commit.rs | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 60 deletions(-)
@@ -1,9 +1,12 @@
use git2::Sort;
use std::path::{Path, PathBuf};
use time::OffsetDateTime;
use tracing::info;
use crate::database::schema::commit::{Author, Commit};
use crate::database::schema::repository::{Repository, RepositoryId};
use crate::database::schema::{
commit::Commit,
repository::{Repository, RepositoryId},
};
pub fn run_indexer(db: &sled::Db) {
let scan_path = Path::new("/Users/jordan/Code/test-git");
@@ -43,7 +46,7 @@
fn update_repository_reflog(scan_path: &Path, db: &sled::Db) {
for (relative_path, db_repository) in Repository::fetch_all(&db) {
let git_repository = git2::Repository::open(scan_path.join(relative_path)).unwrap();
let git_repository = git2::Repository::open(scan_path.join(&relative_path)).unwrap();
for reference in git_repository.references().unwrap() {
let reference = if let Some(reference) = reference.as_ref().ok().and_then(|v| v.name())
@@ -53,61 +56,44 @@
continue;
};
let commit_tree = db_repository.commit_tree(db, reference);
if !reference.starts_with("refs/heads/") {
continue;
}
let mut revwalk = git_repository.revwalk().unwrap();
revwalk.set_sorting(Sort::REVERSE).unwrap();
revwalk.push_ref(reference).unwrap();
let mut i = 0;
for rev in revwalk {
let rev = rev.unwrap();
let commit = if let Ok(commit) = git_repository.find_commit(rev) {
commit
} else {
continue;
};
let author = commit.author();
let committer = commit.committer();
let author = Author {
name: author.name().map(ToString::to_string).unwrap_or_default(),
email: author.email().map(ToString::to_string).unwrap_or_default(),
time: OffsetDateTime::from_unix_timestamp(author.when().seconds()).unwrap(),
};
let committer = Author {
name: committer
.name()
.map(ToString::to_string)
.unwrap_or_default(),
email: committer
.email()
.map(ToString::to_string)
.unwrap_or_default(),
time: OffsetDateTime::from_unix_timestamp(committer.when().seconds()).unwrap(),
};
let db_commit = Commit {
summary: commit
.summary()
.map(ToString::to_string)
.unwrap_or_default(),
message: commit.body().map(ToString::to_string).unwrap_or_default(),
committer,
author,
hash: commit.id().as_bytes().to_vec(),
};
info!("Updating indexes for {} on {}", reference, relative_path);
i += 1;
let commit_tree = db_repository.commit_tree(db, reference);
db_commit.insert(&commit_tree, i);
}
commit_tree
.transaction::<_, _, std::io::Error>(|tx| {
let mut revwalk = git_repository.revwalk().unwrap();
revwalk.set_sorting(Sort::REVERSE).unwrap();
revwalk.push_ref(reference).unwrap();
let mut i = 0;
for rev in revwalk {
let rev = rev.unwrap();
let commit = if let Ok(commit) = git_repository.find_commit(rev) {
commit
} else {
continue;
};
i += 1;
Commit::from(commit).insert(tx, i);
}
for to_remove in (i + 1)..(i + 100) {
tx.remove(&to_remove.to_be_bytes())?;
}
Ok(())
})
.unwrap();
}
}
}
@@ -1,4 +1,6 @@
use git2::Signature;
use serde::{Deserialize, Serialize};
use sled::transaction::TransactionalTree;
use std::ops::Deref;
use time::OffsetDateTime;
@@ -11,6 +13,29 @@
pub hash: Vec<u8>,
}
impl From<git2::Commit<'_>> for Commit {
fn from(commit: git2::Commit<'_>) -> Self {
Commit {
summary: commit
.summary()
.map(ToString::to_string)
.unwrap_or_default(),
message: commit.body().map(ToString::to_string).unwrap_or_default(),
committer: commit.committer().into(),
author: commit.author().into(),
hash: commit.id().as_bytes().to_vec(),
}
}
}
impl Commit {
pub fn insert(&self, database: &TransactionalTree, id: usize) {
database
.insert(&id.to_be_bytes(), bincode::serialize(self).unwrap())
.unwrap();
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Author {
pub name: String,
@@ -18,11 +43,14 @@
pub time: OffsetDateTime,
}
impl Commit {
pub fn insert(&self, database: &CommitTree, id: usize) {
database
.insert(id.to_be_bytes(), bincode::serialize(self).unwrap())
.unwrap();
impl From<git2::Signature<'_>> for Author {
fn from(author: Signature<'_>) -> Self {
Self {
name: author.name().map(ToString::to_string).unwrap_or_default(),
email: author.email().map(ToString::to_string).unwrap_or_default(),
time: OffsetDateTime::from_unix_timestamp(author.when().seconds()).unwrap(),
}
}
}