fork
Configure Feed
Select the types of activity you want to include in your feed.
just playing with tangled
fork
Configure Feed
Select the types of activity you want to include in your feed.
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::CommandOutput;
16use crate::common::TestEnvironment;
17use crate::common::TestWorkDir;
18
19#[test]
20fn test_new() {
21 let test_env = TestEnvironment::default();
22 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
23 let work_dir = test_env.work_dir("repo");
24
25 work_dir.run_jj(["describe", "-m", "add a file"]).success();
26 work_dir.run_jj(["new", "-m", "a new commit"]).success();
27
28 insta::assert_snapshot!(get_log_output(&work_dir), @r"
29 @ 34f3c770f1db22ac5c58df21d587aed1a030201f a new commit
30 ○ bf8753cb48b860b68386c5c8cc997e8e37122485 add a file
31 ◆ 0000000000000000000000000000000000000000
32 [EOF]
33 ");
34
35 // Start a new change off of a specific commit (the root commit in this case).
36 work_dir
37 .run_jj(["new", "-m", "off of root", "root()"])
38 .success();
39 insta::assert_snapshot!(get_log_output(&work_dir), @r"
40 @ 026537ddb96b801b9cb909985d5443aab44616c1 off of root
41 │ ○ 34f3c770f1db22ac5c58df21d587aed1a030201f a new commit
42 │ ○ bf8753cb48b860b68386c5c8cc997e8e37122485 add a file
43 ├─╯
44 ◆ 0000000000000000000000000000000000000000
45 [EOF]
46 ");
47
48 // --edit is a no-op
49 work_dir
50 .run_jj(["new", "--edit", "-m", "yet another commit"])
51 .success();
52 insta::assert_snapshot!(get_log_output(&work_dir), @r"
53 @ 101cbec5cae8049cb9850a906ef3675631ed48fa yet another commit
54 ○ 026537ddb96b801b9cb909985d5443aab44616c1 off of root
55 │ ○ 34f3c770f1db22ac5c58df21d587aed1a030201f a new commit
56 │ ○ bf8753cb48b860b68386c5c8cc997e8e37122485 add a file
57 ├─╯
58 ◆ 0000000000000000000000000000000000000000
59 [EOF]
60 ");
61
62 // --edit cannot be used with --no-edit
63 let output = work_dir.run_jj(["new", "--edit", "B", "--no-edit", "D"]);
64 insta::assert_snapshot!(output, @r"
65 ------- stderr -------
66 error: the argument '--edit' cannot be used with '--no-edit'
67
68 Usage: jj new <REVSETS>...
69
70 For more information, try '--help'.
71 [EOF]
72 [exit status: 2]
73 ");
74}
75
76#[test]
77fn test_new_merge() {
78 let test_env = TestEnvironment::default();
79 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
80 let work_dir = test_env.work_dir("repo");
81
82 work_dir
83 .run_jj(["bookmark", "create", "-r@", "main"])
84 .success();
85 work_dir.run_jj(["describe", "-m", "add file1"]).success();
86 work_dir.write_file("file1", "a");
87 work_dir
88 .run_jj(["new", "root()", "-m", "add file2"])
89 .success();
90 work_dir.write_file("file2", "b");
91
92 // Create a merge commit
93 work_dir.run_jj(["new", "main", "@"]).success();
94 insta::assert_snapshot!(get_log_output(&work_dir), @r"
95 @ 2f9a61ea1fef257eca52fcee2feec1cbd2e41660
96 ├─╮
97 │ ○ f399209d9dda06e8a25a0c8e9a0cde9f421ff35d add file2
98 ○ │ 8d996e001c23e298d0d353ab455665c81bf2080c add file1
99 ├─╯
100 ◆ 0000000000000000000000000000000000000000
101 [EOF]
102 ");
103 let output = work_dir.run_jj(["file", "show", "file1"]);
104 insta::assert_snapshot!(output, @"a[EOF]");
105 let output = work_dir.run_jj(["file", "show", "file2"]);
106 insta::assert_snapshot!(output, @"b[EOF]");
107
108 // Same test with `--no-edit`
109 work_dir.run_jj(["undo"]).success();
110 let output = work_dir.run_jj(["new", "main", "@", "--no-edit"]);
111 insta::assert_snapshot!(output, @r"
112 ------- stderr -------
113 Created new commit znkkpsqq 496490a6 (empty) (no description set)
114 [EOF]
115 ");
116 insta::assert_snapshot!(get_log_output(&work_dir), @r"
117 ○ 496490a66cebb31730c4103b7b22a1098d49af91
118 ├─╮
119 │ @ f399209d9dda06e8a25a0c8e9a0cde9f421ff35d add file2
120 ○ │ 8d996e001c23e298d0d353ab455665c81bf2080c add file1
121 ├─╯
122 ◆ 0000000000000000000000000000000000000000
123 [EOF]
124 ");
125
126 // Same test with `jj new`
127 work_dir.run_jj(["undo"]).success();
128 work_dir.run_jj(["new", "main", "@"]).success();
129 insta::assert_snapshot!(get_log_output(&work_dir), @r"
130 @ 114023233c454e2eca22b8b209f9e42f755eb28c
131 ├─╮
132 │ ○ f399209d9dda06e8a25a0c8e9a0cde9f421ff35d add file2
133 ○ │ 8d996e001c23e298d0d353ab455665c81bf2080c add file1
134 ├─╯
135 ◆ 0000000000000000000000000000000000000000
136 [EOF]
137 ");
138
139 // merge with non-unique revisions
140 let output = work_dir.run_jj(["new", "@", "3a44e"]);
141 insta::assert_snapshot!(output, @r"
142 ------- stderr -------
143 Error: Revision `3a44e` doesn't exist
144 [EOF]
145 [exit status: 1]
146 ");
147 // if prefixed with all:, duplicates are allowed
148 let output = work_dir.run_jj(["new", "@", "all:visible_heads()"]);
149 insta::assert_snapshot!(output, @r"
150 ------- stderr -------
151 Working copy (@) now at: nkmrtpmo ed2dc1d9 (empty) (no description set)
152 Parent commit (@-) : wqnwkozp 11402323 (empty) (no description set)
153 [EOF]
154 ");
155
156 // merge with root
157 let output = work_dir.run_jj(["new", "@", "root()"]);
158 insta::assert_snapshot!(output, @r"
159 ------- stderr -------
160 Error: The Git backend does not support creating merge commits with the root commit as one of the parents.
161 [EOF]
162 [exit status: 1]
163 ");
164}
165
166#[test]
167fn test_new_insert_after() {
168 let test_env = TestEnvironment::default();
169 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
170 let work_dir = test_env.work_dir("repo");
171 setup_before_insertion(&work_dir);
172 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
173 @ F
174 ├─╮
175 │ ○ E
176 ○ │ D
177 ├─╯
178 │ ○ C
179 │ ○ B
180 │ ○ A
181 ├─╯
182 ◆ root
183 [EOF]
184 ");
185
186 // --insert-after can be repeated; --after is an alias
187 let output = work_dir.run_jj(["new", "-m", "G", "--insert-after", "B", "--after", "D"]);
188 insta::assert_snapshot!(output, @r"
189 ------- stderr -------
190 Rebased 2 descendant commits
191 Working copy (@) now at: kxryzmor 1fc93fd1 (empty) G
192 Parent commit (@-) : kkmpptxz bfd4157e B | (empty) B
193 Parent commit (@-) : vruxwmqv c9257eff D | (empty) D
194 [EOF]
195 ");
196 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
197 ○ C
198 │ ○ F
199 ╭─┤
200 @ │ G
201 ├───╮
202 │ │ ○ D
203 ○ │ │ B
204 ○ │ │ A
205 ├───╯
206 │ ○ E
207 ├─╯
208 ◆ root
209 [EOF]
210 ");
211
212 let output = work_dir.run_jj(["new", "-m", "H", "--insert-after", "D"]);
213 insta::assert_snapshot!(output, @r"
214 ------- stderr -------
215 Rebased 3 descendant commits
216 Working copy (@) now at: uyznsvlq fcf8281b (empty) H
217 Parent commit (@-) : vruxwmqv c9257eff D | (empty) D
218 [EOF]
219 ");
220 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
221 ○ C
222 │ ○ F
223 ╭─┤
224 ○ │ G
225 ├───╮
226 │ │ @ H
227 │ │ ○ D
228 ○ │ │ B
229 ○ │ │ A
230 ├───╯
231 │ ○ E
232 ├─╯
233 ◆ root
234 [EOF]
235 ");
236
237 // --after cannot be used with revisions
238 let output = work_dir.run_jj(["new", "--after", "B", "D"]);
239 insta::assert_snapshot!(output, @r"
240 ------- stderr -------
241 error: the argument '--insert-after <REVSETS>' cannot be used with '[REVSETS]...'
242
243 Usage: jj new --insert-after <REVSETS> [REVSETS]...
244
245 For more information, try '--help'.
246 [EOF]
247 [exit status: 2]
248 ");
249}
250
251#[test]
252fn test_new_insert_after_children() {
253 let test_env = TestEnvironment::default();
254 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
255 let work_dir = test_env.work_dir("repo");
256 setup_before_insertion(&work_dir);
257 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
258 @ F
259 ├─╮
260 │ ○ E
261 ○ │ D
262 ├─╯
263 │ ○ C
264 │ ○ B
265 │ ○ A
266 ├─╯
267 ◆ root
268 [EOF]
269 ");
270
271 // Attempting to insert G after A and C errors out due to the cycle created
272 // as A is an ancestor of C.
273 let output = work_dir.run_jj([
274 "new",
275 "-m",
276 "G",
277 "--insert-after",
278 "A",
279 "--insert-after",
280 "C",
281 ]);
282 insta::assert_snapshot!(output, @r"
283 ------- stderr -------
284 Error: Refusing to create a loop: commit 83376b270925 would be both an ancestor and a descendant of the new commit
285 [EOF]
286 [exit status: 1]
287 ");
288}
289
290#[test]
291fn test_new_insert_before() {
292 let test_env = TestEnvironment::default();
293 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
294 let work_dir = test_env.work_dir("repo");
295 setup_before_insertion(&work_dir);
296 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
297 @ F
298 ├─╮
299 │ ○ E
300 ○ │ D
301 ├─╯
302 │ ○ C
303 │ ○ B
304 │ ○ A
305 ├─╯
306 ◆ root
307 [EOF]
308 ");
309
310 let output = work_dir.run_jj([
311 "new",
312 "-m",
313 "G",
314 "--insert-before",
315 "C",
316 "--insert-before",
317 "F",
318 ]);
319 insta::assert_snapshot!(output, @r"
320 ------- stderr -------
321 Rebased 2 descendant commits
322 Working copy (@) now at: kxryzmor 7ed2d6ff (empty) G
323 Parent commit (@-) : kkmpptxz bfd4157e B | (empty) B
324 Parent commit (@-) : vruxwmqv c9257eff D | (empty) D
325 Parent commit (@-) : znkkpsqq 41a89ffc E | (empty) E
326 [EOF]
327 ");
328 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
329 ○ F
330 │ ○ C
331 ├─╯
332 @ G
333 ├─┬─╮
334 │ │ ○ E
335 │ ○ │ D
336 │ ├─╯
337 ○ │ B
338 ○ │ A
339 ├─╯
340 ◆ root
341 [EOF]
342 ");
343
344 // --before cannot be used with revisions
345 let output = work_dir.run_jj(["new", "--before", "B", "D"]);
346 insta::assert_snapshot!(output, @r"
347 ------- stderr -------
348 error: the argument '--insert-before <REVSETS>' cannot be used with '[REVSETS]...'
349
350 Usage: jj new --insert-before <REVSETS> [REVSETS]...
351
352 For more information, try '--help'.
353 [EOF]
354 [exit status: 2]
355 ");
356}
357
358#[test]
359fn test_new_insert_before_root_successors() {
360 let test_env = TestEnvironment::default();
361 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
362 let work_dir = test_env.work_dir("repo");
363 setup_before_insertion(&work_dir);
364 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
365 @ F
366 ├─╮
367 │ ○ E
368 ○ │ D
369 ├─╯
370 │ ○ C
371 │ ○ B
372 │ ○ A
373 ├─╯
374 ◆ root
375 [EOF]
376 ");
377
378 let output = work_dir.run_jj([
379 "new",
380 "-m",
381 "G",
382 "--insert-before",
383 "A",
384 "--insert-before",
385 "D",
386 ]);
387 insta::assert_snapshot!(output, @r"
388 ------- stderr -------
389 Rebased 5 descendant commits
390 Working copy (@) now at: kxryzmor 36541977 (empty) G
391 Parent commit (@-) : zzzzzzzz 00000000 (empty) (no description set)
392 [EOF]
393 ");
394 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
395 ○ F
396 ├─╮
397 │ ○ E
398 ○ │ D
399 │ │ ○ C
400 │ │ ○ B
401 │ │ ○ A
402 ├───╯
403 @ │ G
404 ├─╯
405 ◆ root
406 [EOF]
407 ");
408}
409
410#[test]
411fn test_new_insert_before_no_loop() {
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 setup_before_insertion(&work_dir);
416 let template = r#"commit_id.short() ++ " " ++ if(description, description, "root")"#;
417 let output = work_dir.run_jj(["log", "-T", template]);
418 insta::assert_snapshot!(output, @r"
419 @ 7705d353bf5d F
420 ├─╮
421 │ ○ 41a89ffcbba2 E
422 ○ │ c9257eff5bf9 D
423 ├─╯
424 │ ○ 83376b270925 C
425 │ ○ bfd4157e6ea4 B
426 │ ○ 5ef24e4bf2be A
427 ├─╯
428 ◆ 000000000000 root
429 [EOF]
430 ");
431
432 let output = work_dir.run_jj([
433 "new",
434 "-m",
435 "G",
436 "--insert-before",
437 "A",
438 "--insert-before",
439 "C",
440 ]);
441 insta::assert_snapshot!(output, @r"
442 ------- stderr -------
443 Error: Refusing to create a loop: commit bfd4157e6ea4 would be both an ancestor and a descendant of the new commit
444 [EOF]
445 [exit status: 1]
446 ");
447}
448
449#[test]
450fn test_new_insert_before_no_root_merge() {
451 let test_env = TestEnvironment::default();
452 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
453 let work_dir = test_env.work_dir("repo");
454 setup_before_insertion(&work_dir);
455 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
456 @ F
457 ├─╮
458 │ ○ E
459 ○ │ D
460 ├─╯
461 │ ○ C
462 │ ○ B
463 │ ○ A
464 ├─╯
465 ◆ root
466 [EOF]
467 ");
468
469 let output = work_dir.run_jj([
470 "new",
471 "-m",
472 "G",
473 "--insert-before",
474 "B",
475 "--insert-before",
476 "D",
477 ]);
478 insta::assert_snapshot!(output, @r"
479 ------- stderr -------
480 Error: The Git backend does not support creating merge commits with the root commit as one of the parents.
481 [EOF]
482 [exit status: 1]
483 ");
484}
485
486#[test]
487fn test_new_insert_before_root() {
488 let test_env = TestEnvironment::default();
489 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
490 let work_dir = test_env.work_dir("repo");
491 setup_before_insertion(&work_dir);
492 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
493 @ F
494 ├─╮
495 │ ○ E
496 ○ │ D
497 ├─╯
498 │ ○ C
499 │ ○ B
500 │ ○ A
501 ├─╯
502 ◆ root
503 [EOF]
504 ");
505
506 let output = work_dir.run_jj(["new", "-m", "G", "--insert-before", "root()"]);
507 insta::assert_snapshot!(output, @r"
508 ------- stderr -------
509 Error: The root commit 000000000000 is immutable
510 [EOF]
511 [exit status: 1]
512 ");
513}
514
515#[test]
516fn test_new_insert_after_before() {
517 let test_env = TestEnvironment::default();
518 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
519 let work_dir = test_env.work_dir("repo");
520 setup_before_insertion(&work_dir);
521 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
522 @ F
523 ├─╮
524 │ ○ E
525 ○ │ D
526 ├─╯
527 │ ○ C
528 │ ○ B
529 │ ○ A
530 ├─╯
531 ◆ root
532 [EOF]
533 ");
534
535 let output = work_dir.run_jj(["new", "-m", "G", "--after", "C", "--before", "F"]);
536 insta::assert_snapshot!(output, @r"
537 ------- stderr -------
538 Rebased 1 descendant commits
539 Working copy (@) now at: kxryzmor 78a97058 (empty) G
540 Parent commit (@-) : mzvwutvl 83376b27 C | (empty) C
541 [EOF]
542 ");
543 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
544 ○ F
545 ├─┬─╮
546 │ │ @ G
547 │ │ ○ C
548 │ │ ○ B
549 │ │ ○ A
550 │ ○ │ E
551 │ ├─╯
552 ○ │ D
553 ├─╯
554 ◆ root
555 [EOF]
556 ");
557
558 let output = work_dir.run_jj(["new", "-m", "H", "--after", "D", "--before", "B"]);
559 insta::assert_snapshot!(output, @r"
560 ------- stderr -------
561 Rebased 4 descendant commits
562 Working copy (@) now at: uyznsvlq fcf8281b (empty) H
563 Parent commit (@-) : vruxwmqv c9257eff D | (empty) D
564 [EOF]
565 ");
566 insta::assert_snapshot!(get_short_log_output(&work_dir), @r"
567 ○ F
568 ├─┬─╮
569 │ │ ○ G
570 │ │ ○ C
571 │ │ ○ B
572 │ │ ├─╮
573 │ │ │ @ H
574 ├─────╯
575 ○ │ │ D
576 │ │ ○ A
577 ├───╯
578 │ ○ E
579 ├─╯
580 ◆ root
581 [EOF]
582 ");
583}
584
585#[test]
586fn test_new_insert_after_before_no_loop() {
587 let test_env = TestEnvironment::default();
588 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
589 let work_dir = test_env.work_dir("repo");
590 setup_before_insertion(&work_dir);
591 let template = r#"commit_id.short() ++ " " ++ if(description, description, "root")"#;
592 let output = work_dir.run_jj(["log", "-T", template]);
593 insta::assert_snapshot!(output, @r"
594 @ 7705d353bf5d F
595 ├─╮
596 │ ○ 41a89ffcbba2 E
597 ○ │ c9257eff5bf9 D
598 ├─╯
599 │ ○ 83376b270925 C
600 │ ○ bfd4157e6ea4 B
601 │ ○ 5ef24e4bf2be A
602 ├─╯
603 ◆ 000000000000 root
604 [EOF]
605 ");
606
607 let output = work_dir.run_jj([
608 "new",
609 "-m",
610 "G",
611 "--insert-before",
612 "A",
613 "--insert-after",
614 "C",
615 ]);
616 insta::assert_snapshot!(output, @r"
617 ------- stderr -------
618 Error: Refusing to create a loop: commit 83376b270925 would be both an ancestor and a descendant of the new commit
619 [EOF]
620 [exit status: 1]
621 ");
622}
623
624#[test]
625fn test_new_conflicting_bookmarks() {
626 let test_env = TestEnvironment::default();
627 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
628 let work_dir = test_env.work_dir("repo");
629
630 work_dir.run_jj(["describe", "-m", "one"]).success();
631 work_dir.run_jj(["new", "-m", "two", "@-"]).success();
632 work_dir
633 .run_jj(["bookmark", "create", "-r@", "foo"])
634 .success();
635 work_dir
636 .run_jj([
637 "--at-op=@-",
638 "bookmark",
639 "create",
640 "foo",
641 "-r",
642 r#"description("one")"#,
643 ])
644 .success();
645
646 // Trigger resolution of divergent operations
647 work_dir.run_jj(["st"]).success();
648
649 let output = work_dir.run_jj(["new", "foo"]);
650 insta::assert_snapshot!(output, @r"
651 ------- stderr -------
652 Error: Revset `foo` resolved to more than one revision
653 Hint: Bookmark foo resolved to multiple revisions because it's conflicted.
654 It resolved to these revisions:
655 kkmpptxz 66c6502d foo?? | (empty) two
656 qpvuntsm 876f4b7e foo?? | (empty) one
657 Hint: Set which revision the bookmark points to with `jj bookmark set foo -r <REVISION>`.
658 [EOF]
659 [exit status: 1]
660 ");
661}
662
663#[test]
664fn test_new_conflicting_change_ids() {
665 let test_env = TestEnvironment::default();
666 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
667 let work_dir = test_env.work_dir("repo");
668
669 work_dir.run_jj(["describe", "-m", "one"]).success();
670 work_dir
671 .run_jj(["--at-op=@-", "describe", "-m", "two"])
672 .success();
673
674 // Trigger resolution of divergent operations
675 work_dir.run_jj(["st"]).success();
676
677 let output = work_dir.run_jj(["new", "qpvuntsm"]);
678 insta::assert_snapshot!(output, @r"
679 ------- stderr -------
680 Error: Revset `qpvuntsm` resolved to more than one revision
681 Hint: The revset `qpvuntsm` resolved to these revisions:
682 qpvuntsm?? 66c6502d (empty) two
683 qpvuntsm?? 876f4b7e (empty) one
684 Hint: Some of these commits have the same change id. Abandon one of them with `jj abandon -r <REVISION>`.
685 [EOF]
686 [exit status: 1]
687 ");
688}
689
690#[test]
691fn test_new_error_revision_does_not_exist() {
692 let test_env = TestEnvironment::default();
693 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
694 let work_dir = test_env.work_dir("repo");
695
696 work_dir.run_jj(["describe", "-m", "one"]).success();
697 work_dir.run_jj(["new", "-m", "two"]).success();
698
699 let output = work_dir.run_jj(["new", "this"]);
700 insta::assert_snapshot!(output, @r"
701 ------- stderr -------
702 Error: Revision `this` doesn't exist
703 [EOF]
704 [exit status: 1]
705 ");
706}
707
708fn setup_before_insertion(work_dir: &TestWorkDir) {
709 work_dir
710 .run_jj(["bookmark", "create", "-r@", "A"])
711 .success();
712 work_dir.run_jj(["commit", "-m", "A"]).success();
713 work_dir
714 .run_jj(["bookmark", "create", "-r@", "B"])
715 .success();
716 work_dir.run_jj(["commit", "-m", "B"]).success();
717 work_dir
718 .run_jj(["bookmark", "create", "-r@", "C"])
719 .success();
720 work_dir.run_jj(["describe", "-m", "C"]).success();
721 work_dir.run_jj(["new", "-m", "D", "root()"]).success();
722 work_dir
723 .run_jj(["bookmark", "create", "-r@", "D"])
724 .success();
725 work_dir.run_jj(["new", "-m", "E", "root()"]).success();
726 work_dir
727 .run_jj(["bookmark", "create", "-r@", "E"])
728 .success();
729 // Any number of -r's is ignored
730 work_dir
731 .run_jj(["new", "-m", "F", "-r", "D", "-r", "E"])
732 .success();
733 work_dir
734 .run_jj(["bookmark", "create", "-r@", "F"])
735 .success();
736}
737
738#[must_use]
739fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {
740 let template = r#"commit_id ++ " " ++ description"#;
741 work_dir.run_jj(["log", "-T", template])
742}
743
744#[must_use]
745fn get_short_log_output(work_dir: &TestWorkDir) -> CommandOutput {
746 let template = r#"if(description, description, "root")"#;
747 work_dir.run_jj(["log", "-T", template])
748}