just playing with tangled
at ig/vimdiffwarn 530 lines 16 kB view raw
1// Copyright 2023 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; 16use crate::common::CommandOutput; 17use crate::common::TestEnvironment; 18use crate::common::TestWorkDir; 19 20#[test] 21fn test_basics() { 22 let test_env = TestEnvironment::default(); 23 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 24 let work_dir = test_env.work_dir("repo"); 25 26 create_commit(&work_dir, "a", &[]); 27 create_commit(&work_dir, "b", &["a"]); 28 create_commit(&work_dir, "c", &[]); 29 create_commit(&work_dir, "d", &["c"]); 30 create_commit(&work_dir, "e", &["a", "d"]); 31 // Test the setup 32 insta::assert_snapshot!(get_log_output(&work_dir), @r" 33 @ [znk] e 34 ├─╮ 35 │ ○ [vru] d 36 │ ○ [roy] c 37 │ │ ○ [zsu] b 38 ├───╯ 39 ○ │ [rlv] a 40 ├─╯ 41 ◆ [zzz] 42 [EOF] 43 "); 44 45 let output = work_dir.run_jj(["abandon", "--retain-bookmarks", "d"]); 46 insta::assert_snapshot!(output, @r" 47 ------- stderr ------- 48 Abandoned 1 commits: 49 vruxwmqv b7c62f28 d | d 50 Rebased 1 descendant commits onto parents of abandoned commits 51 Working copy (@) now at: znkkpsqq 11a2e10e e | e 52 Parent commit (@-) : rlvkpnrz 2443ea76 a | a 53 Parent commit (@-) : royxmykx fe2e8e8b c d | c 54 Added 0 files, modified 0 files, removed 1 files 55 [EOF] 56 "); 57 insta::assert_snapshot!(get_log_output(&work_dir), @r" 58 @ [znk] e 59 ├─╮ 60 │ ○ [roy] c d 61 │ │ ○ [zsu] b 62 ├───╯ 63 ○ │ [rlv] a 64 ├─╯ 65 ◆ [zzz] 66 [EOF] 67 "); 68 69 work_dir.run_jj(["undo"]).success(); 70 let output = work_dir.run_jj(["abandon", "--retain-bookmarks"]); // abandons `e` 71 insta::assert_snapshot!(output, @r" 72 ------- stderr ------- 73 Abandoned 1 commits: 74 znkkpsqq 5557ece3 e | e 75 Working copy (@) now at: nkmrtpmo d4f8ea73 (empty) (no description set) 76 Parent commit (@-) : rlvkpnrz 2443ea76 a e?? | a 77 Parent commit (@-) : vruxwmqv b7c62f28 d e?? | d 78 Added 0 files, modified 0 files, removed 1 files 79 [EOF] 80 "); 81 insta::assert_snapshot!(get_log_output(&work_dir), @r" 82 @ [nkm] 83 ├─╮ 84 │ ○ [vru] d e?? 85 │ ○ [roy] c 86 │ │ ○ [zsu] b 87 ├───╯ 88 ○ │ [rlv] a e?? 89 ├─╯ 90 ◆ [zzz] 91 [EOF] 92 "); 93 94 work_dir.run_jj(["undo"]).success(); 95 let output = work_dir.run_jj(["abandon", "descendants(d)"]); 96 insta::assert_snapshot!(output, @r" 97 ------- stderr ------- 98 Abandoned 2 commits: 99 znkkpsqq 5557ece3 e | e 100 vruxwmqv b7c62f28 d | d 101 Deleted bookmarks: d, e 102 Working copy (@) now at: xtnwkqum fa4ee8e6 (empty) (no description set) 103 Parent commit (@-) : rlvkpnrz 2443ea76 a | a 104 Parent commit (@-) : royxmykx fe2e8e8b c | c 105 Added 0 files, modified 0 files, removed 2 files 106 [EOF] 107 "); 108 insta::assert_snapshot!(get_log_output(&work_dir), @r" 109 @ [xtn] 110 ├─╮ 111 │ ○ [roy] c 112 │ │ ○ [zsu] b 113 ├───╯ 114 ○ │ [rlv] a 115 ├─╯ 116 ◆ [zzz] 117 [EOF] 118 "); 119 120 // Test abandoning the same commit twice directly 121 work_dir.run_jj(["undo"]).success(); 122 let output = work_dir.run_jj(["abandon", "-rb", "b"]); 123 insta::assert_snapshot!(output, @r" 124 ------- stderr ------- 125 Abandoned 1 commits: 126 zsuskuln 1394f625 b | b 127 Deleted bookmarks: b 128 [EOF] 129 "); 130 insta::assert_snapshot!(get_log_output(&work_dir), @r" 131 @ [znk] e 132 ├─╮ 133 │ ○ [vru] d 134 │ ○ [roy] c 135 ○ │ [rlv] a 136 ├─╯ 137 ◆ [zzz] 138 [EOF] 139 "); 140 141 // Test abandoning the same commit twice indirectly 142 work_dir.run_jj(["undo"]).success(); 143 let output = work_dir.run_jj(["abandon", "d::", "e"]); 144 insta::assert_snapshot!(output, @r" 145 ------- stderr ------- 146 Abandoned 2 commits: 147 znkkpsqq 5557ece3 e | e 148 vruxwmqv b7c62f28 d | d 149 Deleted bookmarks: d, e 150 Working copy (@) now at: xlzxqlsl 14991aec (empty) (no description set) 151 Parent commit (@-) : rlvkpnrz 2443ea76 a | a 152 Parent commit (@-) : royxmykx fe2e8e8b c | c 153 Added 0 files, modified 0 files, removed 2 files 154 [EOF] 155 "); 156 insta::assert_snapshot!(get_log_output(&work_dir), @r" 157 @ [xlz] 158 ├─╮ 159 │ ○ [roy] c 160 │ │ ○ [zsu] b 161 ├───╯ 162 ○ │ [rlv] a 163 ├─╯ 164 ◆ [zzz] 165 [EOF] 166 "); 167 168 let output = work_dir.run_jj(["abandon", "none()"]); 169 insta::assert_snapshot!(output, @r" 170 ------- stderr ------- 171 No revisions to abandon. 172 [EOF] 173 "); 174} 175 176#[test] 177fn test_abandon_many() { 178 let test_env = TestEnvironment::default(); 179 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 180 let work_dir = test_env.work_dir("repo"); 181 182 for i in 0..10 { 183 work_dir.run_jj(["new", &format!("-mcommit{i}")]).success(); 184 } 185 186 // The list of commits should be elided. 187 let output = work_dir.run_jj(["abandon", ".."]); 188 insta::assert_snapshot!(output, @r" 189 ------- stderr ------- 190 Abandoned 11 commits: 191 kpqxywon 0b998aa3 (empty) commit9 192 znkkpsqq c37abefb (empty) commit8 193 yostqsxw 6256698f (empty) commit7 194 vruxwmqv 9350f605 (empty) commit6 195 yqosqzyt 196bd23d (empty) commit5 196 royxmykx bb676781 (empty) commit4 197 mzvwutvl 6f1e55a6 (empty) commit3 198 zsuskuln baf1311c (empty) commit2 199 kkmpptxz 5fc5f374 (empty) commit1 200 rlvkpnrz 9451b4ea (empty) commit0 201 ... 202 Working copy (@) now at: kmkuslsw 822a2cf5 (empty) (no description set) 203 Parent commit (@-) : zzzzzzzz 00000000 (empty) (no description set) 204 [EOF] 205 "); 206} 207 208// This behavior illustrates https://github.com/jj-vcs/jj/issues/2600. 209// See also the corresponding test in `test_rebase_command` 210#[test] 211fn test_bug_2600() { 212 let test_env = TestEnvironment::default(); 213 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 214 let work_dir = test_env.work_dir("repo"); 215 216 // We will not touch "nottherootcommit". See the 217 // `test_bug_2600_rootcommit_special_case` for the one case where base being the 218 // child of the root commit changes the expected behavior. 219 create_commit(&work_dir, "nottherootcommit", &[]); 220 create_commit(&work_dir, "base", &["nottherootcommit"]); 221 create_commit(&work_dir, "a", &["base"]); 222 create_commit(&work_dir, "b", &["base", "a"]); 223 create_commit(&work_dir, "c", &["b"]); 224 225 // Test the setup 226 insta::assert_snapshot!(get_log_output(&work_dir), @r" 227 @ [znk] c 228 ○ [vru] b 229 ├─╮ 230 │ ○ [roy] a 231 ├─╯ 232 ○ [zsu] base 233 ○ [rlv] nottherootcommit 234 ◆ [zzz] 235 [EOF] 236 "); 237 let setup_opid = work_dir.current_operation_id(); 238 239 work_dir.run_jj(["op", "restore", &setup_opid]).success(); 240 let output = work_dir.run_jj(["abandon", "base"]); 241 insta::assert_snapshot!(output, @r" 242 ------- stderr ------- 243 Abandoned 1 commits: 244 zsuskuln 73c929fc base | base 245 Deleted bookmarks: base 246 Rebased 3 descendant commits onto parents of abandoned commits 247 Working copy (@) now at: znkkpsqq 86e31bec c | c 248 Parent commit (@-) : vruxwmqv fd6eb121 b | b 249 Added 0 files, modified 0 files, removed 1 files 250 [EOF] 251 "); 252 // Commits "a" and "b" should both have "nottherootcommit" as parent, and "b" 253 // should keep "a" as second parent. 254 insta::assert_snapshot!(get_log_output(&work_dir), @r" 255 @ [znk] c 256 ○ [vru] b 257 ├─╮ 258 │ ○ [roy] a 259 ├─╯ 260 ○ [rlv] nottherootcommit 261 ◆ [zzz] 262 [EOF] 263 "); 264 265 work_dir.run_jj(["op", "restore", &setup_opid]).success(); 266 let output = work_dir.run_jj(["abandon", "a"]); 267 insta::assert_snapshot!(output, @r" 268 ------- stderr ------- 269 Abandoned 1 commits: 270 royxmykx 98f3b9ba a | a 271 Deleted bookmarks: a 272 Rebased 2 descendant commits onto parents of abandoned commits 273 Working copy (@) now at: znkkpsqq 683b9435 c | c 274 Parent commit (@-) : vruxwmqv c10cb7b4 b | b 275 Added 0 files, modified 0 files, removed 1 files 276 [EOF] 277 "); 278 // Commit "b" should have "base" as parent. It should not have two parent 279 // pointers to that commit even though it was a merge commit before we abandoned 280 // "a". 281 insta::assert_snapshot!(get_log_output(&work_dir), @r" 282 @ [znk] c 283 ○ [vru] b 284 ○ [zsu] base 285 ○ [rlv] nottherootcommit 286 ◆ [zzz] 287 [EOF] 288 "); 289 290 work_dir.run_jj(["op", "restore", &setup_opid]).success(); 291 let output = work_dir.run_jj(["abandon", "b"]); 292 insta::assert_snapshot!(output, @r" 293 ------- stderr ------- 294 Abandoned 1 commits: 295 vruxwmqv 8c0dced0 b | b 296 Deleted bookmarks: b 297 Rebased 1 descendant commits onto parents of abandoned commits 298 Working copy (@) now at: znkkpsqq 33a94991 c | c 299 Parent commit (@-) : zsuskuln 73c929fc base | base 300 Parent commit (@-) : royxmykx 98f3b9ba a | a 301 Added 0 files, modified 0 files, removed 1 files 302 [EOF] 303 "); 304 // Commit "c" should inherit the parents from the abndoned commit "b". 305 insta::assert_snapshot!(get_log_output(&work_dir), @r" 306 @ [znk] c 307 ├─╮ 308 │ ○ [roy] a 309 ├─╯ 310 ○ [zsu] base 311 ○ [rlv] nottherootcommit 312 ◆ [zzz] 313 [EOF] 314 "); 315 316 work_dir.run_jj(["op", "restore", &setup_opid]).success(); 317 // ========= Reminder of the setup =========== 318 insta::assert_snapshot!(get_log_output(&work_dir), @r" 319 @ [znk] c 320 ○ [vru] b 321 ├─╮ 322 │ ○ [roy] a 323 ├─╯ 324 ○ [zsu] base 325 ○ [rlv] nottherootcommit 326 ◆ [zzz] 327 [EOF] 328 "); 329 let output = work_dir.run_jj(["abandon", "--retain-bookmarks", "a", "b"]); 330 insta::assert_snapshot!(output, @r" 331 ------- stderr ------- 332 Abandoned 2 commits: 333 vruxwmqv 8c0dced0 b | b 334 royxmykx 98f3b9ba a | a 335 Rebased 1 descendant commits onto parents of abandoned commits 336 Working copy (@) now at: znkkpsqq 84fac1f8 c | c 337 Parent commit (@-) : zsuskuln 73c929fc a b base | base 338 Added 0 files, modified 0 files, removed 2 files 339 [EOF] 340 "); 341 // Commit "c" should have "base" as parent. As when we abandoned "a", it should 342 // not have two parent pointers to the same commit. 343 insta::assert_snapshot!(get_log_output(&work_dir), @r" 344 @ [znk] c 345 ○ [zsu] a b base 346 ○ [rlv] nottherootcommit 347 ◆ [zzz] 348 [EOF] 349 "); 350 let output = work_dir.run_jj(["bookmark", "list", "b"]); 351 insta::assert_snapshot!(output, @r" 352 b: zsuskuln 73c929fc base 353 [EOF] 354 "); 355} 356 357#[test] 358fn test_bug_2600_rootcommit_special_case() { 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 // Set up like `test_bug_2600`, but without the `nottherootcommit` commit. 364 create_commit(&work_dir, "base", &[]); 365 create_commit(&work_dir, "a", &["base"]); 366 create_commit(&work_dir, "b", &["base", "a"]); 367 create_commit(&work_dir, "c", &["b"]); 368 369 // Setup 370 insta::assert_snapshot!(get_log_output(&work_dir), @r" 371 @ [vru] c 372 ○ [roy] b 373 ├─╮ 374 │ ○ [zsu] a 375 ├─╯ 376 ○ [rlv] base 377 ◆ [zzz] 378 [EOF] 379 "); 380 381 // Now, the test 382 let output = work_dir.run_jj(["abandon", "base"]); 383 insta::assert_snapshot!(output, @r" 384 ------- stderr ------- 385 Error: The Git backend does not support creating merge commits with the root commit as one of the parents. 386 [EOF] 387 [exit status: 1] 388 "); 389} 390 391#[test] 392fn test_double_abandon() { 393 let test_env = TestEnvironment::default(); 394 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 395 let work_dir = test_env.work_dir("repo"); 396 397 create_commit(&work_dir, "a", &[]); 398 // Test the setup 399 insta::assert_snapshot!(work_dir.run_jj(["log", "--no-graph", "-r", "a"]), @r" 400 rlvkpnrz test.user@example.com 2001-02-03 08:05:09 a 2443ea76 401 a 402 [EOF] 403 "); 404 405 let commit_id = work_dir 406 .run_jj(["log", "--no-graph", "--color=never", "-T=commit_id", "-r=a"]) 407 .success() 408 .stdout 409 .into_raw(); 410 411 let output = work_dir.run_jj(["abandon", &commit_id]); 412 insta::assert_snapshot!(output, @r" 413 ------- stderr ------- 414 Abandoned 1 commits: 415 rlvkpnrz 2443ea76 a | a 416 Deleted bookmarks: a 417 Working copy (@) now at: royxmykx f37b4afd (empty) (no description set) 418 Parent commit (@-) : zzzzzzzz 00000000 (empty) (no description set) 419 Added 0 files, modified 0 files, removed 1 files 420 [EOF] 421 "); 422 let output = work_dir.run_jj(["abandon", &commit_id]); 423 insta::assert_snapshot!(output, @r" 424 ------- stderr ------- 425 Abandoned 1 commits: 426 rlvkpnrz hidden 2443ea76 a 427 Nothing changed. 428 [EOF] 429 "); 430} 431 432#[test] 433fn test_abandon_restore_descendants() { 434 let test_env = TestEnvironment::default(); 435 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 436 let work_dir = test_env.work_dir("repo"); 437 438 work_dir.write_file("file", "foo\n"); 439 work_dir.run_jj(["new"]).success(); 440 work_dir.write_file("file", "bar\n"); 441 work_dir.run_jj(["new"]).success(); 442 work_dir.write_file("file", "baz\n"); 443 444 // Remove the commit containing "bar" 445 let output = work_dir.run_jj(["abandon", "-r@-", "--restore-descendants"]); 446 insta::assert_snapshot!(output, @r" 447 ------- stderr ------- 448 Abandoned 1 commits: 449 rlvkpnrz 225adef1 (no description set) 450 Rebased 1 descendant commits (while preserving their content) onto parents of abandoned commits 451 Working copy (@) now at: kkmpptxz a734deb0 (no description set) 452 Parent commit (@-) : qpvuntsm 485d52a9 (no description set) 453 [EOF] 454 "); 455 let output = work_dir.run_jj(["diff", "--git"]); 456 insta::assert_snapshot!(output, @r" 457 diff --git a/file b/file 458 index 257cc5642c..76018072e0 100644 459 --- a/file 460 +++ b/file 461 @@ -1,1 +1,1 @@ 462 -foo 463 +baz 464 [EOF] 465 "); 466} 467 468#[test] 469fn test_abandon_tracking_bookmarks() { 470 let test_env = TestEnvironment::default(); 471 472 test_env.run_jj_in(".", ["git", "init", "remote"]).success(); 473 let remote_dir = test_env.work_dir("remote"); 474 remote_dir 475 .run_jj(["bookmark", "set", "-r@", "foo"]) 476 .success(); 477 remote_dir.run_jj(["git", "export"]).success(); 478 479 // Create colocated Git repo which may have @git tracking bookmarks 480 test_env 481 .run_jj_in( 482 ".", 483 [ 484 "git", 485 "clone", 486 "--colocate", 487 "--config=git.auto-local-bookmark=true", 488 "remote/.jj/repo/store/git", 489 "local", 490 ], 491 ) 492 .success(); 493 let local_dir = test_env.work_dir("local"); 494 local_dir 495 .run_jj(["bookmark", "set", "-r@", "bar"]) 496 .success(); 497 insta::assert_snapshot!(get_log_output(&local_dir), @r" 498 @ [zsu] bar 499 │ ○ [vvk] foo 500 ├─╯ 501 ◆ [zzz] 502 [EOF] 503 "); 504 505 let output = local_dir.run_jj(["abandon", "foo"]); 506 insta::assert_snapshot!(output, @r" 507 ------- stderr ------- 508 Abandoned 1 commits: 509 vvkvtnvv 230dd059 foo | (empty) (no description set) 510 Deleted bookmarks: foo 511 Warning: Remote bookmarks tracked by deleted bookmarks will be deleted on the next `jj git push`. 512 [EOF] 513 "); 514 let output = local_dir.run_jj(["abandon", "bar"]); 515 insta::assert_snapshot!(output, @r" 516 ------- stderr ------- 517 Abandoned 1 commits: 518 zsuskuln f652c321 bar | (empty) (no description set) 519 Deleted bookmarks: bar 520 Working copy (@) now at: vruxwmqv 41658cf4 (empty) (no description set) 521 Parent commit (@-) : zzzzzzzz 00000000 (empty) (no description set) 522 [EOF] 523 "); 524} 525 526#[must_use] 527fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput { 528 let template = r#"separate(" ", "[" ++ change_id.short(3) ++ "]", bookmarks)"#; 529 work_dir.run_jj(["log", "-T", template]) 530}