forked from mirrors/jj
commit_templater: add an AnyMap for extensions to cache their own info
This commit is contained in:
parent
6e8f1fb390
commit
84118e1edd
2 changed files with 72 additions and 4 deletions
|
@ -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::backend::CommitId;
|
||||
use jj_lib::commit::Commit;
|
||||
use jj_lib::extensions_map::ExtensionsMap;
|
||||
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> {
|
||||
|
@ -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(
|
||||
|
@ -78,6 +126,10 @@ impl CommitTemplateLanguageExtension for HexCounter {
|
|||
|
||||
table
|
||||
}
|
||||
|
||||
fn build_cache_extensions(&self, extensions: &mut ExtensionsMap) {
|
||||
extensions.insert(MostDigitsInId::new());
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> std::process::ExitCode {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// 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;
|
||||
|
@ -20,6 +21,7 @@ use std::rc::Rc;
|
|||
use itertools::Itertools as _;
|
||||
use jj_lib::backend::{ChangeId, CommitId};
|
||||
use jj_lib::commit::Commit;
|
||||
use jj_lib::extensions_map::ExtensionsMap;
|
||||
use jj_lib::hex_util::to_reverse_hex;
|
||||
use jj_lib::id_prefix::IdPrefixContext;
|
||||
use jj_lib::object_id::ObjectId as _;
|
||||
|
@ -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 ExtensionsMap);
|
||||
}
|
||||
|
||||
pub struct CommitTemplateLanguage<'repo> {
|
||||
|
@ -50,6 +54,7 @@ pub struct CommitTemplateLanguage<'repo> {
|
|||
id_prefix_context: &'repo IdPrefixContext,
|
||||
build_fn_table: CommitTemplateBuildFnTable<'repo>,
|
||||
keyword_cache: CommitKeywordCache,
|
||||
cache_extensions: ExtensionsMap,
|
||||
}
|
||||
|
||||
impl<'repo> CommitTemplateLanguage<'repo> {
|
||||
|
@ -62,15 +67,22 @@ impl<'repo> CommitTemplateLanguage<'repo> {
|
|||
extension: Option<&dyn CommitTemplateLanguageExtension>,
|
||||
) -> Self {
|
||||
let mut build_fn_table = CommitTemplateBuildFnTable::builtin();
|
||||
let mut cache_extensions = ExtensionsMap::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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue