forked from mirrors/jj
templater: move id prefix shortening onto a new type
I would like to copy Mercurial's way of abbreviating ids within a user-configurable revset. We would do it for both commit ids and change ids. For that feature, we need a place to keep the set of commits the revset evaluates to. This commit adds a new `IdPrefixContext` type which will eventually be that place. The new type has functions for going back and forth between full and abbreviated ids. I've updated the templater to use it.
This commit is contained in:
parent
db0d14569b
commit
c8648cb300
4 changed files with 97 additions and 7 deletions
51
lib/src/id_prefix.rs
Normal file
51
lib/src/id_prefix.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::backend::{ChangeId, CommitId};
|
||||
use crate::index::{HexPrefix, PrefixResolution};
|
||||
use crate::repo::Repo;
|
||||
|
||||
pub struct IdPrefixContext<'repo> {
|
||||
repo: &'repo dyn Repo,
|
||||
}
|
||||
|
||||
impl IdPrefixContext<'_> {
|
||||
pub fn new(repo: &dyn Repo) -> IdPrefixContext {
|
||||
IdPrefixContext { repo }
|
||||
}
|
||||
|
||||
/// Resolve an unambiguous commit ID prefix.
|
||||
pub fn resolve_commit_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<CommitId> {
|
||||
self.repo.index().resolve_prefix(prefix)
|
||||
}
|
||||
|
||||
/// Returns the shortest length of a prefix of `commit_id` that
|
||||
/// can still be resolved by `resolve_commit_prefix()`.
|
||||
pub fn shortest_commit_prefix_len(&self, commit_id: &CommitId) -> usize {
|
||||
self.repo
|
||||
.index()
|
||||
.shortest_unique_commit_id_prefix_len(commit_id)
|
||||
}
|
||||
|
||||
/// Resolve an unambiguous change ID prefix to the commit IDs in the revset.
|
||||
pub fn resolve_change_prefix(&self, prefix: &HexPrefix) -> PrefixResolution<Vec<CommitId>> {
|
||||
self.repo.resolve_change_id_prefix(prefix)
|
||||
}
|
||||
|
||||
/// Returns the shortest length of a prefix of `change_id` that
|
||||
/// can still be resolved by `resolve_change_prefix()`.
|
||||
pub fn shortest_change_prefix_len(&self, change_id: &ChangeId) -> usize {
|
||||
self.repo.shortest_unique_change_id_prefix_len(change_id)
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ pub mod git;
|
|||
pub mod git_backend;
|
||||
pub mod gitignore;
|
||||
pub mod hex_util;
|
||||
pub mod id_prefix;
|
||||
pub mod index;
|
||||
pub mod local_backend;
|
||||
pub mod lock;
|
||||
|
|
|
@ -34,6 +34,7 @@ use jujutsu_lib::commit::Commit;
|
|||
use jujutsu_lib::git::{GitExportError, GitImportError};
|
||||
use jujutsu_lib::gitignore::GitIgnoreFile;
|
||||
use jujutsu_lib::hex_util::to_reverse_hex;
|
||||
use jujutsu_lib::id_prefix::IdPrefixContext;
|
||||
use jujutsu_lib::matchers::{EverythingMatcher, Matcher, PrefixMatcher, Visit};
|
||||
use jujutsu_lib::op_heads_store::{self, OpHeadResolutionError, OpHeadsStore};
|
||||
use jujutsu_lib::op_store::{OpStore, OpStoreError, OperationId, RefTarget, WorkspaceId};
|
||||
|
@ -56,6 +57,7 @@ use jujutsu_lib::working_copy::{
|
|||
};
|
||||
use jujutsu_lib::workspace::{Workspace, WorkspaceInitError, WorkspaceLoadError, WorkspaceLoader};
|
||||
use jujutsu_lib::{dag_walk, file_util, git, revset};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use thiserror::Error;
|
||||
use toml_edit;
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
@ -546,11 +548,15 @@ impl CommandHelper {
|
|||
/// data is lazily loaded.
|
||||
struct ReadonlyUserRepo {
|
||||
repo: Arc<ReadonlyRepo>,
|
||||
id_prefix_context: OnceCell<IdPrefixContext<'static>>,
|
||||
}
|
||||
|
||||
impl ReadonlyUserRepo {
|
||||
fn new(repo: Arc<ReadonlyRepo>) -> Self {
|
||||
Self { repo }
|
||||
Self {
|
||||
repo,
|
||||
id_prefix_context: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -584,9 +590,11 @@ impl WorkspaceCommandHelper {
|
|||
// Parse commit_summary template early to report error before starting mutable
|
||||
// operation.
|
||||
// TODO: Parsed template can be cached if it doesn't capture repo
|
||||
let id_prefix_context = IdPrefixContext::new(repo.as_ref());
|
||||
parse_commit_summary_template(
|
||||
repo.as_ref(),
|
||||
workspace.workspace_id(),
|
||||
&id_prefix_context,
|
||||
&template_aliases_map,
|
||||
&settings,
|
||||
)?;
|
||||
|
@ -919,6 +927,14 @@ impl WorkspaceCommandHelper {
|
|||
DefaultSymbolResolver::new(self.repo().as_ref(), Some(self.workspace_id()))
|
||||
}
|
||||
|
||||
pub fn id_prefix_context(&self) -> &IdPrefixContext<'_> {
|
||||
self.user_repo.id_prefix_context.get_or_init(|| {
|
||||
let context: IdPrefixContext<'_> = IdPrefixContext::new(self.user_repo.repo.as_ref());
|
||||
let context: IdPrefixContext<'static> = unsafe { std::mem::transmute(context) };
|
||||
context
|
||||
})
|
||||
}
|
||||
|
||||
pub fn template_aliases_map(&self) -> &TemplateAliasesMap {
|
||||
&self.template_aliases_map
|
||||
}
|
||||
|
@ -930,6 +946,7 @@ impl WorkspaceCommandHelper {
|
|||
commit_templater::parse(
|
||||
self.repo().as_ref(),
|
||||
self.workspace_id(),
|
||||
self.id_prefix_context(),
|
||||
template_text,
|
||||
&self.template_aliases_map,
|
||||
)
|
||||
|
@ -952,6 +969,7 @@ impl WorkspaceCommandHelper {
|
|||
let template = parse_commit_summary_template(
|
||||
self.repo().as_ref(),
|
||||
self.workspace_id(),
|
||||
self.id_prefix_context(),
|
||||
&self.template_aliases_map,
|
||||
&self.settings,
|
||||
)
|
||||
|
@ -1259,9 +1277,11 @@ impl WorkspaceCommandTransaction<'_> {
|
|||
formatter: &mut dyn Formatter,
|
||||
commit: &Commit,
|
||||
) -> std::io::Result<()> {
|
||||
let id_prefix_context = IdPrefixContext::new(self.tx.repo());
|
||||
let template = parse_commit_summary_template(
|
||||
self.tx.repo(),
|
||||
self.helper.workspace_id(),
|
||||
&id_prefix_context,
|
||||
&self.helper.template_aliases_map,
|
||||
&self.helper.settings,
|
||||
)
|
||||
|
@ -1696,6 +1716,7 @@ fn load_template_aliases(
|
|||
fn parse_commit_summary_template<'a>(
|
||||
repo: &'a dyn Repo,
|
||||
workspace_id: &WorkspaceId,
|
||||
id_prefix_context: &'a IdPrefixContext<'a>,
|
||||
aliases_map: &TemplateAliasesMap,
|
||||
settings: &UserSettings,
|
||||
) -> Result<Box<dyn Template<Commit> + 'a>, CommandError> {
|
||||
|
@ -1703,6 +1724,7 @@ fn parse_commit_summary_template<'a>(
|
|||
Ok(commit_templater::parse(
|
||||
repo,
|
||||
workspace_id,
|
||||
id_prefix_context,
|
||||
&template_text,
|
||||
aliases_map,
|
||||
)?)
|
||||
|
|
|
@ -19,6 +19,7 @@ use itertools::Itertools as _;
|
|||
use jujutsu_lib::backend::{ChangeId, CommitId, ObjectId as _};
|
||||
use jujutsu_lib::commit::Commit;
|
||||
use jujutsu_lib::hex_util::to_reverse_hex;
|
||||
use jujutsu_lib::id_prefix::IdPrefixContext;
|
||||
use jujutsu_lib::op_store::WorkspaceId;
|
||||
use jujutsu_lib::repo::Repo;
|
||||
use jujutsu_lib::rewrite;
|
||||
|
@ -39,6 +40,7 @@ use crate::text_util;
|
|||
struct CommitTemplateLanguage<'repo, 'b> {
|
||||
repo: &'repo dyn Repo,
|
||||
workspace_id: &'b WorkspaceId,
|
||||
id_prefix_context: &'repo IdPrefixContext<'repo>,
|
||||
}
|
||||
|
||||
impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo, '_> {
|
||||
|
@ -383,11 +385,15 @@ impl CommitOrChangeId {
|
|||
|
||||
/// The length of the id printed will be the maximum of `total_len` and the
|
||||
/// length of the shortest unique prefix
|
||||
pub fn shortest(&self, repo: &dyn Repo, total_len: usize) -> ShortestIdPrefix {
|
||||
pub fn shortest(
|
||||
&self,
|
||||
id_prefix_context: &IdPrefixContext,
|
||||
total_len: usize,
|
||||
) -> ShortestIdPrefix {
|
||||
let mut hex = self.hex();
|
||||
let prefix_len = match self {
|
||||
CommitOrChangeId::Commit(id) => repo.index().shortest_unique_commit_id_prefix_len(id),
|
||||
CommitOrChangeId::Change(id) => repo.shortest_unique_change_id_prefix_len(id),
|
||||
CommitOrChangeId::Commit(id) => id_prefix_context.shortest_commit_prefix_len(id),
|
||||
CommitOrChangeId::Change(id) => id_prefix_context.shortest_change_prefix_len(id),
|
||||
};
|
||||
hex.truncate(max(prefix_len, total_len));
|
||||
let rest = hex.split_off(prefix_len);
|
||||
|
@ -422,11 +428,16 @@ fn build_commit_or_change_id_method<'repo>(
|
|||
))
|
||||
}
|
||||
"shortest" => {
|
||||
let repo = language.repo;
|
||||
let id_prefix_context = &language.id_prefix_context;
|
||||
let len_property = parse_optional_integer(function)?;
|
||||
language.wrap_shortest_id_prefix(TemplateFunction::new(
|
||||
(self_property, len_property),
|
||||
|(id, len)| id.shortest(repo, len.and_then(|l| l.try_into().ok()).unwrap_or(0)),
|
||||
|(id, len)| {
|
||||
id.shortest(
|
||||
id_prefix_context,
|
||||
len.and_then(|l| l.try_into().ok()).unwrap_or(0),
|
||||
)
|
||||
},
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
|
@ -504,10 +515,15 @@ fn build_shortest_id_prefix_method<'repo>(
|
|||
pub fn parse<'repo>(
|
||||
repo: &'repo dyn Repo,
|
||||
workspace_id: &WorkspaceId,
|
||||
id_prefix_context: &'repo IdPrefixContext<'repo>,
|
||||
template_text: &str,
|
||||
aliases_map: &TemplateAliasesMap,
|
||||
) -> TemplateParseResult<Box<dyn Template<Commit> + 'repo>> {
|
||||
let language = CommitTemplateLanguage { repo, workspace_id };
|
||||
let language = CommitTemplateLanguage {
|
||||
repo,
|
||||
workspace_id,
|
||||
id_prefix_context,
|
||||
};
|
||||
let node = template_parser::parse(template_text, aliases_map)?;
|
||||
template_builder::build(&language, &node)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue