forked from mirrors/jj
revset: add generation parameter to RevsetExpression::Ancestors/Range
Parents(heads) will be translated to Ancestors(heads, 1..2).
This commit is contained in:
parent
29a565e3fb
commit
46b1465324
1 changed files with 79 additions and 21 deletions
|
@ -318,6 +318,9 @@ impl error::Error for RevsetParseError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assumes index has less than u32::MAX entries.
|
||||||
|
const GENERATION_RANGE_FULL: Range<u32> = 0..u32::MAX;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum RevsetFilterPredicate {
|
pub enum RevsetFilterPredicate {
|
||||||
/// Commits with number of parents in the range.
|
/// Commits with number of parents in the range.
|
||||||
|
@ -340,11 +343,15 @@ pub enum RevsetExpression {
|
||||||
Symbol(String),
|
Symbol(String),
|
||||||
Parents(Rc<RevsetExpression>),
|
Parents(Rc<RevsetExpression>),
|
||||||
Children(Rc<RevsetExpression>),
|
Children(Rc<RevsetExpression>),
|
||||||
Ancestors(Rc<RevsetExpression>),
|
Ancestors {
|
||||||
|
heads: Rc<RevsetExpression>,
|
||||||
|
generation: Range<u32>,
|
||||||
|
},
|
||||||
// Commits that are ancestors of "heads" but not ancestors of "roots"
|
// Commits that are ancestors of "heads" but not ancestors of "roots"
|
||||||
Range {
|
Range {
|
||||||
roots: Rc<RevsetExpression>,
|
roots: Rc<RevsetExpression>,
|
||||||
heads: Rc<RevsetExpression>,
|
heads: Rc<RevsetExpression>,
|
||||||
|
generation: Range<u32>,
|
||||||
},
|
},
|
||||||
// Commits that are descendants of "roots" and ancestors of "heads"
|
// Commits that are descendants of "roots" and ancestors of "heads"
|
||||||
DagRange {
|
DagRange {
|
||||||
|
@ -440,7 +447,10 @@ impl RevsetExpression {
|
||||||
|
|
||||||
/// Ancestors of `self`, including `self`.
|
/// Ancestors of `self`, including `self`.
|
||||||
pub fn ancestors(self: &Rc<RevsetExpression>) -> Rc<RevsetExpression> {
|
pub fn ancestors(self: &Rc<RevsetExpression>) -> Rc<RevsetExpression> {
|
||||||
Rc::new(RevsetExpression::Ancestors(self.clone()))
|
Rc::new(RevsetExpression::Ancestors {
|
||||||
|
heads: self.clone(),
|
||||||
|
generation: GENERATION_RANGE_FULL,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Children of `self`.
|
/// Children of `self`.
|
||||||
|
@ -479,6 +489,7 @@ impl RevsetExpression {
|
||||||
Rc::new(RevsetExpression::Range {
|
Rc::new(RevsetExpression::Range {
|
||||||
roots: self.clone(),
|
roots: self.clone(),
|
||||||
heads: heads.clone(),
|
heads: heads.clone(),
|
||||||
|
generation: GENERATION_RANGE_FULL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,11 +1088,23 @@ fn transform_expression_bottom_up(
|
||||||
RevsetExpression::Children(roots) => {
|
RevsetExpression::Children(roots) => {
|
||||||
transform_rec(roots, f).map(RevsetExpression::Children)
|
transform_rec(roots, f).map(RevsetExpression::Children)
|
||||||
}
|
}
|
||||||
RevsetExpression::Ancestors(base) => {
|
RevsetExpression::Ancestors { heads, generation } => {
|
||||||
transform_rec(base, f).map(RevsetExpression::Ancestors)
|
transform_rec(heads, f).map(|heads| RevsetExpression::Ancestors {
|
||||||
|
heads,
|
||||||
|
generation: generation.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
RevsetExpression::Range { roots, heads } => transform_rec_pair((roots, heads), f)
|
RevsetExpression::Range {
|
||||||
.map(|(roots, heads)| RevsetExpression::Range { roots, heads }),
|
roots,
|
||||||
|
heads,
|
||||||
|
generation,
|
||||||
|
} => transform_rec_pair((roots, heads), f).map(|(roots, heads)| {
|
||||||
|
RevsetExpression::Range {
|
||||||
|
roots,
|
||||||
|
heads,
|
||||||
|
generation: generation.clone(),
|
||||||
|
}
|
||||||
|
}),
|
||||||
RevsetExpression::DagRange { roots, heads } => transform_rec_pair((roots, heads), f)
|
RevsetExpression::DagRange { roots, heads } => transform_rec_pair((roots, heads), f)
|
||||||
.map(|(roots, heads)| RevsetExpression::DagRange { roots, heads }),
|
.map(|(roots, heads)| RevsetExpression::DagRange { roots, heads }),
|
||||||
RevsetExpression::VisibleHeads => None,
|
RevsetExpression::VisibleHeads => None,
|
||||||
|
@ -1268,12 +1291,17 @@ fn fold_difference(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpress
|
||||||
) -> Rc<RevsetExpression> {
|
) -> Rc<RevsetExpression> {
|
||||||
match (expression.as_ref(), complement.as_ref()) {
|
match (expression.as_ref(), complement.as_ref()) {
|
||||||
// :heads & ~(:roots) -> roots..heads
|
// :heads & ~(:roots) -> roots..heads
|
||||||
(RevsetExpression::Ancestors(heads), RevsetExpression::Ancestors(roots)) => {
|
(
|
||||||
Rc::new(RevsetExpression::Range {
|
RevsetExpression::Ancestors { heads, generation },
|
||||||
roots: roots.clone(),
|
RevsetExpression::Ancestors {
|
||||||
heads: heads.clone(),
|
heads: roots,
|
||||||
})
|
generation: GENERATION_RANGE_FULL,
|
||||||
}
|
},
|
||||||
|
) => Rc::new(RevsetExpression::Range {
|
||||||
|
roots: roots.clone(),
|
||||||
|
heads: heads.clone(),
|
||||||
|
generation: generation.clone(),
|
||||||
|
}),
|
||||||
_ => expression.minus(complement),
|
_ => expression.minus(complement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1301,8 +1329,16 @@ fn fold_difference(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpress
|
||||||
fn unfold_difference(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>> {
|
fn unfold_difference(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>> {
|
||||||
transform_expression_bottom_up(expression, |expression| match expression.as_ref() {
|
transform_expression_bottom_up(expression, |expression| match expression.as_ref() {
|
||||||
// roots..heads -> :heads & ~(:roots)
|
// roots..heads -> :heads & ~(:roots)
|
||||||
RevsetExpression::Range { roots, heads } => {
|
RevsetExpression::Range {
|
||||||
Some(heads.ancestors().intersection(&roots.ancestors().negated()))
|
roots,
|
||||||
|
heads,
|
||||||
|
generation,
|
||||||
|
} => {
|
||||||
|
let heads_ancestors = Rc::new(RevsetExpression::Ancestors {
|
||||||
|
heads: heads.clone(),
|
||||||
|
generation: generation.clone(),
|
||||||
|
});
|
||||||
|
Some(heads_ancestors.intersection(&roots.ancestors().negated()))
|
||||||
}
|
}
|
||||||
RevsetExpression::Difference(expression1, expression2) => {
|
RevsetExpression::Difference(expression1, expression2) => {
|
||||||
Some(expression1.intersection(&expression2.negated()))
|
Some(expression1.intersection(&expression2.negated()))
|
||||||
|
@ -1762,16 +1798,30 @@ pub fn evaluate_expression<'repo>(
|
||||||
candidate_set,
|
candidate_set,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
RevsetExpression::Ancestors(base_expression) => RevsetExpression::none()
|
RevsetExpression::Ancestors { heads, generation } => {
|
||||||
.range(base_expression)
|
let range_expression = RevsetExpression::Range {
|
||||||
.evaluate(repo, workspace_ctx),
|
roots: RevsetExpression::none(),
|
||||||
RevsetExpression::Range { roots, heads } => {
|
heads: heads.clone(),
|
||||||
|
generation: generation.clone(),
|
||||||
|
};
|
||||||
|
range_expression.evaluate(repo, workspace_ctx)
|
||||||
|
}
|
||||||
|
RevsetExpression::Range {
|
||||||
|
roots,
|
||||||
|
heads,
|
||||||
|
generation,
|
||||||
|
} => {
|
||||||
let root_set = roots.evaluate(repo, workspace_ctx)?;
|
let root_set = roots.evaluate(repo, workspace_ctx)?;
|
||||||
let root_ids = root_set.iter().commit_ids().collect_vec();
|
let root_ids = root_set.iter().commit_ids().collect_vec();
|
||||||
let head_set = heads.evaluate(repo, workspace_ctx)?;
|
let head_set = heads.evaluate(repo, workspace_ctx)?;
|
||||||
let head_ids = head_set.iter().commit_ids().collect_vec();
|
let head_ids = head_set.iter().commit_ids().collect_vec();
|
||||||
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
||||||
Ok(Box::new(RevWalkRevset { walk }))
|
if generation == &GENERATION_RANGE_FULL {
|
||||||
|
Ok(Box::new(RevWalkRevset { walk }))
|
||||||
|
} else {
|
||||||
|
let walk = walk.filter_by_generation(generation.clone());
|
||||||
|
Ok(Box::new(RevWalkRevset { walk }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Clippy doesn't seem to understand that we collect the iterator in order to iterate in
|
// Clippy doesn't seem to understand that we collect the iterator in order to iterate in
|
||||||
// reverse
|
// reverse
|
||||||
|
@ -2067,7 +2117,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wc_symbol.ancestors(),
|
wc_symbol.ancestors(),
|
||||||
Rc::new(RevsetExpression::Ancestors(wc_symbol.clone()))
|
Rc::new(RevsetExpression::Ancestors {
|
||||||
|
heads: wc_symbol.clone(),
|
||||||
|
generation: GENERATION_RANGE_FULL,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
foo_symbol.children(),
|
foo_symbol.children(),
|
||||||
|
@ -2098,7 +2151,8 @@ mod tests {
|
||||||
foo_symbol.range(&wc_symbol),
|
foo_symbol.range(&wc_symbol),
|
||||||
Rc::new(RevsetExpression::Range {
|
Rc::new(RevsetExpression::Range {
|
||||||
roots: foo_symbol.clone(),
|
roots: foo_symbol.clone(),
|
||||||
heads: wc_symbol.clone()
|
heads: wc_symbol.clone(),
|
||||||
|
generation: GENERATION_RANGE_FULL,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2672,6 +2726,7 @@ mod tests {
|
||||||
heads: Symbol(
|
heads: Symbol(
|
||||||
"foo",
|
"foo",
|
||||||
),
|
),
|
||||||
|
generation: 0..4294967295,
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
insta::assert_debug_snapshot!(optimize(parse("~:foo & :bar").unwrap()), @r###"
|
insta::assert_debug_snapshot!(optimize(parse("~:foo & :bar").unwrap()), @r###"
|
||||||
|
@ -2682,6 +2737,7 @@ mod tests {
|
||||||
heads: Symbol(
|
heads: Symbol(
|
||||||
"bar",
|
"bar",
|
||||||
),
|
),
|
||||||
|
generation: 0..4294967295,
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
insta::assert_debug_snapshot!(optimize(parse("foo..").unwrap()), @r###"
|
insta::assert_debug_snapshot!(optimize(parse("foo..").unwrap()), @r###"
|
||||||
|
@ -2690,6 +2746,7 @@ mod tests {
|
||||||
"foo",
|
"foo",
|
||||||
),
|
),
|
||||||
heads: VisibleHeads,
|
heads: VisibleHeads,
|
||||||
|
generation: 0..4294967295,
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
insta::assert_debug_snapshot!(optimize(parse("foo..bar").unwrap()), @r###"
|
insta::assert_debug_snapshot!(optimize(parse("foo..bar").unwrap()), @r###"
|
||||||
|
@ -2700,6 +2757,7 @@ mod tests {
|
||||||
heads: Symbol(
|
heads: Symbol(
|
||||||
"bar",
|
"bar",
|
||||||
),
|
),
|
||||||
|
generation: 0..4294967295,
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue