From 791460f64582450b8ca7181c897ca2bb242c0769 Mon Sep 17 00:00:00 2001 From: ranger-ross Date: Thu, 26 Dec 2024 15:23:28 +0900 Subject: [PATCH] Added logic to preserve carriage returns when updating the manifest file --- src/cargo/util/toml_mut/manifest.rs | 33 ++++++++++++++++- tests/testsuite/cargo_add/mod.rs | 1 + .../preserve_carriage_returns/in/Cargo.toml | 6 ++++ .../preserve_carriage_returns/in/src/lib.rs | 0 .../preserve_carriage_returns/mod.rs | 36 +++++++++++++++++++ .../preserve_carriage_returns/out/Cargo.toml | 9 +++++ .../preserve_carriage_returns/stderr.term.svg | 31 ++++++++++++++++ tests/testsuite/cargo_remove/mod.rs | 1 + .../preserve_carriage_returns/in/Cargo.toml | 9 +++++ .../preserve_carriage_returns/in/src/lib.rs | 0 .../preserve_carriage_returns/mod.rs | 36 +++++++++++++++++++ .../preserve_carriage_returns/out/Cargo.toml | 6 ++++ .../preserve_carriage_returns/stderr.term.svg | 27 ++++++++++++++ 13 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 tests/testsuite/cargo_add/preserve_carriage_returns/in/Cargo.toml create mode 100644 tests/testsuite/cargo_add/preserve_carriage_returns/in/src/lib.rs create mode 100644 tests/testsuite/cargo_add/preserve_carriage_returns/mod.rs create mode 100644 tests/testsuite/cargo_add/preserve_carriage_returns/out/Cargo.toml create mode 100644 tests/testsuite/cargo_add/preserve_carriage_returns/stderr.term.svg create mode 100644 tests/testsuite/cargo_remove/preserve_carriage_returns/in/Cargo.toml create mode 100644 tests/testsuite/cargo_remove/preserve_carriage_returns/in/src/lib.rs create mode 100644 tests/testsuite/cargo_remove/preserve_carriage_returns/mod.rs create mode 100644 tests/testsuite/cargo_remove/preserve_carriage_returns/out/Cargo.toml create mode 100644 tests/testsuite/cargo_remove/preserve_carriage_returns/stderr.term.svg diff --git a/src/cargo/util/toml_mut/manifest.rs b/src/cargo/util/toml_mut/manifest.rs index 79fd24029de..03f43afe1d4 100644 --- a/src/cargo/util/toml_mut/manifest.rs +++ b/src/cargo/util/toml_mut/manifest.rs @@ -300,7 +300,7 @@ impl LocalManifest { /// Write changes back to the file. pub fn write(&self) -> CargoResult<()> { let mut manifest = self.manifest.data.to_string(); - let raw = match self.embedded.as_ref() { + let mut raw = match self.embedded.as_ref() { Some(Embedded::Implicit(start)) => { if !manifest.ends_with("\n") { manifest.push_str("\n"); @@ -321,6 +321,11 @@ impl LocalManifest { } None => manifest, }; + + if self.is_crlf() { + raw = to_crlf_line_ending(&raw); + } + let new_contents_bytes = raw.as_bytes(); cargo_util::paths::write_atomic(&self.path, new_contents_bytes) @@ -566,6 +571,10 @@ impl LocalManifest { } status } + + fn is_crlf(&self) -> bool { + return self.raw.contains("\r\n"); + } } impl std::fmt::Display for LocalManifest { @@ -753,3 +762,25 @@ fn remove_array_index(array: &mut toml_edit::Array, index: usize) { array.set_trailing(merged_lines); } } + +fn to_crlf_line_ending(input: &str) -> String { + let mut result = String::with_capacity(input.len()); + let mut chars = input.chars().peekable(); + + while let Some(c) = chars.next() { + match c { + '\r' if chars.peek() == Some(&'\n') => { + chars.next(); + result.push('\r'); + result.push('\n'); + } + '\n' => { + result.push('\r'); + result.push('\n'); + } + _ => result.push(c), + } + } + + result +} diff --git a/tests/testsuite/cargo_add/mod.rs b/tests/testsuite/cargo_add/mod.rs index 35ab71346c6..28ba890bc9c 100644 --- a/tests/testsuite/cargo_add/mod.rs +++ b/tests/testsuite/cargo_add/mod.rs @@ -120,6 +120,7 @@ mod path_base_unstable; mod path_dev; mod path_inferred_name; mod path_inferred_name_conflicts_full_feature; +mod preserve_carriage_returns; mod preserve_dep_std_table; mod preserve_features_sorted; mod preserve_features_table; diff --git a/tests/testsuite/cargo_add/preserve_carriage_returns/in/Cargo.toml b/tests/testsuite/cargo_add/preserve_carriage_returns/in/Cargo.toml new file mode 100644 index 00000000000..48c5359a5ba --- /dev/null +++ b/tests/testsuite/cargo_add/preserve_carriage_returns/in/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +edition = "2015" diff --git a/tests/testsuite/cargo_add/preserve_carriage_returns/in/src/lib.rs b/tests/testsuite/cargo_add/preserve_carriage_returns/in/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add/preserve_carriage_returns/mod.rs b/tests/testsuite/cargo_add/preserve_carriage_returns/mod.rs new file mode 100644 index 00000000000..59e64083de0 --- /dev/null +++ b/tests/testsuite/cargo_add/preserve_carriage_returns/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + // Verify the content matches first (for nicer error output) + assert_ui().subset_matches(current_dir!().join("out"), &project_root); + + // Snapbox normalizes lines so we also need to do a string comparision to verify line endings + let expected = current_dir!().join("out/Cargo.toml"); + let actual = project_root.join("Cargo.toml"); + assert_eq!( + std::fs::read_to_string(expected).unwrap(), + std::fs::read_to_string(actual).unwrap() + ); +} diff --git a/tests/testsuite/cargo_add/preserve_carriage_returns/out/Cargo.toml b/tests/testsuite/cargo_add/preserve_carriage_returns/out/Cargo.toml new file mode 100644 index 00000000000..f9c0a3d7665 --- /dev/null +++ b/tests/testsuite/cargo_add/preserve_carriage_returns/out/Cargo.toml @@ -0,0 +1,9 @@ +[workspace] + +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +edition = "2015" + +[dependencies] +my-package = "0.1.0" diff --git a/tests/testsuite/cargo_add/preserve_carriage_returns/stderr.term.svg b/tests/testsuite/cargo_add/preserve_carriage_returns/stderr.term.svg new file mode 100644 index 00000000000..eaa9c860056 --- /dev/null +++ b/tests/testsuite/cargo_add/preserve_carriage_returns/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/tests/testsuite/cargo_remove/mod.rs b/tests/testsuite/cargo_remove/mod.rs index 3510ece4b40..d9d77a3994f 100644 --- a/tests/testsuite/cargo_remove/mod.rs +++ b/tests/testsuite/cargo_remove/mod.rs @@ -24,6 +24,7 @@ mod optional_dep_feature; mod optional_dep_feature_formatting; mod optional_feature; mod package; +mod preserve_carriage_returns; mod remove_basic; mod script; mod script_last; diff --git a/tests/testsuite/cargo_remove/preserve_carriage_returns/in/Cargo.toml b/tests/testsuite/cargo_remove/preserve_carriage_returns/in/Cargo.toml new file mode 100644 index 00000000000..f9c0a3d7665 --- /dev/null +++ b/tests/testsuite/cargo_remove/preserve_carriage_returns/in/Cargo.toml @@ -0,0 +1,9 @@ +[workspace] + +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +edition = "2015" + +[dependencies] +my-package = "0.1.0" diff --git a/tests/testsuite/cargo_remove/preserve_carriage_returns/in/src/lib.rs b/tests/testsuite/cargo_remove/preserve_carriage_returns/in/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_remove/preserve_carriage_returns/mod.rs b/tests/testsuite/cargo_remove/preserve_carriage_returns/mod.rs new file mode 100644 index 00000000000..08b812822af --- /dev/null +++ b/tests/testsuite/cargo_remove/preserve_carriage_returns/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .arg_line("my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + // Verify the content matches first (for nicer error output) + assert_ui().subset_matches(current_dir!().join("out"), &project_root); + + // Snapbox normalizes lines so we also need to do a string comparision to verify line endings + let expected = current_dir!().join("out/Cargo.toml"); + let actual = project_root.join("Cargo.toml"); + assert_eq!( + std::fs::read_to_string(expected).unwrap(), + std::fs::read_to_string(actual).unwrap() + ); +} diff --git a/tests/testsuite/cargo_remove/preserve_carriage_returns/out/Cargo.toml b/tests/testsuite/cargo_remove/preserve_carriage_returns/out/Cargo.toml new file mode 100644 index 00000000000..48c5359a5ba --- /dev/null +++ b/tests/testsuite/cargo_remove/preserve_carriage_returns/out/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +edition = "2015" diff --git a/tests/testsuite/cargo_remove/preserve_carriage_returns/stderr.term.svg b/tests/testsuite/cargo_remove/preserve_carriage_returns/stderr.term.svg new file mode 100644 index 00000000000..583ddb69f38 --- /dev/null +++ b/tests/testsuite/cargo_remove/preserve_carriage_returns/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing my-package from dependencies + + + + + +