just playing with tangled
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 common::TestEnvironment; 16 17pub mod common; 18 19#[test] 20fn test_diff_basic() { 21 let test_env = TestEnvironment::default(); 22 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 23 let repo_path = test_env.env_root().join("repo"); 24 25 std::fs::write(repo_path.join("file1"), "foo\n").unwrap(); 26 std::fs::write(repo_path.join("file2"), "foo\n").unwrap(); 27 test_env.jj_cmd_success(&repo_path, &["new"]); 28 std::fs::remove_file(repo_path.join("file1")).unwrap(); 29 std::fs::write(repo_path.join("file2"), "foo\nbar\n").unwrap(); 30 std::fs::write(repo_path.join("file3"), "foo\n").unwrap(); 31 32 let stdout = test_env.jj_cmd_success(&repo_path, &["diff"]); 33 insta::assert_snapshot!(stdout, @r###" 34 Removed regular file file1: 35 1 : foo 36 Modified regular file file2: 37 1 1: foo 38 2: bar 39 Added regular file file3: 40 1: foo 41 "###); 42 43 let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); 44 insta::assert_snapshot!(stdout, @r###" 45 R file1 46 M file2 47 A file3 48 "###); 49 50 let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--types"]); 51 insta::assert_snapshot!(stdout, @r###" 52 F- file1 53 FF file2 54 -F file3 55 "###); 56 57 let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]); 58 insta::assert_snapshot!(stdout, @r###" 59 diff --git a/file1 b/file1 60 deleted file mode 100644 61 index 257cc5642c..0000000000 62 --- a/file1 63 +++ /dev/null 64 @@ -1,1 +1,0 @@ 65 -foo 66 diff --git a/file2 b/file2 67 index 257cc5642c...3bd1f0e297 100644 68 --- a/file2 69 +++ b/file2 70 @@ -1,1 +1,2 @@ 71 foo 72 +bar 73 diff --git a/file3 b/file3 74 new file mode 100644 75 index 0000000000..257cc5642c 76 --- /dev/null 77 +++ b/file3 78 @@ -1,0 +1,1 @@ 79 +foo 80 "###); 81 82 let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s", "--git"]); 83 insta::assert_snapshot!(stdout, @r###" 84 R file1 85 M file2 86 A file3 87 diff --git a/file1 b/file1 88 deleted file mode 100644 89 index 257cc5642c..0000000000 90 --- a/file1 91 +++ /dev/null 92 @@ -1,1 +1,0 @@ 93 -foo 94 diff --git a/file2 b/file2 95 index 257cc5642c...3bd1f0e297 100644 96 --- a/file2 97 +++ b/file2 98 @@ -1,1 +1,2 @@ 99 foo 100 +bar 101 diff --git a/file3 b/file3 102 new file mode 100644 103 index 0000000000..257cc5642c 104 --- /dev/null 105 +++ b/file3 106 @@ -1,0 +1,1 @@ 107 +foo 108 "###); 109} 110 111#[test] 112fn test_diff_types() { 113 let test_env = TestEnvironment::default(); 114 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 115 let repo_path = test_env.env_root().join("repo"); 116 117 let file_path = repo_path.join("foo"); 118 119 // Missing 120 test_env.jj_cmd_success(&repo_path, &["new", "root", "-m=missing"]); 121 122 // Normal file 123 test_env.jj_cmd_success(&repo_path, &["new", "root", "-m=file"]); 124 std::fs::write(&file_path, "foo").unwrap(); 125 126 // Conflict (add/add) 127 test_env.jj_cmd_success(&repo_path, &["new", "root", "-m=conflict"]); 128 std::fs::write(&file_path, "foo").unwrap(); 129 test_env.jj_cmd_success(&repo_path, &["new", "root"]); 130 std::fs::write(&file_path, "bar").unwrap(); 131 test_env.jj_cmd_success(&repo_path, &["move", r#"--to=description("conflict")"#]); 132 133 #[cfg(unix)] 134 { 135 use std::os::unix::fs::PermissionsExt; 136 use std::path::PathBuf; 137 138 // Executable 139 test_env.jj_cmd_success(&repo_path, &["new", "root", "-m=executable"]); 140 std::fs::write(&file_path, "foo").unwrap(); 141 std::fs::set_permissions(&file_path, std::fs::Permissions::from_mode(0o755)).unwrap(); 142 143 // Symlink 144 test_env.jj_cmd_success(&repo_path, &["new", "root", "-m=symlink"]); 145 std::os::unix::fs::symlink(PathBuf::from("."), &file_path).unwrap(); 146 } 147 148 let diff = |from: &str, to: &str| { 149 test_env.jj_cmd_success( 150 &repo_path, 151 &[ 152 "diff", 153 "--types", 154 &format!(r#"--from=description("{}")"#, from), 155 &format!(r#"--to=description("{}")"#, to), 156 ], 157 ) 158 }; 159 insta::assert_snapshot!(diff("missing", "file"), @r###" 160 -F foo 161 "###); 162 insta::assert_snapshot!(diff("file", "conflict"), @r###" 163 FC foo 164 "###); 165 insta::assert_snapshot!(diff("conflict", "missing"), @r###" 166 C- foo 167 "###); 168 169 #[cfg(unix)] 170 { 171 insta::assert_snapshot!(diff("symlink", "file"), @r###" 172 LF foo 173 "###); 174 insta::assert_snapshot!(diff("missing", "executable"), @r###" 175 -F foo 176 "###); 177 } 178} 179 180#[test] 181fn test_diff_bad_args() { 182 let test_env = TestEnvironment::default(); 183 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 184 let repo_path = test_env.env_root().join("repo"); 185 186 let stderr = test_env.jj_cmd_cli_error(&repo_path, &["diff", "-s", "--types"]); 187 insta::assert_snapshot!(stderr, @r###" 188 error: the argument '--summary' cannot be used with '--types' 189 190 Usage: jj diff --summary [PATHS]... 191 192 For more information, try '--help'. 193 "###); 194 195 let stderr = test_env.jj_cmd_cli_error(&repo_path, &["diff", "--color-words", "--git"]); 196 insta::assert_snapshot!(stderr, @r###" 197 error: the argument '--color-words' cannot be used with '--git' 198 199 Usage: jj diff --color-words [PATHS]... 200 201 For more information, try '--help'. 202 "###); 203} 204 205#[test] 206fn test_diff_relative_paths() { 207 let test_env = TestEnvironment::default(); 208 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 209 let repo_path = test_env.env_root().join("repo"); 210 211 std::fs::create_dir_all(repo_path.join("dir1").join("subdir1")).unwrap(); 212 std::fs::create_dir(repo_path.join("dir2")).unwrap(); 213 std::fs::write(repo_path.join("file1"), "foo1\n").unwrap(); 214 std::fs::write(repo_path.join("dir1").join("file2"), "foo2\n").unwrap(); 215 std::fs::write( 216 repo_path.join("dir1").join("subdir1").join("file3"), 217 "foo3\n", 218 ) 219 .unwrap(); 220 std::fs::write(repo_path.join("dir2").join("file4"), "foo4\n").unwrap(); 221 test_env.jj_cmd_success(&repo_path, &["new"]); 222 std::fs::write(repo_path.join("file1"), "bar1\n").unwrap(); 223 std::fs::write(repo_path.join("dir1").join("file2"), "bar2\n").unwrap(); 224 std::fs::write( 225 repo_path.join("dir1").join("subdir1").join("file3"), 226 "bar3\n", 227 ) 228 .unwrap(); 229 std::fs::write(repo_path.join("dir2").join("file4"), "bar4\n").unwrap(); 230 231 let stdout = test_env.jj_cmd_success(&repo_path.join("dir1"), &["diff"]); 232 #[cfg(unix)] 233 insta::assert_snapshot!(stdout, @r###" 234 Modified regular file file2: 235 1 1: foo2bar2 236 Modified regular file subdir1/file3: 237 1 1: foo3bar3 238 Modified regular file ../dir2/file4: 239 1 1: foo4bar4 240 Modified regular file ../file1: 241 1 1: foo1bar1 242 "###); 243 #[cfg(windows)] 244 insta::assert_snapshot!(stdout, @r###" 245 Modified regular file file2: 246 1 1: foo2bar2 247 Modified regular file subdir1\file3: 248 1 1: foo3bar3 249 Modified regular file ..\dir2\file4: 250 1 1: foo4bar4 251 Modified regular file ..\file1: 252 1 1: foo1bar1 253 "###); 254 255 let stdout = test_env.jj_cmd_success(&repo_path.join("dir1"), &["diff", "-s"]); 256 #[cfg(unix)] 257 insta::assert_snapshot!(stdout, @r###" 258 M file2 259 M subdir1/file3 260 M ../dir2/file4 261 M ../file1 262 "###); 263 #[cfg(windows)] 264 insta::assert_snapshot!(stdout, @r###" 265 M file2 266 M subdir1\file3 267 M ..\dir2\file4 268 M ..\file1 269 "###); 270 271 let stdout = test_env.jj_cmd_success(&repo_path.join("dir1"), &["diff", "--types"]); 272 #[cfg(unix)] 273 insta::assert_snapshot!(stdout, @r###" 274 FF file2 275 FF subdir1/file3 276 FF ../dir2/file4 277 FF ../file1 278 "###); 279 #[cfg(windows)] 280 insta::assert_snapshot!(stdout, @r###" 281 FF file2 282 FF subdir1\file3 283 FF ..\dir2\file4 284 FF ..\file1 285 "###); 286 287 let stdout = test_env.jj_cmd_success(&repo_path.join("dir1"), &["diff", "--git"]); 288 insta::assert_snapshot!(stdout, @r###" 289 diff --git a/dir1/file2 b/dir1/file2 290 index 54b060eee9...1fe912cdd8 100644 291 --- a/dir1/file2 292 +++ b/dir1/file2 293 @@ -1,1 +1,1 @@ 294 -foo2 295 +bar2 296 diff --git a/dir1/subdir1/file3 b/dir1/subdir1/file3 297 index c1ec6c6f12...f3c8b75ec6 100644 298 --- a/dir1/subdir1/file3 299 +++ b/dir1/subdir1/file3 300 @@ -1,1 +1,1 @@ 301 -foo3 302 +bar3 303 diff --git a/dir2/file4 b/dir2/file4 304 index a0016dbc4c...17375f7a12 100644 305 --- a/dir2/file4 306 +++ b/dir2/file4 307 @@ -1,1 +1,1 @@ 308 -foo4 309 +bar4 310 diff --git a/file1 b/file1 311 index 1715acd6a5...05c4fe6772 100644 312 --- a/file1 313 +++ b/file1 314 @@ -1,1 +1,1 @@ 315 -foo1 316 +bar1 317 "###); 318} 319 320#[test] 321fn test_diff_missing_newline() { 322 let test_env = TestEnvironment::default(); 323 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 324 let repo_path = test_env.env_root().join("repo"); 325 326 std::fs::write(repo_path.join("file1"), "foo").unwrap(); 327 std::fs::write(repo_path.join("file2"), "foo\nbar").unwrap(); 328 test_env.jj_cmd_success(&repo_path, &["new"]); 329 std::fs::write(repo_path.join("file1"), "foo\nbar").unwrap(); 330 std::fs::write(repo_path.join("file2"), "foo").unwrap(); 331 332 let stdout = test_env.jj_cmd_success(&repo_path, &["diff"]); 333 insta::assert_snapshot!(stdout, @r###" 334 Modified regular file file1: 335 1 1: foo 336 2: bar 337 Modified regular file file2: 338 1 1: foo 339 2 : bar 340 "###); 341 342 let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]); 343 insta::assert_snapshot!(stdout, @r###" 344 diff --git a/file1 b/file1 345 index 1910281566...a907ec3f43 100644 346 --- a/file1 347 +++ b/file1 348 @@ -1,1 +1,2 @@ 349 -foo 350 \ No newline at end of file 351 +foo 352 +bar 353 \ No newline at end of file 354 diff --git a/file2 b/file2 355 index a907ec3f43...1910281566 100644 356 --- a/file2 357 +++ b/file2 358 @@ -1,2 +1,1 @@ 359 -foo 360 -bar 361 \ No newline at end of file 362 +foo 363 \ No newline at end of file 364 "###); 365} 366 367#[test] 368fn test_color_words_diff_missing_newline() { 369 let test_env = TestEnvironment::default(); 370 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 371 let repo_path = test_env.env_root().join("repo"); 372 373 std::fs::write(repo_path.join("file1"), "").unwrap(); 374 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Empty"]); 375 std::fs::write(repo_path.join("file1"), "a\nb\nc\nd\ne\nf\ng\nh\ni").unwrap(); 376 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Add no newline"]); 377 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\ne\nf\ng\nh\ni").unwrap(); 378 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Modify first line"]); 379 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\nE\nf\ng\nh\ni").unwrap(); 380 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Modify middle line"]); 381 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\nE\nf\ng\nh\nI").unwrap(); 382 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Modify last line"]); 383 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\nE\nf\ng\nh\nI\n").unwrap(); 384 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Append newline"]); 385 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\nE\nf\ng\nh\nI").unwrap(); 386 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Remove newline"]); 387 std::fs::write(repo_path.join("file1"), "").unwrap(); 388 test_env.jj_cmd_success(&repo_path, &["commit", "-m", "=== Empty"]); 389 390 let stdout = test_env.jj_cmd_success( 391 &repo_path, 392 &[ 393 "log", 394 "-Tdescription", 395 "-pr::@-", 396 "--no-graph", 397 "--reversed", 398 ], 399 ); 400 insta::assert_snapshot!(stdout, @r###" 401 === Empty 402 Added regular file file1: 403 === Add no newline 404 Modified regular file file1: 405 1: a 406 2: b 407 3: c 408 4: d 409 5: e 410 6: f 411 7: g 412 8: h 413 9: i 414 === Modify first line 415 Modified regular file file1: 416 1 1: aA 417 2 2: b 418 3 3: c 419 4 4: d 420 ... 421 === Modify middle line 422 Modified regular file file1: 423 1 1: A 424 2 2: b 425 3 3: c 426 4 4: d 427 5 5: eE 428 6 6: f 429 7 7: g 430 8 8: h 431 9 9: i 432 === Modify last line 433 Modified regular file file1: 434 ... 435 6 6: f 436 7 7: g 437 8 8: h 438 9 9: iI 439 === Append newline 440 Modified regular file file1: 441 ... 442 6 6: f 443 7 7: g 444 8 8: h 445 9 9: I 446 === Remove newline 447 Modified regular file file1: 448 ... 449 6 6: f 450 7 7: g 451 8 8: h 452 9 9: I 453 === Empty 454 Modified regular file file1: 455 1 : A 456 2 : b 457 3 : c 458 4 : d 459 5 : E 460 6 : f 461 7 : g 462 8 : h 463 9 : I 464 "###); 465} 466 467#[test] 468fn test_diff_skipped_context() { 469 let test_env = TestEnvironment::default(); 470 test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); 471 let repo_path = test_env.env_root().join("repo"); 472 473 std::fs::write(repo_path.join("file1"), "a\nb\nc\nd\ne\nf\ng\nh\ni\nj").unwrap(); 474 test_env.jj_cmd_success(&repo_path, &["describe", "-m", "=== Left side of diffs"]); 475 476 test_env.jj_cmd_success(&repo_path, &["new", "@", "-m", "=== Must skip 2 lines"]); 477 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\ne\nf\ng\nh\ni\nJ").unwrap(); 478 test_env.jj_cmd_success(&repo_path, &["new", "@-", "-m", "=== Don't skip 1 line"]); 479 std::fs::write(repo_path.join("file1"), "A\nb\nc\nd\ne\nf\ng\nh\nI\nj").unwrap(); 480 test_env.jj_cmd_success(&repo_path, &["new", "@-", "-m", "=== No gap to skip"]); 481 std::fs::write(repo_path.join("file1"), "a\nB\nc\nd\ne\nf\ng\nh\nI\nj").unwrap(); 482 test_env.jj_cmd_success(&repo_path, &["new", "@-", "-m", "=== No gap to skip"]); 483 std::fs::write(repo_path.join("file1"), "a\nb\nC\nd\ne\nf\ng\nh\nI\nj").unwrap(); 484 test_env.jj_cmd_success(&repo_path, &["new", "@-", "-m", "=== 1 line at start"]); 485 std::fs::write(repo_path.join("file1"), "a\nb\nc\nd\nE\nf\ng\nh\ni\nj").unwrap(); 486 test_env.jj_cmd_success(&repo_path, &["new", "@-", "-m", "=== 1 line at end"]); 487 std::fs::write(repo_path.join("file1"), "a\nb\nc\nd\ne\nF\ng\nh\ni\nj").unwrap(); 488 489 let stdout = test_env.jj_cmd_success( 490 &repo_path, 491 &["log", "-Tdescription", "-p", "--no-graph", "--reversed"], 492 ); 493 insta::assert_snapshot!(stdout, @r###" 494 === Left side of diffs 495 Added regular file file1: 496 1: a 497 2: b 498 3: c 499 4: d 500 5: e 501 6: f 502 7: g 503 8: h 504 9: i 505 10: j 506 === Must skip 2 lines 507 Modified regular file file1: 508 1 1: aA 509 2 2: b 510 3 3: c 511 4 4: d 512 ... 513 7 7: g 514 8 8: h 515 9 9: i 516 10 10: jJ 517 === Don't skip 1 line 518 Modified regular file file1: 519 1 1: aA 520 2 2: b 521 3 3: c 522 4 4: d 523 5 5: e 524 6 6: f 525 7 7: g 526 8 8: h 527 9 9: iI 528 10 10: j 529 === No gap to skip 530 Modified regular file file1: 531 1 1: a 532 2 2: bB 533 3 3: c 534 4 4: d 535 5 5: e 536 6 6: f 537 7 7: g 538 8 8: h 539 9 9: iI 540 10 10: j 541 === No gap to skip 542 Modified regular file file1: 543 1 1: a 544 2 2: b 545 3 3: cC 546 4 4: d 547 5 5: e 548 6 6: f 549 7 7: g 550 8 8: h 551 9 9: iI 552 10 10: j 553 === 1 line at start 554 Modified regular file file1: 555 1 1: a 556 2 2: b 557 3 3: c 558 4 4: d 559 5 5: eE 560 6 6: f 561 7 7: g 562 8 8: h 563 ... 564 === 1 line at end 565 Modified regular file file1: 566 ... 567 3 3: c 568 4 4: d 569 5 5: e 570 6 6: fF 571 7 7: g 572 8 8: h 573 9 9: i 574 10 10: j 575 "###); 576}