Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR: Add builtin_immutable_heads() #4162

Closed
jennings opened this issue Jul 25, 2024 · 8 comments · Fixed by #4195
Closed

FR: Add builtin_immutable_heads() #4162

jennings opened this issue Jul 25, 2024 · 8 comments · Fixed by #4195
Assignees
Labels
enhancement New feature or request

Comments

@jennings
Copy link
Contributor

Is your feature request related to a problem? Please describe.

When redefining immutable_heads(), there is no way to include the default set. Since the default set occasionally changes, the user has to change their config to get the new settings.

Describe the solution you'd like

Define the default set in builtin_immutable_heads() and redefine immutable_heads() like so:

[revset-aliases]
'builtin_immutable_heads()' = 'trunk() | tags() | untracked_remote_branches()'
'immutable_heads()' = 'builtin_immutable_heads()'

If a user overrides immutable_heads() and includes builtin_immutable_heads(), updates to jj's default will automatically be used.

If the user doesn't want to include the default set, they simply omit builtin_immutable_heads(). This means this change wouldn't adversely affect anyone until they opt-in by adding builtin_immutable_heads() to their config.

Describe alternatives you've considered

If we wanted the user to opt out of the default set rather than opting in, the definition could be like so:

[revset-aliases]
'immutable_heads()' = 'none()'

# This becomes the revset function that jj uses
'real_immutable_heads()' = 'immutable_heads() | trunk() | tags() | untracked_remote_branches()'

The user could still opt out by defining real_immutable_heads() instead.

However, I think this alternative is too opinionated, not backwards compatible, and harder to explain:

If you want to include the default set of immutable heads, define immutable_heads(). If you want to completely replace the set, use real_immutable_heads().

Versus:

Define immutable_heads() as desired. The default revset can be included as builtin_immutable_heads().

Additional context

This was discussed in another pull request with @yuja, @scott2000, and @ilyagr.

@PhilipMetzger PhilipMetzger added the enhancement New feature or request label Jul 26, 2024
@essiene
Copy link
Contributor

essiene commented Aug 1, 2024

I'm taking a stab at this in #4195 and I have a few questions:

  1. Is the right thing to do here to define builtin_immutable_heads() in code? I'm guessing it's the right thing since we don't want users to be able to overwrite it, on account of being "built-in" an all.

  2. If we define it in code, what version of "trunk" should we use? trunk() is currently defined as an alias, so users can redefine it. However, immutable_heads is currently defined as trunk()|tags()|untracked_remote_branches().

    • If we use trunk() the alias, which can be redefined, then builtin_immutable_heads() can be indirectly redefined by redefining trunk.
    • If that's not good enough, then we need to defined trunk() as a built in. But that would mean taking it away from users. So should I define a builtin_trunk() as well?

Thoughts?

@martinvonz
Copy link
Member

  • If we use trunk() the alias, which can be redefined, then builtin_immutable_heads() can be indirectly redefined by redefining trunk.

That seems fine to me. I think the trunk() alias is typically overridden without keeping any part of the original (builtin) trunk() alias, so I don't think we need to split that up into a separate builtin_trunk() function. Makes sense?

@essiene
Copy link
Contributor

essiene commented Aug 1, 2024

  • If we use trunk() the alias, which can be redefined, then builtin_immutable_heads() can be indirectly redefined by redefining trunk.

That seems fine to me. I think the trunk() alias is typically overridden without keeping any part of the original (builtin) trunk() alias, so I don't think we need to split that up into a separate builtin_trunk() function. Makes sense?

Yes. This makes sense. Let me see how I can make that work.

Thanks

essiene added a commit that referenced this issue Aug 13, 2024
* Add `builtin_immutable_heads()` in the `revsets.toml`.
* Redefine `immutable_heads()` in terms of `builtin_immutable_heads()`
* Warn if user redefines `builtin_immutable_heads()`, `mutable()` or
  `immutable()`.
* Update module constant in revset_util.rs from BUILTIN_IMMUTABLE_HEADS
  to USER_IMMUTABLE_HEADS to avoid confusion since it points at
  `immutable_heads()` **and** we now have a revset-alias
  literally named `builtin_immutable_heads()`.
* Add unittest
* Update CHANGELOG
* Update documentation.

