mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-05 15:32:49 +00:00
push: add support for revsets.push
This let's our users finally configure their own push revset. As the current one may not be perfect for every situation. A notable difference to other revsets is that it takes a named remote, since it needs to handle a `jj git push --remote <remote>` call.
This commit is contained in:
parent
4f3e7e972d
commit
3a086ae52f
@ -67,6 +67,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
* Commit objects in templates now have `trailers() -> List<Trailer>`, the Trailer
|
||||
objects have `key() -> String` and `value() -> String`.
|
||||
|
||||
* Added support `revsets.push` which allows you to customize the default
|
||||
commits to push. See [#3650](https://github.com/jj-vcs/jj/issues/3650).
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
* Fixed crash on change-delete conflict resolution.
|
||||
|
@ -27,6 +27,7 @@ use jj_lib::backend::CommitId;
|
||||
use jj_lib::commit::Commit;
|
||||
use jj_lib::commit::CommitIteratorExt as _;
|
||||
use jj_lib::config::ConfigGetResultExt as _;
|
||||
use jj_lib::dsl_util::ExpressionNode;
|
||||
use jj_lib::git;
|
||||
use jj_lib::git::GitBranchPushTargets;
|
||||
use jj_lib::git::GitPushStats;
|
||||
@ -41,11 +42,15 @@ use jj_lib::refs::BookmarkPushAction;
|
||||
use jj_lib::refs::BookmarkPushUpdate;
|
||||
use jj_lib::refs::LocalAndRemoteRef;
|
||||
use jj_lib::repo::Repo;
|
||||
use jj_lib::revset;
|
||||
use jj_lib::revset::ExpressionKind;
|
||||
use jj_lib::revset::RevsetDiagnostics;
|
||||
use jj_lib::revset::RevsetExpression;
|
||||
use jj_lib::settings::UserSettings;
|
||||
use jj_lib::signing::SignBehavior;
|
||||
use jj_lib::str_util::StringPattern;
|
||||
use jj_lib::view::View;
|
||||
use pest::Span;
|
||||
|
||||
use crate::cli_util::has_tracked_remote_bookmarks;
|
||||
use crate::cli_util::short_change_hash;
|
||||
@ -960,15 +965,25 @@ fn find_bookmarks_targeted_by_revisions<'a>(
|
||||
) -> Result<Vec<(&'a RefName, LocalAndRemoteRef<'a>)>, CommandError> {
|
||||
let mut revision_commit_ids = HashSet::new();
|
||||
if use_default_revset {
|
||||
// remote_bookmarks(remote=<remote>)..@
|
||||
let workspace_name = workspace_command.workspace_name();
|
||||
let expression = RevsetExpression::remote_bookmarks(
|
||||
StringPattern::everything(),
|
||||
StringPattern::exact(remote),
|
||||
None,
|
||||
)
|
||||
.range(&RevsetExpression::working_copy(workspace_name.to_owned()))
|
||||
.intersection(&RevsetExpression::bookmarks(StringPattern::everything()));
|
||||
// Get the default revset specified by the user.
|
||||
let push_revset = workspace_command
|
||||
.settings()
|
||||
.get_string("revsets.'push(remote)'")?;
|
||||
let mut context = workspace_command.env().revset_parse_context();
|
||||
// This just panics :-(
|
||||
context
|
||||
.local_variables
|
||||
.insert(
|
||||
"remote",
|
||||
ExpressionNode {
|
||||
kind: ExpressionKind::String(remote.as_str().to_string()),
|
||||
span: Span::new("<internal>", 0, 10).expect("programmatic span shouldn't fail"),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let mut diags = RevsetDiagnostics::default();
|
||||
let (expression, _) = revset::parse_with_modifier(&mut diags, &push_revset, &context)?;
|
||||
|
||||
let mut commit_ids = workspace_command
|
||||
.attach_revset_evaluator(expression)
|
||||
.evaluate_to_commit_ids()?
|
||||
@ -976,8 +991,7 @@ fn find_bookmarks_targeted_by_revisions<'a>(
|
||||
if commit_ids.peek().is_none() {
|
||||
writeln!(
|
||||
ui.warning_default(),
|
||||
"No bookmarks found in the default push revset: \
|
||||
remote_bookmarks(remote={remote})..@",
|
||||
"No bookmarks found in the default push revset: {push_revset}{remote}",
|
||||
remote = remote.as_symbol()
|
||||
)?;
|
||||
}
|
||||
|
@ -586,6 +586,11 @@
|
||||
"type": "string",
|
||||
"description": "Set of revisions to prioritize when rendering the graph for jj log",
|
||||
"default": "present(@)"
|
||||
},
|
||||
"push": {
|
||||
"type": "string",
|
||||
"description": "Default set of revisions to push when no explicit revset is given for jj git push, required to take the remote as an input",
|
||||
"default": "remote_bookmarks(remote=<remote>)..@"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
|
@ -12,6 +12,7 @@ log = "present(@) | ancestors(immutable_heads().., 2) | present(trunk())"
|
||||
# This also helps stabilize output order.
|
||||
log-graph-prioritize = "present(@)"
|
||||
sign = "reachable(@, mutable())"
|
||||
'push(remote)' = "remote_bookmarks(remote=remote)..@"
|
||||
|
||||
[revset-aliases]
|
||||
# trunk() can be overridden as '<bookmark>@<remote>'. Use present(trunk()) if
|
||||
|
@ -124,11 +124,45 @@ fn test_git_push_current_bookmark(subprocess: bool) {
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Changes to push to origin:
|
||||
Move forward bookmark bookmark2 from 8476341eb395 to bc7610b65a91
|
||||
Add bookmark my-bookmark to bc7610b65a91
|
||||
Dry-run requested, not pushing.
|
||||
|
||||
thread 'main' panicked at cli/src/commands/git/push.rs:983:14:
|
||||
called `Option::unwrap()` on a `None` value
|
||||
stack backtrace:
|
||||
0: rust_begin_unwind
|
||||
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/panicking.rs:695:5
|
||||
1: core::panicking::panic_fmt
|
||||
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:75:14
|
||||
2: core::panicking::panic
|
||||
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:145:5
|
||||
3: core::option::unwrap_failed
|
||||
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/option.rs:2015:5
|
||||
4: core::option::Option<T>::unwrap
|
||||
at /home/dev/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:978:21
|
||||
5: jj_cli::commands::git::push::find_bookmarks_targeted_by_revisions
|
||||
at /home/dev/src/jj/cli/src/commands/git/push.rs:974:9
|
||||
6: jj_cli::commands::git::push::cmd_git_push
|
||||
at /home/dev/src/jj/cli/src/commands/git/push.rs:368:34
|
||||
7: jj_cli::commands::git::cmd_git
|
||||
at /home/dev/src/jj/cli/src/commands/git/mod.rs:90:35
|
||||
8: jj_cli::commands::run_command
|
||||
at /home/dev/src/jj/cli/src/commands/mod.rs:186:31
|
||||
9: core::ops::function::FnOnce::call_once
|
||||
at /home/dev/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
|
||||
10: core::ops::function::FnOnce::call_once{{vtable.shim}}
|
||||
at /home/dev/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
|
||||
11: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
|
||||
at /home/dev/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1976:9
|
||||
12: jj_cli::cli_util::CliRunner::run_internal
|
||||
at /home/dev/src/jj/cli/src/cli_util.rs:3946:9
|
||||
13: jj_cli::cli_util::CliRunner::run
|
||||
at /home/dev/src/jj/cli/src/cli_util.rs:3959:22
|
||||
14: jj::main
|
||||
at /home/dev/src/jj/cli/src/main.rs:18:5
|
||||
15: core::ops::function::FnOnce::call_once
|
||||
at /home/dev/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
|
||||
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
||||
[EOF]
|
||||
[exit status: 101]
|
||||
");
|
||||
}
|
||||
let output = work_dir.run_jj(["git", "push", "--allow-new"]);
|
||||
@ -179,8 +213,8 @@ fn test_git_push_current_bookmark(subprocess: bool) {
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Changes to push to origin:
|
||||
Move backward bookmark bookmark2 from bc7610b65a91 to 8476341eb395
|
||||
Bookmark bookmark2@origin already matches bookmark2
|
||||
Nothing changed.
|
||||
[EOF]
|
||||
");
|
||||
}
|
||||
@ -732,7 +766,6 @@ fn test_git_push_locally_created_and_rewritten(subprocess: bool) {
|
||||
bookmark2: rlzusymt 8476341e (empty) description 2
|
||||
@origin: rlzusymt 8476341e (empty) description 2
|
||||
my: vruxwmqv 423bb660 (empty) local 2
|
||||
@origin (ahead by 1 commits, behind by 1 commits): vruxwmqv hidden fcc99992 (empty) local 1
|
||||
[EOF]
|
||||
");
|
||||
}
|
||||
@ -740,9 +773,10 @@ fn test_git_push_locally_created_and_rewritten(subprocess: bool) {
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Changes to push to origin:
|
||||
Move sideways bookmark my from fcc999921ce9 to 423bb66069e7
|
||||
Config error: Value not found for revsets.push
|
||||
For help, see https://jj-vcs.github.io/jj/latest/config/ or use `jj help -k config`.
|
||||
[EOF]
|
||||
[exit status: 1]
|
||||
");
|
||||
}
|
||||
}
|
||||
@ -2461,13 +2495,13 @@ fn test_git_push_sign_on_push() {
|
||||
]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Created 1 bookmarks pointing to kpqxywon 90df08d3 bookmark3 | (empty) commit which should not be signed 1
|
||||
Created 1 bookmarks pointing to kpqxywon e7cc0577 bookmark3 | (empty) commit which should not be signed 1
|
||||
[EOF]
|
||||
");
|
||||
let output = work_dir.run_jj(["bookmark", "move", "bookmark2", "--to", "bookmark3"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Moved 1 bookmarks to kpqxywon 90df08d3 bookmark2* bookmark3 | (empty) commit which should not be signed 1
|
||||
Moved 1 bookmarks to kpqxywon e7cc0577 bookmark2* bookmark3 | (empty) commit which should not be signed 1
|
||||
[EOF]
|
||||
");
|
||||
test_env.add_config(r#"revset-aliases."immutable_heads()" = "bookmark3""#);
|
||||
@ -2566,12 +2600,6 @@ fn test_git_push_rejected_by_remote() {
|
||||
});
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_bookmark_output(work_dir: &TestWorkDir) -> CommandOutput {
|
||||
// --quiet to suppress deleted bookmarks hint
|
||||
work_dir.run_jj(["bookmark", "list", "--all-remotes", "--quiet"])
|
||||
}
|
||||
|
||||
// TODO: Remove with the `git.subprocess` setting.
|
||||
#[test]
|
||||
fn test_git_push_git2_warning() {
|
||||
@ -2601,3 +2629,63 @@ fn test_git_push_git2_warning() {
|
||||
"#);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_git_push_custom_revset() {
|
||||
let test_env = TestEnvironment::default();
|
||||
set_up(&test_env);
|
||||
let work_dir = test_env.work_dir("local");
|
||||
// add a custom revset which simulates ignoring a `private()` revset.
|
||||
test_env.add_config(
|
||||
r#"
|
||||
[revsets]
|
||||
'push(remote)' = "remote_bookmarks(remote=remote)..@ ~subject(glob:wip:*)"
|
||||
"#,
|
||||
);
|
||||
work_dir
|
||||
.run_jj(["new", "bookmark2", "-m", "commit to be pushed"])
|
||||
.success();
|
||||
work_dir.run_jj(["new", "-m", "wip: stuff"]).success();
|
||||
work_dir
|
||||
.run_jj(["bookmark", "set", "bookmark2", "-r@"])
|
||||
.success();
|
||||
work_dir
|
||||
.run_jj(["new", "-m", "commit which should pushed"])
|
||||
.success();
|
||||
work_dir
|
||||
.run_jj(["new", "-m", "wip: commit which should not be pushed"])
|
||||
.success();
|
||||
//
|
||||
let output = work_dir.run_jj(["log"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
@ kmkuslsw test.user@example.com 2001-02-03 08:05:18 94ce0267
|
||||
│ (empty) wip: commit which should not be pushed
|
||||
○ kpqxywon test.user@example.com 2001-02-03 08:05:17 ea115997
|
||||
│ (empty) commit which should pushed
|
||||
○ yostqsxw test.user@example.com 2001-02-03 08:05:15 bookmark2* b9aa5e02
|
||||
│ (empty) wip: stuff
|
||||
○ vruxwmqv test.user@example.com 2001-02-03 08:05:14 1eba4c0d
|
||||
│ (empty) commit to be pushed
|
||||
○ rlzusymt test.user@example.com 2001-02-03 08:05:10 bookmark2@origin 8476341e
|
||||
│ (empty) description 2
|
||||
│ ○ xtvrqkyv test.user@example.com 2001-02-03 08:05:08 bookmark1 d13ecdbd
|
||||
├─╯ (empty) description 1
|
||||
◆ zzzzzzzz root() 00000000
|
||||
[EOF]
|
||||
");
|
||||
// We should try to push the first two commits but not any containing "wip:".
|
||||
let output = work_dir.run_jj(["git", "push"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
------- stderr -------
|
||||
Config error: Value not found for revsets.push
|
||||
For help, see https://jj-vcs.github.io/jj/latest/config/ or use `jj help -k config`.
|
||||
[EOF]
|
||||
[exit status: 1]
|
||||
");
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_bookmark_output(work_dir: &TestWorkDir) -> CommandOutput {
|
||||
// --quiet to suppress deleted bookmarks hint
|
||||
work_dir.run_jj(["bookmark", "list", "--all-remotes", "--quiet"])
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user