use super::*;
fn discard(head: &str, rendered: &str, worktree: &str) -> Discarded {
discard_render(head, rendered, worktree).expect("merges")
}
#[test]
fn test11134_an_untouched_render_goes_back_whole() {
let head = "version = \"1.0.0\"\nname = \"thing\"\n";
let rendered = "version = \"1.1.0\"\nname = \"thing\"\n";
let result = discard(head, rendered, rendered);
assert_eq!(result.content, head);
assert_eq!(result.kept, 0);
assert!(!result.is_noop());
}
#[test]
fn test11135_an_edit_beside_the_render_survives_it() {
let head = "version = \"1.0.0\"\nname = \"thing\"\n";
let rendered = "version = \"1.1.0\"\nname = \"thing\"\n";
let worktree = "version = \"1.1.0\"\nname = \"renamed\"\n";
let result = discard(head, rendered, worktree);
assert_eq!(
result.content, "version = \"1.0.0\"\nname = \"renamed\"\n",
"the version goes back, the rename stays"
);
assert_eq!(result.reverted, 1);
assert_eq!(result.kept, 0);
}
#[test]
fn test11136_an_edit_on_the_rendered_line_itself_is_kept_and_reported() {
let head = "version = \"1.0.0\"\n";
let rendered = "version = \"1.1.0\"\n";
let worktree = "version = \"9.9.9\"\n";
let result = discard(head, rendered, worktree);
assert_eq!(result.content, worktree, "their line is untouched");
assert_eq!(result.kept, 1, "and it is reported rather than silently kept");
}
#[test]
fn test11137_a_render_that_contributes_nothing_changes_nothing() {
let head = "stable\ncontent\n";
let worktree = "stable\nmine\n";
let result = discard(head, head, worktree);
assert_eq!(result.content, worktree);
assert!(result.is_noop());
}
#[test]
fn test11138_lines_added_by_a_person_are_not_removed() {
let head = "one\ntwo\n";
let rendered = "one\nTWO\n";
let worktree = "one\nTWO\nthree added by hand\n";
let result = discard(head, rendered, worktree);
assert_eq!(result.content, "one\ntwo\nthree added by hand\n");
}
#[test]
fn test11139_lines_the_render_added_are_removed_again() {
let head = "one\n";
let rendered = "one\ngenerated\n";
let result = discard(head, rendered, rendered);
assert_eq!(result.content, "one\n");
}
#[test]
fn test11140_two_separate_regions_are_decided_separately() {
let head = "a\nb\nc\nd\ne\n";
let rendered = "a\nB\nc\nd\ne\n";
let worktree = "a\nB\nc\nD\ne\n";
let result = discard(head, rendered, worktree);
assert_eq!(result.content, "a\nb\nc\nD\ne\n");
assert_eq!(result.reverted, 1);
assert_eq!(result.kept, 0);
}
#[test]
fn test11141_a_file_the_render_created_is_emptied_back_to_nothing() {
let result = discard("", "generated\n", "generated\n");
assert_eq!(result.content, "");
assert!(!result.is_noop());
}
#[test]
fn test11142_a_created_file_a_person_added_to_keeps_what_they_added() {
let result = discard("", "generated\n", "generated\nmine\n");
assert_eq!(result.content, "mine\n", "only the generated line goes");
}
#[test]
fn test11143_a_trailing_newline_the_render_added_is_taken_back() {
let result = discard("a", "a\n", "a\n");
assert_eq!(result.content, "a");
}
#[test]
fn test11144_a_whole_file_rewritten_by_the_render_goes_back_whole() {
let head = "old\nfile\ncontents\n";
let rendered = "completely\ndifferent\n";
let result = discard(head, rendered, rendered);
assert_eq!(result.content, head);
}
#[test]
fn test11145_an_empty_worktree_file_is_not_refilled_from_head() {
let head = "one\n";
let rendered = "one\ntwo\n";
let result = discard(head, rendered, "");
assert_eq!(result.content, "", "their empty file stays empty");
}
mod against_a_tree {
use super::super::*;
use std::fs;
fn git(root: &Path, args: &[&str]) {
let out = crate::git_backend::git_command()
.arg("-C")
.arg(root)
.args(args)
.output()
.expect("git runs");
assert!(
out.status.success(),
"git {args:?}: {}",
String::from_utf8_lossy(&out.stderr)
);
}
fn workspace() -> tempfile::TempDir {
let dir = tempfile::TempDir::new().expect("temp dir");
let root = dir.path();
git(root, &["init", "-q"]);
git(root, &["config", "user.email", "t@example.com"]);
git(root, &["config", "user.name", "t"]);
fs::write(root.join("version.txt"), "1.0.0\n").expect("version");
fs::write(
root.join("thing.toml.wstemplate"),
"name = \"thing\"\nversion = \"{{ project.version }}\"\n",
)
.expect("template");
fs::write(
root.join("thing.toml"),
"name = \"thing\"\nversion = \"0.0.1\"\n",
)
.expect("output");
git(root, &["add", "-A"]);
git(root, &["commit", "-qm", "base"]);
dir
}
#[test]
fn test11146_a_hand_edit_beside_a_rendered_line_survives_the_discard() {
let dir = workspace();
let output = dir.path().join("thing.toml");
fs::write(&output, "name = \"renamed by hand\"\nversion = \"9.9.9\"\n")
.expect("both edits");
let head = String::from_utf8_lossy(
&crate::git_backend::git_command()
.arg("-C")
.arg(dir.path())
.args(["show", "HEAD:thing.toml"])
.output()
.expect("git show")
.stdout,
)
.into_owned();
let rendered = "name = \"thing\"\nversion = \"9.9.9\"\n";
let merged = discard_render(&head, rendered, "name = \"renamed by hand\"\nversion = \"9.9.9\"\n")
.expect("merges");
assert_eq!(
merged.content,
"name = \"renamed by hand\"\nversion = \"0.0.1\"\n",
"the rendered version goes back; the hand-written name stays"
);
}
#[test]
fn test11147_head_is_read_from_the_repository_that_owns_the_file() {
let dir = workspace();
let text = super::super::head_text(&dir.path().join("thing.toml"))
.expect("the committed version is found");
assert_eq!(text, "name = \"thing\"\nversion = \"0.0.1\"\n");
assert!(
super::super::head_text(&dir.path().join("never-committed.toml")).is_none(),
"a file with no committed version says so"
);
}
fn locally_rendered_workspace() -> tempfile::TempDir {
let dir = tempfile::TempDir::new().expect("temp dir");
let root = dir.path();
git(root, &["init", "-q"]);
git(root, &["config", "user.email", "t@example.com"]);
git(root, &["config", "user.name", "t"]);
fs::create_dir_all(root.join(".wsb")).expect("state dir");
fs::write(
root.join(".wsb/state.json"),
format!(
r#"{{"version":1,"version_suffix":null,
"project_name":"thing","tools":{{}},
"wstemplate_entries":[{{"root":".","alias":"thing"}}],
"completion_hint_shown":false}}"#
),
)
.expect("state");
fs::write(
root.join(".wsb/stamp.json"),
r#"{"local": {"variable": "LOCAL_LIBS"}}"#,
)
.expect("stamp configuration");
fs::write(root.join("version.txt"), "1.0.0\n").expect("version");
fs::write(
root.join("dep.toml.wstemplate"),
"{%- if env.LOCAL_LIBS %}\ndep = { path = \"../dep\" }\n\
{%- else %}\ndep = { tag = \"v1\" }\n{%- endif %}\n",
)
.expect("template");
fs::write(root.join("dep.toml"), "\ndep = { path = \"../dep\" }\n").expect("output");
git(root, &["add", "-A"]);
git(root, &["commit", "-qm", "base"]);
dir
}
#[test]
fn test12579_a_manifest_taken_back_takes_its_lock_back() {
let dir = tempfile::TempDir::new().expect("temp dir");
let root = dir.path();
git(root, &["init", "-q"]);
git(root, &["config", "user.email", "t@example.com"]);
git(root, &["config", "user.name", "t"]);
fs::create_dir_all(root.join(".wsb")).expect("state dir");
fs::write(
root.join(".wsb/state.json"),
r#"{"version":1,"project_name":"thing","tools":{},"wstemplate_entries":[{"root":".","alias":"thing"}]}"#,
)
.expect("state");
fs::write(root.join("version.txt"), "1.0.0\n").expect("version");
fs::write(
root.join("package.json.wstemplate"),
"{\"name\":\"thing\",\"dependencies\":{\"dep\":\"{% if env.LOCAL_LIBS %}file:../dep{% else %}^1.0.0{% endif %}\"}}\n",
)
.expect("template");
let published = "{\"name\":\"thing\",\"dependencies\":{\"dep\":\"^1.0.0\"}}\n";
let committed_lock = "{\"name\":\"thing\",\"lockfileVersion\":3,\"packages\":{\"\":{\"name\":\"thing\",\"dependencies\":{\"dep\":\"^1.0.0\"}}}}\n";
fs::write(root.join("package.json"), published).expect("manifest");
fs::write(root.join("package-lock.json"), committed_lock).expect("lock");
git(root, &["add", "-A"]);
git(root, &["commit", "-qm", "base"]);
fs::write(root.join("package.json"), "{\"name\":\"thing\",\"dependencies\":{\"dep\":\"file:../dep\"}}\n")
.expect("local manifest");
fs::write(
root.join("package-lock.json"),
"{\"name\":\"thing\",\"lockfileVersion\":3,\"packages\":{\"\":{\"name\":\"thing\",\"dependencies\":{\"dep\":\"file:../dep\"}}},\"relocked\":\"locally\"}\n",
)
.expect("local lock");
let _local = crate::test_environment::Environment::set(&[("LOCAL_LIBS", "1")]);
super::super::run(root, false).expect("taken back");
assert_eq!(fs::read_to_string(root.join("package.json")).unwrap(), published);
assert_eq!(
fs::read_to_string(root.join("package-lock.json")).unwrap(),
committed_lock,
"the lock was not put back as committed"
);
}
#[test]
fn test11161_the_local_render_is_recognised_without_the_variable_set() {
let dir = locally_rendered_workspace();
std::env::remove_var("LOCAL_LIBS");
let settled = super::super::rendered_as_written(dir.path(), &crate::state::RunCache::new())
.expect("classifies");
assert!(
settled.contains(&dir.path().join("dep.toml")),
"the file holds exactly what a local render writes, so the renderer \
wrote it — not a person. Settled: {settled:#?}"
);
assert!(
std::env::var_os("LOCAL_LIBS").is_none(),
"a read-only query must not leave the variable set for whatever renders next"
);
}
#[test]
fn test11162_a_hand_edited_generated_file_is_still_reported() {
let dir = locally_rendered_workspace();
fs::write(
dir.path().join("dep.toml"),
"\ndep = { path = \"../somewhere-else\" }\n",
)
.expect("edit");
let settled = super::super::rendered_as_written(dir.path(), &crate::state::RunCache::new())
.expect("classifies");
assert!(
!settled.contains(&dir.path().join("dep.toml")),
"this matches neither render, so it is somebody's edit and stays visible"
);
}
#[test]
fn test11148_a_dry_run_writes_nothing() {
let dir = workspace();
let output = dir.path().join("thing.toml");
let before = "name = \"mine\"\nversion = \"2.0.0\"\n";
fs::write(&output, before).expect("edit");
let planned = run(dir.path(), true);
assert!(
planned.is_err(),
"a directory that is not a workspace is refused"
);
assert_eq!(
fs::read_to_string(&output).expect("read"),
before,
"and nothing was written"
);
}
}