ok/jj
1
0
Fork 0
forked from mirrors/jj

revset: split RevsetError into RevsetResolution/EvaluationError

This makes it clear that RevsetExpression::Present node is noop at the
evaluation stage.

RevsetEvaluationError::StoreError is unused right now, but I'm not sure if
it should be removed. It makes some sense that evaluate() can propagate
StoreError as it has access to the store.
This commit is contained in:
Yuya Nishihara 2023-04-02 10:59:22 +09:00
parent f2e0836b1e
commit c28d2d7784
6 changed files with 70 additions and 52 deletions

View file

@ -44,7 +44,7 @@ use crate::index::{
use crate::nightly_shims::BTreeSetExt; use crate::nightly_shims::BTreeSetExt;
use crate::op_store::OperationId; use crate::op_store::OperationId;
use crate::operation::Operation; use crate::operation::Operation;
use crate::revset::{Revset, RevsetError, RevsetExpression}; use crate::revset::{Revset, RevsetEvaluationError, RevsetExpression};
use crate::store::Store; use crate::store::Store;
use crate::{backend, dag_walk, default_revset_engine}; use crate::{backend, dag_walk, default_revset_engine};
@ -732,7 +732,7 @@ impl Index for MutableIndexImpl {
expression: &RevsetExpression, expression: &RevsetExpression,
store: &Arc<Store>, store: &Arc<Store>,
visible_heads: &[CommitId], visible_heads: &[CommitId],
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> { ) -> Result<Box<dyn Revset<'index> + 'index>, RevsetEvaluationError> {
let revset_impl = default_revset_engine::evaluate( let revset_impl = default_revset_engine::evaluate(
expression, expression,
store, store,
@ -1820,7 +1820,7 @@ impl Index for ReadonlyIndexImpl {
expression: &RevsetExpression, expression: &RevsetExpression,
store: &Arc<Store>, store: &Arc<Store>,
visible_heads: &[CommitId], visible_heads: &[CommitId],
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> { ) -> Result<Box<dyn Revset<'index> + 'index>, RevsetEvaluationError> {
let revset_impl = default_revset_engine::evaluate( let revset_impl = default_revset_engine::evaluate(
expression, expression,
store, store,

View file

@ -26,8 +26,8 @@ use crate::default_revset_graph_iterator::RevsetGraphIterator;
use crate::index::{HexPrefix, Index, PrefixResolution}; use crate::index::{HexPrefix, Index, PrefixResolution};
use crate::matchers::{EverythingMatcher, Matcher, PrefixMatcher}; use crate::matchers::{EverythingMatcher, Matcher, PrefixMatcher};
use crate::revset::{ use crate::revset::{
ChangeIdIndex, Revset, RevsetError, RevsetExpression, RevsetFilterPredicate, RevsetGraphEdge, ChangeIdIndex, Revset, RevsetEvaluationError, RevsetExpression, RevsetFilterPredicate,
GENERATION_RANGE_FULL, RevsetGraphEdge, GENERATION_RANGE_FULL,
}; };
use crate::store::Store; use crate::store::Store;
use crate::{backend, rewrite}; use crate::{backend, rewrite};
@ -507,7 +507,7 @@ pub fn evaluate<'index>(
index: &'index dyn Index, index: &'index dyn Index,
composite_index: CompositeIndex<'index>, composite_index: CompositeIndex<'index>,
visible_heads: &[CommitId], visible_heads: &[CommitId],
) -> Result<RevsetImpl<'index>, RevsetError> { ) -> Result<RevsetImpl<'index>, RevsetEvaluationError> {
let context = EvaluationContext { let context = EvaluationContext {
store: store.clone(), store: store.clone(),
index, index,
@ -529,7 +529,7 @@ impl<'index, 'heads> EvaluationContext<'index, 'heads> {
fn evaluate( fn evaluate(
&self, &self,
expression: &RevsetExpression, expression: &RevsetExpression,
) -> Result<Box<dyn InternalRevset<'index> + 'index>, RevsetError> { ) -> Result<Box<dyn InternalRevset<'index> + 'index>, RevsetEvaluationError> {
match expression { match expression {
RevsetExpression::Symbol(_) RevsetExpression::Symbol(_)
| RevsetExpression::Branches(_) | RevsetExpression::Branches(_)
@ -644,11 +644,7 @@ impl<'index, 'heads> EvaluationContext<'index, 'heads> {
predicate: build_predicate_fn(self.store.clone(), self.index, predicate), predicate: build_predicate_fn(self.store.clone(), self.index, predicate),
})), })),
RevsetExpression::AsFilter(candidates) => self.evaluate(candidates), RevsetExpression::AsFilter(candidates) => self.evaluate(candidates),
RevsetExpression::Present(candidates) => match self.evaluate(candidates) { RevsetExpression::Present(candidates) => self.evaluate(candidates),
Ok(set) => Ok(set),
Err(RevsetError::NoSuchRevision(_)) => Ok(Box::new(EagerRevset::empty())),
r @ Err(RevsetError::AmbiguousIdPrefix(_) | RevsetError::StoreError(_)) => r,
},
RevsetExpression::NotIn(complement) => { RevsetExpression::NotIn(complement) => {
let set1 = self.evaluate(&RevsetExpression::All)?; let set1 = self.evaluate(&RevsetExpression::All)?;
let set2 = self.evaluate(complement)?; let set2 = self.evaluate(complement)?;

View file

@ -23,7 +23,7 @@ use crate::commit::Commit;
use crate::default_index_store::{IndexEntry, RevWalk}; use crate::default_index_store::{IndexEntry, RevWalk};
use crate::op_store::OperationId; use crate::op_store::OperationId;
use crate::operation::Operation; use crate::operation::Operation;
use crate::revset::{Revset, RevsetError, RevsetExpression}; use crate::revset::{Revset, RevsetEvaluationError, RevsetExpression};
use crate::store::Store; use crate::store::Store;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -73,7 +73,7 @@ pub trait Index: Send + Sync {
expression: &RevsetExpression, expression: &RevsetExpression,
store: &Arc<Store>, store: &Arc<Store>,
visible_heads: &[CommitId], visible_heads: &[CommitId],
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError>; ) -> Result<Box<dyn Revset<'index> + 'index>, RevsetEvaluationError>;
} }
pub trait ReadonlyIndex: Send + Sync { pub trait ReadonlyIndex: Send + Sync {

View file

@ -37,8 +37,9 @@ use crate::repo::Repo;
use crate::repo_path::{FsPathParseError, RepoPath}; use crate::repo_path::{FsPathParseError, RepoPath};
use crate::store::Store; use crate::store::Store;
/// Error occurred during symbol resolution.
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum RevsetError { pub enum RevsetResolutionError {
#[error("Revision \"{0}\" doesn't exist")] #[error("Revision \"{0}\" doesn't exist")]
NoSuchRevision(String), NoSuchRevision(String),
#[error("Commit or change id prefix \"{0}\" is ambiguous")] #[error("Commit or change id prefix \"{0}\" is ambiguous")]
@ -47,6 +48,13 @@ pub enum RevsetError {
StoreError(#[source] BackendError), StoreError(#[source] BackendError),
} }
/// Error occurred during revset evaluation.
#[derive(Debug, Error)]
pub enum RevsetEvaluationError {
#[error("Unexpected error from store: {0}")]
StoreError(#[source] BackendError),
}
#[derive(Parser)] #[derive(Parser)]
#[grammar = "revset.pest"] #[grammar = "revset.pest"]
pub struct RevsetParser; pub struct RevsetParser;
@ -402,7 +410,7 @@ impl RevsetExpression {
pub fn evaluate<'index>( pub fn evaluate<'index>(
&self, &self,
repo: &'index dyn Repo, repo: &'index dyn Repo,
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> { ) -> Result<Box<dyn Revset<'index> + 'index>, RevsetEvaluationError> {
repo.index().evaluate_revset( repo.index().evaluate_revset(
self, self,
repo.store(), repo.store(),
@ -1101,7 +1109,8 @@ fn transform_expression_bottom_up(
try_transform_expression_bottom_up(expression, |expression| Ok(f(expression))).unwrap() try_transform_expression_bottom_up(expression, |expression| Ok(f(expression))).unwrap()
} }
type TransformResult = Result<Option<Rc<RevsetExpression>>, RevsetError>; type TransformResult = Result<Option<Rc<RevsetExpression>>, RevsetResolutionError>;
/// Walks `expression` tree and applies `f` recursively from leaf nodes. /// Walks `expression` tree and applies `f` recursively from leaf nodes.
/// ///
/// If `f` returns `None`, the original expression node is reused. If no nodes /// If `f` returns `None`, the original expression node is reused. If no nodes
@ -1167,8 +1176,11 @@ fn try_transform_expression_bottom_up(
RevsetExpression::Present(candidates) => match transform_rec(candidates, f) { RevsetExpression::Present(candidates) => match transform_rec(candidates, f) {
Ok(None) => None, Ok(None) => None,
Ok(Some(expression)) => Some(RevsetExpression::Present(expression)), Ok(Some(expression)) => Some(RevsetExpression::Present(expression)),
Err(RevsetError::NoSuchRevision(_)) => Some(RevsetExpression::None), Err(RevsetResolutionError::NoSuchRevision(_)) => Some(RevsetExpression::None),
r @ Err(RevsetError::AmbiguousIdPrefix(_) | RevsetError::StoreError(_)) => { r @ Err(
RevsetResolutionError::AmbiguousIdPrefix(_)
| RevsetResolutionError::StoreError(_),
) => {
return r; return r;
} }
}, },
@ -1202,7 +1214,7 @@ fn try_transform_expression_bottom_up(
fn transform_rec_pair( fn transform_rec_pair(
(expression1, expression2): (&Rc<RevsetExpression>, &Rc<RevsetExpression>), (expression1, expression2): (&Rc<RevsetExpression>, &Rc<RevsetExpression>),
f: &mut impl FnMut(&Rc<RevsetExpression>) -> TransformResult, f: &mut impl FnMut(&Rc<RevsetExpression>) -> TransformResult,
) -> Result<Option<(Rc<RevsetExpression>, Rc<RevsetExpression>)>, RevsetError> { ) -> Result<Option<(Rc<RevsetExpression>, Rc<RevsetExpression>)>, RevsetResolutionError> {
match ( match (
transform_rec(expression1, f)?, transform_rec(expression1, f)?,
transform_rec(expression2, f)?, transform_rec(expression2, f)?,
@ -1475,7 +1487,7 @@ fn resolve_branch(repo: &dyn Repo, symbol: &str) -> Option<Vec<CommitId>> {
fn resolve_full_commit_id( fn resolve_full_commit_id(
repo: &dyn Repo, repo: &dyn Repo,
symbol: &str, symbol: &str,
) -> Result<Option<Vec<CommitId>>, RevsetError> { ) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
if let Ok(binary_commit_id) = hex::decode(symbol) { if let Ok(binary_commit_id) = hex::decode(symbol) {
if repo.store().commit_id_length() != binary_commit_id.len() { if repo.store().commit_id_length() != binary_commit_id.len() {
return Ok(None); return Ok(None);
@ -1485,7 +1497,7 @@ fn resolve_full_commit_id(
// Only recognize a commit if we have indexed it // Only recognize a commit if we have indexed it
Ok(_) if repo.index().has_id(&commit_id) => Ok(Some(vec![commit_id])), Ok(_) if repo.index().has_id(&commit_id) => Ok(Some(vec![commit_id])),
Ok(_) | Err(BackendError::ObjectNotFound { .. }) => Ok(None), Ok(_) | Err(BackendError::ObjectNotFound { .. }) => Ok(None),
Err(err) => Err(RevsetError::StoreError(err)), Err(err) => Err(RevsetResolutionError::StoreError(err)),
} }
} else { } else {
Ok(None) Ok(None)
@ -1495,12 +1507,12 @@ fn resolve_full_commit_id(
fn resolve_short_commit_id( fn resolve_short_commit_id(
repo: &dyn Repo, repo: &dyn Repo,
symbol: &str, symbol: &str,
) -> Result<Option<Vec<CommitId>>, RevsetError> { ) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
if let Some(prefix) = HexPrefix::new(symbol) { if let Some(prefix) = HexPrefix::new(symbol) {
match repo.index().resolve_prefix(&prefix) { match repo.index().resolve_prefix(&prefix) {
PrefixResolution::NoMatch => Ok(None), PrefixResolution::NoMatch => Ok(None),
PrefixResolution::AmbiguousMatch => { PrefixResolution::AmbiguousMatch => {
Err(RevsetError::AmbiguousIdPrefix(symbol.to_owned())) Err(RevsetResolutionError::AmbiguousIdPrefix(symbol.to_owned()))
} }
PrefixResolution::SingleMatch(commit_id) => Ok(Some(vec![commit_id])), PrefixResolution::SingleMatch(commit_id) => Ok(Some(vec![commit_id])),
} }
@ -1509,12 +1521,15 @@ fn resolve_short_commit_id(
} }
} }
fn resolve_change_id(repo: &dyn Repo, symbol: &str) -> Result<Option<Vec<CommitId>>, RevsetError> { fn resolve_change_id(
repo: &dyn Repo,
symbol: &str,
) -> Result<Option<Vec<CommitId>>, RevsetResolutionError> {
if let Some(prefix) = to_forward_hex(symbol).as_deref().and_then(HexPrefix::new) { if let Some(prefix) = to_forward_hex(symbol).as_deref().and_then(HexPrefix::new) {
match repo.resolve_change_id_prefix(&prefix) { match repo.resolve_change_id_prefix(&prefix) {
PrefixResolution::NoMatch => Ok(None), PrefixResolution::NoMatch => Ok(None),
PrefixResolution::AmbiguousMatch => { PrefixResolution::AmbiguousMatch => {
Err(RevsetError::AmbiguousIdPrefix(symbol.to_owned())) Err(RevsetResolutionError::AmbiguousIdPrefix(symbol.to_owned()))
} }
PrefixResolution::SingleMatch(entries) => Ok(Some(entries)), PrefixResolution::SingleMatch(entries) => Ok(Some(entries)),
} }
@ -1527,13 +1542,13 @@ pub fn resolve_symbol(
repo: &dyn Repo, repo: &dyn Repo,
symbol: &str, symbol: &str,
workspace_id: Option<&WorkspaceId>, workspace_id: Option<&WorkspaceId>,
) -> Result<Vec<CommitId>, RevsetError> { ) -> Result<Vec<CommitId>, RevsetResolutionError> {
if symbol.ends_with('@') { if symbol.ends_with('@') {
let target_workspace = if symbol == "@" { let target_workspace = if symbol == "@" {
if let Some(workspace_id) = workspace_id { if let Some(workspace_id) = workspace_id {
workspace_id.clone() workspace_id.clone()
} else { } else {
return Err(RevsetError::NoSuchRevision(symbol.to_owned())); return Err(RevsetResolutionError::NoSuchRevision(symbol.to_owned()));
} }
} else { } else {
WorkspaceId::new(symbol.strip_suffix('@').unwrap().to_string()) WorkspaceId::new(symbol.strip_suffix('@').unwrap().to_string())
@ -1541,7 +1556,7 @@ pub fn resolve_symbol(
if let Some(commit_id) = repo.view().get_wc_commit_id(&target_workspace) { if let Some(commit_id) = repo.view().get_wc_commit_id(&target_workspace) {
Ok(vec![commit_id.clone()]) Ok(vec![commit_id.clone()])
} else { } else {
Err(RevsetError::NoSuchRevision(symbol.to_owned())) Err(RevsetResolutionError::NoSuchRevision(symbol.to_owned()))
} }
} else if symbol == "root" { } else if symbol == "root" {
Ok(vec![repo.store().root_commit_id().clone()]) Ok(vec![repo.store().root_commit_id().clone()])
@ -1577,7 +1592,7 @@ pub fn resolve_symbol(
return Ok(ids); return Ok(ids);
} }
Err(RevsetError::NoSuchRevision(symbol.to_owned())) Err(RevsetResolutionError::NoSuchRevision(symbol.to_owned()))
} }
} }
@ -1588,7 +1603,7 @@ pub fn resolve_symbols(
repo: &dyn Repo, repo: &dyn Repo,
expression: Rc<RevsetExpression>, expression: Rc<RevsetExpression>,
workspace_ctx: Option<&RevsetWorkspaceContext>, workspace_ctx: Option<&RevsetWorkspaceContext>,
) -> Result<Rc<RevsetExpression>, RevsetError> { ) -> Result<Rc<RevsetExpression>, RevsetResolutionError> {
Ok( Ok(
try_transform_expression_bottom_up(&expression, |expression| { try_transform_expression_bottom_up(&expression, |expression| {
Ok(match expression.as_ref() { Ok(match expression.as_ref() {

View file

@ -25,8 +25,8 @@ use jujutsu_lib::repo::Repo;
use jujutsu_lib::repo_path::RepoPath; use jujutsu_lib::repo_path::RepoPath;
use jujutsu_lib::revset::{ use jujutsu_lib::revset::{
optimize, parse, resolve_symbol, resolve_symbols, ReverseRevsetGraphIterator, Revset, optimize, parse, resolve_symbol, resolve_symbols, ReverseRevsetGraphIterator, Revset,
RevsetAliasesMap, RevsetError, RevsetExpression, RevsetFilterPredicate, RevsetGraphEdge, RevsetAliasesMap, RevsetExpression, RevsetFilterPredicate, RevsetGraphEdge,
RevsetWorkspaceContext, RevsetResolutionError, RevsetWorkspaceContext,
}; };
use jujutsu_lib::settings::GitSettings; use jujutsu_lib::settings::GitSettings;
use jujutsu_lib::workspace::Workspace; use jujutsu_lib::workspace::Workspace;
@ -141,7 +141,7 @@ fn test_resolve_symbol_commit_id() {
// Test empty commit id // Test empty commit id
assert_matches!( assert_matches!(
resolve_symbol(repo.as_ref(), "", None), resolve_symbol(repo.as_ref(), "", None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s.is_empty() Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s.is_empty()
); );
// Test commit id prefix // Test commit id prefix
@ -151,28 +151,28 @@ fn test_resolve_symbol_commit_id() {
); );
assert_matches!( assert_matches!(
resolve_symbol(repo.as_ref(), "04", None), resolve_symbol(repo.as_ref(), "04", None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s == "04" Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s == "04"
); );
assert_matches!( assert_matches!(
resolve_symbol(repo.as_ref(), "", None), resolve_symbol(repo.as_ref(), "", None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s.is_empty() Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s.is_empty()
); );
assert_matches!( assert_matches!(
resolve_symbol(repo.as_ref(), "040", None), resolve_symbol(repo.as_ref(), "040", None),
Err(RevsetError::NoSuchRevision(s)) if s == "040" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "040"
); );
// Test non-hex string // Test non-hex string
assert_matches!( assert_matches!(
resolve_symbol(repo.as_ref(), "foo", None), resolve_symbol(repo.as_ref(), "foo", None),
Err(RevsetError::NoSuchRevision(s)) if s == "foo" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "foo"
); );
// Test present() suppresses only NoSuchRevision error // Test present() suppresses only NoSuchRevision error
assert_eq!(resolve_commit_ids(repo.as_ref(), "present(foo)"), []); assert_eq!(resolve_commit_ids(repo.as_ref(), "present(foo)"), []);
assert_matches!( assert_matches!(
resolve_symbols(repo.as_ref(), optimize(parse("present(04)", &RevsetAliasesMap::new(), None).unwrap()), None), resolve_symbols(repo.as_ref(), optimize(parse("present(04)", &RevsetAliasesMap::new(), None).unwrap()), None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s == "04" Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s == "04"
); );
assert_eq!( assert_eq!(
resolve_commit_ids(repo.as_ref(), "present(046)"), resolve_commit_ids(repo.as_ref(), "present(046)"),
@ -288,15 +288,15 @@ fn test_resolve_symbol_change_id(readonly: bool) {
); );
assert_matches!( assert_matches!(
resolve_symbol(repo, "zvly", None), resolve_symbol(repo, "zvly", None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s == "zvly" Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s == "zvly"
); );
assert_matches!( assert_matches!(
resolve_symbol(repo, "", None), resolve_symbol(repo, "", None),
Err(RevsetError::AmbiguousIdPrefix(s)) if s.is_empty() Err(RevsetResolutionError::AmbiguousIdPrefix(s)) if s.is_empty()
); );
assert_matches!( assert_matches!(
resolve_symbol(repo, "zvlyw", None), resolve_symbol(repo, "zvlyw", None),
Err(RevsetError::NoSuchRevision(s)) if s == "zvlyw" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "zvlyw"
); );
// Test that commit and changed id don't conflict ("040" and "zvz" are the // Test that commit and changed id don't conflict ("040" and "zvz" are the
@ -317,7 +317,7 @@ fn test_resolve_symbol_change_id(readonly: bool) {
// Test non-hex string // Test non-hex string
assert_matches!( assert_matches!(
resolve_symbol(repo, "foo", None), resolve_symbol(repo, "foo", None),
Err(RevsetError::NoSuchRevision(s)) if s == "foo" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "foo"
); );
} }
@ -340,15 +340,15 @@ fn test_resolve_symbol_checkout(use_git: bool) {
// With no workspaces, no variation can be resolved // With no workspaces, no variation can be resolved
assert_matches!( assert_matches!(
resolve_symbol(mut_repo, "@", None), resolve_symbol(mut_repo, "@", None),
Err(RevsetError::NoSuchRevision(s)) if s == "@" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "@"
); );
assert_matches!( assert_matches!(
resolve_symbol(mut_repo, "@", Some(&ws1)), resolve_symbol(mut_repo, "@", Some(&ws1)),
Err(RevsetError::NoSuchRevision(s)) if s == "@" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "@"
); );
assert_matches!( assert_matches!(
resolve_symbol(mut_repo, "ws1@", Some(&ws1)), resolve_symbol(mut_repo, "ws1@", Some(&ws1)),
Err(RevsetError::NoSuchRevision(s)) if s == "ws1@" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "ws1@"
); );
// Add some workspaces // Add some workspaces
@ -359,7 +359,7 @@ fn test_resolve_symbol_checkout(use_git: bool) {
// @ cannot be resolved without a default workspace ID // @ cannot be resolved without a default workspace ID
assert_matches!( assert_matches!(
resolve_symbol(mut_repo, "@", None), resolve_symbol(mut_repo, "@", None),
Err(RevsetError::NoSuchRevision(s)) if s == "@" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "@"
); );
// Can resolve "@" shorthand with a default workspace ID // Can resolve "@" shorthand with a default workspace ID
assert_eq!( assert_eq!(
@ -415,7 +415,7 @@ fn test_resolve_symbol_git_refs() {
// Nonexistent ref // Nonexistent ref
assert_matches!( assert_matches!(
resolve_symbol(mut_repo, "nonexistent", None), resolve_symbol(mut_repo, "nonexistent", None),
Err(RevsetError::NoSuchRevision(s)) if s == "nonexistent" Err(RevsetResolutionError::NoSuchRevision(s)) if s == "nonexistent"
); );
// Full ref // Full ref

View file

@ -44,8 +44,9 @@ use jujutsu_lib::repo::{
}; };
use jujutsu_lib::repo_path::{FsPathParseError, RepoPath}; use jujutsu_lib::repo_path::{FsPathParseError, RepoPath};
use jujutsu_lib::revset::{ use jujutsu_lib::revset::{
resolve_symbols, Revset, RevsetAliasesMap, RevsetError, RevsetExpression, RevsetIteratorExt, resolve_symbols, Revset, RevsetAliasesMap, RevsetEvaluationError, RevsetExpression,
RevsetParseError, RevsetParseErrorKind, RevsetWorkspaceContext, RevsetIteratorExt, RevsetParseError, RevsetParseErrorKind, RevsetResolutionError,
RevsetWorkspaceContext,
}; };
use jujutsu_lib::settings::UserSettings; use jujutsu_lib::settings::UserSettings;
use jujutsu_lib::transaction::Transaction; use jujutsu_lib::transaction::Transaction;
@ -249,6 +250,12 @@ impl From<GitExportError> for CommandError {
} }
} }
impl From<RevsetEvaluationError> for CommandError {
fn from(err: RevsetEvaluationError) -> Self {
user_error(format!("{err}"))
}
}
impl From<RevsetParseError> for CommandError { impl From<RevsetParseError> for CommandError {
fn from(err: RevsetParseError) -> Self { fn from(err: RevsetParseError) -> Self {
let message = iter::successors(Some(&err), |e| e.origin()).join("\n"); let message = iter::successors(Some(&err), |e| e.origin()).join("\n");
@ -276,8 +283,8 @@ impl From<RevsetParseError> for CommandError {
} }
} }
impl From<RevsetError> for CommandError { impl From<RevsetResolutionError> for CommandError {
fn from(err: RevsetError) -> Self { fn from(err: RevsetResolutionError) -> Self {
user_error(format!("{err}")) user_error(format!("{err}"))
} }
} }