Skip to content

Commit

Permalink
perf(changelog): build cache once
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Mar 7, 2024
1 parent 3f1d2cf commit 1ca130f
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 38 deletions.
71 changes: 40 additions & 31 deletions src/git/rev/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,52 @@ use crate::git::error::TagError;
use crate::git::oid::OidOf;
use crate::git::repository::Repository;
use crate::git::tag::Tag;
use once_cell::sync::Lazy;
use once_cell::sync::{Lazy, OnceCell};
use std::collections::BTreeMap;
use std::sync::{Arc, Mutex, MutexGuard};

// TODO: we need to handle the case where multiple tags point to the same commit Oid
static REPO_CACHE: Lazy<Arc<Mutex<BTreeMap<String, OidOf>>>> =
Lazy::new(|| Arc::new(Mutex::new(BTreeMap::new())));

pub(crate) fn init(repository: &Repository) -> MutexGuard<'_, BTreeMap<String, OidOf>> {
let mut cache = REPO_CACHE.lock().unwrap();
let head = repository.get_head_commit().expect("HEAD");
let first = repository.get_first_commit().expect("first commit");

cache.insert(head.id().to_string(), OidOf::Head(head.id()));
cache.insert(first.to_string(), OidOf::FirstCommit(first));

let tag_iter = repository.0.tag_names(None).expect("tags");

let tag_iter = tag_iter
.into_iter()
.flatten()
.filter_map(|tag| repository.resolve_tag(tag).ok());
static FIRST_COMMIT: OnceCell<OidOf> = OnceCell::new();

for tag in tag_iter {
if let Some(target) = tag.target.as_ref() {
let target = target.to_string();
cache.insert(target.clone(), OidOf::Tag(tag.clone()));
cache.insert(target[0..7].to_string(), OidOf::Tag(tag.clone()));
}

if let Some(oid) = tag.oid.as_ref() {
let string = oid.to_string();
cache.insert(string.clone(), OidOf::Tag(tag.clone()));
cache.insert(string[0..7].to_string(), OidOf::Tag(tag.clone()));
// TODO: we need to handle the case where multiple tags point to the same commit Oid
pub(crate) fn get_cache(repository: &Repository) -> MutexGuard<'_, BTreeMap<String, OidOf>> {
let mut cache = REPO_CACHE.lock().unwrap();
if cache.is_empty() {
let head = repository.get_head_commit().expect("HEAD");
let first = FIRST_COMMIT.get_or_init(|| {
OidOf::FirstCommit(repository.get_first_commit().expect("first commit"))
});

cache.insert(head.id().to_string(), OidOf::Head(head.id()));
cache.insert(
first.to_string(),
FIRST_COMMIT.get().expect("first commit").clone(),
);

let tag_iter = repository.0.tag_names(None).expect("tags");

let tag_iter = tag_iter
.into_iter()
.flatten()
.filter_map(|tag| repository.resolve_tag(tag).ok());

for tag in tag_iter {
if let Some(target) = tag.target.as_ref() {
let target = target.to_string();
cache.insert(target.clone(), OidOf::Tag(tag.clone()));
cache.insert(target[0..7].to_string(), OidOf::Tag(tag.clone()));
}

if let Some(oid) = tag.oid.as_ref() {
let string = oid.to_string();
cache.insert(string.clone(), OidOf::Tag(tag.clone()));
cache.insert(string[0..7].to_string(), OidOf::Tag(tag.clone()));
}

cache.insert(tag.to_string(), OidOf::Tag(tag));
}

cache.insert(tag.to_string(), OidOf::Tag(tag));
}

cache
Expand All @@ -63,7 +72,7 @@ impl Repository {
#[cfg(test)]
mod test {
use crate::git::repository::Repository;
use crate::git::rev::cache::init;
use crate::git::rev::cache::get_cache;
use crate::test_helpers::git_init_no_gpg;
use cmd_lib::run_cmd;
use sealed_test::prelude::*;
Expand All @@ -72,7 +81,7 @@ mod test {
#[test]
fn init_cache_ok() -> anyhow::Result<()> {
let repo = Repository::open(".")?;
let cache = init(&repo);
let cache = get_cache(&repo);
assert_that!(cache.is_empty()).is_false();
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions src/git/rev/revspec.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::git::error::Git2Error;
use crate::git::oid::OidOf;
use crate::git::repository::Repository;
use crate::git::rev::cache::init;
use crate::git::rev::cache::get_cache;
use crate::git::tag::Tag;
use git2::Oid;
use std::fmt;
Expand Down Expand Up @@ -61,7 +61,7 @@ impl Repository {
}

pub(super) fn resolve_oid_of(&self, from: &str) -> Result<OidOf, Git2Error> {
let cache = init(self);
let cache = get_cache(self);

let oid = cache.get(from).cloned();

Expand Down
2 changes: 1 addition & 1 deletion src/git/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl Repository {

pub fn tag_lookup(&self, option: TagLookUpOptions) -> Result<Vec<Tag>, TagError> {
let prefix = SETTINGS.tag_prefix.as_ref();
let repo_cache = crate::git::rev::cache::init(self);
let repo_cache = crate::git::rev::cache::get_cache(self);
let include_pre_release = option.include_pre_release;

let tag_filter = |tag: &Tag| {
Expand Down
12 changes: 11 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use std::process::{Command, Stdio};

Expand All @@ -16,6 +16,7 @@ use git::repository::Repository;
use settings::Settings;

use crate::git::error::{Git2Error, TagError};
use crate::git::rev::cache::get_cache;

use crate::git::tag::Tag;

Expand Down Expand Up @@ -145,12 +146,21 @@ impl CocoGitto {
.map(|path| path.join(".git/COMMIT_EDITMSG"))
.expect("git repository")
}

// Currently only used in test to force rebuild the tag cache
pub fn clear_cache(&self) {
let mut cache = get_cache(&self.repository);
*cache = BTreeMap::new();
}
}

#[cfg(test)]
pub mod test_helpers {
use crate::git::repository::Repository;
use crate::git::rev::cache::get_cache;
use crate::CocoGitto;
use cmd_lib::{run_cmd, run_fun};
use std::collections::BTreeMap;

pub(crate) fn git_init_no_gpg() -> anyhow::Result<Repository> {
run_cmd!(
Expand Down
17 changes: 14 additions & 3 deletions tests/lib_tests/bump.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::path::PathBuf;

Expand All @@ -7,12 +7,11 @@ use cmd_lib::run_cmd;
use sealed_test::prelude::*;
use speculoos::prelude::*;

use crate::helpers::*;
use cocogitto::command::bump::{BumpOptions, PackageBumpOptions};
use cocogitto::settings::{MonoRepoPackage, Settings};
use cocogitto::{conventional::version::IncrementCommand, CocoGitto};

use crate::helpers::*;

#[sealed_test]
fn bump_ok() -> Result<()> {
// Arrange
Expand Down Expand Up @@ -241,6 +240,8 @@ fn consecutive_package_bump_ok() -> Result<()> {
..Default::default()
})?;

cocogitto.clear_cache();

cocogitto.create_package_version(PackageBumpOptions {
package_name: "jenkins",
package: &jenkins(),
Expand All @@ -254,6 +255,8 @@ fn consecutive_package_bump_ok() -> Result<()> {
git commit -m "fix(jenkins): bug fix on jenkins package";
)?;

cocogitto.clear_cache();

cocogitto.create_package_version(PackageBumpOptions {
package_name: "jenkins",
package: &jenkins(),
Expand Down Expand Up @@ -370,6 +373,8 @@ fn auto_bump_package_only_ok() -> Result<()> {
assert_tag_exists("thumbor-0.1.0")?;
assert_tag_does_not_exist("0.1.0")?;

cocogitto.clear_cache();

run_cmd!(
echo "fix jenkins bug" > jenkins/fix;
git add .;
Expand Down Expand Up @@ -575,8 +580,12 @@ fn bump_no_error_should_be_thrown_on_only_chore_docs_commit() -> Result<()> {
git commit -m "docs(jenkins): jenkins docs";
)?;

cocogitto.clear_cache();

cocogitto.create_monorepo_version(BumpOptions::default())?;

cocogitto.clear_cache();

cocogitto.create_package_version(PackageBumpOptions {
package_name: "jenkins",
package: &jenkins(),
Expand All @@ -590,6 +599,8 @@ fn bump_no_error_should_be_thrown_on_only_chore_docs_commit() -> Result<()> {
git commit -m "feat(thumbor): more feat on thumbor";
)?;

cocogitto.clear_cache();

cocogitto.create_monorepo_version(BumpOptions::default())?;

// Assert
Expand Down

0 comments on commit 1ca130f

Please sign in to comment.