// Copyright 2022 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use indoc::indoc;use testutils::TestResult;use testutils::git; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir;use crate::common::to_toml_value; fn git_repo_dir_for_jj_repo(work_dir: &TestWorkDir<'_>) -> std::path::PathBuf { work_dir .root() .join(".jj") .join("repo") .join("store") .join("git")} fn set_up(test_env: &TestEnvironment) { test_env.run_jj_in(".", ["git", "init", "origin"]).success(); let origin_dir = test_env.work_dir("origin"); let origin_git_repo_path = git_repo_dir_for_jj_repo(&origin_dir); origin_dir .run_jj(["describe", "-m=description 1"]) .success(); origin_dir .run_jj(["bookmark", "create", "-r@", "bookmark1"]) .success(); origin_dir .run_jj(["new", "root()", "-m=description 2"]) .success(); origin_dir .run_jj(["bookmark", "create", "-r@", "bookmark2"]) .success(); origin_dir.run_jj(["git", "export"]).success(); test_env .run_jj_in( ".", [ "git", "clone", "--config=remotes.origin.auto-track-bookmarks='*'", origin_git_repo_path.to_str().unwrap(), "local", ], ) .success();} #[test]fn test_git_push_nothing() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Show the setup. `insta` has trouble if this is done inside `set_up()` insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm 9b2e76de (empty) description 1 @origin: qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @origin: zsuskuln 38a20473 (empty) description 2 [EOF] "); // No bookmarks to push yet let output = work_dir.run_jj(["git", "push", "--all"]); insta::assert_snapshot!(output, @" ------- stderr ------- Nothing changed. [EOF] "); // Tracked bookmark is up to date work_dir .run_jj(["bookmark", "track", "bookmark1@origin"]) .success(); let output = work_dir.run_jj(["git", "push", "--tracked"]); insta::assert_snapshot!(output, @" ------- stderr ------- Nothing changed. [EOF] ");} #[test]fn test_git_push_default_remote_selection() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // add a second remote (actually the same) let other_remote_path = test_env .env_root() .join("origin") .join(".jj") .join("repo") .join("store") .join("git"); work_dir .run_jj([ "git", "remote", "add", "other", other_remote_path.to_str().unwrap(), ]) .success(); // select remote based on git.push config let output = work_dir.run_jj(["git", "push", "--config=git.push=other", "-b", "bookmark1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: Refusing to create new remote bookmark bookmark1@other Hint: Run `jj bookmark track bookmark1@other` and try again. [EOF] [exit status: 1] "); // remove origin, should select other (with hint) work_dir .run_jj(["git", "remote", "remove", "origin"]) .success(); let output = work_dir.run_jj(["git", "push", "-b", "bookmark1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Hint: Pushing to the only existing remote: other Changes to push to other: bookmark: bookmark1 [add to 9b2e76de3920] [EOF] ");} #[test]fn test_git_push_current_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); test_env.add_config("remotes.origin.auto-track-bookmarks = '*'"); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); // Update some bookmarks. `bookmark1` is not a current bookmark, but // `bookmark2` and `my-bookmark` are. work_dir .run_jj(["describe", "bookmark1", "-m", "modified bookmark1 commit"]) .success(); work_dir.run_jj(["new", "bookmark2"]).success(); work_dir .run_jj(["bookmark", "set", "bookmark2", "-r@"]) .success(); work_dir .run_jj(["bookmark", "create", "-r@", "my-bookmark"]) .success(); work_dir.run_jj(["describe", "-m", "foo"]).success(); // Check the setup insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm e5ce6d9a (empty) modified bookmark1 commit @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm/1 9b2e76de (hidden) (empty) description 1 bookmark2: yostqsxw 88ca14a7 (empty) foo @origin (behind by 1 commits): zsuskuln 38a20473 (empty) description 2 my-bookmark: yostqsxw 88ca14a7 (empty) foo @origin (not created yet) [EOF] "); // First dry-run. `bookmark1` should not get pushed. let output = work_dir.run_jj(["git", "push", "--dry-run"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move forward from 38a204733702 to 88ca14a7d46f] bookmark: my-bookmark [add to 88ca14a7d46f] Dry-run requested, not pushing. [EOF] "); let output = work_dir.run_jj(["git", "push", "--no-integrate-operation"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: --no-integrate-operation is not respected; use --dry-run [EOF] [exit status: 2] "); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move forward from 38a204733702 to 88ca14a7d46f] bookmark: my-bookmark [add to 88ca14a7d46f] [EOF] "); insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm e5ce6d9a (empty) modified bookmark1 commit @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm/1 9b2e76de (hidden) (empty) description 1 bookmark2: yostqsxw 88ca14a7 (empty) foo @origin: yostqsxw 88ca14a7 (empty) foo my-bookmark: yostqsxw 88ca14a7 (empty) foo @origin: yostqsxw 88ca14a7 (empty) foo [EOF] "); // Try pushing backwards work_dir .run_jj([ "bookmark", "set", "bookmark2", "-rbookmark2-", "--allow-backwards", ]) .success(); // This behavior is a strangeness of our definition of the default push revset. // We could consider changing it. let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); // We can move a bookmark backwards let output = work_dir.run_jj(["git", "push", "-bbookmark2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move backward from 88ca14a7d46f to 38a204733702] [EOF] ");} #[test]fn test_git_push_parent_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); work_dir.run_jj(["edit", "bookmark1"]).success(); work_dir .run_jj(["describe", "-m", "modified bookmark1 commit"]) .success(); work_dir .run_jj(["new", "-m", "non-empty description"]) .success(); work_dir.write_file("file", "file"); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 80560a3e08e2] [EOF] ");} #[test]fn test_git_push_tag_in_default_target() { let test_env = TestEnvironment::default(); test_env .run_jj_in(".", ["git", "init", "--colocate", "origin"]) .success(); let origin_dir = test_env.work_dir("origin"); origin_dir.run_jj(["commit", "-morigin"]).success(); origin_dir.run_jj(["tag", "set", "-r@-", "tag1"]).success(); test_env .run_jj_in(".", ["git", "clone", "--tag=*", "origin", "local"]) .success(); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["commit", "-mlocal"]).success(); work_dir .run_jj(["tag", "set", "--allow-move", "-r@-", "tag1"]) .success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: tag: tag1 [move sideways from 110db8edfa5f to b60842ac7691] [EOF] ");} #[test]fn test_git_push_no_matching_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["new"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] ");} #[test]fn test_git_push_matching_bookmark_unchanged() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["new", "bookmark1"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] ");} /// Test that `jj git push` without arguments pushes a bookmark to the specified/// remote even if it's already up to date on another remote/// (`remote_bookmarks(remote=<remote>)..@` vs. `remote_bookmarks()..@`).#[test]fn test_git_push_other_remote_has_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); // Create another remote (but actually the same) let other_remote_path = test_env .env_root() .join("origin") .join(".jj") .join("repo") .join("store") .join("git"); work_dir .run_jj([ "git", "remote", "add", "other", other_remote_path.to_str().unwrap(), ]) .success(); // Modify bookmark1 and push it to `origin` work_dir.run_jj(["edit", "bookmark1"]).success(); work_dir.run_jj(["describe", "-m=modified"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to a843bfad2abb] [EOF] "); // Since it's already pushed to origin, nothing will happen if push again let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); // The bookmark was moved on the "other" remote as well (since it's actually the // same remote), but `jj` is not aware of that since it thinks this is a // different remote. So, the push should fail. // // But it succeeds! That's because the bookmark is created at the same location // as it is on the remote. This would also work for a descendant. // // TODO: Saner test? work_dir .run_jj(["bookmark", "track", "bookmark1", "--remote=other"]) .success(); let output = work_dir.run_jj(["git", "push", "--remote=other"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to other: bookmark: bookmark1 [add to a843bfad2abb] [EOF] ");} #[test]fn test_git_push_forward_unexpectedly_moved() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Move bookmark1 forward on the remote let origin_dir = test_env.work_dir("origin"); origin_dir .run_jj(["new", "bookmark1", "-m=remote"]) .success(); origin_dir.write_file("remote", "remote"); origin_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); origin_dir.run_jj(["git", "export"]).success(); // Move bookmark1 forward to another commit locally work_dir.run_jj(["new", "bookmark1", "-m=local"]).success(); work_dir.write_file("local", "local"); work_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); // Pushing should fail let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move forward from 9b2e76de3920 to 624f94a35f00] Warning: The following references unexpectedly moved on the remote: refs/heads/bookmark1 (reason: stale info) Hint: Try fetching from the remote, then make the bookmark point to where you want it to be, and push again. Error: Failed to push some bookmarks [EOF] [exit status: 1] "); // The ref name should be colorized let output = work_dir.run_jj(["git", "push", "--color=always"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move forward from 9b2e76de3920 to 624f94a35f00] [1m[38;5;3mWarning: [39mThe following references unexpectedly moved on the remote:[0m [38;5;2mrefs/heads/bookmark1[39m (reason: stale info) [1m[38;5;6mHint: [0m[39mTry fetching from the remote, then make the bookmark point to where you want it to be, and push again.[39m [1m[38;5;1mError: [39mFailed to push some bookmarks[0m [EOF] [exit status: 1] ");} #[test]fn test_git_push_sideways_unexpectedly_moved() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Move bookmark1 forward on the remote let origin_dir = test_env.work_dir("origin"); origin_dir .run_jj(["new", "bookmark1", "-m=remote"]) .success(); origin_dir.write_file("remote", "remote"); origin_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); insta::assert_snapshot!(get_bookmark_output(&origin_dir), @" bookmark1: vruxwmqv 7ce4029e remote @git (behind by 1 commits): qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @git: zsuskuln 38a20473 (empty) description 2 [EOF] "); origin_dir.run_jj(["git", "export"]).success(); // Move bookmark1 sideways to another commit locally work_dir.run_jj(["new", "root()", "-m=local"]).success(); work_dir.write_file("local", "local"); work_dir .run_jj(["bookmark", "set", "bookmark1", "--allow-backwards", "-r@"]) .success(); insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: kmkuslsw 827b8a38 local @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @origin: zsuskuln 38a20473 (empty) description 2 [EOF] "); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 827b8a385853] Warning: The following references unexpectedly moved on the remote: refs/heads/bookmark1 (reason: stale info) Hint: Try fetching from the remote, then make the bookmark point to where you want it to be, and push again. Error: Failed to push some bookmarks [EOF] [exit status: 1] "); // The ref name should be colorized let output = work_dir.run_jj(["git", "push", "--color=always"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 827b8a385853] [1m[38;5;3mWarning: [39mThe following references unexpectedly moved on the remote:[0m [38;5;2mrefs/heads/bookmark1[39m (reason: stale info) [1m[38;5;6mHint: [0m[39mTry fetching from the remote, then make the bookmark point to where you want it to be, and push again.[39m [1m[38;5;1mError: [39mFailed to push some bookmarks[0m [EOF]Lines 1–500 of 2968. Load more
// Copyright 2022 The Jujutsu Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use indoc::indoc; use testutils::TestResult; use testutils::git; use crate::common::CommandOutput; use crate::common::TestEnvironment; use crate::common::TestWorkDir; use crate::common::to_toml_value; fn git_repo_dir_for_jj_repo(work_dir: &TestWorkDir<'_>) -> std::path::PathBuf { work_dir .root() .join(".jj") .join("repo") .join("store") .join("git") } fn set_up(test_env: &TestEnvironment) { test_env.run_jj_in(".", ["git", "init", "origin"]).success(); let origin_dir = test_env.work_dir("origin"); let origin_git_repo_path = git_repo_dir_for_jj_repo(&origin_dir); origin_dir .run_jj(["describe", "-m=description 1"]) .success(); origin_dir .run_jj(["bookmark", "create", "-r@", "bookmark1"]) .success(); origin_dir .run_jj(["new", "root()", "-m=description 2"]) .success(); origin_dir .run_jj(["bookmark", "create", "-r@", "bookmark2"]) .success(); origin_dir.run_jj(["git", "export"]).success(); test_env .run_jj_in( ".", [ "git", "clone", "--config=remotes.origin.auto-track-bookmarks='*'", origin_git_repo_path.to_str().unwrap(), "local", ], ) .success(); } #[test] fn test_git_push_nothing() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Show the setup. `insta` has trouble if this is done inside `set_up()` insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm 9b2e76de (empty) description 1 @origin: qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @origin: zsuskuln 38a20473 (empty) description 2 [EOF] "); // No bookmarks to push yet let output = work_dir.run_jj(["git", "push", "--all"]); insta::assert_snapshot!(output, @" ------- stderr ------- Nothing changed. [EOF] "); // Tracked bookmark is up to date work_dir .run_jj(["bookmark", "track", "bookmark1@origin"]) .success(); let output = work_dir.run_jj(["git", "push", "--tracked"]); insta::assert_snapshot!(output, @" ------- stderr ------- Nothing changed. [EOF] "); } #[test] fn test_git_push_default_remote_selection() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // add a second remote (actually the same) let other_remote_path = test_env .env_root() .join("origin") .join(".jj") .join("repo") .join("store") .join("git"); work_dir .run_jj([ "git", "remote", "add", "other", other_remote_path.to_str().unwrap(), ]) .success(); // select remote based on git.push config let output = work_dir.run_jj(["git", "push", "--config=git.push=other", "-b", "bookmark1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: Refusing to create new remote bookmark bookmark1@other Hint: Run `jj bookmark track bookmark1@other` and try again. [EOF] [exit status: 1] "); // remove origin, should select other (with hint) work_dir .run_jj(["git", "remote", "remove", "origin"]) .success(); let output = work_dir.run_jj(["git", "push", "-b", "bookmark1"]); insta::assert_snapshot!(output, @" ------- stderr ------- Hint: Pushing to the only existing remote: other Changes to push to other: bookmark: bookmark1 [add to 9b2e76de3920] [EOF] "); } #[test] fn test_git_push_current_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); test_env.add_config("remotes.origin.auto-track-bookmarks = '*'"); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); // Update some bookmarks. `bookmark1` is not a current bookmark, but // `bookmark2` and `my-bookmark` are. work_dir .run_jj(["describe", "bookmark1", "-m", "modified bookmark1 commit"]) .success(); work_dir.run_jj(["new", "bookmark2"]).success(); work_dir .run_jj(["bookmark", "set", "bookmark2", "-r@"]) .success(); work_dir .run_jj(["bookmark", "create", "-r@", "my-bookmark"]) .success(); work_dir.run_jj(["describe", "-m", "foo"]).success(); // Check the setup insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm e5ce6d9a (empty) modified bookmark1 commit @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm/1 9b2e76de (hidden) (empty) description 1 bookmark2: yostqsxw 88ca14a7 (empty) foo @origin (behind by 1 commits): zsuskuln 38a20473 (empty) description 2 my-bookmark: yostqsxw 88ca14a7 (empty) foo @origin (not created yet) [EOF] "); // First dry-run. `bookmark1` should not get pushed. let output = work_dir.run_jj(["git", "push", "--dry-run"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move forward from 38a204733702 to 88ca14a7d46f] bookmark: my-bookmark [add to 88ca14a7d46f] Dry-run requested, not pushing. [EOF] "); let output = work_dir.run_jj(["git", "push", "--no-integrate-operation"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: --no-integrate-operation is not respected; use --dry-run [EOF] [exit status: 2] "); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move forward from 38a204733702 to 88ca14a7d46f] bookmark: my-bookmark [add to 88ca14a7d46f] [EOF] "); insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: qpvuntsm e5ce6d9a (empty) modified bookmark1 commit @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm/1 9b2e76de (hidden) (empty) description 1 bookmark2: yostqsxw 88ca14a7 (empty) foo @origin: yostqsxw 88ca14a7 (empty) foo my-bookmark: yostqsxw 88ca14a7 (empty) foo @origin: yostqsxw 88ca14a7 (empty) foo [EOF] "); // Try pushing backwards work_dir .run_jj([ "bookmark", "set", "bookmark2", "-rbookmark2-", "--allow-backwards", ]) .success(); // This behavior is a strangeness of our definition of the default push revset. // We could consider changing it. let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); // We can move a bookmark backwards let output = work_dir.run_jj(["git", "push", "-bbookmark2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark2 [move backward from 88ca14a7d46f to 38a204733702] [EOF] "); } #[test] fn test_git_push_parent_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); work_dir.run_jj(["edit", "bookmark1"]).success(); work_dir .run_jj(["describe", "-m", "modified bookmark1 commit"]) .success(); work_dir .run_jj(["new", "-m", "non-empty description"]) .success(); work_dir.write_file("file", "file"); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 80560a3e08e2] [EOF] "); } #[test] fn test_git_push_tag_in_default_target() { let test_env = TestEnvironment::default(); test_env .run_jj_in(".", ["git", "init", "--colocate", "origin"]) .success(); let origin_dir = test_env.work_dir("origin"); origin_dir.run_jj(["commit", "-morigin"]).success(); origin_dir.run_jj(["tag", "set", "-r@-", "tag1"]).success(); test_env .run_jj_in(".", ["git", "clone", "--tag=*", "origin", "local"]) .success(); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["commit", "-mlocal"]).success(); work_dir .run_jj(["tag", "set", "--allow-move", "-r@-", "tag1"]) .success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: tag: tag1 [move sideways from 110db8edfa5f to b60842ac7691] [EOF] "); } #[test] fn test_git_push_no_matching_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["new"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); } #[test] fn test_git_push_matching_bookmark_unchanged() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); work_dir.run_jj(["new", "bookmark1"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); } /// Test that `jj git push` without arguments pushes a bookmark to the specified /// remote even if it's already up to date on another remote /// (`remote_bookmarks(remote=<remote>)..@` vs. `remote_bookmarks()..@`). #[test] fn test_git_push_other_remote_has_bookmark() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); // Create another remote (but actually the same) let other_remote_path = test_env .env_root() .join("origin") .join(".jj") .join("repo") .join("store") .join("git"); work_dir .run_jj([ "git", "remote", "add", "other", other_remote_path.to_str().unwrap(), ]) .success(); // Modify bookmark1 and push it to `origin` work_dir.run_jj(["edit", "bookmark1"]).success(); work_dir.run_jj(["describe", "-m=modified"]).success(); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to a843bfad2abb] [EOF] "); // Since it's already pushed to origin, nothing will happen if push again let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No bookmarks/tags found in the default push revset: remote_bookmarks(remote=origin)..@ Nothing changed. [EOF] "); // The bookmark was moved on the "other" remote as well (since it's actually the // same remote), but `jj` is not aware of that since it thinks this is a // different remote. So, the push should fail. // // But it succeeds! That's because the bookmark is created at the same location // as it is on the remote. This would also work for a descendant. // // TODO: Saner test? work_dir .run_jj(["bookmark", "track", "bookmark1", "--remote=other"]) .success(); let output = work_dir.run_jj(["git", "push", "--remote=other"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to other: bookmark: bookmark1 [add to a843bfad2abb] [EOF] "); } #[test] fn test_git_push_forward_unexpectedly_moved() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Move bookmark1 forward on the remote let origin_dir = test_env.work_dir("origin"); origin_dir .run_jj(["new", "bookmark1", "-m=remote"]) .success(); origin_dir.write_file("remote", "remote"); origin_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); origin_dir.run_jj(["git", "export"]).success(); // Move bookmark1 forward to another commit locally work_dir.run_jj(["new", "bookmark1", "-m=local"]).success(); work_dir.write_file("local", "local"); work_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); // Pushing should fail let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move forward from 9b2e76de3920 to 624f94a35f00] Warning: The following references unexpectedly moved on the remote: refs/heads/bookmark1 (reason: stale info) Hint: Try fetching from the remote, then make the bookmark point to where you want it to be, and push again. Error: Failed to push some bookmarks [EOF] [exit status: 1] "); // The ref name should be colorized let output = work_dir.run_jj(["git", "push", "--color=always"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move forward from 9b2e76de3920 to 624f94a35f00] [1m[38;5;3mWarning: [39mThe following references unexpectedly moved on the remote:[0m [38;5;2mrefs/heads/bookmark1[39m (reason: stale info) [1m[38;5;6mHint: [0m[39mTry fetching from the remote, then make the bookmark point to where you want it to be, and push again.[39m [1m[38;5;1mError: [39mFailed to push some bookmarks[0m [EOF] [exit status: 1] "); } #[test] fn test_git_push_sideways_unexpectedly_moved() { let test_env = TestEnvironment::default(); set_up(&test_env); let work_dir = test_env.work_dir("local"); // Move bookmark1 forward on the remote let origin_dir = test_env.work_dir("origin"); origin_dir .run_jj(["new", "bookmark1", "-m=remote"]) .success(); origin_dir.write_file("remote", "remote"); origin_dir .run_jj(["bookmark", "set", "bookmark1", "-r@"]) .success(); insta::assert_snapshot!(get_bookmark_output(&origin_dir), @" bookmark1: vruxwmqv 7ce4029e remote @git (behind by 1 commits): qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @git: zsuskuln 38a20473 (empty) description 2 [EOF] "); origin_dir.run_jj(["git", "export"]).success(); // Move bookmark1 sideways to another commit locally work_dir.run_jj(["new", "root()", "-m=local"]).success(); work_dir.write_file("local", "local"); work_dir .run_jj(["bookmark", "set", "bookmark1", "--allow-backwards", "-r@"]) .success(); insta::assert_snapshot!(get_bookmark_output(&work_dir), @" bookmark1: kmkuslsw 827b8a38 local @origin (ahead by 1 commits, behind by 1 commits): qpvuntsm 9b2e76de (empty) description 1 bookmark2: zsuskuln 38a20473 (empty) description 2 @origin: zsuskuln 38a20473 (empty) description 2 [EOF] "); let output = work_dir.run_jj(["git", "push"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 827b8a385853] Warning: The following references unexpectedly moved on the remote: refs/heads/bookmark1 (reason: stale info) Hint: Try fetching from the remote, then make the bookmark point to where you want it to be, and push again. Error: Failed to push some bookmarks [EOF] [exit status: 1] "); // The ref name should be colorized let output = work_dir.run_jj(["git", "push", "--color=always"]); insta::assert_snapshot!(output, @" ------- stderr ------- Changes to push to origin: bookmark: bookmark1 [move sideways from 9b2e76de3920 to 827b8a385853] [1m[38;5;3mWarning: [39mThe following references unexpectedly moved on the remote:[0m [38;5;2mrefs/heads/bookmark1[39m (reason: stale info) [1m[38;5;6mHint: [0m[39mTry fetching from the remote, then make the bookmark point to where you want it to be, and push again.[39m [1m[38;5;1mError: [39mFailed to push some bookmarks[0m [EOF]