Fixes: #4162
essiene added a commit that referenced this issue Aug 13, 2024
* Add `builtin_immutable_heads()` in the `revsets.toml`.
* Redefine `immutable_heads()` in terms of `builtin_immutable_heads()`
* Warn if user redefines `builtin_immutable_heads()`, `mutable()` or
  `immutable()`.
* Update module constant in revset_util.rs from BUILTIN_IMMUTABLE_HEADS
  to USER_IMMUTABLE_HEADS to avoid confusion since it points at
  `immutable_heads()` **and** we now have a revset-alias
  literally named `builtin_immutable_heads()`.
* Add unittest
* Update CHANGELOG
* Update documentation.

Fixes: #4162
essiene added a commit that referenced this issue Aug 13, 2024
* Add `builtin_immutable_heads()` in the `revsets.toml`.
* Redefine `immutable_heads()` in terms of `builtin_immutable_heads()`
* Warn if user redefines `builtin_immutable_heads()`, `mutable()` or
  `immutable()`.
* Update module constant in revset_util.rs from BUILTIN_IMMUTABLE_HEADS
  to USER_IMMUTABLE_HEADS to avoid confusion since it points at
  `immutable_heads()` **and** we now have a revset-alias
  literally named `builtin_immutable_heads()`.
* Add unittest
* Update CHANGELOG
* Update documentation.

Fixes: #4162
@essiene essiene self-assigned this Aug 13, 2024
essiene added a commit that referenced this issue Aug 14, 2024
* Add `builtin_immutable_heads()` in the `revsets.toml`.
* Redefine `immutable_heads()` in terms of `builtin_immutable_heads()`
* Warn if user redefines `builtin_immutable_heads()`, `mutable()` or
  `immutable()`.
* Update module constant in revset_util.rs from BUILTIN_IMMUTABLE_HEADS
  to USER_IMMUTABLE_HEADS to avoid confusion since it points at
  `immutable_heads()` **and** we now have a revset-alias
  literally named `builtin_immutable_heads()`.
* Add unittest
* Update CHANGELOG
* Update documentation.

Fixes: #4162
essiene added a commit that referenced this issue Aug 14, 2024
* Add `builtin_immutable_heads()` in the `revsets.toml`.
* Redefine `immutable_heads()` in terms of `builtin_immutable_heads()`
* Warn if user redefines `builtin_immutable_heads()`, `mutable()` or
  `immutable()`.
* Update module constant in revset_util.rs from BUILTIN_IMMUTABLE_HEADS
  to USER_IMMUTABLE_HEADS to avoid confusion since it points at
  `immutable_heads()` **and** we now have a revset-alias
  literally named `builtin_immutable_heads()`.
* Add unittest
* Update CHANGELOG
* Update documentation.

Fixes: #4162
@ilyagr
Copy link
Contributor

ilyagr commented Aug 15, 2024

This is slightly outside the scope of this FR, but I wonder whether we also want want builtin_revsets_log. Somebody on Discord seems to want to show some commits on the main branch in their default revset, and I think being able to set that up in terms of builtin_revsets_log should be good.

@yuja
Copy link
Contributor

yuja commented Aug 15, 2024

but I wonder whether we also want want builtin_revsets_log.

Possibly? but I suspect user log revset would often subtract revisions from the default.

@ErichDonGubler
Copy link

but I wonder whether we also want want builtin_revsets_log.

Possibly? but I suspect user log revset would often subtract revisions from the default.

I'm not sure that this is a valid argument against builtin_revsets_log if valid use cases exist and we want to support them. You're saying you think it's unlikely enough that we shouldn't?

@scott2000
Copy link
Contributor

One other option might be to simplify the log revset so that it's easier to remember/understand. When I was first trying to configure the log, the ancestors(immutable_heads().., 2) part was confusing to me, so I'm wondering if we could simplify it like this:

[revsets]
log = "@ | trunk() | context(mutable())"

[revset-aliases]
"context(x)" = "ancestors(x, 2)"

I think this is easier to remember, since it reads more like a sentence ("I want to see @, trunk, and also all mutable commits with context").

@yuja
Copy link
Contributor

yuja commented Aug 15, 2024

I'm not sure that this is a valid argument against builtin_revsets_log if valid use cases exist and we want to support them.

If many users can't leverage it, builtin_* indirection would just add complexity.

I think context(x) is good idea if we can find a better name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants