just playing with tangled
at ig/vimdiffwarn 545 lines 20 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 crate::common::create_commit_with_files; 16use crate::common::TestEnvironment; 17 18#[test] 19fn test_status_copies() { 20 let test_env = TestEnvironment::default(); 21 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 22 let repo_path = test_env.env_root().join("repo"); 23 24 std::fs::write(repo_path.join("copy-source"), "copy1\ncopy2\ncopy3\n").unwrap(); 25 std::fs::write(repo_path.join("rename-source"), "rename").unwrap(); 26 test_env.run_jj_in(&repo_path, ["new"]).success(); 27 std::fs::write( 28 repo_path.join("copy-source"), 29 "copy1\ncopy2\ncopy3\nsource\n", 30 ) 31 .unwrap(); 32 std::fs::write( 33 repo_path.join("copy-target"), 34 "copy1\ncopy2\ncopy3\ntarget\n", 35 ) 36 .unwrap(); 37 std::fs::remove_file(repo_path.join("rename-source")).unwrap(); 38 std::fs::write(repo_path.join("rename-target"), "rename").unwrap(); 39 40 let output = test_env.run_jj_in(&repo_path, ["status"]); 41 insta::assert_snapshot!(output, @r" 42 Working copy changes: 43 M copy-source 44 C {copy-source => copy-target} 45 R {rename-source => rename-target} 46 Working copy (@) : rlvkpnrz a96c3086 (no description set) 47 Parent commit (@-): qpvuntsm e3e2c703 (no description set) 48 [EOF] 49 "); 50} 51 52#[test] 53fn test_status_merge() { 54 let test_env = TestEnvironment::default(); 55 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 56 let repo_path = test_env.env_root().join("repo"); 57 58 std::fs::write(repo_path.join("file"), "base").unwrap(); 59 test_env.run_jj_in(&repo_path, ["new", "-m=left"]).success(); 60 test_env 61 .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "left"]) 62 .success(); 63 test_env 64 .run_jj_in(&repo_path, ["new", "@-", "-m=right"]) 65 .success(); 66 std::fs::write(repo_path.join("file"), "right").unwrap(); 67 test_env 68 .run_jj_in(&repo_path, ["new", "left", "@"]) 69 .success(); 70 71 // The output should mention each parent, and the diff should be empty (compared 72 // to the auto-merged parents) 73 let output = test_env.run_jj_in(&repo_path, ["status"]); 74 insta::assert_snapshot!(output, @r" 75 The working copy has no changes. 76 Working copy (@) : mzvwutvl a538c72d (empty) (no description set) 77 Parent commit (@-): rlvkpnrz d3dd19f1 left | (empty) left 78 Parent commit (@-): zsuskuln 705a356d right 79 [EOF] 80 "); 81} 82 83// See https://github.com/jj-vcs/jj/issues/2051. 84#[test] 85fn test_status_ignored_gitignore() { 86 let test_env = TestEnvironment::default(); 87 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 88 let repo_path = test_env.env_root().join("repo"); 89 90 std::fs::create_dir(repo_path.join("untracked")).unwrap(); 91 std::fs::write(repo_path.join("untracked").join("inside_untracked"), "test").unwrap(); 92 std::fs::write( 93 repo_path.join("untracked").join(".gitignore"), 94 "!inside_untracked\n", 95 ) 96 .unwrap(); 97 std::fs::write(repo_path.join(".gitignore"), "untracked/\n!dummy\n").unwrap(); 98 99 let output = test_env.run_jj_in(&repo_path, ["status"]); 100 insta::assert_snapshot!(output, @r" 101 Working copy changes: 102 A .gitignore 103 Working copy (@) : qpvuntsm 3cef2183 (no description set) 104 Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set) 105 [EOF] 106 "); 107} 108 109#[test] 110fn test_status_filtered() { 111 let test_env = TestEnvironment::default(); 112 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 113 let repo_path = test_env.env_root().join("repo"); 114 115 std::fs::write(repo_path.join("file_1"), "file_1").unwrap(); 116 std::fs::write(repo_path.join("file_2"), "file_2").unwrap(); 117 118 // The output filtered to file_1 should not list the addition of file_2. 119 let output = test_env.run_jj_in(&repo_path, ["status", "file_1"]); 120 insta::assert_snapshot!(output, @r" 121 Working copy changes: 122 A file_1 123 Working copy (@) : qpvuntsm c8fb8395 (no description set) 124 Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set) 125 [EOF] 126 "); 127} 128 129// See <https://github.com/jj-vcs/jj/issues/3108> 130// See <https://github.com/jj-vcs/jj/issues/4147> 131#[test] 132fn test_status_display_relevant_working_commit_conflict_hints() { 133 let test_env = TestEnvironment::default(); 134 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 135 136 let repo_path = test_env.env_root().join("repo"); 137 let conflicted_path = repo_path.join("conflicted.txt"); 138 139 // PARENT: Write the initial file 140 std::fs::write(&conflicted_path, "initial contents").unwrap(); 141 test_env 142 .run_jj_in(&repo_path, ["describe", "--message", "Initial contents"]) 143 .success(); 144 145 // CHILD1: New commit on top of <PARENT> 146 test_env 147 .run_jj_in( 148 &repo_path, 149 ["new", "--message", "First part of conflicting change"], 150 ) 151 .success(); 152 std::fs::write(&conflicted_path, "Child 1").unwrap(); 153 154 // CHILD2: New commit also on top of <PARENT> 155 test_env 156 .run_jj_in( 157 &repo_path, 158 [ 159 "new", 160 "--message", 161 "Second part of conflicting change", 162 "@-", 163 ], 164 ) 165 .success(); 166 std::fs::write(&conflicted_path, "Child 2").unwrap(); 167 168 // CONFLICT: New commit that is conflicted by merging <CHILD1> and <CHILD2> 169 test_env 170 .run_jj_in(&repo_path, ["new", "--message", "boom", "all:(@-)+"]) 171 .success(); 172 // Adding more descendants to ensure we correctly find the root ancestors with 173 // conflicts, not just the parents. 174 test_env 175 .run_jj_in(&repo_path, ["new", "--message", "boom-cont"]) 176 .success(); 177 test_env 178 .run_jj_in(&repo_path, ["new", "--message", "boom-cont-2"]) 179 .success(); 180 181 let output = test_env.run_jj_in(&repo_path, ["log", "-r", "::"]); 182 183 insta::assert_snapshot!(output, @r" 184 @ yqosqzyt test.user@example.com 2001-02-03 08:05:13 dcb25635 conflict 185 │ (empty) boom-cont-2 186 × royxmykx test.user@example.com 2001-02-03 08:05:12 664a4c6c conflict 187 │ (empty) boom-cont 188 × mzvwutvl test.user@example.com 2001-02-03 08:05:11 c5a4e9cb conflict 189 ├─╮ (empty) boom 190 │ ○ kkmpptxz test.user@example.com 2001-02-03 08:05:10 1e8c2956 191 │ │ First part of conflicting change 192 ○ │ zsuskuln test.user@example.com 2001-02-03 08:05:11 2c8b19fd 193 ├─╯ Second part of conflicting change 194 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:08 aade7195 195 │ Initial contents 196 ◆ zzzzzzzz root() 00000000 197 [EOF] 198 "); 199 200 let output = test_env.run_jj_in(&repo_path, ["status"]); 201 insta::assert_snapshot!(output, @r" 202 The working copy has no changes. 203 Working copy (@) : yqosqzyt dcb25635 (conflict) (empty) boom-cont-2 204 Parent commit (@-): royxmykx 664a4c6c (conflict) (empty) boom-cont 205 Warning: There are unresolved conflicts at these paths: 206 conflicted.txt 2-sided conflict 207 Hint: To resolve the conflicts, start by updating to the first one: 208 jj new mzvwutvl 209 Then use `jj resolve`, or edit the conflict markers in the file directly. 210 Once the conflicts are resolved, you may want to inspect the result with `jj diff`. 211 Then run `jj squash` to move the resolution into the conflicted commit. 212 [EOF] 213 "); 214 215 let output = test_env.run_jj_in(&repo_path, ["status", "--color=always"]); 216 insta::assert_snapshot!(output, @r" 217 The working copy has no changes. 218 Working copy (@) : yqosqzyt dcb25635 (conflict) (empty) boom-cont-2 219 Parent commit (@-): royxmykx 664a4c6c (conflict) (empty) boom-cont 220 Warning: There are unresolved conflicts at these paths: 221 conflicted.txt 2-sided conflict 222 Hint: To resolve the conflicts, start by updating to the first one: 223  jj new mzvwutvl 224 Then use `jj resolve`, or edit the conflict markers in the file directly. 225 Once the conflicts are resolved, you may want to inspect the result with `jj diff`. 226 Then run `jj squash` to move the resolution into the conflicted commit. 227 [EOF] 228 "); 229 230 let output = test_env.run_jj_in( 231 &repo_path, 232 ["status", "--config=hints.resolving-conflicts=false"], 233 ); 234 insta::assert_snapshot!(output, @r" 235 The working copy has no changes. 236 Working copy (@) : yqosqzyt dcb25635 (conflict) (empty) boom-cont-2 237 Parent commit (@-): royxmykx 664a4c6c (conflict) (empty) boom-cont 238 Warning: There are unresolved conflicts at these paths: 239 conflicted.txt 2-sided conflict 240 [EOF] 241 "); 242 243 // Resolve conflict 244 test_env 245 .run_jj_in(&repo_path, ["new", "--message", "fixed 1"]) 246 .success(); 247 std::fs::write(&conflicted_path, "first commit to fix conflict").unwrap(); 248 249 // Add one more commit atop the commit that resolves the conflict. 250 test_env 251 .run_jj_in(&repo_path, ["new", "--message", "fixed 2"]) 252 .success(); 253 std::fs::write(&conflicted_path, "edit not conflict").unwrap(); 254 255 // wc is now conflict free, parent is also conflict free 256 let output = test_env.run_jj_in(&repo_path, ["log", "-r", "::"]); 257 258 insta::assert_snapshot!(output, @r" 259 @ wqnwkozp test.user@example.com 2001-02-03 08:05:20 c4a6dbc2 260 │ fixed 2 261 ○ kmkuslsw test.user@example.com 2001-02-03 08:05:19 fcebf6ee 262 │ fixed 1 263 × yqosqzyt test.user@example.com 2001-02-03 08:05:13 dcb25635 conflict 264 │ (empty) boom-cont-2 265 × royxmykx test.user@example.com 2001-02-03 08:05:12 664a4c6c conflict 266 │ (empty) boom-cont 267 × mzvwutvl test.user@example.com 2001-02-03 08:05:11 c5a4e9cb conflict 268 ├─╮ (empty) boom 269 │ ○ kkmpptxz test.user@example.com 2001-02-03 08:05:10 1e8c2956 270 │ │ First part of conflicting change 271 ○ │ zsuskuln test.user@example.com 2001-02-03 08:05:11 2c8b19fd 272 ├─╯ Second part of conflicting change 273 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:08 aade7195 274 │ Initial contents 275 ◆ zzzzzzzz root() 00000000 276 [EOF] 277 "); 278 279 let output = test_env.run_jj_in(&repo_path, ["status"]); 280 281 insta::assert_snapshot!(output, @r" 282 Working copy changes: 283 M conflicted.txt 284 Working copy (@) : wqnwkozp c4a6dbc2 fixed 2 285 Parent commit (@-): kmkuslsw fcebf6ee fixed 1 286 [EOF] 287 "); 288 289 // Step back one. 290 // wc is still conflict free, parent has a conflict. 291 test_env.run_jj_in(&repo_path, ["edit", "@-"]).success(); 292 let output = test_env.run_jj_in(&repo_path, ["log", "-r", "::"]); 293 294 insta::assert_snapshot!(output, @r" 295 ○ wqnwkozp test.user@example.com 2001-02-03 08:05:20 c4a6dbc2 296 │ fixed 2 297 @ kmkuslsw test.user@example.com 2001-02-03 08:05:19 fcebf6ee 298 │ fixed 1 299 × yqosqzyt test.user@example.com 2001-02-03 08:05:13 dcb25635 conflict 300 │ (empty) boom-cont-2 301 × royxmykx test.user@example.com 2001-02-03 08:05:12 664a4c6c conflict 302 │ (empty) boom-cont 303 × mzvwutvl test.user@example.com 2001-02-03 08:05:11 c5a4e9cb conflict 304 ├─╮ (empty) boom 305 │ ○ kkmpptxz test.user@example.com 2001-02-03 08:05:10 1e8c2956 306 │ │ First part of conflicting change 307 ○ │ zsuskuln test.user@example.com 2001-02-03 08:05:11 2c8b19fd 308 ├─╯ Second part of conflicting change 309 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:08 aade7195 310 │ Initial contents 311 ◆ zzzzzzzz root() 00000000 312 [EOF] 313 "); 314 315 let output = test_env.run_jj_in(&repo_path, ["status"]); 316 317 insta::assert_snapshot!(output, @r" 318 Working copy changes: 319 M conflicted.txt 320 Working copy (@) : kmkuslsw fcebf6ee fixed 1 321 Parent commit (@-): yqosqzyt dcb25635 (conflict) (empty) boom-cont-2 322 Hint: Conflict in parent commit has been resolved in working copy 323 [EOF] 324 "); 325 326 // Step back to all the way to `root()+` so that wc has no conflict, even though 327 // there is a conflict later in the tree. So that we can confirm 328 // our hinting logic doesn't get confused. 329 test_env 330 .run_jj_in(&repo_path, ["edit", "root()+"]) 331 .success(); 332 let output = test_env.run_jj_in(&repo_path, ["log", "-r", "::"]); 333 334 insta::assert_snapshot!(output, @r" 335 ○ wqnwkozp test.user@example.com 2001-02-03 08:05:20 c4a6dbc2 336 │ fixed 2 337 ○ kmkuslsw test.user@example.com 2001-02-03 08:05:19 fcebf6ee 338 │ fixed 1 339 × yqosqzyt test.user@example.com 2001-02-03 08:05:13 dcb25635 conflict 340 │ (empty) boom-cont-2 341 × royxmykx test.user@example.com 2001-02-03 08:05:12 664a4c6c conflict 342 │ (empty) boom-cont 343 × mzvwutvl test.user@example.com 2001-02-03 08:05:11 c5a4e9cb conflict 344 ├─╮ (empty) boom 345 │ ○ kkmpptxz test.user@example.com 2001-02-03 08:05:10 1e8c2956 346 │ │ First part of conflicting change 347 ○ │ zsuskuln test.user@example.com 2001-02-03 08:05:11 2c8b19fd 348 ├─╯ Second part of conflicting change 349 @ qpvuntsm test.user@example.com 2001-02-03 08:05:08 aade7195 350 │ Initial contents 351 ◆ zzzzzzzz root() 00000000 352 [EOF] 353 "); 354 355 let output = test_env.run_jj_in(&repo_path, ["status"]); 356 357 insta::assert_snapshot!(output, @r" 358 Working copy changes: 359 A conflicted.txt 360 Working copy (@) : qpvuntsm aade7195 Initial contents 361 Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set) 362 [EOF] 363 "); 364} 365 366#[test] 367fn test_status_simplify_conflict_sides() { 368 let test_env = TestEnvironment::default(); 369 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 370 let repo_path = test_env.env_root().join("repo"); 371 372 // Creates a 4-sided conflict, with fileA and fileB having different conflicts: 373 // fileA: A - B + C - B + B - B + B 374 // fileB: A - A + A - A + B - C + D 375 create_commit_with_files( 376 &test_env.work_dir(&repo_path), 377 "base", 378 &[], 379 &[("fileA", "base\n"), ("fileB", "base\n")], 380 ); 381 create_commit_with_files( 382 &test_env.work_dir(&repo_path), 383 "a1", 384 &["base"], 385 &[("fileA", "1\n")], 386 ); 387 create_commit_with_files( 388 &test_env.work_dir(&repo_path), 389 "a2", 390 &["base"], 391 &[("fileA", "2\n")], 392 ); 393 create_commit_with_files( 394 &test_env.work_dir(&repo_path), 395 "b1", 396 &["base"], 397 &[("fileB", "1\n")], 398 ); 399 create_commit_with_files( 400 &test_env.work_dir(&repo_path), 401 "b2", 402 &["base"], 403 &[("fileB", "2\n")], 404 ); 405 create_commit_with_files( 406 &test_env.work_dir(&repo_path), 407 "conflictA", 408 &["a1", "a2"], 409 &[], 410 ); 411 create_commit_with_files( 412 &test_env.work_dir(&repo_path), 413 "conflictB", 414 &["b1", "b2"], 415 &[], 416 ); 417 create_commit_with_files( 418 &test_env.work_dir(&repo_path), 419 "conflict", 420 &["conflictA", "conflictB"], 421 &[], 422 ); 423 424 insta::assert_snapshot!(test_env.run_jj_in(&repo_path, ["status"]), 425 @r" 426 The working copy has no changes. 427 Working copy (@) : nkmrtpmo 83c4b9e7 conflict | (conflict) (empty) conflict 428 Parent commit (@-): kmkuslsw 4601566f conflictA | (conflict) (empty) conflictA 429 Parent commit (@-): lylxulpl 6f8d8381 conflictB | (conflict) (empty) conflictB 430 Warning: There are unresolved conflicts at these paths: 431 fileA 2-sided conflict 432 fileB 2-sided conflict 433 Hint: To resolve the conflicts, start by updating to one of the first ones: 434 jj new lylxulpl 435 jj new kmkuslsw 436 Then use `jj resolve`, or edit the conflict markers in the file directly. 437 Once the conflicts are resolved, you may want to inspect the result with `jj diff`. 438 Then run `jj squash` to move the resolution into the conflicted commit. 439 [EOF] 440 "); 441} 442 443#[test] 444fn test_status_untracked_files() { 445 let test_env = TestEnvironment::default(); 446 test_env.add_config(r#"snapshot.auto-track = "none()""#); 447 448 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 449 let repo_path = test_env.env_root().join("repo"); 450 451 std::fs::write(repo_path.join("always-untracked-file"), "...").unwrap(); 452 std::fs::write(repo_path.join("initially-untracked-file"), "...").unwrap(); 453 std::fs::create_dir(repo_path.join("sub")).unwrap(); 454 std::fs::write(repo_path.join("sub").join("always-untracked"), "...").unwrap(); 455 std::fs::write(repo_path.join("sub").join("initially-untracked"), "...").unwrap(); 456 457 let output = test_env.run_jj_in(&repo_path, ["status"]); 458 insta::assert_snapshot!(output.normalize_backslash(), @r" 459 Untracked paths: 460 ? always-untracked-file 461 ? initially-untracked-file 462 ? sub/always-untracked 463 ? sub/initially-untracked 464 Working copy (@) : qpvuntsm 230dd059 (empty) (no description set) 465 Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set) 466 [EOF] 467 "); 468 469 test_env 470 .run_jj_in( 471 &repo_path, 472 [ 473 "file", 474 "track", 475 "initially-untracked-file", 476 "sub/initially-untracked", 477 ], 478 ) 479 .success(); 480 481 let output = test_env.run_jj_in(&repo_path, ["status"]); 482 insta::assert_snapshot!(output.normalize_backslash(), @r" 483 Working copy changes: 484 A initially-untracked-file 485 A sub/initially-untracked 486 Untracked paths: 487 ? always-untracked-file 488 ? sub/always-untracked 489 Working copy (@) : qpvuntsm 99798fcd (no description set) 490 Parent commit (@-): zzzzzzzz 00000000 (empty) (no description set) 491 [EOF] 492 "); 493 494 test_env.run_jj_in(&repo_path, ["new"]).success(); 495 496 let output = test_env.run_jj_in(&repo_path, ["status"]); 497 insta::assert_snapshot!(output.normalize_backslash(), @r" 498 Untracked paths: 499 ? always-untracked-file 500 ? sub/always-untracked 501 Working copy (@) : mzvwutvl 30e53c74 (empty) (no description set) 502 Parent commit (@-): qpvuntsm 99798fcd (no description set) 503 [EOF] 504 "); 505 506 test_env 507 .run_jj_in( 508 &repo_path, 509 [ 510 "file", 511 "untrack", 512 "initially-untracked-file", 513 "sub/initially-untracked", 514 ], 515 ) 516 .success(); 517 let output = test_env.run_jj_in(&repo_path, ["status"]); 518 insta::assert_snapshot!(output.normalize_backslash(), @r" 519 Working copy changes: 520 D initially-untracked-file 521 D sub/initially-untracked 522 Untracked paths: 523 ? always-untracked-file 524 ? initially-untracked-file 525 ? sub/always-untracked 526 ? sub/initially-untracked 527 Working copy (@) : mzvwutvl bb362aaf (no description set) 528 Parent commit (@-): qpvuntsm 99798fcd (no description set) 529 [EOF] 530 "); 531 532 test_env.run_jj_in(&repo_path, ["new"]).success(); 533 534 let output = test_env.run_jj_in(&repo_path, ["status"]); 535 insta::assert_snapshot!(output.normalize_backslash(), @r" 536 Untracked paths: 537 ? always-untracked-file 538 ? initially-untracked-file 539 ? sub/always-untracked 540 ? sub/initially-untracked 541 Working copy (@) : yostqsxw 8e8c02fe (empty) (no description set) 542 Parent commit (@-): mzvwutvl bb362aaf (no description set) 543 [EOF] 544 "); 545}