2024-05-15 22:19:55 +00:00
|
|
|
// Copyright 2024 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.
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
use jj_lib::file_util::try_symlink;
|
|
|
|
|
|
|
|
use crate::common::TestEnvironment;
|
|
|
|
|
|
|
|
/// Set up a repo where the `jj fix` command uses the fake editor with the given
|
|
|
|
/// flags.
|
|
|
|
fn init_with_fake_formatter(args: &[&str]) -> (TestEnvironment, PathBuf) {
|
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
let formatter_path = assert_cmd::cargo::cargo_bin("fake-formatter");
|
|
|
|
assert!(formatter_path.is_file());
|
|
|
|
let escaped_formatter_path = formatter_path.to_str().unwrap().replace('\\', r"\\");
|
|
|
|
test_env.add_config(&format!(
|
|
|
|
r#"fix.tool-command = ["{}"]"#,
|
|
|
|
[escaped_formatter_path.as_str()]
|
|
|
|
.iter()
|
|
|
|
.chain(args)
|
|
|
|
.join(r#"", ""#)
|
|
|
|
));
|
|
|
|
(test_env, repo_path)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_no_config() {
|
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Config error: Invalid `fix.tool-command`
|
|
|
|
Caused by: configuration property "fix.tool-command" not found
|
|
|
|
For help, see https://github.com/martinvonz/jj/blob/main/docs/config.md.
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_empty_commit() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_leaf_commit() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "unaffected").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "affected").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: rlvkpnrz 85ce8924 (no description set)
|
|
|
|
Parent commit : qpvuntsm b2ca2bc5 (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@-"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"unaffected");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"AFFECTED");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_parent_commit() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
// Using one file name for all commits adds coverage of some possible bugs.
|
|
|
|
std::fs::write(repo_path.join("file"), "parent").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "parent"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "child1").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child1"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "parent"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "child2").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child2"]);
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "parent"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 3 commits of 3 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: mzvwutvl d30c8ae2 child2 | (no description set)
|
|
|
|
Parent commit : qpvuntsm 70a4dae2 parent | (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "parent"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"PARENT");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child1"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHILD1");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child2"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHILD2");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_sibling_commit() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "parent").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "parent"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "child1").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child1"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "parent"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "child2").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "child2"]);
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "child1"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "parent"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"parent");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child1"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHILD1");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child2"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"child2");
|
|
|
|
}
|
|
|
|
|
2024-06-07 02:42:50 +00:00
|
|
|
#[test]
|
|
|
|
fn test_default_revset() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
std::fs::write(repo_path.join("file"), "trunk1").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "trunk1"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "trunk2").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "trunk2"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "trunk1"]);
|
2024-06-07 02:42:50 +00:00
|
|
|
std::fs::write(repo_path.join("file"), "foo").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "trunk1"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "bar1").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar1"]);
|
2024-06-07 02:42:50 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
std::fs::write(repo_path.join("file"), "bar2").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar2"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "bar3").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar3"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["edit", "bar2"]);
|
|
|
|
|
|
|
|
// With no args and no revset configuration, we fix `reachable(@, mutable())`,
|
|
|
|
// which includes bar{1,2,3} and excludes trunk{1,2} (which is immutable) and
|
|
|
|
// foo (which is mutable but not reachable).
|
|
|
|
test_env.add_config(r#"revset-aliases."immutable_heads()" = "trunk2""#);
|
2024-06-07 02:42:50 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2024-06-07 03:10:21 +00:00
|
|
|
Fixed 3 commits of 3 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: yostqsxw dabc47b2 bar2 | (no description set)
|
|
|
|
Parent commit : yqosqzyt 984b5924 bar1 | (no description set)
|
2024-06-07 02:42:50 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "trunk1"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
insta::assert_snapshot!(content, @"trunk1");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "trunk2"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
insta::assert_snapshot!(content, @"trunk2");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "foo"]);
|
2024-06-07 02:42:50 +00:00
|
|
|
insta::assert_snapshot!(content, @"foo");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "bar1"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR1");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "bar2"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR2");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "bar3"]);
|
2024-06-07 03:10:21 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR3");
|
2024-06-07 02:42:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_custom_default_revset() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
|
|
|
|
std::fs::write(repo_path.join("file"), "foo").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "bar").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar"]);
|
|
|
|
|
2024-06-07 03:10:21 +00:00
|
|
|
// Check out a different commit so that the schema default `reachable(@,
|
|
|
|
// mutable())` would behave differently from our customized default.
|
2024-06-07 02:42:50 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "-r", "foo"]);
|
|
|
|
test_env.add_config(r#"revsets.fix = "bar""#);
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "foo"]);
|
2024-06-07 02:42:50 +00:00
|
|
|
insta::assert_snapshot!(content, @"foo");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "bar"]);
|
2024-06-07 02:42:50 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR");
|
|
|
|
}
|
|
|
|
|
2024-05-15 22:19:55 +00:00
|
|
|
#[test]
|
|
|
|
fn test_fix_immutable_commit() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "immutable").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "immutable"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "mutable").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "mutable"]);
|
|
|
|
test_env.add_config(r#"revset-aliases."immutable_heads()" = "immutable""#);
|
|
|
|
|
|
|
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["fix", "-s", "immutable"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2024-06-23 22:20:33 +00:00
|
|
|
Error: Commit e4b41a3ce243 is immutable
|
2024-05-15 22:19:55 +00:00
|
|
|
Hint: Pass `--ignore-immutable` or configure the set of immutable commits via `revset-aliases.immutable_heads()`.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "immutable"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"immutable");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "mutable"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"mutable");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_empty_file() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"");
|
|
|
|
}
|
|
|
|
|
2024-06-10 08:48:19 +00:00
|
|
|
#[test]
|
|
|
|
fn test_fix_some_paths() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file1"), "foo").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file2"), "bar").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@", "file1"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm 54a90d2b (no description set)
|
2024-06-10 08:48:19 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file1"]);
|
2024-06-10 08:48:19 +00:00
|
|
|
insta::assert_snapshot!(content, @r###"
|
|
|
|
FOO
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file2"]);
|
2024-06-10 08:48:19 +00:00
|
|
|
insta::assert_snapshot!(content, @"bar");
|
|
|
|
}
|
|
|
|
|
2024-05-15 22:19:55 +00:00
|
|
|
#[test]
|
|
|
|
fn test_fix_cyclic() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--reverse"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content\n").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm bf5e6a5a (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"tnetnoc\n");
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm 0e2d20d6 (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_deduplication() {
|
|
|
|
// Append all fixed content to a log file. This assumes we're running the tool
|
|
|
|
// in the root directory of the repo, which is worth reconsidering if we
|
|
|
|
// establish a contract regarding cwd.
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase", "--tee", "$path-fixlog"]);
|
|
|
|
|
|
|
|
// There are at least two interesting cases: the content is repeated immediately
|
|
|
|
// in the child commit, or later in another descendant.
|
|
|
|
std::fs::write(repo_path.join("file"), "foo\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "bar\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "bar\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "c"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "foo\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "d"]);
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 4 commits of 4 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: yqosqzyt cf770245 d | (no description set)
|
|
|
|
Parent commit : mzvwutvl 370615a5 c | (empty) (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "a"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"FOO\n");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "b"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR\n");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "c"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"BAR\n");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "d"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"FOO\n");
|
|
|
|
|
|
|
|
// Each new content string only appears once in the log, because all the other
|
|
|
|
// inputs (like file name) were identical, and so the results were re-used. We
|
|
|
|
// sort the log because the order of execution inside `jj fix` is undefined.
|
|
|
|
insta::assert_snapshot!(sorted_lines(repo_path.join("file-fixlog")), @"BAR\nFOO\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn sorted_lines(path: PathBuf) -> String {
|
|
|
|
let mut log: Vec<_> = std::fs::read_to_string(path.as_os_str())
|
|
|
|
.unwrap()
|
|
|
|
.lines()
|
|
|
|
.map(String::from)
|
|
|
|
.collect();
|
|
|
|
log.sort();
|
|
|
|
log.join("\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_executed_but_nothing_changed() {
|
|
|
|
// Show that the tool ran by causing a side effect with --tee, and test that we
|
|
|
|
// do the right thing when the tool's output is exactly equal to its input.
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--tee", "$path-copy"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content\n").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content\n");
|
|
|
|
let copy_content = std::fs::read_to_string(repo_path.join("file-copy").as_os_str()).unwrap();
|
|
|
|
insta::assert_snapshot!(copy_content, @"content\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_failure() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--fail"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_stderr_success() {
|
|
|
|
let (test_env, repo_path) =
|
|
|
|
init_with_fake_formatter(&["--stderr", "error", "--stdout", "new content"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "old content").unwrap();
|
|
|
|
|
|
|
|
// TODO: Associate the stderr lines with the relevant tool/file/commit instead
|
|
|
|
// of passing it through directly.
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
errorFixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm 487808ba (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"new content");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_stderr_failure() {
|
|
|
|
let (test_env, repo_path) =
|
|
|
|
init_with_fake_formatter(&["--stderr", "error", "--stdout", "new content", "--fail"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "old content").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
errorFixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"old content");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_missing_command() {
|
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
test_env.add_config(r#"fix.tool-command = ["this_executable_shouldnt_exist"]"#);
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
// TODO: We should display a warning about invalid tool configurations. When we
|
|
|
|
// support multiple tools, we should also keep going to see if any of the other
|
|
|
|
// executions succeed.
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_file_types() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content").unwrap();
|
|
|
|
std::fs::create_dir(repo_path.join("dir")).unwrap();
|
|
|
|
try_symlink("file", repo_path.join("link")).unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm 6836a9e4 (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CONTENT");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
#[test]
|
|
|
|
fn test_fix_executable() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
let path = repo_path.join("file");
|
|
|
|
std::fs::write(&path, "content").unwrap();
|
|
|
|
let mut permissions = std::fs::metadata(&path).unwrap().permissions();
|
|
|
|
permissions.set_mode(permissions.mode() | 0o111);
|
|
|
|
std::fs::set_permissions(&path, permissions).unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: qpvuntsm fee78e99 (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
|
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CONTENT");
|
|
|
|
let executable = std::fs::metadata(&path).unwrap().permissions().mode() & 0o111;
|
|
|
|
assert_eq!(executable, 0o111);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_trivial_merge_commit() {
|
|
|
|
// All the changes are attributable to a parent, so none are fixed (in the same
|
|
|
|
// way that none would be shown in `jj diff -r @`).
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
|
|
|
std::fs::write(repo_path.join("file_b"), "content b").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 0 commits of 1 checked.
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_a", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content a");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_b", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content b");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_c", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"content c");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_adding_merge_commit() {
|
|
|
|
// None of the changes are attributable to a parent, so they are all fixed (in
|
|
|
|
// the same way that they would be shown in `jj diff -r @`).
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
|
|
|
std::fs::write(repo_path.join("file_b"), "content b").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
|
|
|
std::fs::write(repo_path.join("file_a"), "change a").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_b"), "change b").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_c"), "change c").unwrap();
|
|
|
|
std::fs::write(repo_path.join("file_d"), "change d").unwrap();
|
|
|
|
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 1 commits of 1 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: mzvwutvl f93eb5a9 (no description set)
|
|
|
|
Parent commit : qpvuntsm 6e64e7a7 a | (no description set)
|
|
|
|
Parent commit : kkmpptxz c536f264 b | (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 4 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_a", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHANGE A");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_b", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHANGE B");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_c", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHANGE C");
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_d", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @"CHANGE D");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_both_sides_of_conflict() {
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content a\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "content b\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
|
|
|
|
|
|
|
// The conflicts are not different from the merged parent, so they would not be
|
|
|
|
// fixed if we didn't fix the parents also.
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a", "-s", "b"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 3 commits of 3 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: mzvwutvl 88866235 (conflict) (empty) (no description set)
|
|
|
|
Parent commit : qpvuntsm 8e8aad69 a | (no description set)
|
|
|
|
Parent commit : kkmpptxz 91f9b284 b | (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
There are unresolved conflicts at these paths:
|
|
|
|
file 2-sided conflict
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "a"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @r###"
|
|
|
|
CONTENT A
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "b"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @r###"
|
|
|
|
CONTENT B
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @r###"
|
|
|
|
<<<<<<< Conflict 1 of 1
|
|
|
|
%%%%%%% Changes from base to side #1
|
|
|
|
+CONTENT A
|
|
|
|
+++++++ Contents of side #2
|
|
|
|
CONTENT B
|
|
|
|
>>>>>>> Conflict 1 of 1 ends
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fix_resolve_conflict() {
|
|
|
|
// If both sides of the conflict look the same after being fixed, the conflict
|
|
|
|
// will be resolved.
|
|
|
|
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "Content\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "a"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
|
|
|
|
std::fs::write(repo_path.join("file"), "cOnTeNt\n").unwrap();
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "b"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new", "a", "b"]);
|
|
|
|
|
|
|
|
// The conflicts are not different from the merged parent, so they would not be
|
|
|
|
// fixed if we didn't fix the parents also.
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a", "-s", "b"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Fixed 3 commits of 3 checked.
|
2024-06-23 22:20:33 +00:00
|
|
|
Working copy now at: mzvwutvl 50fd048d (empty) (no description set)
|
|
|
|
Parent commit : qpvuntsm dd2721f1 a | (no description set)
|
|
|
|
Parent commit : kkmpptxz 07c27a8e b | (no description set)
|
2024-05-15 22:19:55 +00:00
|
|
|
Added 0 files, modified 1 files, removed 0 files
|
|
|
|
"###);
|
2024-06-26 01:17:11 +00:00
|
|
|
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
|
2024-05-15 22:19:55 +00:00
|
|
|
insta::assert_snapshot!(content, @r###"
|
|
|
|
CONTENT
|
|
|
|
"###);
|
|
|
|
}
|