Skip to content

Commit

Permalink
revsets: allow :: as synonym for :
Browse files Browse the repository at this point in the history
The `--allow-large-revsets` flag we have on `jj rebase` and `jj new`
allows the user to do e.g. `jj rebase --allow-large-revsets -b
main.. -d main` to rebase all commits that are not in main onto
main. The reason we don't allow these revsets to resolve to multiple
commits by default is that we think users might specify multiple
commits by mistake. That's probably not much of a problem with `jj
rebase -b` (maybe we should always allow that to resolve to multiple
commits), but the user might want to know if `jj rebase -d @-`
resolves to multiple commits.

One problem with having a flag to allow multiple commits is that it
needs to be added to every command where we want to allow multiple
commits but default to one. Also, it should probably apply to each
revset argument those commands take. For example, even if the user
meant `-b main..` to resolve to multiple commits, they might not have
meant `-d main` to resolve to multiple commits (which it will in case
of a conflicted branch), so we might want separate
`--allow-large-revsets-in-destination` and
`--allow-large-revsets-in-source`, which gets quite cumbersome. It
seems better to have some syntax in the individual revsets for saying
that multiple commits are allowed.

One proposal I had was to use a `multiple()` revset function which
would have no effect in general but would be used as a marker if used
at the top level (e.g. `jj rebase -d 'multiple(@-)'`). After some
discussion on the PR adding that function (#1911), it seems that the
consensus is to instead use a prefix like `many:` or `all:`. That
avoids the problem with having a function that has no effect unless
it's used at the top level (`jj rebase -d 'multiple(x)|y'` would have
no effect).

Since we already have the `:` operator for DAG ranges, we need to
change it to make room for `many:`/`all:` syntax. This commit starts
that by allowing both `:` and `::`.

I have tried to update the documentation in this commit to either
mention both forms, or just the new and preferred `::` form. However,
it's useless to search for `:` in Rust code, so I'm sure I've missed
many instances. We'll have to address those as we notice them. I'll
let most tests use `:` until we deprecate it or delete it.
  • Loading branch information
martinvonz committed Jul 28, 2023
1 parent 4b635e9 commit 3d70118
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 79 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `jj log` output is now topologically grouped.
[#242](https://github.com/martinvonz/jj/issues/242)

* The `:` revset operator can now be written as `::` instead. We plan to
deprecate the `:` form.

### Fixed bugs

## [0.8.0] - 2023-07-09
Expand Down
2 changes: 1 addition & 1 deletion docs/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ remote
Log all remote branches, which you authored or committed to
`jj log -r 'remote_branches() & (committer([email protected]) | author([email protected]))'`
Log all descendants of the current working copy, which aren't on a remote
`jj log -r ':@ & ~remote_branches()'`
`jj log -r '::@ & ~remote_branches()'`

## Merge conflicts

Expand Down
22 changes: 11 additions & 11 deletions docs/revsets.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ only symbols.
* `~x`: Revisions that are not in `x`.
* `x-`: Parents of `x`.
* `x+`: Children of `x`.
* `:x`: Ancestors of `x`, including the commits in `x` itself.
* `x:`: Descendants of `x`, including the commits in `x` itself.
* `x:y`: Descendants of `x` that are also ancestors of `y`. Equivalent to
`x: & :y`. This is what `git log` calls `--ancestry-path x..y`.
* `::x` or `:x`: Ancestors of `x`, including the commits in `x` itself.
* `x::` or `x:`: Descendants of `x`, including the commits in `x` itself.
* `x::y` or `x:y`: Descendants of `x` that are also ancestors of `y`. Equivalent
to `x:: & ::y`. This is what `git log` calls `--ancestry-path x..y`.
* `x..y`: Ancestors of `y` that are not also ancestors of `x`. Equivalent to
`:y ~ :x`. This is what `git log` calls `x..y` (i.e. the same as we call it).
`::y ~ ::x`. This is what `git log` calls `x..y` (i.e. the same as we call it).
* `..x`: Ancestors of `x`, including the commits in `x` itself. Equivalent to
`:x` and provided for consistency.
`::x` and provided for consistency.
* `x..`: Revisions that are not ancestors of `x`.

You can use parentheses to control evaluation order, such as `(x & y) | z` or
Expand All @@ -78,9 +78,9 @@ revsets (expressions) as arguments.

* `parents(x)`: Same as `x-`.
* `children(x)`: Same as `x+`.
* `ancestors(x)`: Same as `:x`.
* `descendants(x)`: Same as `x:`.
* `connected(x)`: Same as `x:x`. Useful when `x` includes several commits.
* `ancestors(x)`: Same as `::x`.
* `descendants(x)`: Same as `x::`.
* `connected(x)`: Same as `x::x`. Useful when `x` includes several commits.
* `all()`: All visible commits in the repo.
* `none()`: No commits. This function is rarely useful; it is provided for
completeness.
Expand Down Expand Up @@ -169,7 +169,7 @@ jj log -r 'remote_branches(remote=origin)..'
Show all ancestors of the working copy (almost like plain `git log`)

```
jj log -r :@
jj log -r ::@
```

Show the initial commits in the repo (the ones Git calls "root commits"):
Expand All @@ -188,7 +188,7 @@ Show local commits leading up to the working copy, as well as descendants of
those commits:

```
jj log -r '(remote_branches()..@):'
jj log -r '(remote_branches()..@)::'
```

Show commits authored by "martinvonz" and containing the word "reset" in the
Expand Down
2 changes: 1 addition & 1 deletion lib/src/default_index_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2951,7 +2951,7 @@ mod tests {
);

// Merge range with sub-range (1..4 + 2..3 should be 1..4, not 1..3):
// 8,7,6->5:1..4, B5_1->5:2..3
// 8,7,6->5::1..4, B5_1->5::2..3
assert_eq!(
walk_commit_ids(
&[&ids[8], &ids[7], &ids[6], &id_branch5_1].map(Clone::clone),
Expand Down
2 changes: 1 addition & 1 deletion lib/src/default_revset_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ impl<'index> EvaluationContext<'index> {
}
}

/// Calculates `root_set:head_set`.
/// Calculates `root_set::head_set`.
fn collect_dag_range<'a, 'b, S, T>(
&self,
root_set: &S,
Expand Down
16 changes: 10 additions & 6 deletions lib/src/revset.pest
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ parents_op = { "-" }
children_op = { "+" }
compat_parents_op = { "^" }

dag_range_op = { ":" }
dag_range_pre_op = { ":" }
dag_range_post_op = { ":" }
dag_range_op = { "::" }
dag_range_pre_op = { "::" }
dag_range_post_op = { "::" }
// TODO: Drop support for these in 0.12+
legacy_dag_range_op = { ":" }
legacy_dag_range_pre_op = { ":" }
legacy_dag_range_post_op = { ":" }
range_op = { ".." }
range_pre_op = { ".." }
range_post_op = { ".." }
range_ops = _{ dag_range_op | range_op }
range_pre_ops = _{ dag_range_pre_op | range_pre_op }
range_post_ops = _{ dag_range_post_op | range_post_op }
range_ops = _{ dag_range_op | legacy_dag_range_op | range_op }
range_pre_ops = _{ dag_range_pre_op | legacy_dag_range_pre_op | range_pre_op }
range_post_ops = _{ dag_range_post_op | legacy_dag_range_post_op | range_post_op }

negate_op = { "~" }
union_op = { "|" }
Expand Down
Loading

0 comments on commit 3d70118

Please sign in to comment.