Skip to content

Commit

Permalink
commit_templater: add an AnyMap for extensions to cache their own info
Browse files Browse the repository at this point in the history
  • Loading branch information
torquestomp committed Mar 11, 2024
1 parent bd5a536 commit 347f455
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 4 deletions.
60 changes: 56 additions & 4 deletions cli/examples/custom-commit-templater/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,24 @@ use jj_cli::commit_templater::{CommitTemplateBuildFnTable, CommitTemplateLanguag
use jj_cli::template_builder::TemplateLanguage;
use jj_cli::template_parser::{self, TemplateParseError};
use jj_cli::templater::{TemplateFunction, TemplatePropertyError};
use jj_lib::any_map::AnyMap;
use jj_lib::backend::CommitId;
use jj_lib::commit::Commit;
use jj_lib::object_id::ObjectId;
use jj_lib::repo::Repo;
use jj_lib::revset::RevsetExpression;
use once_cell::sync::OnceCell;

struct HexCounter;

fn num_digits_in_id(commit: Commit) -> Result<i64, TemplatePropertyError> {
fn num_digits_in_id(id: &CommitId) -> i64 {
let mut count = 0;
for ch in commit.id().hex().chars() {
for ch in id.hex().chars() {
if ch.is_ascii_digit() {
count += 1;
}
}
Ok(count)
count
}

fn num_char_in_id(commit: Commit, ch_match: char) -> Result<i64, TemplatePropertyError> {
Expand All @@ -42,14 +47,57 @@ fn num_char_in_id(commit: Commit, ch_match: char) -> Result<i64, TemplatePropert
Ok(count)
}

struct MostDigitsInId {
count: OnceCell<i64>,
}

impl MostDigitsInId {
fn new() -> Self {
Self {
count: OnceCell::new(),
}
}

fn count(&self, repo: &dyn Repo) -> i64 {
*self.count.get_or_init(|| {
RevsetExpression::all()
.evaluate_programmatic(repo)
.unwrap()
.iter()
.map(|id| num_digits_in_id(&id))
.max()
.unwrap_or(0)
})
}
}

impl CommitTemplateLanguageExtension for HexCounter {
fn build_fn_table<'repo>(&self) -> CommitTemplateBuildFnTable<'repo> {
let mut table = CommitTemplateBuildFnTable::empty();
table.commit_methods.insert(
"has_most_digits",
|language, _build_context, property, call| {
template_parser::expect_no_arguments(call)?;
let most_digits = language
.cache_extension::<MostDigitsInId>()
.unwrap()
.count(language.repo());
Ok(
language.wrap_boolean(TemplateFunction::new(property, move |commit| {
Ok(num_digits_in_id(commit.id()) == most_digits)
})),
)
},
);
table.commit_methods.insert(
"num_digits_in_id",
|language, _build_context, property, call| {
template_parser::expect_no_arguments(call)?;
Ok(language.wrap_integer(TemplateFunction::new(property, num_digits_in_id)))
Ok(
language.wrap_integer(TemplateFunction::new(property, |commit| {
Ok(num_digits_in_id(commit.id()))
})),
)
},
);
table.commit_methods.insert(
Expand Down Expand Up @@ -78,6 +126,10 @@ impl CommitTemplateLanguageExtension for HexCounter {

table
}

fn build_cache_extensions(&self, extensions: &mut AnyMap) {
extensions.insert(MostDigitsInId::new());
}
}

fn main() -> std::process::ExitCode {
Expand Down
16 changes: 16 additions & 0 deletions cli/src/commit_templater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::any::Any;
use std::cmp::max;
use std::collections::HashMap;
use std::io;
use std::rc::Rc;

use itertools::Itertools as _;
use jj_lib::any_map::AnyMap;
use jj_lib::backend::{ChangeId, CommitId};
use jj_lib::commit::Commit;
use jj_lib::hex_util::to_reverse_hex;
Expand All @@ -42,6 +44,8 @@ use crate::text_util;

pub trait CommitTemplateLanguageExtension {
fn build_fn_table<'repo>(&self) -> CommitTemplateBuildFnTable<'repo>;

fn build_cache_extensions(&self, extensions: &mut AnyMap);
}

pub struct CommitTemplateLanguage<'repo> {
Expand All @@ -50,6 +54,7 @@ pub struct CommitTemplateLanguage<'repo> {
id_prefix_context: &'repo IdPrefixContext,
build_fn_table: CommitTemplateBuildFnTable<'repo>,
keyword_cache: CommitKeywordCache,
cache_extensions: AnyMap,
}

impl<'repo> CommitTemplateLanguage<'repo> {
Expand All @@ -62,15 +67,22 @@ impl<'repo> CommitTemplateLanguage<'repo> {
extension: Option<&dyn CommitTemplateLanguageExtension>,
) -> Self {
let mut build_fn_table = CommitTemplateBuildFnTable::builtin();
let mut cache_extensions = AnyMap::empty();

// TODO: Extension methods should be refactored to be plural, to support
// multiple extensions in a dynamic load environment
if let Some(extension) = extension {
build_fn_table.merge(extension.build_fn_table());
extension.build_cache_extensions(&mut cache_extensions);
}

CommitTemplateLanguage {
repo,
workspace_id: workspace_id.clone(),
id_prefix_context,
build_fn_table,
keyword_cache: CommitKeywordCache::default(),
cache_extensions,
}
}
}
Expand Down Expand Up @@ -156,6 +168,10 @@ impl<'repo> CommitTemplateLanguage<'repo> {
&self.keyword_cache
}

pub fn cache_extension<T: Any>(&self) -> Option<&T> {
self.cache_extensions.get::<T>()
}

pub fn wrap_commit(
&self,
property: impl TemplateProperty<Commit, Output = Commit> + 'repo,
Expand Down

0 comments on commit 347f455

Please sign in to comment.