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 indoc::indoc;
16
17use crate::common::TestEnvironment;
18
19#[test]
20fn test_diffedit() {
21 let mut test_env = TestEnvironment::default();
22 let edit_script = test_env.set_up_fake_diff_editor();
23 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
24 let work_dir = test_env.work_dir("repo");
25
26 work_dir.write_file("file1", "a\n");
27 work_dir.run_jj(["new"]).success();
28 work_dir.write_file("file2", "a\n");
29 work_dir.write_file("file3", "a\n");
30 work_dir.run_jj(["new"]).success();
31 work_dir.remove_file("file1");
32 work_dir.write_file("file2", "b\n");
33
34 // Test the setup; nothing happens if we make no changes
35 std::fs::write(
36 &edit_script,
37 [
38 "files-before file1 file2",
39 "files-after JJ-INSTRUCTIONS file2",
40 "dump JJ-INSTRUCTIONS instrs",
41 ]
42 .join("\0"),
43 )
44 .unwrap();
45 let output = work_dir.run_jj(["diffedit"]);
46 insta::assert_snapshot!(output, @r"
47 ------- stderr -------
48 Nothing changed.
49 [EOF]
50 ");
51 insta::assert_snapshot!(
52 std::fs::read_to_string(test_env.env_root().join("instrs")).unwrap(), @r"
53 You are editing changes in: kkmpptxz 3d4cce89 (no description set)
54
55 The diff initially shows the commit's changes.
56
57 Adjust the right side until it shows the contents you want. If you
58 don't make any changes, then the operation will be aborted.
59 ");
60 let output = work_dir.run_jj(["diff", "-s"]);
61 insta::assert_snapshot!(output, @r"
62 D file1
63 M file2
64 [EOF]
65 ");
66
67 // Try again with ui.diff-instructions=false
68 std::fs::write(&edit_script, "files-before file1 file2\0files-after file2").unwrap();
69 let output = work_dir.run_jj(["diffedit", "--config=ui.diff-instructions=false"]);
70 insta::assert_snapshot!(output, @r"
71 ------- stderr -------
72 Nothing changed.
73 [EOF]
74 ");
75 let output = work_dir.run_jj(["diff", "-s"]);
76 insta::assert_snapshot!(output, @r"
77 D file1
78 M file2
79 [EOF]
80 ");
81
82 // Try again with --tool=<name>
83 std::fs::write(
84 &edit_script,
85 "files-before file1 file2\0files-after JJ-INSTRUCTIONS file2",
86 )
87 .unwrap();
88 let output = work_dir.run_jj([
89 "diffedit",
90 "--config=ui.diff-editor='false'",
91 "--tool=fake-diff-editor",
92 ]);
93 insta::assert_snapshot!(output, @r"
94 ------- stderr -------
95 Nothing changed.
96 [EOF]
97 ");
98 let output = work_dir.run_jj(["diff", "-s"]);
99 insta::assert_snapshot!(output, @r"
100 D file1
101 M file2
102 [EOF]
103 ");
104
105 // Nothing happens if the diff-editor exits with an error
106 std::fs::write(&edit_script, "rm file2\0fail").unwrap();
107 let output = work_dir.run_jj(["diffedit"]);
108 insta::assert_snapshot!(output.normalize_stderr_exit_status(), @r"
109 ------- stderr -------
110 Error: Failed to edit diff
111 Caused by: Tool exited with exit status: 1 (run with --debug to see the exact invocation)
112 [EOF]
113 [exit status: 1]
114 ");
115 let output = work_dir.run_jj(["diff", "-s"]);
116 insta::assert_snapshot!(output, @r"
117 D file1
118 M file2
119 [EOF]
120 ");
121
122 // Can edit changes to individual files
123 std::fs::write(&edit_script, "reset file2").unwrap();
124 let output = work_dir.run_jj(["diffedit"]);
125 insta::assert_snapshot!(output, @r"
126 ------- stderr -------
127 Created kkmpptxz cbc7a725 (no description set)
128 Working copy (@) now at: kkmpptxz cbc7a725 (no description set)
129 Parent commit (@-) : rlvkpnrz a72506cd (no description set)
130 Added 0 files, modified 1 files, removed 0 files
131 [EOF]
132 ");
133 let output = work_dir.run_jj(["diff", "-s"]);
134 insta::assert_snapshot!(output, @r"
135 D file1
136 [EOF]
137 ");
138
139 // Changes to a commit are propagated to descendants
140 work_dir.run_jj(["undo"]).success();
141 std::fs::write(&edit_script, "write file3\nmodified\n").unwrap();
142 let output = work_dir.run_jj(["diffedit", "-r", "@-"]);
143 insta::assert_snapshot!(output, @r"
144 ------- stderr -------
145 Created rlvkpnrz d4eef3fc (no description set)
146 Rebased 1 descendant commits
147 Working copy (@) now at: kkmpptxz 59ef1b95 (no description set)
148 Parent commit (@-) : rlvkpnrz d4eef3fc (no description set)
149 Added 0 files, modified 1 files, removed 0 files
150 [EOF]
151 ");
152 let contents = work_dir.read_file("file3");
153 insta::assert_snapshot!(contents, @"modified");
154
155 // Test diffedit --from @--
156 work_dir.run_jj(["undo"]).success();
157 std::fs::write(
158 &edit_script,
159 "files-before file1\0files-after JJ-INSTRUCTIONS file2 file3\0reset file2",
160 )
161 .unwrap();
162 let output = work_dir.run_jj(["diffedit", "--from", "@--"]);
163 insta::assert_snapshot!(output, @r"
164 ------- stderr -------
165 Created kkmpptxz 5b585bd1 (no description set)
166 Working copy (@) now at: kkmpptxz 5b585bd1 (no description set)
167 Parent commit (@-) : rlvkpnrz a72506cd (no description set)
168 Added 0 files, modified 0 files, removed 1 files
169 [EOF]
170 ");
171 let output = work_dir.run_jj(["diff", "-s"]);
172 insta::assert_snapshot!(output, @r"
173 D file1
174 D file2
175 [EOF]
176 ");
177}
178
179#[test]
180fn test_diffedit_new_file() {
181 let mut test_env = TestEnvironment::default();
182 let edit_script = test_env.set_up_fake_diff_editor();
183 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
184 let work_dir = test_env.work_dir("repo");
185
186 work_dir.write_file("file1", "a\n");
187 work_dir.run_jj(["new"]).success();
188 work_dir.remove_file("file1");
189 work_dir.write_file("file2", "b\n");
190
191 // Test the setup; nothing happens if we make no changes
192 std::fs::write(
193 &edit_script,
194 "files-before file1\0files-after JJ-INSTRUCTIONS file2",
195 )
196 .unwrap();
197 let output = work_dir.run_jj(["diffedit"]);
198 insta::assert_snapshot!(output, @r"
199 ------- stderr -------
200 Nothing changed.
201 [EOF]
202 ");
203 let output = work_dir.run_jj(["diff", "-s"]);
204 insta::assert_snapshot!(output, @r"
205 D file1
206 A file2
207 [EOF]
208 ");
209
210 // Creating `file1` on the right side is noticed by `jj diffedit`
211 std::fs::write(&edit_script, "write file1\nmodified\n").unwrap();
212 let output = work_dir.run_jj(["diffedit"]);
213 insta::assert_snapshot!(output, @r"
214 ------- stderr -------
215 Created rlvkpnrz b0376e2b (no description set)
216 Working copy (@) now at: rlvkpnrz b0376e2b (no description set)
217 Parent commit (@-) : qpvuntsm b739eb46 (no description set)
218 Added 1 files, modified 0 files, removed 0 files
219 [EOF]
220 ");
221 let output = work_dir.run_jj(["diff", "-s"]);
222 insta::assert_snapshot!(output, @r"
223 M file1
224 A file2
225 [EOF]
226 ");
227
228 // Creating a file that wasn't on either side is ignored by diffedit.
229 // TODO(ilyagr) We should decide whether we like this behavior.
230 //
231 // On one hand, it is unexpected and potentially a minor BUG. On the other
232 // hand, this prevents `jj` from loading any backup files the merge tool
233 // generates.
234 work_dir.run_jj(["undo"]).success();
235 std::fs::write(&edit_script, "write new_file\nnew file\n").unwrap();
236 let output = work_dir.run_jj(["diffedit"]);
237 insta::assert_snapshot!(output, @r"
238 ------- stderr -------
239 Nothing changed.
240 [EOF]
241 ");
242 let output = work_dir.run_jj(["diff", "-s"]);
243 insta::assert_snapshot!(output, @r"
244 D file1
245 A file2
246 [EOF]
247 ");
248}
249
250#[test]
251fn test_diffedit_external_tool_conflict_marker_style() {
252 let mut test_env = TestEnvironment::default();
253 let edit_script = test_env.set_up_fake_diff_editor();
254 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
255 let work_dir = test_env.work_dir("repo");
256 let file_path = "file";
257
258 // Create a conflict
259 work_dir.write_file(
260 file_path,
261 indoc! {"
262 line 1
263 line 2
264 line 3
265 line 4
266 line 5
267 "},
268 );
269 work_dir.run_jj(["commit", "-m", "base"]).success();
270 work_dir.write_file(
271 file_path,
272 indoc! {"
273 line 1
274 line 2.1
275 line 2.2
276 line 3
277 line 4.1
278 line 5
279 "},
280 );
281 work_dir.run_jj(["describe", "-m", "side-a"]).success();
282 work_dir
283 .run_jj(["new", "description(base)", "-m", "side-b"])
284 .success();
285 work_dir.write_file(
286 file_path,
287 indoc! {"
288 line 1
289 line 2.3
290 line 3
291 line 4.2
292 line 4.3
293 line 5
294 "},
295 );
296
297 // Resolve one of the conflicts in the working copy
298 work_dir
299 .run_jj(["new", "description(side-a)", "description(side-b)"])
300 .success();
301 work_dir.write_file(
302 file_path,
303 indoc! {"
304 line 1
305 line 2.1
306 line 2.2
307 line 2.3
308 line 3
309 <<<<<<<
310 %%%%%%%
311 -line 4
312 +line 4.1
313 +++++++
314 line 4.2
315 line 4.3
316 >>>>>>>
317 line 5
318 "},
319 );
320
321 // Set up diff editor to use "snapshot" conflict markers
322 test_env.add_config(r#"merge-tools.fake-diff-editor.conflict-marker-style = "snapshot""#);
323
324 // We want to see whether the diff editor is using the correct conflict markers,
325 // and reset it to make sure that it parses the conflict markers as well
326 std::fs::write(
327 &edit_script,
328 [
329 "files-before file",
330 "files-after JJ-INSTRUCTIONS file",
331 "dump file after-file",
332 "reset file",
333 "dump file before-file",
334 ]
335 .join("\0"),
336 )
337 .unwrap();
338 let output = work_dir.run_jj(["diffedit"]);
339 insta::assert_snapshot!(output, @r"
340 ------- stderr -------
341 Created mzvwutvl fb39e804 (conflict) (empty) (no description set)
342 Working copy (@) now at: mzvwutvl fb39e804 (conflict) (empty) (no description set)
343 Parent commit (@-) : rlvkpnrz 3765cc27 side-a
344 Parent commit (@-) : zsuskuln 8b3de837 side-b
345 Added 0 files, modified 1 files, removed 0 files
346 Warning: There are unresolved conflicts at these paths:
347 file 2-sided conflict
348 Existing conflicts were resolved or abandoned from 1 commits.
349 [EOF]
350 ");
351 // Conflicts should render using "snapshot" format in diff editor
352 insta::assert_snapshot!(
353 std::fs::read_to_string(test_env.env_root().join("before-file")).unwrap(), @r"
354 line 1
355 <<<<<<< Conflict 1 of 2
356 +++++++ Contents of side #1
357 line 2.1
358 line 2.2
359 ------- Contents of base
360 line 2
361 +++++++ Contents of side #2
362 line 2.3
363 >>>>>>> Conflict 1 of 2 ends
364 line 3
365 <<<<<<< Conflict 2 of 2
366 +++++++ Contents of side #1
367 line 4.1
368 ------- Contents of base
369 line 4
370 +++++++ Contents of side #2
371 line 4.2
372 line 4.3
373 >>>>>>> Conflict 2 of 2 ends
374 line 5
375 ");
376 insta::assert_snapshot!(
377 std::fs::read_to_string(test_env.env_root().join("after-file")).unwrap(), @r"
378 line 1
379 line 2.1
380 line 2.2
381 line 2.3
382 line 3
383 <<<<<<< Conflict 1 of 1
384 +++++++ Contents of side #1
385 line 4.1
386 ------- Contents of base
387 line 4
388 +++++++ Contents of side #2
389 line 4.2
390 line 4.3
391 >>>>>>> Conflict 1 of 1 ends
392 line 5
393 ");
394 // Conflicts should be materialized using "diff" format in working copy
395 insta::assert_snapshot!(work_dir.read_file(file_path), @r"
396 line 1
397 <<<<<<< Conflict 1 of 2
398 +++++++ Contents of side #1
399 line 2.1
400 line 2.2
401 %%%%%%% Changes from base to side #2
402 -line 2
403 +line 2.3
404 >>>>>>> Conflict 1 of 2 ends
405 line 3
406 <<<<<<< Conflict 2 of 2
407 %%%%%%% Changes from base to side #1
408 -line 4
409 +line 4.1
410 +++++++ Contents of side #2
411 line 4.2
412 line 4.3
413 >>>>>>> Conflict 2 of 2 ends
414 line 5
415 ");
416
417 // File should be conflicted with no changes
418 let output = work_dir.run_jj(["st"]);
419 insta::assert_snapshot!(output, @r"
420 The working copy has no changes.
421 Working copy (@) : mzvwutvl fb39e804 (conflict) (empty) (no description set)
422 Parent commit (@-): rlvkpnrz 3765cc27 side-a
423 Parent commit (@-): zsuskuln 8b3de837 side-b
424 Warning: There are unresolved conflicts at these paths:
425 file 2-sided conflict
426 [EOF]
427 ");
428}
429
430#[test]
431fn test_diffedit_3pane() {
432 let mut test_env = TestEnvironment::default();
433 let edit_script = test_env.set_up_fake_diff_editor();
434 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
435 let work_dir = test_env.work_dir("repo");
436
437 work_dir.write_file("file1", "a\n");
438 work_dir.run_jj(["new"]).success();
439 work_dir.write_file("file2", "a\n");
440 work_dir.write_file("file3", "a\n");
441 work_dir.run_jj(["new"]).success();
442 work_dir.remove_file("file1");
443 work_dir.write_file("file2", "b\n");
444
445 // 2 configs for a 3-pane setup. In the first, "$right" is passed to what the
446 // fake diff editor considers the "after" state.
447 let config_with_right_as_after =
448 "merge-tools.fake-diff-editor.edit-args=['$left', '$right', '--ignore=$output']";
449 let config_with_output_as_after =
450 "merge-tools.fake-diff-editor.edit-args=['$left', '$output', '--ignore=$right']";
451 std::fs::write(&edit_script, "").unwrap();
452
453 // Nothing happens if we make no changes
454 std::fs::write(
455 &edit_script,
456 "files-before file1 file2\0files-after JJ-INSTRUCTIONS file2",
457 )
458 .unwrap();
459 let output = work_dir.run_jj(["diffedit", "--config", config_with_output_as_after]);
460 insta::assert_snapshot!(output, @r"
461 ------- stderr -------
462 Nothing changed.
463 [EOF]
464 ");
465 let output = work_dir.run_jj(["diff", "-s"]);
466 insta::assert_snapshot!(output, @r"
467 D file1
468 M file2
469 [EOF]
470 ");
471 // Nothing happens if we make no changes, `config_with_right_as_after` version
472 let output = work_dir.run_jj(["diffedit", "--config", config_with_right_as_after]);
473 insta::assert_snapshot!(output, @r"
474 ------- stderr -------
475 Nothing changed.
476 [EOF]
477 ");
478 let output = work_dir.run_jj(["diff", "-s"]);
479 insta::assert_snapshot!(output, @r"
480 D file1
481 M file2
482 [EOF]
483 ");
484
485 // Can edit changes to individual files
486 std::fs::write(&edit_script, "reset file2").unwrap();
487 let output = work_dir.run_jj(["diffedit", "--config", config_with_output_as_after]);
488 insta::assert_snapshot!(output, @r"
489 ------- stderr -------
490 Created kkmpptxz ed8aada3 (no description set)
491 Working copy (@) now at: kkmpptxz ed8aada3 (no description set)
492 Parent commit (@-) : rlvkpnrz a72506cd (no description set)
493 Added 0 files, modified 1 files, removed 0 files
494 [EOF]
495 ");
496 let output = work_dir.run_jj(["diff", "-s"]);
497 insta::assert_snapshot!(output, @r"
498 D file1
499 [EOF]
500 ");
501
502 // Can write something new to `file1`
503 work_dir.run_jj(["undo"]).success();
504 std::fs::write(&edit_script, "write file1\nnew content").unwrap();
505 let output = work_dir.run_jj(["diffedit", "--config", config_with_output_as_after]);
506 insta::assert_snapshot!(output, @r"
507 ------- stderr -------
508 Created kkmpptxz 7c19e689 (no description set)
509 Working copy (@) now at: kkmpptxz 7c19e689 (no description set)
510 Parent commit (@-) : rlvkpnrz a72506cd (no description set)
511 Added 1 files, modified 0 files, removed 0 files
512 [EOF]
513 ");
514 let output = work_dir.run_jj(["diff", "-s"]);
515 insta::assert_snapshot!(output, @r"
516 M file1
517 M file2
518 [EOF]
519 ");
520
521 // But nothing happens if we modify the right side
522 work_dir.run_jj(["undo"]).success();
523 std::fs::write(&edit_script, "write file1\nnew content").unwrap();
524 let output = work_dir.run_jj(["diffedit", "--config", config_with_right_as_after]);
525 insta::assert_snapshot!(output, @r"
526 ------- stderr -------
527 Nothing changed.
528 [EOF]
529 ");
530 let output = work_dir.run_jj(["diff", "-s"]);
531 insta::assert_snapshot!(output, @r"
532 D file1
533 M file2
534 [EOF]
535 ");
536
537 // TODO: test with edit_script of "reset file2". This fails on right side
538 // since the file is readonly.
539}
540
541#[test]
542fn test_diffedit_merge() {
543 let mut test_env = TestEnvironment::default();
544 let edit_script = test_env.set_up_fake_diff_editor();
545 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
546 let work_dir = test_env.work_dir("repo");
547
548 work_dir.write_file("file1", "a\n");
549 work_dir.write_file("file2", "a\n");
550 work_dir.run_jj(["new"]).success();
551 work_dir
552 .run_jj(["bookmark", "create", "-r@", "b"])
553 .success();
554 work_dir.write_file("file1", "b\n");
555 work_dir.write_file("file2", "b\n");
556 work_dir.run_jj(["new", "@-"]).success();
557 work_dir.run_jj(["new"]).success();
558 work_dir.write_file("file1", "c\n");
559 work_dir.write_file("file2", "c\n");
560 work_dir.run_jj(["new", "@", "b", "-m", "merge"]).success();
561 // Resolve the conflict in file1, but leave the conflict in file2
562 work_dir.write_file("file1", "d\n");
563 work_dir.write_file("file3", "d\n");
564 work_dir.run_jj(["new"]).success();
565 // Test the setup
566 let output = work_dir.run_jj(["diff", "-r", "@-", "-s"]);
567 insta::assert_snapshot!(output, @r"
568 M file1
569 A file3
570 [EOF]
571 ");
572
573 // Remove file1. The conflict remains in the working copy on top of the merge.
574 std::fs::write(
575 edit_script,
576 "files-before file1\0files-after JJ-INSTRUCTIONS file1 file3\0rm file1",
577 )
578 .unwrap();
579 let output = work_dir.run_jj(["diffedit", "-r", "@-"]);
580 insta::assert_snapshot!(output, @r"
581 ------- stderr -------
582 Created royxmykx 0105de4a (conflict) merge
583 Rebased 1 descendant commits
584 Working copy (@) now at: yqosqzyt abbb78c1 (conflict) (empty) (no description set)
585 Parent commit (@-) : royxmykx 0105de4a (conflict) merge
586 Added 0 files, modified 0 files, removed 1 files
587 Warning: There are unresolved conflicts at these paths:
588 file2 2-sided conflict
589 [EOF]
590 ");
591 let output = work_dir.run_jj(["diff", "-s", "-r", "@-"]);
592 insta::assert_snapshot!(output, @r"
593 D file1
594 A file3
595 [EOF]
596 ");
597 assert!(!work_dir.root().join("file1").exists());
598 let output = work_dir.run_jj(["file", "show", "file2"]);
599 insta::assert_snapshot!(output, @r"
600 <<<<<<< Conflict 1 of 1
601 %%%%%%% Changes from base to side #1
602 -a
603 +c
604 +++++++ Contents of side #2
605 b
606 >>>>>>> Conflict 1 of 1 ends
607 [EOF]
608 ");
609}
610
611#[test]
612fn test_diffedit_old_restore_interactive_tests() {
613 let mut test_env = TestEnvironment::default();
614 let edit_script = test_env.set_up_fake_diff_editor();
615 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
616 let work_dir = test_env.work_dir("repo");
617
618 work_dir.write_file("file1", "a\n");
619 work_dir.write_file("file2", "a\n");
620 work_dir.run_jj(["new"]).success();
621 work_dir.remove_file("file1");
622 work_dir.write_file("file2", "b\n");
623 work_dir.write_file("file3", "b\n");
624
625 // Nothing happens if we make no changes
626 let output = work_dir.run_jj(["diffedit", "--from", "@-"]);
627 insta::assert_snapshot!(output, @r"
628 ------- stderr -------
629 Nothing changed.
630 [EOF]
631 ");
632 let output = work_dir.run_jj(["diff", "-s"]);
633 insta::assert_snapshot!(output, @r"
634 D file1
635 M file2
636 C {file2 => file3}
637 [EOF]
638 ");
639
640 // Nothing happens if the diff-editor exits with an error
641 std::fs::write(&edit_script, "rm file2\0fail").unwrap();
642 let output = work_dir.run_jj(["diffedit", "--from", "@-"]);
643 insta::assert_snapshot!(output.normalize_stderr_exit_status(), @r"
644 ------- stderr -------
645 Error: Failed to edit diff
646 Caused by: Tool exited with exit status: 1 (run with --debug to see the exact invocation)
647 [EOF]
648 [exit status: 1]
649 ");
650 let output = work_dir.run_jj(["diff", "-s"]);
651 insta::assert_snapshot!(output, @r"
652 D file1
653 M file2
654 C {file2 => file3}
655 [EOF]
656 ");
657
658 // Can restore changes to individual files
659 std::fs::write(&edit_script, "reset file2\0reset file3").unwrap();
660 let output = work_dir.run_jj(["diffedit", "--from", "@-"]);
661 insta::assert_snapshot!(output, @r"
662 ------- stderr -------
663 Created rlvkpnrz 69811eda (no description set)
664 Working copy (@) now at: rlvkpnrz 69811eda (no description set)
665 Parent commit (@-) : qpvuntsm fc687cb8 (no description set)
666 Added 0 files, modified 1 files, removed 1 files
667 [EOF]
668 ");
669 let output = work_dir.run_jj(["diff", "-s"]);
670 insta::assert_snapshot!(output, @r"
671 D file1
672 [EOF]
673 ");
674
675 // Can make unrelated edits
676 work_dir.run_jj(["undo"]).success();
677 std::fs::write(&edit_script, "write file3\nunrelated\n").unwrap();
678 let output = work_dir.run_jj(["diffedit", "--from", "@-"]);
679 insta::assert_snapshot!(output, @r"
680 ------- stderr -------
681 Created rlvkpnrz 2b76a42e (no description set)
682 Working copy (@) now at: rlvkpnrz 2b76a42e (no description set)
683 Parent commit (@-) : qpvuntsm fc687cb8 (no description set)
684 Added 0 files, modified 1 files, removed 0 files
685 [EOF]
686 ");
687 let output = work_dir.run_jj(["diff", "--git"]);
688 insta::assert_snapshot!(output, @r"
689 diff --git a/file1 b/file1
690 deleted file mode 100644
691 index 7898192261..0000000000
692 --- a/file1
693 +++ /dev/null
694 @@ -1,1 +0,0 @@
695 -a
696 diff --git a/file2 b/file2
697 index 7898192261..6178079822 100644
698 --- a/file2
699 +++ b/file2
700 @@ -1,1 +1,1 @@
701 -a
702 +b
703 diff --git a/file3 b/file3
704 new file mode 100644
705 index 0000000000..c21c9352f7
706 --- /dev/null
707 +++ b/file3
708 @@ -0,0 +1,1 @@
709 +unrelated
710 [EOF]
711 ");
712}
713
714#[test]
715fn test_diffedit_restore_descendants() {
716 let mut test_env = TestEnvironment::default();
717 let edit_script = test_env.set_up_fake_diff_editor();
718 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
719 let work_dir = test_env.work_dir("repo");
720
721 work_dir.write_file("file", "println!(\"foo\")\n");
722 work_dir.run_jj(["new"]).success();
723 work_dir.write_file("file", "println!(\"bar\")\n");
724 work_dir.run_jj(["new"]).success();
725 work_dir.write_file("file", "println!(\"baz\");\n");
726
727 // Add a ";" after the line with "bar". There should be no conflict.
728 std::fs::write(edit_script, "write file\nprintln!(\"bar\");\n").unwrap();
729 let output = work_dir.run_jj(["diffedit", "-r", "@-", "--restore-descendants"]);
730 insta::assert_snapshot!(output, @r"
731 ------- stderr -------
732 Created rlvkpnrz 62b8c2ce (no description set)
733 Rebased 1 descendant commits (while preserving their content)
734 Working copy (@) now at: kkmpptxz 321d1cd1 (no description set)
735 Parent commit (@-) : rlvkpnrz 62b8c2ce (no description set)
736 [EOF]
737 ");
738 let output = work_dir.run_jj(["diff", "--git"]);
739 insta::assert_snapshot!(output, @r#"
740 diff --git a/file b/file
741 index 1a598a8fc9..7b6a85ab5a 100644
742 --- a/file
743 +++ b/file
744 @@ -1,1 +1,1 @@
745 -println!("bar");
746 +println!("baz");
747 [EOF]
748 "#);
749}