just playing with tangled
at gvimdiff 453 lines 15 kB view raw
1// Copyright 2022 The Jujutsu Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15use std::path::PathBuf; 16 17use crate::common::CommandOutput; 18use crate::common::TestEnvironment; 19use crate::common::TestWorkDir; 20 21#[test] 22fn test_commit_with_description_from_cli() { 23 let test_env = TestEnvironment::default(); 24 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 25 let work_dir = test_env.work_dir("repo"); 26 27 // Description applies to the current working-copy (not the new one) 28 work_dir.run_jj(["commit", "-m=first"]).success(); 29 insta::assert_snapshot!(get_log_output(&work_dir), @r" 30 @ e8ea92a8b6b3 31 ○ fa15625b4a98 first 32 ◆ 000000000000 33 [EOF] 34 "); 35} 36 37#[test] 38fn test_commit_with_editor() { 39 let mut test_env = TestEnvironment::default(); 40 let edit_script = test_env.set_up_fake_editor(); 41 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 42 let work_dir = test_env.work_dir("repo"); 43 44 // Check that the text file gets initialized with the current description and 45 // set a new one 46 work_dir.run_jj(["describe", "-m=initial"]).success(); 47 std::fs::write(&edit_script, ["dump editor0", "write\nmodified"].join("\0")).unwrap(); 48 work_dir.run_jj(["commit"]).success(); 49 insta::assert_snapshot!(get_log_output(&work_dir), @r" 50 @ a57b2c95fb75 51 ○ 159271101e05 modified 52 ◆ 000000000000 53 [EOF] 54 "); 55 insta::assert_snapshot!( 56 std::fs::read_to_string(test_env.env_root().join("editor0")).unwrap(), @r#" 57 initial 58 59 JJ: Lines starting with "JJ:" (like this one) will be removed. 60 "#); 61 62 // Check that the editor content includes diff summary 63 work_dir.write_file("file1", "foo\n"); 64 work_dir.write_file("file2", "foo\n"); 65 work_dir.run_jj(["describe", "-m=add files"]).success(); 66 std::fs::write(&edit_script, "dump editor1").unwrap(); 67 work_dir.run_jj(["commit"]).success(); 68 insta::assert_snapshot!( 69 std::fs::read_to_string(test_env.env_root().join("editor1")).unwrap(), @r#" 70 add files 71 72 JJ: This commit contains the following changes: 73 JJ: A file1 74 JJ: A file2 75 JJ: 76 JJ: Lines starting with "JJ:" (like this one) will be removed. 77 "#); 78} 79 80#[test] 81fn test_commit_with_editor_avoids_unc() { 82 let mut test_env = TestEnvironment::default(); 83 let edit_script = test_env.set_up_fake_editor(); 84 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 85 let work_dir = test_env.work_dir("repo"); 86 87 std::fs::write(edit_script, "dump-path path").unwrap(); 88 work_dir.run_jj(["commit"]).success(); 89 90 let edited_path = 91 PathBuf::from(std::fs::read_to_string(test_env.env_root().join("path")).unwrap()); 92 // While `assert!(!edited_path.starts_with("//?/"))` could work here in most 93 // cases, it fails when it is not safe to strip the prefix, such as paths 94 // over 260 chars. 95 assert_eq!(edited_path, dunce::simplified(&edited_path)); 96} 97 98#[test] 99fn test_commit_interactive() { 100 let mut test_env = TestEnvironment::default(); 101 let edit_script = test_env.set_up_fake_editor(); 102 let diff_editor = test_env.set_up_fake_diff_editor(); 103 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 104 let work_dir = test_env.work_dir("repo"); 105 106 work_dir.write_file("file1", "foo\n"); 107 work_dir.write_file("file2", "bar\n"); 108 work_dir.run_jj(["describe", "-m=add files"]).success(); 109 std::fs::write(edit_script, ["dump editor"].join("\0")).unwrap(); 110 111 let diff_script = ["rm file2", "dump JJ-INSTRUCTIONS instrs"].join("\0"); 112 std::fs::write(diff_editor, diff_script).unwrap(); 113 114 // Create a commit interactively and select only file1 115 work_dir.run_jj(["commit", "-i"]).success(); 116 117 insta::assert_snapshot!( 118 std::fs::read_to_string(test_env.env_root().join("instrs")).unwrap(), @r" 119 You are splitting the working-copy commit: qpvuntsm 4219467e add files 120 121 The diff initially shows all changes. Adjust the right side until it shows the 122 contents you want for the first commit. The remainder will be included in the 123 new working-copy commit. 124 "); 125 126 insta::assert_snapshot!( 127 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 128 add files 129 130 JJ: This commit contains the following changes: 131 JJ: A file1 132 JJ: 133 JJ: Lines starting with "JJ:" (like this one) will be removed. 134 "#); 135 136 // Try again with --tool=<name>, which implies --interactive 137 work_dir.run_jj(["undo"]).success(); 138 work_dir 139 .run_jj([ 140 "commit", 141 "--config=ui.diff-editor='false'", 142 "--tool=fake-diff-editor", 143 ]) 144 .success(); 145 146 insta::assert_snapshot!( 147 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 148 add files 149 150 JJ: This commit contains the following changes: 151 JJ: A file1 152 JJ: 153 JJ: Lines starting with "JJ:" (like this one) will be removed. 154 "#); 155 156 let output = work_dir.run_jj(["log", "--summary"]); 157 insta::assert_snapshot!(output, @r" 158 @ mzvwutvl test.user@example.com 2001-02-03 08:05:11 21b846a6 159 │ (no description set) 160 │ A file2 161 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:11 7d156390 162 │ add files 163 │ A file1 164 ◆ zzzzzzzz root() 00000000 165 [EOF] 166 "); 167} 168 169#[test] 170fn test_commit_interactive_with_paths() { 171 let mut test_env = TestEnvironment::default(); 172 let edit_script = test_env.set_up_fake_editor(); 173 let diff_editor = test_env.set_up_fake_diff_editor(); 174 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 175 let work_dir = test_env.work_dir("repo"); 176 177 work_dir.write_file("file2", ""); 178 work_dir.write_file("file3", ""); 179 work_dir.run_jj(["new", "-medit"]).success(); 180 work_dir.write_file("file1", "foo\n"); 181 work_dir.write_file("file2", "bar\n"); 182 work_dir.write_file("file3", "baz\n"); 183 184 std::fs::write(edit_script, ["dump editor"].join("\0")).unwrap(); 185 let diff_script = [ 186 "files-before file2", 187 "files-after JJ-INSTRUCTIONS file1 file2", 188 "reset file2", 189 ] 190 .join("\0"); 191 std::fs::write(diff_editor, diff_script).unwrap(); 192 193 // Select file1 and file2 by args, then select file1 interactively 194 let output = work_dir.run_jj(["commit", "-i", "file1", "file2"]); 195 insta::assert_snapshot!(output, @r" 196 ------- stderr ------- 197 Working copy (@) now at: kkmpptxz f3e6062e (no description set) 198 Parent commit (@-) : rlvkpnrz 9453cb28 edit 199 [EOF] 200 "); 201 202 insta::assert_snapshot!( 203 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 204 edit 205 206 JJ: This commit contains the following changes: 207 JJ: A file1 208 JJ: 209 JJ: Lines starting with "JJ:" (like this one) will be removed. 210 "#); 211 212 let output = work_dir.run_jj(["log", "--summary"]); 213 insta::assert_snapshot!(output, @r" 214 @ kkmpptxz test.user@example.com 2001-02-03 08:05:09 f3e6062e 215 │ (no description set) 216 │ M file2 217 │ M file3 218 ○ rlvkpnrz test.user@example.com 2001-02-03 08:05:09 9453cb28 219 │ edit 220 │ A file1 221 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:08 497ed465 222 │ (no description set) 223 │ A file2 224 │ A file3 225 ◆ zzzzzzzz root() 00000000 226 [EOF] 227 "); 228} 229 230#[test] 231fn test_commit_with_default_description() { 232 let mut test_env = TestEnvironment::default(); 233 let edit_script = test_env.set_up_fake_editor(); 234 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 235 test_env.add_config(r#"ui.default-description = "\n\nTESTED=TODO""#); 236 let work_dir = test_env.work_dir("repo"); 237 238 work_dir.write_file("file1", "foo\n"); 239 work_dir.write_file("file2", "bar\n"); 240 std::fs::write(edit_script, ["dump editor"].join("\0")).unwrap(); 241 work_dir.run_jj(["commit"]).success(); 242 243 insta::assert_snapshot!(get_log_output(&work_dir), @r" 244 @ c65242099289 245 ○ 573b6df51aea TESTED=TODO 246 ◆ 000000000000 247 [EOF] 248 "); 249 insta::assert_snapshot!( 250 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 251 TESTED=TODO 252 253 JJ: This commit contains the following changes: 254 JJ: A file1 255 JJ: A file2 256 JJ: 257 JJ: Lines starting with "JJ:" (like this one) will be removed. 258 "#); 259} 260 261#[test] 262fn test_commit_with_description_template() { 263 let mut test_env = TestEnvironment::default(); 264 let edit_script = test_env.set_up_fake_editor(); 265 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 266 test_env.add_config( 267 r#" 268 [templates] 269 draft_commit_description = ''' 270 concat( 271 description, 272 "\n", 273 indent( 274 "JJ: ", 275 concat( 276 "Author: " ++ format_detailed_signature(author) ++ "\n", 277 "Committer: " ++ format_detailed_signature(committer) ++ "\n", 278 "\n", 279 diff.stat(76), 280 ), 281 ), 282 ) 283 ''' 284 "#, 285 ); 286 let work_dir = test_env.work_dir("repo"); 287 288 std::fs::write(edit_script, ["dump editor"].join("\0")).unwrap(); 289 290 work_dir.write_file("file1", "foo\n"); 291 work_dir.write_file("file2", "bar\n"); 292 work_dir.write_file("file3", "foobar\n"); 293 294 // Only file1 should be included in the diff 295 work_dir.run_jj(["commit", "file1"]).success(); 296 insta::assert_snapshot!( 297 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 298 JJ: Author: Test User <test.user@example.com> (2001-02-03 08:05:08) 299 JJ: Committer: Test User <test.user@example.com> (2001-02-03 08:05:08) 300 301 JJ: file1 | 1 + 302 JJ: 1 file changed, 1 insertion(+), 0 deletions(-) 303 JJ: 304 JJ: Lines starting with "JJ:" (like this one) will be removed. 305 "#); 306 307 // Only file2 with modified author should be included in the diff 308 work_dir 309 .run_jj([ 310 "commit", 311 "--author", 312 "Another User <another.user@example.com>", 313 "file2", 314 ]) 315 .success(); 316 insta::assert_snapshot!( 317 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 318 JJ: Author: Another User <another.user@example.com> (2001-02-03 08:05:08) 319 JJ: Committer: Test User <test.user@example.com> (2001-02-03 08:05:09) 320 321 JJ: file2 | 1 + 322 JJ: 1 file changed, 1 insertion(+), 0 deletions(-) 323 JJ: 324 JJ: Lines starting with "JJ:" (like this one) will be removed. 325 "#); 326 327 // Timestamp after the reset should be available to the template 328 work_dir.run_jj(["commit", "--reset-author"]).success(); 329 insta::assert_snapshot!( 330 std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" 331 JJ: Author: Test User <test.user@example.com> (2001-02-03 08:05:10) 332 JJ: Committer: Test User <test.user@example.com> (2001-02-03 08:05:10) 333 334 JJ: file3 | 1 + 335 JJ: 1 file changed, 1 insertion(+), 0 deletions(-) 336 JJ: 337 JJ: Lines starting with "JJ:" (like this one) will be removed. 338 "#); 339} 340 341#[test] 342fn test_commit_without_working_copy() { 343 let test_env = TestEnvironment::default(); 344 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 345 let work_dir = test_env.work_dir("repo"); 346 347 work_dir.run_jj(["workspace", "forget"]).success(); 348 let output = work_dir.run_jj(["commit", "-m=first"]); 349 insta::assert_snapshot!(output, @r" 350 ------- stderr ------- 351 Error: This command requires a working copy 352 [EOF] 353 [exit status: 1] 354 "); 355} 356 357#[test] 358fn test_commit_paths() { 359 let test_env = TestEnvironment::default(); 360 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 361 let work_dir = test_env.work_dir("repo"); 362 363 work_dir.write_file("file1", "foo\n"); 364 work_dir.write_file("file2", "bar\n"); 365 366 work_dir.run_jj(["commit", "-m=first", "file1"]).success(); 367 let output = work_dir.run_jj(["diff", "-r", "@-"]); 368 insta::assert_snapshot!(output, @r" 369 Added regular file file1: 370 1: foo 371 [EOF] 372 "); 373 374 let output = work_dir.run_jj(["diff"]); 375 insta::assert_snapshot!(output, @r" 376 Added regular file file2: 377 1: bar 378 [EOF] 379 "); 380} 381 382#[test] 383fn test_commit_paths_warning() { 384 let test_env = TestEnvironment::default(); 385 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 386 let work_dir = test_env.work_dir("repo"); 387 388 work_dir.write_file("file1", "foo\n"); 389 work_dir.write_file("file2", "bar\n"); 390 391 let output = work_dir.run_jj(["commit", "-m=first", "file3"]); 392 insta::assert_snapshot!(output, @r" 393 ------- stderr ------- 394 Warning: The given paths do not match any file: file3 395 Working copy (@) now at: rlvkpnrz d1872100 (no description set) 396 Parent commit (@-) : qpvuntsm fa15625b (empty) first 397 [EOF] 398 "); 399 400 let output = work_dir.run_jj(["diff"]); 401 insta::assert_snapshot!(output, @r" 402 Added regular file file1: 403 1: foo 404 Added regular file file2: 405 1: bar 406 [EOF] 407 "); 408} 409 410#[test] 411fn test_commit_reset_author() { 412 let test_env = TestEnvironment::default(); 413 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 414 let work_dir = test_env.work_dir("repo"); 415 416 test_env.add_config( 417 r#"[template-aliases] 418'format_signature(signature)' = 'signature.name() ++ " " ++ signature.email() ++ " " ++ signature.timestamp()'"#, 419 ); 420 let get_signatures = || { 421 let template = r#"format_signature(author) ++ "\n" ++ format_signature(committer)"#; 422 work_dir.run_jj(["log", "-r@", "-T", template]) 423 }; 424 insta::assert_snapshot!(get_signatures(), @r" 425 @ Test User test.user@example.com 2001-02-03 04:05:07.000 +07:00 426 │ Test User test.user@example.com 2001-02-03 04:05:07.000 +07:00 427 ~ 428 [EOF] 429 "); 430 431 // Reset the author (the committer is always reset) 432 work_dir 433 .run_jj([ 434 "commit", 435 "--config=user.name=Ove Ridder", 436 "--config=user.email=ove.ridder@example.com", 437 "--reset-author", 438 "-m1", 439 ]) 440 .success(); 441 insta::assert_snapshot!(get_signatures(), @r" 442 @ Ove Ridder ove.ridder@example.com 2001-02-03 04:05:09.000 +07:00 443 │ Ove Ridder ove.ridder@example.com 2001-02-03 04:05:09.000 +07:00 444 ~ 445 [EOF] 446 "); 447} 448 449#[must_use] 450fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput { 451 let template = r#"commit_id.short() ++ " " ++ description"#; 452 work_dir.run_jj(["log", "-T", template]) 453}