1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use std::fmt::Write;
use eyre::WrapErr;
use lib::core::dag::{CommitSet, Dag};
use lib::core::effects::Effects;
use lib::git::Repo;
use thiserror::Error;
use tracing::instrument;
use crate::opts::{ResolveRevsetOptions, Revset};
use crate::revset::Expr;
use super::eval::EvalError;
use super::parser::ParseError;
use super::{eval, parse};
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Error)]
pub enum ResolveError {
#[error("parse error in {expr:?}: {source}")]
ParseError { expr: String, source: ParseError },
#[error("evaluation error in {expr:?}: {source}")]
EvalError { expr: String, source: EvalError },
#[error("DAG query error: {source}")]
DagError { source: eden_dag::Error },
#[error(transparent)]
OtherError { source: eyre::Error },
}
impl ResolveError {
pub fn describe(self, effects: &Effects) -> eyre::Result<()> {
match self {
ResolveError::ParseError { expr, source } => {
writeln!(
effects.get_error_stream(),
"Parse error for expression '{}': {}",
expr,
source
)?;
Ok(())
}
ResolveError::EvalError { expr, source } => {
writeln!(
effects.get_error_stream(),
"Evaluation error for expression '{}': {}",
expr,
source
)?;
Ok(())
}
ResolveError::DagError { source } => Err(source.into()),
ResolveError::OtherError { source } => Err(source),
}
}
}
pub fn check_revset_syntax(repo: &Repo, revsets: &[Revset]) -> Result<(), ParseError> {
for Revset(revset) in revsets {
if let Ok(Some(_)) = repo.revparse_single_commit(revset) {
continue;
}
let _expr: Expr = parse(revset)?;
}
Ok(())
}
#[instrument]
pub fn resolve_commits(
effects: &Effects,
repo: &Repo,
dag: &mut Dag,
revsets: &[Revset],
options: &ResolveRevsetOptions,
) -> Result<Vec<CommitSet>, ResolveError> {
let mut dag_with_obsolete = if options.show_hidden_commits {
Some(
dag.clear_obsolete_commits(repo)
.map_err(|err| ResolveError::OtherError { source: err })?,
)
} else {
None
};
let dag = dag_with_obsolete.as_mut().unwrap_or(dag);
let mut commit_sets = Vec::new();
for Revset(revset) in revsets {
if let Ok(Some(commit)) = repo.revparse_single_commit(revset) {
let commit_set = CommitSet::from(commit.get_oid());
dag.sync_from_oids(effects, repo, CommitSet::empty(), commit_set.clone())
.map_err(|err| ResolveError::OtherError { source: err })?;
commit_sets.push(commit_set);
continue;
}
let expr = parse(revset).map_err(|err| ResolveError::ParseError {
expr: revset.clone(),
source: err,
})?;
let commits = eval(effects, repo, dag, &expr).map_err(|err| ResolveError::EvalError {
expr: revset.clone(),
source: err,
})?;
commit_sets.push(commits);
}
Ok(commit_sets)
}
pub fn resolve_default_smartlog_commits(
effects: &Effects,
repo: &Repo,
dag: &mut Dag,
) -> eyre::Result<CommitSet> {
let revset = Revset::default_smartlog_revset();
let results = resolve_commits(
effects,
repo,
dag,
&[revset],
&ResolveRevsetOptions::default(),
)
.wrap_err("Resolving default smartlog commits")?;
let commits = results.first().unwrap();
Ok(commits.clone())
}