just playing with tangled
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_duplicate() {
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", &[]);
28 create_commit(&work_dir, "c", &["a", "b"]);
29 // Test the setup
30 insta::assert_snapshot!(get_log_output(&work_dir), @r"
31 @ 17a00fc21654 c
32 ├─╮
33 │ ○ d370aee184ba b
34 ○ │ 2443ea76b0b1 a
35 ├─╯
36 ◆ 000000000000
37 [EOF]
38 ");
39
40 let output = work_dir.run_jj(["duplicate", "all()"]);
41 insta::assert_snapshot!(output, @r"
42 ------- stderr -------
43 Error: Cannot duplicate the root commit
44 [EOF]
45 [exit status: 1]
46 ");
47
48 let output = work_dir.run_jj(["duplicate", "none()"]);
49 insta::assert_snapshot!(output, @r"
50 ------- stderr -------
51 No revisions to duplicate.
52 [EOF]
53 ");
54
55 let output = work_dir.run_jj(["duplicate", "a"]);
56 insta::assert_snapshot!(output, @r"
57 ------- stderr -------
58 Duplicated 2443ea76b0b1 as kpqxywon f5b1e687 a
59 [EOF]
60 ");
61 insta::assert_snapshot!(get_log_output(&work_dir), @r"
62 @ 17a00fc21654 c
63 ├─╮
64 │ ○ d370aee184ba b
65 ○ │ 2443ea76b0b1 a
66 ├─╯
67 │ ○ f5b1e68729d6 a
68 ├─╯
69 ◆ 000000000000
70 [EOF]
71 ");
72
73 let output = work_dir.run_jj(["undo"]);
74 insta::assert_snapshot!(output, @r"
75 ------- stderr -------
76 Undid operation: 6eead29c6998 (2001-02-03 08:05:17) duplicate 1 commit(s)
77 [EOF]
78 ");
79 let output = work_dir.run_jj(["duplicate" /* duplicates `c` */]);
80 insta::assert_snapshot!(output, @r"
81 ------- stderr -------
82 Duplicated 17a00fc21654 as lylxulpl ef3b0f3d c
83 [EOF]
84 ");
85 insta::assert_snapshot!(get_log_output(&work_dir), @r"
86 @ 17a00fc21654 c
87 ├─╮
88 │ │ ○ ef3b0f3d1046 c
89 ╭─┬─╯
90 │ ○ d370aee184ba b
91 ○ │ 2443ea76b0b1 a
92 ├─╯
93 ◆ 000000000000
94 [EOF]
95 ");
96}
97
98#[test]
99fn test_duplicate_many() {
100 let test_env = TestEnvironment::default();
101 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
102 let work_dir = test_env.work_dir("repo");
103
104 create_commit(&work_dir, "a", &[]);
105 create_commit(&work_dir, "b", &["a"]);
106 create_commit(&work_dir, "c", &["a"]);
107 create_commit(&work_dir, "d", &["c"]);
108 create_commit(&work_dir, "e", &["b", "d"]);
109 // Test the setup
110 insta::assert_snapshot!(get_log_output(&work_dir), @r"
111 @ 921dde6e55c0 e
112 ├─╮
113 │ ○ ebd06dba20ec d
114 │ ○ c0cb3a0b73e7 c
115 ○ │ 1394f625cbbd b
116 ├─╯
117 ○ 2443ea76b0b1 a
118 ◆ 000000000000
119 [EOF]
120 ");
121
122 let output = work_dir.run_jj(["duplicate", "b::"]);
123 insta::assert_snapshot!(output, @r"
124 ------- stderr -------
125 Duplicated 1394f625cbbd as wqnwkozp 3b74d969 b
126 Duplicated 921dde6e55c0 as mouksmqu 8348ddce e
127 [EOF]
128 ");
129 insta::assert_snapshot!(get_log_output(&work_dir), @r"
130 @ 921dde6e55c0 e
131 ├─╮
132 ○ │ 1394f625cbbd b
133 │ │ ○ 8348ddcec733 e
134 │ ╭─┤
135 │ ○ │ ebd06dba20ec d
136 │ ○ │ c0cb3a0b73e7 c
137 ├─╯ │
138 │ ○ 3b74d9691015 b
139 ├───╯
140 ○ 2443ea76b0b1 a
141 ◆ 000000000000
142 [EOF]
143 ");
144
145 // Try specifying the same commit twice directly
146 work_dir.run_jj(["undo"]).success();
147 let output = work_dir.run_jj(["duplicate", "b", "b"]);
148 insta::assert_snapshot!(output, @r"
149 ------- stderr -------
150 Duplicated 1394f625cbbd as nkmrtpmo 0276d3d7 b
151 [EOF]
152 ");
153 insta::assert_snapshot!(get_log_output(&work_dir), @r"
154 @ 921dde6e55c0 e
155 ├─╮
156 │ ○ ebd06dba20ec d
157 │ ○ c0cb3a0b73e7 c
158 ○ │ 1394f625cbbd b
159 ├─╯
160 │ ○ 0276d3d7c24d b
161 ├─╯
162 ○ 2443ea76b0b1 a
163 ◆ 000000000000
164 [EOF]
165 ");
166
167 // Try specifying the same commit twice indirectly
168 work_dir.run_jj(["undo"]).success();
169 let output = work_dir.run_jj(["duplicate", "b::", "d::"]);
170 insta::assert_snapshot!(output, @r"
171 ------- stderr -------
172 Duplicated 1394f625cbbd as xtnwkqum fa167d18 b
173 Duplicated ebd06dba20ec as pqrnrkux 2181781b d
174 Duplicated 921dde6e55c0 as ztxkyksq 0f7430f2 e
175 [EOF]
176 ");
177 insta::assert_snapshot!(get_log_output(&work_dir), @r"
178 @ 921dde6e55c0 e
179 ├─╮
180 │ ○ ebd06dba20ec d
181 ○ │ 1394f625cbbd b
182 │ │ ○ 0f7430f2727a e
183 │ │ ├─╮
184 │ │ │ ○ 2181781b4f81 d
185 │ ├───╯
186 │ ○ │ c0cb3a0b73e7 c
187 ├─╯ │
188 │ ○ fa167d18a83a b
189 ├───╯
190 ○ 2443ea76b0b1 a
191 ◆ 000000000000
192 [EOF]
193 ");
194
195 work_dir.run_jj(["undo"]).success();
196 // Reminder of the setup
197 insta::assert_snapshot!(get_log_output(&work_dir), @r"
198 @ 921dde6e55c0 e
199 ├─╮
200 │ ○ ebd06dba20ec d
201 │ ○ c0cb3a0b73e7 c
202 ○ │ 1394f625cbbd b
203 ├─╯
204 ○ 2443ea76b0b1 a
205 ◆ 000000000000
206 [EOF]
207 ");
208 let output = work_dir.run_jj(["duplicate", "d::", "a"]);
209 insta::assert_snapshot!(output, @r"
210 ------- stderr -------
211 Duplicated 2443ea76b0b1 as nlrtlrxv c6f7f8c4 a
212 Duplicated ebd06dba20ec as plymsszl d94e4c55 d
213 Duplicated 921dde6e55c0 as urrlptpw 9bd4389f e
214 [EOF]
215 ");
216 insta::assert_snapshot!(get_log_output(&work_dir), @r"
217 @ 921dde6e55c0 e
218 ├─╮
219 │ ○ ebd06dba20ec d
220 │ │ ○ 9bd4389f5d47 e
221 ╭───┤
222 │ │ ○ d94e4c55a68b d
223 │ ├─╯
224 │ ○ c0cb3a0b73e7 c
225 ○ │ 1394f625cbbd b
226 ├─╯
227 ○ 2443ea76b0b1 a
228 │ ○ c6f7f8c4512e a
229 ├─╯
230 ◆ 000000000000
231 [EOF]
232 ");
233
234 // Check for BUG -- makes too many 'a'-s, etc.
235 work_dir.run_jj(["undo"]).success();
236 let output = work_dir.run_jj(["duplicate", "a::"]);
237 insta::assert_snapshot!(output, @r"
238 ------- stderr -------
239 Duplicated 2443ea76b0b1 as uuuvxpvw 0fe67a05 a
240 Duplicated 1394f625cbbd as nmpuuozl e13ac0ad b
241 Duplicated c0cb3a0b73e7 as kzpokyyw df53fa58 c
242 Duplicated ebd06dba20ec as yxrlprzz 2f2442db d
243 Duplicated 921dde6e55c0 as mvkzkxrl ee8fe64e e
244 [EOF]
245 ");
246 insta::assert_snapshot!(get_log_output(&work_dir), @r"
247 @ 921dde6e55c0 e
248 ├─╮
249 │ ○ ebd06dba20ec d
250 │ ○ c0cb3a0b73e7 c
251 ○ │ 1394f625cbbd b
252 ├─╯
253 ○ 2443ea76b0b1 a
254 │ ○ ee8fe64ed254 e
255 │ ├─╮
256 │ │ ○ 2f2442db08eb d
257 │ │ ○ df53fa589286 c
258 │ ○ │ e13ac0adabdf b
259 │ ├─╯
260 │ ○ 0fe67a05989e a
261 ├─╯
262 ◆ 000000000000
263 [EOF]
264 ");
265}
266
267#[test]
268fn test_duplicate_destination() {
269 let test_env = TestEnvironment::default();
270 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
271 let work_dir = test_env.work_dir("repo");
272
273 create_commit(&work_dir, "a1", &[]);
274 create_commit(&work_dir, "a2", &["a1"]);
275 create_commit(&work_dir, "a3", &["a2"]);
276 create_commit(&work_dir, "b", &[]);
277 create_commit(&work_dir, "c", &[]);
278 create_commit(&work_dir, "d", &[]);
279 let setup_opid = work_dir.current_operation_id();
280
281 // Test the setup
282 insta::assert_snapshot!(get_log_output(&work_dir), @r"
283 @ f7550bb42c6f d
284 │ ○ b75b7aa4b90e c
285 ├─╯
286 │ ○ 9a27d5939bef b
287 ├─╯
288 │ ○ 17072aa2b823 a3
289 │ ○ 47df67757a64 a2
290 │ ○ 9e85a474f005 a1
291 ├─╯
292 ◆ 000000000000
293 [EOF]
294 ");
295
296 // Duplicate a single commit onto a single destination.
297 let output = work_dir.run_jj(["duplicate", "a1", "-d", "c"]);
298 insta::assert_snapshot!(output, @r"
299 ------- stderr -------
300 Duplicated 9e85a474f005 as nkmrtpmo 2944a632 a1
301 [EOF]
302 ");
303 insta::assert_snapshot!(get_log_output(&work_dir), @r"
304 @ f7550bb42c6f d
305 │ ○ 2944a6324f14 a1
306 │ ○ b75b7aa4b90e c
307 ├─╯
308 │ ○ 9a27d5939bef b
309 ├─╯
310 │ ○ 17072aa2b823 a3
311 │ ○ 47df67757a64 a2
312 │ ○ 9e85a474f005 a1
313 ├─╯
314 ◆ 000000000000
315 [EOF]
316 ");
317 work_dir.run_jj(["op", "restore", &setup_opid]).success();
318
319 // Duplicate a single commit onto multiple destinations.
320 let output = work_dir.run_jj(["duplicate", "a1", "-d", "c", "-d", "d"]);
321 insta::assert_snapshot!(output, @r"
322 ------- stderr -------
323 Duplicated 9e85a474f005 as xtnwkqum 155f6a01 a1
324 [EOF]
325 ");
326 insta::assert_snapshot!(get_log_output(&work_dir), @r"
327 ○ 155f6a012334 a1
328 ├─╮
329 │ @ f7550bb42c6f d
330 ○ │ b75b7aa4b90e c
331 ├─╯
332 │ ○ 9a27d5939bef b
333 ├─╯
334 │ ○ 17072aa2b823 a3
335 │ ○ 47df67757a64 a2
336 │ ○ 9e85a474f005 a1
337 ├─╯
338 ◆ 000000000000
339 [EOF]
340 ");
341 work_dir.run_jj(["op", "restore", &setup_opid]).success();
342
343 // Duplicate a single commit onto its descendant.
344 let output = work_dir.run_jj(["duplicate", "a1", "-d", "a3"]);
345 insta::assert_snapshot!(output, @r"
346 ------- stderr -------
347 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
348 Duplicated 9e85a474f005 as wvuyspvk 95585bb2 (empty) a1
349 [EOF]
350 ");
351 insta::assert_snapshot!(get_log_output(&work_dir), @r"
352 @ f7550bb42c6f d
353 │ ○ b75b7aa4b90e c
354 ├─╯
355 │ ○ 9a27d5939bef b
356 ├─╯
357 │ ○ 95585bb2fe05 a1
358 │ ○ 17072aa2b823 a3
359 │ ○ 47df67757a64 a2
360 │ ○ 9e85a474f005 a1
361 ├─╯
362 ◆ 000000000000
363 [EOF]
364 ");
365
366 work_dir.run_jj(["op", "restore", &setup_opid]).success();
367 // Duplicate multiple commits without a direct ancestry relationship onto a
368 // single destination.
369 let output = work_dir.run_jj(["duplicate", "-r=a1", "-r=b", "-d", "c"]);
370 insta::assert_snapshot!(output, @r"
371 ------- stderr -------
372 Duplicated 9e85a474f005 as xlzxqlsl da0996fd a1
373 Duplicated 9a27d5939bef as vnkwvqxw 0af91ca8 b
374 [EOF]
375 ");
376 insta::assert_snapshot!(get_log_output(&work_dir), @r"
377 @ f7550bb42c6f d
378 │ ○ 0af91ca82d9c b
379 │ │ ○ da0996fda8ce a1
380 │ ├─╯
381 │ ○ b75b7aa4b90e c
382 ├─╯
383 │ ○ 9a27d5939bef b
384 ├─╯
385 │ ○ 17072aa2b823 a3
386 │ ○ 47df67757a64 a2
387 │ ○ 9e85a474f005 a1
388 ├─╯
389 ◆ 000000000000
390 [EOF]
391 ");
392 work_dir.run_jj(["op", "restore", &setup_opid]).success();
393
394 // Duplicate multiple commits without a direct ancestry relationship onto
395 // multiple destinations.
396 let output = work_dir.run_jj(["duplicate", "-r=a1", "b", "-d", "c", "-d", "d"]);
397 insta::assert_snapshot!(output, @r"
398 ------- stderr -------
399 Duplicated 9e85a474f005 as oupztwtk 2f519daa a1
400 Duplicated 9a27d5939bef as yxsqzptr c219a744 b
401 [EOF]
402 ");
403 insta::assert_snapshot!(get_log_output(&work_dir), @r"
404 ○ c219a744e19c b
405 ├─╮
406 │ │ ○ 2f519daab24d a1
407 ╭─┬─╯
408 │ @ f7550bb42c6f d
409 ○ │ b75b7aa4b90e c
410 ├─╯
411 │ ○ 9a27d5939bef b
412 ├─╯
413 │ ○ 17072aa2b823 a3
414 │ ○ 47df67757a64 a2
415 │ ○ 9e85a474f005 a1
416 ├─╯
417 ◆ 000000000000
418 [EOF]
419 ");
420 work_dir.run_jj(["op", "restore", &setup_opid]).success();
421
422 // Duplicate multiple commits with an ancestry relationship onto a
423 // single destination.
424 let output = work_dir.run_jj(["duplicate", "a1", "a3", "-d", "c"]);
425 insta::assert_snapshot!(output, @r"
426 ------- stderr -------
427 Duplicated 9e85a474f005 as wtszoswq 806f2b56 a1
428 Duplicated 17072aa2b823 as qmykwtmu 161ce874 a3
429 [EOF]
430 ");
431 insta::assert_snapshot!(get_log_output(&work_dir), @r"
432 @ f7550bb42c6f d
433 │ ○ 161ce87408d5 a3
434 │ ○ 806f2b56207d a1
435 │ ○ b75b7aa4b90e c
436 ├─╯
437 │ ○ 9a27d5939bef b
438 ├─╯
439 │ ○ 17072aa2b823 a3
440 │ ○ 47df67757a64 a2
441 │ ○ 9e85a474f005 a1
442 ├─╯
443 ◆ 000000000000
444 [EOF]
445 ");
446 work_dir.run_jj(["op", "restore", &setup_opid]).success();
447
448 // Duplicate multiple commits with an ancestry relationship onto
449 // multiple destinations.
450 let output = work_dir.run_jj(["duplicate", "a1", "a3", "-d", "c", "-d", "d"]);
451 insta::assert_snapshot!(output, @r"
452 ------- stderr -------
453 Duplicated 9e85a474f005 as rkoyqlrv 02cbff23 a1
454 Duplicated 17072aa2b823 as zxvrqtmq ddcfb95f a3
455 [EOF]
456 ");
457 insta::assert_snapshot!(get_log_output(&work_dir), @r"
458 ○ ddcfb95ff7d8 a3
459 ○ 02cbff23a61d a1
460 ├─╮
461 │ @ f7550bb42c6f d
462 ○ │ b75b7aa4b90e c
463 ├─╯
464 │ ○ 9a27d5939bef b
465 ├─╯
466 │ ○ 17072aa2b823 a3
467 │ ○ 47df67757a64 a2
468 │ ○ 9e85a474f005 a1
469 ├─╯
470 ◆ 000000000000
471 [EOF]
472 ");
473}
474
475#[test]
476fn test_duplicate_insert_after() {
477 let test_env = TestEnvironment::default();
478 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
479 let work_dir = test_env.work_dir("repo");
480
481 create_commit(&work_dir, "a1", &[]);
482 create_commit(&work_dir, "a2", &["a1"]);
483 create_commit(&work_dir, "a3", &["a2"]);
484 create_commit(&work_dir, "a4", &["a3"]);
485 create_commit(&work_dir, "b1", &[]);
486 create_commit(&work_dir, "b2", &["b1"]);
487 create_commit(&work_dir, "c1", &[]);
488 create_commit(&work_dir, "c2", &["c1"]);
489 create_commit(&work_dir, "d1", &[]);
490 create_commit(&work_dir, "d2", &["d1"]);
491 let setup_opid = work_dir.current_operation_id();
492
493 // Test the setup
494 insta::assert_snapshot!(get_log_output(&work_dir), @r"
495 @ 0cdd923e993a d2
496 ○ 0f21c5e185c5 d1
497 │ ○ 09560d60cac4 c2
498 │ ○ b27346e9a9bd c1
499 ├─╯
500 │ ○ 7b44470918f4 b2
501 │ ○ dcc98bc8bbea b1
502 ├─╯
503 │ ○ 196bc1f0efc1 a4
504 │ ○ 17072aa2b823 a3
505 │ ○ 47df67757a64 a2
506 │ ○ 9e85a474f005 a1
507 ├─╯
508 ◆ 000000000000
509 [EOF]
510 ");
511
512 // Duplicate a single commit after a single commit with no direct relationship.
513 let output = work_dir.run_jj(["duplicate", "a1", "--after", "b1"]);
514 insta::assert_snapshot!(output, @r"
515 ------- stderr -------
516 Duplicated 9e85a474f005 as pzsxstzt b71e23da a1
517 Rebased 1 commits onto duplicated commits
518 [EOF]
519 ");
520 insta::assert_snapshot!(get_log_output(&work_dir), @r"
521 @ 0cdd923e993a d2
522 ○ 0f21c5e185c5 d1
523 │ ○ 09560d60cac4 c2
524 │ ○ b27346e9a9bd c1
525 ├─╯
526 │ ○ af12531fa2dc b2
527 │ ○ b71e23da3559 a1
528 │ ○ dcc98bc8bbea b1
529 ├─╯
530 │ ○ 196bc1f0efc1 a4
531 │ ○ 17072aa2b823 a3
532 │ ○ 47df67757a64 a2
533 │ ○ 9e85a474f005 a1
534 ├─╯
535 ◆ 000000000000
536 [EOF]
537 ");
538 work_dir.run_jj(["op", "restore", &setup_opid]).success();
539
540 // Duplicate a single commit after a single ancestor commit.
541 let output = work_dir.run_jj(["duplicate", "a3", "--after", "a1"]);
542 insta::assert_snapshot!(output, @r"
543 ------- stderr -------
544 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
545 Duplicated 17072aa2b823 as qmkrwlvp fd3c891b a3
546 Rebased 3 commits onto duplicated commits
547 [EOF]
548 ");
549 insta::assert_snapshot!(get_log_output(&work_dir), @r"
550 @ 0cdd923e993a d2
551 ○ 0f21c5e185c5 d1
552 │ ○ 09560d60cac4 c2
553 │ ○ b27346e9a9bd c1
554 ├─╯
555 │ ○ 7b44470918f4 b2
556 │ ○ dcc98bc8bbea b1
557 ├─╯
558 │ ○ 027d38df36fa a4
559 │ ○ 6cb0f5884a35 a3
560 │ ○ 80e3e40b66f0 a2
561 │ ○ fd3c891b8b97 a3
562 │ ○ 9e85a474f005 a1
563 ├─╯
564 ◆ 000000000000
565 [EOF]
566 ");
567 work_dir.run_jj(["op", "restore", &setup_opid]).success();
568
569 // Duplicate a single commit after a single descendant commit.
570 let output = work_dir.run_jj(["duplicate", "a1", "--after", "a3"]);
571 insta::assert_snapshot!(output, @r"
572 ------- stderr -------
573 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
574 Duplicated 9e85a474f005 as qwyusntz a4d0b771 (empty) a1
575 Rebased 1 commits onto duplicated commits
576 [EOF]
577 ");
578 insta::assert_snapshot!(get_log_output(&work_dir), @r"
579 @ 0cdd923e993a d2
580 ○ 0f21c5e185c5 d1
581 │ ○ 09560d60cac4 c2
582 │ ○ b27346e9a9bd c1
583 ├─╯
584 │ ○ 7b44470918f4 b2
585 │ ○ dcc98bc8bbea b1
586 ├─╯
587 │ ○ 9fe3808a9067 a4
588 │ ○ a4d0b7715767 a1
589 │ ○ 17072aa2b823 a3
590 │ ○ 47df67757a64 a2
591 │ ○ 9e85a474f005 a1
592 ├─╯
593 ◆ 000000000000
594 [EOF]
595 ");
596 work_dir.run_jj(["op", "restore", &setup_opid]).success();
597
598 // Duplicate a single commit after multiple commits with no direct
599 // relationship.
600 let output = work_dir.run_jj(["duplicate", "a1", "--after", "b1", "--after", "c1"]);
601 insta::assert_snapshot!(output, @r"
602 ------- stderr -------
603 Duplicated 9e85a474f005 as soqnvnyz 3449bde2 a1
604 Rebased 2 commits onto duplicated commits
605 [EOF]
606 ");
607 insta::assert_snapshot!(get_log_output(&work_dir), @r"
608 @ 0cdd923e993a d2
609 ○ 0f21c5e185c5 d1
610 │ ○ c997a412ac93 c2
611 │ │ ○ e570747744ed b2
612 │ ├─╯
613 │ ○ 3449bde20037 a1
614 │ ├─╮
615 │ │ ○ b27346e9a9bd c1
616 ├───╯
617 │ ○ dcc98bc8bbea b1
618 ├─╯
619 │ ○ 196bc1f0efc1 a4
620 │ ○ 17072aa2b823 a3
621 │ ○ 47df67757a64 a2
622 │ ○ 9e85a474f005 a1
623 ├─╯
624 ◆ 000000000000
625 [EOF]
626 ");
627 work_dir.run_jj(["op", "restore", &setup_opid]).success();
628
629 // Duplicate a single commit after multiple commits including an ancestor.
630 let output = work_dir.run_jj(["duplicate", "a3", "--after", "a2", "--after", "b2"]);
631 insta::assert_snapshot!(output, @r"
632 ------- stderr -------
633 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
634 Duplicated 17072aa2b823 as nsrwusvy 48764702 a3
635 Rebased 2 commits onto duplicated commits
636 [EOF]
637 ");
638 insta::assert_snapshot!(get_log_output(&work_dir), @r"
639 @ 0cdd923e993a d2
640 ○ 0f21c5e185c5 d1
641 │ ○ 09560d60cac4 c2
642 │ ○ b27346e9a9bd c1
643 ├─╯
644 │ ○ aead471d6dc8 a4
645 │ ○ 07fb2a10b5de a3
646 │ ○ 48764702c97c a3
647 │ ├─╮
648 │ │ ○ 7b44470918f4 b2
649 │ │ ○ dcc98bc8bbea b1
650 ├───╯
651 │ ○ 47df67757a64 a2
652 │ ○ 9e85a474f005 a1
653 ├─╯
654 ◆ 000000000000
655 [EOF]
656 ");
657 work_dir.run_jj(["op", "restore", &setup_opid]).success();
658
659 // Duplicate a single commit after multiple commits including a descendant.
660 let output = work_dir.run_jj(["duplicate", "a1", "--after", "a3", "--after", "b2"]);
661 insta::assert_snapshot!(output, @r"
662 ------- stderr -------
663 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
664 Duplicated 9e85a474f005 as xpnwykqz 43bcb4dc (empty) a1
665 Rebased 1 commits onto duplicated commits
666 [EOF]
667 ");
668 insta::assert_snapshot!(get_log_output(&work_dir), @r"
669 @ 0cdd923e993a d2
670 ○ 0f21c5e185c5 d1
671 │ ○ 09560d60cac4 c2
672 │ ○ b27346e9a9bd c1
673 ├─╯
674 │ ○ 92782f7d24fe a4
675 │ ○ 43bcb4dc97f4 a1
676 │ ├─╮
677 │ │ ○ 7b44470918f4 b2
678 │ │ ○ dcc98bc8bbea b1
679 ├───╯
680 │ ○ 17072aa2b823 a3
681 │ ○ 47df67757a64 a2
682 │ ○ 9e85a474f005 a1
683 ├─╯
684 ◆ 000000000000
685 [EOF]
686 ");
687 work_dir.run_jj(["op", "restore", &setup_opid]).success();
688
689 // Duplicate multiple commits without a direct ancestry relationship after a
690 // single commit without a direct relationship.
691 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "c1"]);
692 insta::assert_snapshot!(output, @r"
693 ------- stderr -------
694 Duplicated 9e85a474f005 as sryyqqkq 44f57f24 a1
695 Duplicated dcc98bc8bbea as pxnqtknr bcee4b60 b1
696 Rebased 1 commits onto duplicated commits
697 [EOF]
698 ");
699 insta::assert_snapshot!(get_log_output(&work_dir), @r"
700 @ 0cdd923e993a d2
701 ○ 0f21c5e185c5 d1
702 │ ○ 215600d39fed c2
703 │ ├─╮
704 │ │ ○ bcee4b6058e4 b1
705 │ ○ │ 44f57f247bf2 a1
706 │ ├─╯
707 │ ○ b27346e9a9bd c1
708 ├─╯
709 │ ○ 7b44470918f4 b2
710 │ ○ dcc98bc8bbea b1
711 ├─╯
712 │ ○ 196bc1f0efc1 a4
713 │ ○ 17072aa2b823 a3
714 │ ○ 47df67757a64 a2
715 │ ○ 9e85a474f005 a1
716 ├─╯
717 ◆ 000000000000
718 [EOF]
719 ");
720 work_dir.run_jj(["op", "restore", &setup_opid]).success();
721
722 // Duplicate multiple commits without a direct ancestry relationship after a
723 // single commit which is an ancestor of one of the duplicated commits.
724 let output = work_dir.run_jj(["duplicate", "a3", "b1", "--after", "a2"]);
725 insta::assert_snapshot!(output, @r"
726 ------- stderr -------
727 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
728 Duplicated 17072aa2b823 as pyoswmwk 0d11d466 a3
729 Duplicated dcc98bc8bbea as yqnpwwmq c32d1ccc b1
730 Rebased 2 commits onto duplicated commits
731 [EOF]
732 ");
733 insta::assert_snapshot!(get_log_output(&work_dir), @r"
734 @ 0cdd923e993a d2
735 ○ 0f21c5e185c5 d1
736 │ ○ 09560d60cac4 c2
737 │ ○ b27346e9a9bd c1
738 ├─╯
739 │ ○ 7b44470918f4 b2
740 │ ○ dcc98bc8bbea b1
741 ├─╯
742 │ ○ 955959f7bb42 a4
743 │ ○ 7b2b1ab433f0 a3
744 │ ├─╮
745 │ │ ○ c32d1ccc8d5b b1
746 │ ○ │ 0d11d4667aa9 a3
747 │ ├─╯
748 │ ○ 47df67757a64 a2
749 │ ○ 9e85a474f005 a1
750 ├─╯
751 ◆ 000000000000
752 [EOF]
753 ");
754 work_dir.run_jj(["op", "restore", &setup_opid]).success();
755
756 // Duplicate multiple commits without a direct ancestry relationship after a
757 // single commit which is a descendant of one of the duplicated commits.
758 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "a3"]);
759 insta::assert_snapshot!(output, @r"
760 ------- stderr -------
761 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
762 Duplicated 9e85a474f005 as tpmlxquz 213aff50 (empty) a1
763 Duplicated dcc98bc8bbea as uukzylyy 67b82bab b1
764 Rebased 1 commits onto duplicated commits
765 [EOF]
766 ");
767 insta::assert_snapshot!(get_log_output(&work_dir), @r"
768 @ 0cdd923e993a d2
769 ○ 0f21c5e185c5 d1
770 │ ○ 09560d60cac4 c2
771 │ ○ b27346e9a9bd c1
772 ├─╯
773 │ ○ 7b44470918f4 b2
774 │ ○ dcc98bc8bbea b1
775 ├─╯
776 │ ○ 9457bd90ac07 a4
777 │ ├─╮
778 │ │ ○ 67b82babd5f6 b1
779 │ ○ │ 213aff50a82b a1
780 │ ├─╯
781 │ ○ 17072aa2b823 a3
782 │ ○ 47df67757a64 a2
783 │ ○ 9e85a474f005 a1
784 ├─╯
785 ◆ 000000000000
786 [EOF]
787 ");
788 work_dir.run_jj(["op", "restore", &setup_opid]).success();
789
790 // Duplicate multiple commits without a direct ancestry relationship after
791 // multiple commits without a direct relationship to the duplicated commits.
792 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "c1", "--after", "d1"]);
793 insta::assert_snapshot!(output, @r"
794 ------- stderr -------
795 Duplicated 9e85a474f005 as knltnxnu ad0a80e9 a1
796 Duplicated dcc98bc8bbea as krtqozmx 840bbbe5 b1
797 Rebased 2 commits onto duplicated commits
798 Working copy (@) now at: nmzmmopx 9eeade97 d2 | d2
799 Parent commit (@-) : knltnxnu ad0a80e9 a1
800 Parent commit (@-) : krtqozmx 840bbbe5 b1
801 Added 3 files, modified 0 files, removed 0 files
802 [EOF]
803 ");
804 insta::assert_snapshot!(get_log_output(&work_dir), @r"
805 @ 9eeade97a2f7 d2
806 ├─╮
807 │ │ ○ cd045e3862be c2
808 ╭─┬─╯
809 │ ○ 840bbbe57acb b1
810 │ ├─╮
811 ○ │ │ ad0a80e9b011 a1
812 ╰─┬─╮
813 │ ○ 0f21c5e185c5 d1
814 ○ │ b27346e9a9bd c1
815 ├─╯
816 ○ │ 7b44470918f4 b2
817 ○ │ dcc98bc8bbea b1
818 ├─╯
819 │ ○ 196bc1f0efc1 a4
820 │ ○ 17072aa2b823 a3
821 │ ○ 47df67757a64 a2
822 │ ○ 9e85a474f005 a1
823 ├─╯
824 ◆ 000000000000
825 [EOF]
826 ");
827 work_dir.run_jj(["op", "restore", &setup_opid]).success();
828
829 // Duplicate multiple commits without a direct ancestry relationship after
830 // multiple commits including an ancestor of one of the duplicated commits.
831 let output = work_dir.run_jj(["duplicate", "a3", "b1", "--after", "a1", "--after", "c1"]);
832 insta::assert_snapshot!(output, @r"
833 ------- stderr -------
834 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
835 Duplicated 17072aa2b823 as wxzmtyol ade2ae32 a3
836 Duplicated dcc98bc8bbea as musouqkq e1eed3f1 b1
837 Rebased 4 commits onto duplicated commits
838 [EOF]
839 ");
840 insta::assert_snapshot!(get_log_output(&work_dir), @r"
841 @ 0cdd923e993a d2
842 ○ 0f21c5e185c5 d1
843 │ ○ 12a208423aa9 c2
844 │ ├─╮
845 │ │ │ ○ c804d94310fd a4
846 │ │ │ ○ e22e44ff5f22 a3
847 │ │ │ ○ 6ee77bdfc821 a2
848 │ ╭─┬─╯
849 │ │ ○ e1eed3f1c77c b1
850 │ │ ├─╮
851 │ ○ │ │ ade2ae32950a a3
852 │ ╰─┬─╮
853 │ │ ○ b27346e9a9bd c1
854 ├─────╯
855 │ ○ 9e85a474f005 a1
856 ├───╯
857 │ ○ 7b44470918f4 b2
858 │ ○ dcc98bc8bbea b1
859 ├─╯
860 ◆ 000000000000
861 [EOF]
862 ");
863 work_dir.run_jj(["op", "restore", &setup_opid]).success();
864
865 // Duplicate multiple commits without a direct ancestry relationship after
866 // multiple commits including a descendant of one of the duplicated commits.
867 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "a3", "--after", "c2"]);
868 insta::assert_snapshot!(output, @r"
869 ------- stderr -------
870 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
871 Duplicated 9e85a474f005 as quyylypw c4820edd (empty) a1
872 Duplicated dcc98bc8bbea as prukwozq 20cfd11e b1
873 Rebased 1 commits onto duplicated commits
874 [EOF]
875 ");
876 insta::assert_snapshot!(get_log_output(&work_dir), @r"
877 @ 0cdd923e993a d2
878 ○ 0f21c5e185c5 d1
879 │ ○ 2d04909f04b5 a4
880 │ ├─╮
881 │ │ ○ 20cfd11ee3c3 b1
882 │ │ ├─╮
883 │ ○ │ │ c4820eddcd3c a1
884 │ ╰─┬─╮
885 │ │ ○ 09560d60cac4 c2
886 │ │ ○ b27346e9a9bd c1
887 ├─────╯
888 │ ○ 17072aa2b823 a3
889 │ ○ 47df67757a64 a2
890 │ ○ 9e85a474f005 a1
891 ├───╯
892 │ ○ 7b44470918f4 b2
893 │ ○ dcc98bc8bbea b1
894 ├─╯
895 ◆ 000000000000
896 [EOF]
897 ");
898 work_dir.run_jj(["op", "restore", &setup_opid]).success();
899
900 // Duplicate multiple commits with an ancestry relationship after a single
901 // commit without a direct relationship.
902 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--after", "c2"]);
903 insta::assert_snapshot!(output, @r"
904 ------- stderr -------
905 Duplicated 9e85a474f005 as vvvtksvt b44d23b4 a1
906 Duplicated 17072aa2b823 as yvrnrpnw ca8f08f6 a3
907 [EOF]
908 ");
909 insta::assert_snapshot!(get_log_output(&work_dir), @r"
910 @ 0cdd923e993a d2
911 ○ 0f21c5e185c5 d1
912 │ ○ ca8f08f66c5c a3
913 │ ○ b44d23b4c98e a1
914 │ ○ 09560d60cac4 c2
915 │ ○ b27346e9a9bd c1
916 ├─╯
917 │ ○ 7b44470918f4 b2
918 │ ○ dcc98bc8bbea b1
919 ├─╯
920 │ ○ 196bc1f0efc1 a4
921 │ ○ 17072aa2b823 a3
922 │ ○ 47df67757a64 a2
923 │ ○ 9e85a474f005 a1
924 ├─╯
925 ◆ 000000000000
926 [EOF]
927 ");
928 work_dir.run_jj(["op", "restore", &setup_opid]).success();
929
930 // Duplicate multiple commits with an ancestry relationship after a single
931 // ancestor commit.
932 let output = work_dir.run_jj(["duplicate", "a2", "a3", "--after", "a1"]);
933 insta::assert_snapshot!(output, @r"
934 ------- stderr -------
935 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
936 Warning: Duplicating commit 47df67757a64 as an ancestor of itself
937 Duplicated 47df67757a64 as sukptuzs 4324d289 a2
938 Duplicated 17072aa2b823 as rxnrppxl 47586b09 a3
939 Rebased 3 commits onto duplicated commits
940 [EOF]
941 ");
942 insta::assert_snapshot!(get_log_output(&work_dir), @r"
943 @ 0cdd923e993a d2
944 ○ 0f21c5e185c5 d1
945 │ ○ 09560d60cac4 c2
946 │ ○ b27346e9a9bd c1
947 ├─╯
948 │ ○ 7b44470918f4 b2
949 │ ○ dcc98bc8bbea b1
950 ├─╯
951 │ ○ 2174f54d55a9 a4
952 │ ○ 0224bfb4fc3d a3
953 │ ○ 22d3bdc60967 a2
954 │ ○ 47586b09a555 a3
955 │ ○ 4324d289e62c a2
956 │ ○ 9e85a474f005 a1
957 ├─╯
958 ◆ 000000000000
959 [EOF]
960 ");
961 work_dir.run_jj(["op", "restore", &setup_opid]).success();
962
963 // Duplicate multiple commits with an ancestry relationship after a single
964 // descendant commit.
965 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--after", "a3"]);
966 insta::assert_snapshot!(output, @r"
967 ------- stderr -------
968 Warning: Duplicating commit 47df67757a64 as a descendant of itself
969 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
970 Duplicated 9e85a474f005 as rwkyzntp b68b9a00 (empty) a1
971 Duplicated 47df67757a64 as nqtyztop 0dd00ded (empty) a2
972 Rebased 1 commits onto duplicated commits
973 [EOF]
974 ");
975 insta::assert_snapshot!(get_log_output(&work_dir), @r"
976 @ 0cdd923e993a d2
977 ○ 0f21c5e185c5 d1
978 │ ○ 09560d60cac4 c2
979 │ ○ b27346e9a9bd c1
980 ├─╯
981 │ ○ 7b44470918f4 b2
982 │ ○ dcc98bc8bbea b1
983 ├─╯
984 │ ○ 4f02390e56aa a4
985 │ ○ 0dd00dedd0c5 a2
986 │ ○ b68b9a0073cb a1
987 │ ○ 17072aa2b823 a3
988 │ ○ 47df67757a64 a2
989 │ ○ 9e85a474f005 a1
990 ├─╯
991 ◆ 000000000000
992 [EOF]
993 ");
994 work_dir.run_jj(["op", "restore", &setup_opid]).success();
995
996 // Duplicate multiple commits with an ancestry relationship after multiple
997 // commits without a direct relationship to the duplicated commits.
998 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--after", "c2", "--after", "d2"]);
999 insta::assert_snapshot!(output, @r"
1000 ------- stderr -------
1001 Duplicated 9e85a474f005 as nwmqwkzz eb455287 a1
1002 Duplicated 17072aa2b823 as uwrrnrtx 94a1bd80 a3
1003 [EOF]
1004 ");
1005 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1006 ○ 94a1bd8080c6 a3
1007 ○ eb455287f1eb a1
1008 ├─╮
1009 │ @ 0cdd923e993a d2
1010 │ ○ 0f21c5e185c5 d1
1011 ○ │ 09560d60cac4 c2
1012 ○ │ b27346e9a9bd c1
1013 ├─╯
1014 │ ○ 7b44470918f4 b2
1015 │ ○ dcc98bc8bbea b1
1016 ├─╯
1017 │ ○ 196bc1f0efc1 a4
1018 │ ○ 17072aa2b823 a3
1019 │ ○ 47df67757a64 a2
1020 │ ○ 9e85a474f005 a1
1021 ├─╯
1022 ◆ 000000000000
1023 [EOF]
1024 ");
1025 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1026
1027 // Duplicate multiple commits with an ancestry relationship after multiple
1028 // commits including an ancestor of one of the duplicated commits.
1029 let output = work_dir.run_jj(["duplicate", "a3", "a4", "--after", "a2", "--after", "c2"]);
1030 insta::assert_snapshot!(output, @r"
1031 ------- stderr -------
1032 Warning: Duplicating commit 196bc1f0efc1 as an ancestor of itself
1033 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1034 Duplicated 17072aa2b823 as wunttkrp 1ce432e1 a3
1035 Duplicated 196bc1f0efc1 as puxpuzrm 14728ee8 a4
1036 Rebased 2 commits onto duplicated commits
1037 [EOF]
1038 ");
1039 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1040 @ 0cdd923e993a d2
1041 ○ 0f21c5e185c5 d1
1042 │ ○ 5fa41821880b a4
1043 │ ○ 52554e3e9729 a3
1044 │ ○ 14728ee84976 a4
1045 │ ○ 1ce432e1b0ea a3
1046 │ ├─╮
1047 │ │ ○ 09560d60cac4 c2
1048 │ │ ○ b27346e9a9bd c1
1049 ├───╯
1050 │ ○ 47df67757a64 a2
1051 │ ○ 9e85a474f005 a1
1052 ├─╯
1053 │ ○ 7b44470918f4 b2
1054 │ ○ dcc98bc8bbea b1
1055 ├─╯
1056 ◆ 000000000000
1057 [EOF]
1058 ");
1059 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1060
1061 // Duplicate multiple commits with an ancestry relationship after multiple
1062 // commits including a descendant of one of the duplicated commits.
1063 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--after", "a3", "--after", "c2"]);
1064 insta::assert_snapshot!(output, @r"
1065 ------- stderr -------
1066 Warning: Duplicating commit 47df67757a64 as a descendant of itself
1067 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1068 Duplicated 9e85a474f005 as zwvplpop 67dd65d3 (empty) a1
1069 Duplicated 47df67757a64 as znsksvls 7536fd44 (empty) a2
1070 Rebased 1 commits onto duplicated commits
1071 [EOF]
1072 ");
1073 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1074 @ 0cdd923e993a d2
1075 ○ 0f21c5e185c5 d1
1076 │ ○ 83aa2cfb2448 a4
1077 │ ○ 7536fd4475cd a2
1078 │ ○ 67dd65d3d47a a1
1079 │ ├─╮
1080 │ │ ○ 09560d60cac4 c2
1081 │ │ ○ b27346e9a9bd c1
1082 ├───╯
1083 │ ○ 17072aa2b823 a3
1084 │ ○ 47df67757a64 a2
1085 │ ○ 9e85a474f005 a1
1086 ├─╯
1087 │ ○ 7b44470918f4 b2
1088 │ ○ dcc98bc8bbea b1
1089 ├─╯
1090 ◆ 000000000000
1091 [EOF]
1092 ");
1093 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1094
1095 // Should error if a loop will be created.
1096 let output = work_dir.run_jj(["duplicate", "a1", "--after", "b1", "--after", "b2"]);
1097 insta::assert_snapshot!(output, @r"
1098 ------- stderr -------
1099 Error: Refusing to create a loop: commit 7b44470918f4 would be both an ancestor and a descendant of the duplicated commits
1100 [EOF]
1101 [exit status: 1]
1102 ");
1103}
1104
1105#[test]
1106fn test_duplicate_insert_before() {
1107 let test_env = TestEnvironment::default();
1108 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
1109 let work_dir = test_env.work_dir("repo");
1110
1111 create_commit(&work_dir, "a1", &[]);
1112 create_commit(&work_dir, "a2", &["a1"]);
1113 create_commit(&work_dir, "a3", &["a2"]);
1114 create_commit(&work_dir, "a4", &["a3"]);
1115 create_commit(&work_dir, "b1", &[]);
1116 create_commit(&work_dir, "b2", &["b1"]);
1117 create_commit(&work_dir, "c1", &[]);
1118 create_commit(&work_dir, "c2", &["c1"]);
1119 create_commit(&work_dir, "d1", &[]);
1120 create_commit(&work_dir, "d2", &["d1"]);
1121 let setup_opid = work_dir.current_operation_id();
1122
1123 // Test the setup
1124 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1125 @ 0cdd923e993a d2
1126 ○ 0f21c5e185c5 d1
1127 │ ○ 09560d60cac4 c2
1128 │ ○ b27346e9a9bd c1
1129 ├─╯
1130 │ ○ 7b44470918f4 b2
1131 │ ○ dcc98bc8bbea b1
1132 ├─╯
1133 │ ○ 196bc1f0efc1 a4
1134 │ ○ 17072aa2b823 a3
1135 │ ○ 47df67757a64 a2
1136 │ ○ 9e85a474f005 a1
1137 ├─╯
1138 ◆ 000000000000
1139 [EOF]
1140 ");
1141
1142 // Duplicate a single commit before a single commit with no direct relationship.
1143 let output = work_dir.run_jj(["duplicate", "a1", "--before", "b2"]);
1144 insta::assert_snapshot!(output, @r"
1145 ------- stderr -------
1146 Duplicated 9e85a474f005 as pzsxstzt b71e23da a1
1147 Rebased 1 commits onto duplicated commits
1148 [EOF]
1149 ");
1150 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1151 @ 0cdd923e993a d2
1152 ○ 0f21c5e185c5 d1
1153 │ ○ 09560d60cac4 c2
1154 │ ○ b27346e9a9bd c1
1155 ├─╯
1156 │ ○ af12531fa2dc b2
1157 │ ○ b71e23da3559 a1
1158 │ ○ dcc98bc8bbea b1
1159 ├─╯
1160 │ ○ 196bc1f0efc1 a4
1161 │ ○ 17072aa2b823 a3
1162 │ ○ 47df67757a64 a2
1163 │ ○ 9e85a474f005 a1
1164 ├─╯
1165 ◆ 000000000000
1166 [EOF]
1167 ");
1168 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1169
1170 // Duplicate a single commit before a single ancestor commit.
1171 let output = work_dir.run_jj(["duplicate", "a3", "--before", "a1"]);
1172 insta::assert_snapshot!(output, @r"
1173 ------- stderr -------
1174 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1175 Duplicated 17072aa2b823 as qmkrwlvp 2108707c a3
1176 Rebased 4 commits onto duplicated commits
1177 [EOF]
1178 ");
1179 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1180 @ 0cdd923e993a d2
1181 ○ 0f21c5e185c5 d1
1182 │ ○ ef93a98b9dba a4
1183 │ ○ 5952e93b6237 a3
1184 │ ○ f9baa38681ce a2
1185 │ ○ 3096149ab785 a1
1186 │ ○ 2108707c8d39 a3
1187 ├─╯
1188 │ ○ 09560d60cac4 c2
1189 │ ○ b27346e9a9bd c1
1190 ├─╯
1191 │ ○ 7b44470918f4 b2
1192 │ ○ dcc98bc8bbea b1
1193 ├─╯
1194 ◆ 000000000000
1195 [EOF]
1196 ");
1197 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1198
1199 // Duplicate a single commit before a single descendant commit.
1200 let output = work_dir.run_jj(["duplicate", "a1", "--before", "a3"]);
1201 insta::assert_snapshot!(output, @r"
1202 ------- stderr -------
1203 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1204 Duplicated 9e85a474f005 as qwyusntz 2fe2d212 (empty) a1
1205 Rebased 2 commits onto duplicated commits
1206 [EOF]
1207 ");
1208 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1209 @ 0cdd923e993a d2
1210 ○ 0f21c5e185c5 d1
1211 │ ○ 09560d60cac4 c2
1212 │ ○ b27346e9a9bd c1
1213 ├─╯
1214 │ ○ 7b44470918f4 b2
1215 │ ○ dcc98bc8bbea b1
1216 ├─╯
1217 │ ○ 664fce416f57 a4
1218 │ ○ 547efe815e18 a3
1219 │ ○ 2fe2d21257c9 a1
1220 │ ○ 47df67757a64 a2
1221 │ ○ 9e85a474f005 a1
1222 ├─╯
1223 ◆ 000000000000
1224 [EOF]
1225 ");
1226 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1227
1228 // Duplicate a single commit before multiple commits with no direct
1229 // relationship.
1230 let output = work_dir.run_jj(["duplicate", "a1", "--before", "b2", "--before", "c2"]);
1231 insta::assert_snapshot!(output, @r"
1232 ------- stderr -------
1233 Duplicated 9e85a474f005 as soqnvnyz 3449bde2 a1
1234 Rebased 2 commits onto duplicated commits
1235 [EOF]
1236 ");
1237 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1238 @ 0cdd923e993a d2
1239 ○ 0f21c5e185c5 d1
1240 │ ○ c997a412ac93 c2
1241 │ │ ○ e570747744ed b2
1242 │ ├─╯
1243 │ ○ 3449bde20037 a1
1244 │ ├─╮
1245 │ │ ○ b27346e9a9bd c1
1246 ├───╯
1247 │ ○ dcc98bc8bbea b1
1248 ├─╯
1249 │ ○ 196bc1f0efc1 a4
1250 │ ○ 17072aa2b823 a3
1251 │ ○ 47df67757a64 a2
1252 │ ○ 9e85a474f005 a1
1253 ├─╯
1254 ◆ 000000000000
1255 [EOF]
1256 ");
1257 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1258
1259 // Duplicate a single commit before multiple commits including an ancestor.
1260 let output = work_dir.run_jj(["duplicate", "a3", "--before", "a2", "--before", "b2"]);
1261 insta::assert_snapshot!(output, @r"
1262 ------- stderr -------
1263 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1264 Duplicated 17072aa2b823 as nsrwusvy 8648c1c8 a3
1265 Rebased 4 commits onto duplicated commits
1266 [EOF]
1267 ");
1268 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1269 @ 0cdd923e993a d2
1270 ○ 0f21c5e185c5 d1
1271 │ ○ 09560d60cac4 c2
1272 │ ○ b27346e9a9bd c1
1273 ├─╯
1274 │ ○ 1722fb59dee6 b2
1275 │ │ ○ cdeff7751fb6 a4
1276 │ │ ○ 28f70dc150b8 a3
1277 │ │ ○ f38e6d30913d a2
1278 │ ├─╯
1279 │ ○ 8648c1c894f0 a3
1280 │ ├─╮
1281 │ │ ○ dcc98bc8bbea b1
1282 ├───╯
1283 │ ○ 9e85a474f005 a1
1284 ├─╯
1285 ◆ 000000000000
1286 [EOF]
1287 ");
1288 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1289
1290 // Duplicate a single commit before multiple commits including a descendant.
1291 let output = work_dir.run_jj(["duplicate", "a1", "--before", "a3", "--before", "b2"]);
1292 insta::assert_snapshot!(output, @r"
1293 ------- stderr -------
1294 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1295 Duplicated 9e85a474f005 as xpnwykqz 72cf8983 (empty) a1
1296 Rebased 3 commits onto duplicated commits
1297 [EOF]
1298 ");
1299 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1300 @ 0cdd923e993a d2
1301 ○ 0f21c5e185c5 d1
1302 │ ○ 09560d60cac4 c2
1303 │ ○ b27346e9a9bd c1
1304 ├─╯
1305 │ ○ d78b124079a4 b2
1306 │ │ ○ 490d6138ef36 a4
1307 │ │ ○ e349d271ef64 a3
1308 │ ├─╯
1309 │ ○ 72cf89838d1a a1
1310 │ ├─╮
1311 │ │ ○ dcc98bc8bbea b1
1312 ├───╯
1313 │ ○ 47df67757a64 a2
1314 │ ○ 9e85a474f005 a1
1315 ├─╯
1316 ◆ 000000000000
1317 [EOF]
1318 ");
1319 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1320
1321 // Duplicate multiple commits without a direct ancestry relationship before a
1322 // single commit without a direct relationship.
1323 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--before", "c1"]);
1324 insta::assert_snapshot!(output, @r"
1325 ------- stderr -------
1326 Duplicated 9e85a474f005 as sryyqqkq fa625d74 a1
1327 Duplicated dcc98bc8bbea as pxnqtknr 2233b9a8 b1
1328 Rebased 2 commits onto duplicated commits
1329 [EOF]
1330 ");
1331 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1332 @ 0cdd923e993a d2
1333 ○ 0f21c5e185c5 d1
1334 │ ○ cf7c4c4cc8bc c2
1335 │ ○ 6412acdac711 c1
1336 │ ├─╮
1337 │ │ ○ 2233b9a87d86 b1
1338 ├───╯
1339 │ ○ fa625d74e0ae a1
1340 ├─╯
1341 │ ○ 7b44470918f4 b2
1342 │ ○ dcc98bc8bbea b1
1343 ├─╯
1344 │ ○ 196bc1f0efc1 a4
1345 │ ○ 17072aa2b823 a3
1346 │ ○ 47df67757a64 a2
1347 │ ○ 9e85a474f005 a1
1348 ├─╯
1349 ◆ 000000000000
1350 [EOF]
1351 ");
1352 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1353
1354 // Duplicate multiple commits without a direct ancestry relationship before a
1355 // single commit which is an ancestor of one of the duplicated commits.
1356 let output = work_dir.run_jj(["duplicate", "a3", "b1", "--before", "a2"]);
1357 insta::assert_snapshot!(output, @r"
1358 ------- stderr -------
1359 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1360 Duplicated 17072aa2b823 as pyoswmwk cad067c7 a3
1361 Duplicated dcc98bc8bbea as yqnpwwmq 6675be66 b1
1362 Rebased 3 commits onto duplicated commits
1363 [EOF]
1364 ");
1365 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1366 @ 0cdd923e993a d2
1367 ○ 0f21c5e185c5 d1
1368 │ ○ 09560d60cac4 c2
1369 │ ○ b27346e9a9bd c1
1370 ├─╯
1371 │ ○ 7b44470918f4 b2
1372 │ ○ dcc98bc8bbea b1
1373 ├─╯
1374 │ ○ 17391b843937 a4
1375 │ ○ 23f979220309 a3
1376 │ ○ 15a3207cfa72 a2
1377 │ ├─╮
1378 │ │ ○ 6675be66b280 b1
1379 │ ○ │ cad067c7d304 a3
1380 │ ├─╯
1381 │ ○ 9e85a474f005 a1
1382 ├─╯
1383 ◆ 000000000000
1384 [EOF]
1385 ");
1386 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1387
1388 // Duplicate multiple commits without a direct ancestry relationship before a
1389 // single commit which is a descendant of one of the duplicated commits.
1390 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--before", "a3"]);
1391 insta::assert_snapshot!(output, @r"
1392 ------- stderr -------
1393 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1394 Duplicated 9e85a474f005 as tpmlxquz 4d4dc78c (empty) a1
1395 Duplicated dcc98bc8bbea as uukzylyy a065abc9 b1
1396 Rebased 2 commits onto duplicated commits
1397 [EOF]
1398 ");
1399 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1400 @ 0cdd923e993a d2
1401 ○ 0f21c5e185c5 d1
1402 │ ○ 09560d60cac4 c2
1403 │ ○ b27346e9a9bd c1
1404 ├─╯
1405 │ ○ 7b44470918f4 b2
1406 │ ○ dcc98bc8bbea b1
1407 ├─╯
1408 │ ○ adb92c147726 a4
1409 │ ○ fb156cb07e68 a3
1410 │ ├─╮
1411 │ │ ○ a065abc9c61f b1
1412 │ ○ │ 4d4dc78c70a7 a1
1413 │ ├─╯
1414 │ ○ 47df67757a64 a2
1415 │ ○ 9e85a474f005 a1
1416 ├─╯
1417 ◆ 000000000000
1418 [EOF]
1419 ");
1420 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1421
1422 // Duplicate multiple commits without a direct ancestry relationship before
1423 // multiple commits without a direct relationship to the duplicated commits.
1424 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--before", "c1", "--before", "d1"]);
1425 insta::assert_snapshot!(output, @r"
1426 ------- stderr -------
1427 Duplicated 9e85a474f005 as knltnxnu 056a0cb3 a1
1428 Duplicated dcc98bc8bbea as krtqozmx fb68a539 b1
1429 Rebased 4 commits onto duplicated commits
1430 Working copy (@) now at: nmzmmopx 89f9b379 d2 | d2
1431 Parent commit (@-) : xznxytkn 771d0e16 d1 | d1
1432 Added 2 files, modified 0 files, removed 0 files
1433 [EOF]
1434 ");
1435 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1436 @ 89f9b37923a9 d2
1437 ○ 771d0e16b40c d1
1438 ├─╮
1439 │ │ ○ 7e7653d32cf1 c2
1440 │ │ ○ a83b8a44f3fc c1
1441 ╭─┬─╯
1442 │ ○ fb68a539aea7 b1
1443 ○ │ 056a0cb391f8 a1
1444 ├─╯
1445 │ ○ 7b44470918f4 b2
1446 │ ○ dcc98bc8bbea b1
1447 ├─╯
1448 │ ○ 196bc1f0efc1 a4
1449 │ ○ 17072aa2b823 a3
1450 │ ○ 47df67757a64 a2
1451 │ ○ 9e85a474f005 a1
1452 ├─╯
1453 ◆ 000000000000
1454 [EOF]
1455 ");
1456 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1457
1458 // Duplicate multiple commits without a direct ancestry relationship before
1459 // multiple commits including an ancestor of one of the duplicated commits.
1460 let output = work_dir.run_jj(["duplicate", "a3", "b1", "--before", "a1", "--before", "c1"]);
1461 insta::assert_snapshot!(output, @r"
1462 ------- stderr -------
1463 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1464 Duplicated 17072aa2b823 as wxzmtyol 31ca96b8 a3
1465 Duplicated dcc98bc8bbea as musouqkq 4748cf83 b1
1466 Rebased 6 commits onto duplicated commits
1467 [EOF]
1468 ");
1469 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1470 @ 0cdd923e993a d2
1471 ○ 0f21c5e185c5 d1
1472 │ ○ aa431fa5a467 c2
1473 │ ○ f99bc6bf1b1c c1
1474 │ ├─╮
1475 │ │ │ ○ a38ca6dc28f3 a4
1476 │ │ │ ○ 16e3d6c1562a a3
1477 │ │ │ ○ 84b5c2b584d1 a2
1478 │ │ │ ○ cc4ae3a9a31d a1
1479 │ ╭─┬─╯
1480 │ │ ○ 4748cf83e26e b1
1481 ├───╯
1482 │ ○ 31ca96b88527 a3
1483 ├─╯
1484 │ ○ 7b44470918f4 b2
1485 │ ○ dcc98bc8bbea b1
1486 ├─╯
1487 ◆ 000000000000
1488 [EOF]
1489 ");
1490 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1491
1492 // Duplicate multiple commits without a direct ancestry relationship before
1493 // multiple commits including a descendant of one of the duplicated commits.
1494 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--before", "a3", "--before", "c2"]);
1495 insta::assert_snapshot!(output, @r"
1496 ------- stderr -------
1497 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1498 Duplicated 9e85a474f005 as quyylypw 3eefd57d (empty) a1
1499 Duplicated dcc98bc8bbea as prukwozq ed86e70f b1
1500 Rebased 3 commits onto duplicated commits
1501 [EOF]
1502 ");
1503 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1504 @ 0cdd923e993a d2
1505 ○ 0f21c5e185c5 d1
1506 │ ○ 1c0d40fa21ea c2
1507 │ ├─╮
1508 │ │ │ ○ c31979bb15d4 a4
1509 │ │ │ ○ 8daf2e842412 a3
1510 │ ╭─┬─╯
1511 │ │ ○ ed86e70f497f b1
1512 │ │ ├─╮
1513 │ ○ │ │ 3eefd57d676b a1
1514 │ ╰─┬─╮
1515 │ │ ○ b27346e9a9bd c1
1516 ├─────╯
1517 │ ○ 47df67757a64 a2
1518 │ ○ 9e85a474f005 a1
1519 ├───╯
1520 │ ○ 7b44470918f4 b2
1521 │ ○ dcc98bc8bbea b1
1522 ├─╯
1523 ◆ 000000000000
1524 [EOF]
1525 ");
1526 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1527
1528 // Duplicate multiple commits with an ancestry relationship before a single
1529 // commit without a direct relationship.
1530 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--before", "c2"]);
1531 insta::assert_snapshot!(output, @r"
1532 ------- stderr -------
1533 Duplicated 9e85a474f005 as vvvtksvt baee09af a1
1534 Duplicated 17072aa2b823 as yvrnrpnw c17818c1 a3
1535 Rebased 1 commits onto duplicated commits
1536 [EOF]
1537 ");
1538 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1539 @ 0cdd923e993a d2
1540 ○ 0f21c5e185c5 d1
1541 │ ○ 4a25ce233a30 c2
1542 │ ○ c17818c175df a3
1543 │ ○ baee09af0f75 a1
1544 │ ○ b27346e9a9bd c1
1545 ├─╯
1546 │ ○ 7b44470918f4 b2
1547 │ ○ dcc98bc8bbea b1
1548 ├─╯
1549 │ ○ 196bc1f0efc1 a4
1550 │ ○ 17072aa2b823 a3
1551 │ ○ 47df67757a64 a2
1552 │ ○ 9e85a474f005 a1
1553 ├─╯
1554 ◆ 000000000000
1555 [EOF]
1556 ");
1557 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1558
1559 // Duplicate multiple commits with an ancestry relationship before a single
1560 // ancestor commit.
1561 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--before", "a1"]);
1562 insta::assert_snapshot!(output, @r"
1563 ------- stderr -------
1564 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1565 Warning: Duplicating commit 9e85a474f005 as an ancestor of itself
1566 Duplicated 9e85a474f005 as sukptuzs ad0234a3 a1
1567 Duplicated 17072aa2b823 as rxnrppxl e64dcdd1 a3
1568 Rebased 4 commits onto duplicated commits
1569 [EOF]
1570 ");
1571 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1572 @ 0cdd923e993a d2
1573 ○ 0f21c5e185c5 d1
1574 │ ○ 76cbe9641be2 a4
1575 │ ○ 140c783a30c6 a3
1576 │ ○ 940c74f17140 a2
1577 │ ○ d359f7d9dfe7 a1
1578 │ ○ e64dcdd1d1d1 a3
1579 │ ○ ad0234a34661 a1
1580 ├─╯
1581 │ ○ 09560d60cac4 c2
1582 │ ○ b27346e9a9bd c1
1583 ├─╯
1584 │ ○ 7b44470918f4 b2
1585 │ ○ dcc98bc8bbea b1
1586 ├─╯
1587 ◆ 000000000000
1588 [EOF]
1589 ");
1590 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1591
1592 // Duplicate multiple commits with an ancestry relationship before a single
1593 // descendant commit.
1594 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--before", "a3"]);
1595 insta::assert_snapshot!(output, @r"
1596 ------- stderr -------
1597 Warning: Duplicating commit 47df67757a64 as a descendant of itself
1598 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1599 Duplicated 9e85a474f005 as rwkyzntp e614bda1 (empty) a1
1600 Duplicated 47df67757a64 as nqtyztop 5de52186 (empty) a2
1601 Rebased 2 commits onto duplicated commits
1602 [EOF]
1603 ");
1604 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1605 @ 0cdd923e993a d2
1606 ○ 0f21c5e185c5 d1
1607 │ ○ 09560d60cac4 c2
1608 │ ○ b27346e9a9bd c1
1609 ├─╯
1610 │ ○ 7b44470918f4 b2
1611 │ ○ dcc98bc8bbea b1
1612 ├─╯
1613 │ ○ 585cb65f6d57 a4
1614 │ ○ b75dd23ffef0 a3
1615 │ ○ 5de52186bdf3 a2
1616 │ ○ e614bda1f2dc a1
1617 │ ○ 47df67757a64 a2
1618 │ ○ 9e85a474f005 a1
1619 ├─╯
1620 ◆ 000000000000
1621 [EOF]
1622 ");
1623 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1624
1625 // Duplicate multiple commits with an ancestry relationship before multiple
1626 // commits without a direct relationship to the duplicated commits.
1627 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--before", "c2", "--before", "d2"]);
1628 insta::assert_snapshot!(output, @r"
1629 ------- stderr -------
1630 Duplicated 9e85a474f005 as nwmqwkzz 9963be9b a1
1631 Duplicated 17072aa2b823 as uwrrnrtx a5eee87f a3
1632 Rebased 2 commits onto duplicated commits
1633 Working copy (@) now at: nmzmmopx 8161bbbc d2 | d2
1634 Parent commit (@-) : uwrrnrtx a5eee87f a3
1635 Added 3 files, modified 0 files, removed 0 files
1636 [EOF]
1637 ");
1638 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1639 @ 8161bbbc1341 d2
1640 │ ○ 62eea4c098aa c2
1641 ├─╯
1642 ○ a5eee87f5120 a3
1643 ○ 9963be9be4cd a1
1644 ├─╮
1645 │ ○ 0f21c5e185c5 d1
1646 ○ │ b27346e9a9bd c1
1647 ├─╯
1648 │ ○ 7b44470918f4 b2
1649 │ ○ dcc98bc8bbea b1
1650 ├─╯
1651 │ ○ 196bc1f0efc1 a4
1652 │ ○ 17072aa2b823 a3
1653 │ ○ 47df67757a64 a2
1654 │ ○ 9e85a474f005 a1
1655 ├─╯
1656 ◆ 000000000000
1657 [EOF]
1658 ");
1659 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1660
1661 // Duplicate multiple commits with an ancestry relationship before multiple
1662 // commits including an ancestor of one of the duplicated commits.
1663 let output = work_dir.run_jj(["duplicate", "a3", "a4", "--before", "a2", "--before", "c2"]);
1664 insta::assert_snapshot!(output, @r"
1665 ------- stderr -------
1666 Warning: Duplicating commit 196bc1f0efc1 as an ancestor of itself
1667 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1668 Duplicated 17072aa2b823 as wunttkrp 11fcc721 a3
1669 Duplicated 196bc1f0efc1 as puxpuzrm 3a0d76b0 a4
1670 Rebased 4 commits onto duplicated commits
1671 [EOF]
1672 ");
1673 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1674 @ 0cdd923e993a d2
1675 ○ 0f21c5e185c5 d1
1676 │ ○ c7a0da69006c c2
1677 │ │ ○ 8f35827d9ec9 a4
1678 │ │ ○ 1ac63ccfda31 a3
1679 │ │ ○ 96b02cd292f9 a2
1680 │ ├─╯
1681 │ ○ 3a0d76b0e8c2 a4
1682 │ ○ 11fcc72145cc a3
1683 │ ├─╮
1684 │ │ ○ b27346e9a9bd c1
1685 ├───╯
1686 │ ○ 9e85a474f005 a1
1687 ├─╯
1688 │ ○ 7b44470918f4 b2
1689 │ ○ dcc98bc8bbea b1
1690 ├─╯
1691 ◆ 000000000000
1692 [EOF]
1693 ");
1694 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1695
1696 // Duplicate multiple commits with an ancestry relationship before multiple
1697 // commits including a descendant of one of the duplicated commits.
1698 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--before", "a3", "--before", "c2"]);
1699 insta::assert_snapshot!(output, @r"
1700 ------- stderr -------
1701 Warning: Duplicating commit 47df67757a64 as a descendant of itself
1702 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1703 Duplicated 9e85a474f005 as zwvplpop 311e39e4 (empty) a1
1704 Duplicated 47df67757a64 as znsksvls fdaa673d (empty) a2
1705 Rebased 3 commits onto duplicated commits
1706 [EOF]
1707 ");
1708 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1709 @ 0cdd923e993a d2
1710 ○ 0f21c5e185c5 d1
1711 │ ○ f1f4e0efe9fb c2
1712 │ │ ○ a5af2ec2ff05 a4
1713 │ │ ○ 5d98ceaab6a5 a3
1714 │ ├─╯
1715 │ ○ fdaa673dff14 a2
1716 │ ○ 311e39e4de28 a1
1717 │ ├─╮
1718 │ │ ○ b27346e9a9bd c1
1719 ├───╯
1720 │ ○ 47df67757a64 a2
1721 │ ○ 9e85a474f005 a1
1722 ├─╯
1723 │ ○ 7b44470918f4 b2
1724 │ ○ dcc98bc8bbea b1
1725 ├─╯
1726 ◆ 000000000000
1727 [EOF]
1728 ");
1729 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1730
1731 // Should error if a loop will be created.
1732 let output = work_dir.run_jj(["duplicate", "a1", "--before", "b1", "--before", "b2"]);
1733 insta::assert_snapshot!(output, @r"
1734 ------- stderr -------
1735 Error: Refusing to create a loop: commit dcc98bc8bbea would be both an ancestor and a descendant of the duplicated commits
1736 [EOF]
1737 [exit status: 1]
1738 ");
1739}
1740
1741#[test]
1742fn test_duplicate_insert_after_before() {
1743 let test_env = TestEnvironment::default();
1744 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
1745 let work_dir = test_env.work_dir("repo");
1746
1747 create_commit(&work_dir, "a1", &[]);
1748 create_commit(&work_dir, "a2", &["a1"]);
1749 create_commit(&work_dir, "a3", &["a2"]);
1750 create_commit(&work_dir, "a4", &["a3"]);
1751 create_commit(&work_dir, "b1", &[]);
1752 create_commit(&work_dir, "b2", &["b1"]);
1753 create_commit(&work_dir, "c1", &[]);
1754 create_commit(&work_dir, "c2", &["c1"]);
1755 create_commit(&work_dir, "d1", &[]);
1756 create_commit(&work_dir, "d2", &["d1"]);
1757 let setup_opid = work_dir.current_operation_id();
1758
1759 // Test the setup
1760 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1761 @ 0cdd923e993a d2
1762 ○ 0f21c5e185c5 d1
1763 │ ○ 09560d60cac4 c2
1764 │ ○ b27346e9a9bd c1
1765 ├─╯
1766 │ ○ 7b44470918f4 b2
1767 │ ○ dcc98bc8bbea b1
1768 ├─╯
1769 │ ○ 196bc1f0efc1 a4
1770 │ ○ 17072aa2b823 a3
1771 │ ○ 47df67757a64 a2
1772 │ ○ 9e85a474f005 a1
1773 ├─╯
1774 ◆ 000000000000
1775 [EOF]
1776 ");
1777
1778 // Duplicate a single commit in between commits with no direct relationship.
1779 let output = work_dir.run_jj(["duplicate", "a1", "--before", "b2", "--after", "c2"]);
1780 insta::assert_snapshot!(output, @r"
1781 ------- stderr -------
1782 Duplicated 9e85a474f005 as pzsxstzt afc97ea4 a1
1783 Rebased 1 commits onto duplicated commits
1784 [EOF]
1785 ");
1786 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1787 @ 0cdd923e993a d2
1788 ○ 0f21c5e185c5 d1
1789 │ ○ 41f0321a79b8 b2
1790 │ ├─╮
1791 │ │ ○ afc97ea480c1 a1
1792 │ │ ○ 09560d60cac4 c2
1793 │ │ ○ b27346e9a9bd c1
1794 ├───╯
1795 │ ○ dcc98bc8bbea b1
1796 ├─╯
1797 │ ○ 196bc1f0efc1 a4
1798 │ ○ 17072aa2b823 a3
1799 │ ○ 47df67757a64 a2
1800 │ ○ 9e85a474f005 a1
1801 ├─╯
1802 ◆ 000000000000
1803 [EOF]
1804 ");
1805 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1806
1807 // Duplicate a single commit in between ancestor commits.
1808 let output = work_dir.run_jj(["duplicate", "a3", "--before", "a2", "--after", "a1"]);
1809 insta::assert_snapshot!(output, @r"
1810 ------- stderr -------
1811 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1812 Duplicated 17072aa2b823 as qmkrwlvp fd3c891b a3
1813 Rebased 3 commits onto duplicated commits
1814 [EOF]
1815 ");
1816 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1817 @ 0cdd923e993a d2
1818 ○ 0f21c5e185c5 d1
1819 │ ○ 09560d60cac4 c2
1820 │ ○ b27346e9a9bd c1
1821 ├─╯
1822 │ ○ 7b44470918f4 b2
1823 │ ○ dcc98bc8bbea b1
1824 ├─╯
1825 │ ○ 027d38df36fa a4
1826 │ ○ 6cb0f5884a35 a3
1827 │ ○ 80e3e40b66f0 a2
1828 │ ○ fd3c891b8b97 a3
1829 │ ○ 9e85a474f005 a1
1830 ├─╯
1831 ◆ 000000000000
1832 [EOF]
1833 ");
1834 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1835
1836 // Duplicate a single commit in between an ancestor commit and a commit with no
1837 // direct relationship.
1838 let output = work_dir.run_jj(["duplicate", "a3", "--before", "a2", "--after", "b2"]);
1839 insta::assert_snapshot!(output, @r"
1840 ------- stderr -------
1841 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
1842 Duplicated 17072aa2b823 as qwyusntz 4d69f69c a3
1843 Rebased 3 commits onto duplicated commits
1844 [EOF]
1845 ");
1846 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1847 @ 0cdd923e993a d2
1848 ○ 0f21c5e185c5 d1
1849 │ ○ 09560d60cac4 c2
1850 │ ○ b27346e9a9bd c1
1851 ├─╯
1852 │ ○ 1e4a9c0c8247 a4
1853 │ ○ 416da6f255ef a3
1854 │ ○ 335701a7e2f7 a2
1855 │ ├─╮
1856 │ │ ○ 4d69f69ca987 a3
1857 │ │ ○ 7b44470918f4 b2
1858 │ │ ○ dcc98bc8bbea b1
1859 ├───╯
1860 │ ○ 9e85a474f005 a1
1861 ├─╯
1862 ◆ 000000000000
1863 [EOF]
1864 ");
1865 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1866
1867 // Duplicate a single commit in between descendant commits.
1868 let output = work_dir.run_jj(["duplicate", "a1", "--after", "a3", "--before", "a4"]);
1869 insta::assert_snapshot!(output, @r"
1870 ------- stderr -------
1871 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1872 Duplicated 9e85a474f005 as soqnvnyz 00811f7c (empty) a1
1873 Rebased 1 commits onto duplicated commits
1874 [EOF]
1875 ");
1876 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1877 @ 0cdd923e993a d2
1878 ○ 0f21c5e185c5 d1
1879 │ ○ 09560d60cac4 c2
1880 │ ○ b27346e9a9bd c1
1881 ├─╯
1882 │ ○ 7b44470918f4 b2
1883 │ ○ dcc98bc8bbea b1
1884 ├─╯
1885 │ ○ d6d9a67a7882 a4
1886 │ ○ 00811f7ccdb5 a1
1887 │ ○ 17072aa2b823 a3
1888 │ ○ 47df67757a64 a2
1889 │ ○ 9e85a474f005 a1
1890 ├─╯
1891 ◆ 000000000000
1892 [EOF]
1893 ");
1894 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1895
1896 // Duplicate a single commit in between a descendant commit and a commit with no
1897 // direct relationship.
1898 let output = work_dir.run_jj(["duplicate", "a1", "--after", "a3", "--before", "b2"]);
1899 insta::assert_snapshot!(output, @r"
1900 ------- stderr -------
1901 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
1902 Duplicated 9e85a474f005 as nsrwusvy 0b89e8a3 (empty) a1
1903 Rebased 1 commits onto duplicated commits
1904 [EOF]
1905 ");
1906 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1907 @ 0cdd923e993a d2
1908 ○ 0f21c5e185c5 d1
1909 │ ○ 09560d60cac4 c2
1910 │ ○ b27346e9a9bd c1
1911 ├─╯
1912 │ ○ 71f4a83f7122 b2
1913 │ ├─╮
1914 │ │ ○ 0b89e8a32915 a1
1915 │ ○ │ dcc98bc8bbea b1
1916 ├─╯ │
1917 │ ○ │ 196bc1f0efc1 a4
1918 │ ├─╯
1919 │ ○ 17072aa2b823 a3
1920 │ ○ 47df67757a64 a2
1921 │ ○ 9e85a474f005 a1
1922 ├─╯
1923 ◆ 000000000000
1924 [EOF]
1925 ");
1926 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1927
1928 // Duplicate a single commit in between an ancestor commit and a descendant
1929 // commit.
1930 let output = work_dir.run_jj(["duplicate", "a2", "--after", "a1", "--before", "a4"]);
1931 insta::assert_snapshot!(output, @r"
1932 ------- stderr -------
1933 Duplicated 47df67757a64 as xpnwykqz 54cc0161 a2
1934 Rebased 1 commits onto duplicated commits
1935 [EOF]
1936 ");
1937 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1938 @ 0cdd923e993a d2
1939 ○ 0f21c5e185c5 d1
1940 │ ○ 09560d60cac4 c2
1941 │ ○ b27346e9a9bd c1
1942 ├─╯
1943 │ ○ 7b44470918f4 b2
1944 │ ○ dcc98bc8bbea b1
1945 ├─╯
1946 │ ○ b08d6199fab9 a4
1947 │ ├─╮
1948 │ │ ○ 54cc0161a5db a2
1949 │ ○ │ 17072aa2b823 a3
1950 │ ○ │ 47df67757a64 a2
1951 │ ├─╯
1952 │ ○ 9e85a474f005 a1
1953 ├─╯
1954 ◆ 000000000000
1955 [EOF]
1956 ");
1957 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1958
1959 // Duplicate multiple commits without a direct ancestry relationship between
1960 // commits without a direct relationship.
1961 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "c1", "--before", "d2"]);
1962 insta::assert_snapshot!(output, @r"
1963 ------- stderr -------
1964 Duplicated 9e85a474f005 as sryyqqkq 44f57f24 a1
1965 Duplicated dcc98bc8bbea as pxnqtknr bcee4b60 b1
1966 Rebased 1 commits onto duplicated commits
1967 Working copy (@) now at: nmzmmopx 6a5a099f d2 | d2
1968 Parent commit (@-) : xznxytkn 0f21c5e1 d1 | d1
1969 Parent commit (@-) : sryyqqkq 44f57f24 a1
1970 Parent commit (@-) : pxnqtknr bcee4b60 b1
1971 Added 3 files, modified 0 files, removed 0 files
1972 [EOF]
1973 ");
1974 insta::assert_snapshot!(get_log_output(&work_dir), @r"
1975 @ 6a5a099f8a03 d2
1976 ├─┬─╮
1977 │ │ ○ bcee4b6058e4 b1
1978 │ ○ │ 44f57f247bf2 a1
1979 │ ├─╯
1980 ○ │ 0f21c5e185c5 d1
1981 │ │ ○ 09560d60cac4 c2
1982 │ ├─╯
1983 │ ○ b27346e9a9bd c1
1984 ├─╯
1985 │ ○ 7b44470918f4 b2
1986 │ ○ dcc98bc8bbea b1
1987 ├─╯
1988 │ ○ 196bc1f0efc1 a4
1989 │ ○ 17072aa2b823 a3
1990 │ ○ 47df67757a64 a2
1991 │ ○ 9e85a474f005 a1
1992 ├─╯
1993 ◆ 000000000000
1994 [EOF]
1995 ");
1996 work_dir.run_jj(["op", "restore", &setup_opid]).success();
1997
1998 // Duplicate multiple commits without a direct ancestry relationship between a
1999 // commit which is an ancestor of one of the duplicated commits and a commit
2000 // with no direct relationship.
2001 let output = work_dir.run_jj(["duplicate", "a3", "b1", "--after", "a2", "--before", "c2"]);
2002 insta::assert_snapshot!(output, @r"
2003 ------- stderr -------
2004 Duplicated 17072aa2b823 as pyoswmwk 0d11d466 a3
2005 Duplicated dcc98bc8bbea as yqnpwwmq c32d1ccc b1
2006 Rebased 1 commits onto duplicated commits
2007 [EOF]
2008 ");
2009 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2010 @ 0cdd923e993a d2
2011 ○ 0f21c5e185c5 d1
2012 │ ○ 9feaad4c40f3 c2
2013 │ ├─┬─╮
2014 │ │ │ ○ c32d1ccc8d5b b1
2015 │ │ ○ │ 0d11d4667aa9 a3
2016 │ │ ├─╯
2017 │ ○ │ b27346e9a9bd c1
2018 ├─╯ │
2019 │ ○ │ 7b44470918f4 b2
2020 │ ○ │ dcc98bc8bbea b1
2021 ├─╯ │
2022 │ ○ │ 196bc1f0efc1 a4
2023 │ ○ │ 17072aa2b823 a3
2024 │ ├─╯
2025 │ ○ 47df67757a64 a2
2026 │ ○ 9e85a474f005 a1
2027 ├─╯
2028 ◆ 000000000000
2029 [EOF]
2030 ");
2031 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2032
2033 // Duplicate multiple commits without a direct ancestry relationship between a
2034 // commit which is a descendant of one of the duplicated commits and a
2035 // commit with no direct relationship.
2036 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "a3", "--before", "c2"]);
2037 insta::assert_snapshot!(output, @r"
2038 ------- stderr -------
2039 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
2040 Duplicated 9e85a474f005 as tpmlxquz 213aff50 (empty) a1
2041 Duplicated dcc98bc8bbea as uukzylyy 67b82bab b1
2042 Rebased 1 commits onto duplicated commits
2043 [EOF]
2044 ");
2045 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2046 @ 0cdd923e993a d2
2047 ○ 0f21c5e185c5 d1
2048 │ ○ 7c6622beae40 c2
2049 │ ├─┬─╮
2050 │ │ │ ○ 67b82babd5f6 b1
2051 │ │ ○ │ 213aff50a82b a1
2052 │ │ ├─╯
2053 │ ○ │ b27346e9a9bd c1
2054 ├─╯ │
2055 │ ○ │ 7b44470918f4 b2
2056 │ ○ │ dcc98bc8bbea b1
2057 ├─╯ │
2058 │ ○ │ 196bc1f0efc1 a4
2059 │ ├─╯
2060 │ ○ 17072aa2b823 a3
2061 │ ○ 47df67757a64 a2
2062 │ ○ 9e85a474f005 a1
2063 ├─╯
2064 ◆ 000000000000
2065 [EOF]
2066 ");
2067 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2068
2069 // Duplicate multiple commits without a direct ancestry relationship between
2070 // commits without a direct relationship to the duplicated commits.
2071 let output = work_dir.run_jj(["duplicate", "a1", "b1", "--after", "c1", "--before", "d2"]);
2072 insta::assert_snapshot!(output, @r"
2073 ------- stderr -------
2074 Duplicated 9e85a474f005 as knltnxnu a2d38733 a1
2075 Duplicated dcc98bc8bbea as krtqozmx 2512c935 b1
2076 Rebased 1 commits onto duplicated commits
2077 Working copy (@) now at: nmzmmopx 4678ad48 d2 | d2
2078 Parent commit (@-) : xznxytkn 0f21c5e1 d1 | d1
2079 Parent commit (@-) : knltnxnu a2d38733 a1
2080 Parent commit (@-) : krtqozmx 2512c935 b1
2081 Added 3 files, modified 0 files, removed 0 files
2082 [EOF]
2083 ");
2084 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2085 @ 4678ad489eeb d2
2086 ├─┬─╮
2087 │ │ ○ 2512c9358cb7 b1
2088 │ ○ │ a2d387331978 a1
2089 │ ├─╯
2090 ○ │ 0f21c5e185c5 d1
2091 │ │ ○ 09560d60cac4 c2
2092 │ ├─╯
2093 │ ○ b27346e9a9bd c1
2094 ├─╯
2095 │ ○ 7b44470918f4 b2
2096 │ ○ dcc98bc8bbea b1
2097 ├─╯
2098 │ ○ 196bc1f0efc1 a4
2099 │ ○ 17072aa2b823 a3
2100 │ ○ 47df67757a64 a2
2101 │ ○ 9e85a474f005 a1
2102 ├─╯
2103 ◆ 000000000000
2104 [EOF]
2105 ");
2106 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2107
2108 // Duplicate multiple commits with an ancestry relationship between
2109 // commits without a direct relationship to the duplicated commits.
2110 let output = work_dir.run_jj(["duplicate", "a1", "a3", "--after", "c1", "--before", "d2"]);
2111 insta::assert_snapshot!(output, @r"
2112 ------- stderr -------
2113 Duplicated 9e85a474f005 as wxzmtyol 893a647a a1
2114 Duplicated 17072aa2b823 as musouqkq fb14bc1e a3
2115 Rebased 1 commits onto duplicated commits
2116 Working copy (@) now at: nmzmmopx 21321795 d2 | d2
2117 Parent commit (@-) : xznxytkn 0f21c5e1 d1 | d1
2118 Parent commit (@-) : musouqkq fb14bc1e a3
2119 Added 3 files, modified 0 files, removed 0 files
2120 [EOF]
2121 ");
2122 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2123 @ 21321795f72f d2
2124 ├─╮
2125 │ ○ fb14bc1e2c3c a3
2126 │ ○ 893a647a7f64 a1
2127 ○ │ 0f21c5e185c5 d1
2128 │ │ ○ 09560d60cac4 c2
2129 │ ├─╯
2130 │ ○ b27346e9a9bd c1
2131 ├─╯
2132 │ ○ 7b44470918f4 b2
2133 │ ○ dcc98bc8bbea b1
2134 ├─╯
2135 │ ○ 196bc1f0efc1 a4
2136 │ ○ 17072aa2b823 a3
2137 │ ○ 47df67757a64 a2
2138 │ ○ 9e85a474f005 a1
2139 ├─╯
2140 ◆ 000000000000
2141 [EOF]
2142 ");
2143 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2144
2145 // Duplicate multiple commits with an ancestry relationship between a commit
2146 // which is an ancestor of one of the duplicated commits and a commit
2147 // without a direct relationship.
2148 let output = work_dir.run_jj(["duplicate", "a3", "a4", "--after", "a2", "--before", "c2"]);
2149 insta::assert_snapshot!(output, @r"
2150 ------- stderr -------
2151 Duplicated 17072aa2b823 as quyylypw d4d3c907 a3
2152 Duplicated 196bc1f0efc1 as prukwozq 96798f1b a4
2153 Rebased 1 commits onto duplicated commits
2154 [EOF]
2155 ");
2156 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2157 @ 0cdd923e993a d2
2158 ○ 0f21c5e185c5 d1
2159 │ ○ 267f3c6f05a2 c2
2160 │ ├─╮
2161 │ │ ○ 96798f1b59fc a4
2162 │ │ ○ d4d3c9073a3b a3
2163 │ ○ │ b27346e9a9bd c1
2164 ├─╯ │
2165 │ ○ │ 7b44470918f4 b2
2166 │ ○ │ dcc98bc8bbea b1
2167 ├─╯ │
2168 │ ○ │ 196bc1f0efc1 a4
2169 │ ○ │ 17072aa2b823 a3
2170 │ ├─╯
2171 │ ○ 47df67757a64 a2
2172 │ ○ 9e85a474f005 a1
2173 ├─╯
2174 ◆ 000000000000
2175 [EOF]
2176 ");
2177 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2178
2179 // Duplicate multiple commits with an ancestry relationship between a commit
2180 // which is a a descendant of one of the duplicated commits and a commit
2181 // with no direct relationship.
2182 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--before", "a3", "--after", "c2"]);
2183 insta::assert_snapshot!(output, @r"
2184 ------- stderr -------
2185 Duplicated 9e85a474f005 as vvvtksvt b44d23b4 a1
2186 Duplicated 47df67757a64 as yvrnrpnw 4d0d41e2 a2
2187 Rebased 2 commits onto duplicated commits
2188 [EOF]
2189 ");
2190 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2191 @ 0cdd923e993a d2
2192 ○ 0f21c5e185c5 d1
2193 │ ○ 1ed8f9907f23 a4
2194 │ ○ c48cf7ac619c a3
2195 │ ├─╮
2196 │ │ ○ 4d0d41e2b74e a2
2197 │ │ ○ b44d23b4c98e a1
2198 │ │ ○ 09560d60cac4 c2
2199 │ │ ○ b27346e9a9bd c1
2200 ├───╯
2201 │ ○ 47df67757a64 a2
2202 │ ○ 9e85a474f005 a1
2203 ├─╯
2204 │ ○ 7b44470918f4 b2
2205 │ ○ dcc98bc8bbea b1
2206 ├─╯
2207 ◆ 000000000000
2208 [EOF]
2209 ");
2210 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2211
2212 // Duplicate multiple commits with an ancestry relationship between descendant
2213 // commits.
2214 let output = work_dir.run_jj(["duplicate", "a3", "a4", "--after", "a1", "--before", "a2"]);
2215 insta::assert_snapshot!(output, @r"
2216 ------- stderr -------
2217 Warning: Duplicating commit 196bc1f0efc1 as an ancestor of itself
2218 Warning: Duplicating commit 17072aa2b823 as an ancestor of itself
2219 Duplicated 17072aa2b823 as sukptuzs 8678104c a3
2220 Duplicated 196bc1f0efc1 as rxnrppxl b6580274 a4
2221 Rebased 3 commits onto duplicated commits
2222 [EOF]
2223 ");
2224 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2225 @ 0cdd923e993a d2
2226 ○ 0f21c5e185c5 d1
2227 │ ○ 09560d60cac4 c2
2228 │ ○ b27346e9a9bd c1
2229 ├─╯
2230 │ ○ 7b44470918f4 b2
2231 │ ○ dcc98bc8bbea b1
2232 ├─╯
2233 │ ○ 795c1625854d a4
2234 │ ○ c3fbe644a16b a3
2235 │ ○ af75098c676a a2
2236 │ ○ b6580274470b a4
2237 │ ○ 8678104c14af a3
2238 │ ○ 9e85a474f005 a1
2239 ├─╯
2240 ◆ 000000000000
2241 [EOF]
2242 ");
2243 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2244
2245 // Duplicate multiple commits with an ancestry relationship between ancestor
2246 // commits.
2247 let output = work_dir.run_jj(["duplicate", "a1", "a2", "--after", "a3", "--before", "a4"]);
2248 insta::assert_snapshot!(output, @r"
2249 ------- stderr -------
2250 Warning: Duplicating commit 47df67757a64 as a descendant of itself
2251 Warning: Duplicating commit 9e85a474f005 as a descendant of itself
2252 Duplicated 9e85a474f005 as rwkyzntp b68b9a00 (empty) a1
2253 Duplicated 47df67757a64 as nqtyztop 0dd00ded (empty) a2
2254 Rebased 1 commits onto duplicated commits
2255 [EOF]
2256 ");
2257 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2258 @ 0cdd923e993a d2
2259 ○ 0f21c5e185c5 d1
2260 │ ○ 09560d60cac4 c2
2261 │ ○ b27346e9a9bd c1
2262 ├─╯
2263 │ ○ 7b44470918f4 b2
2264 │ ○ dcc98bc8bbea b1
2265 ├─╯
2266 │ ○ 4f02390e56aa a4
2267 │ ○ 0dd00dedd0c5 a2
2268 │ ○ b68b9a0073cb a1
2269 │ ○ 17072aa2b823 a3
2270 │ ○ 47df67757a64 a2
2271 │ ○ 9e85a474f005 a1
2272 ├─╯
2273 ◆ 000000000000
2274 [EOF]
2275 ");
2276 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2277
2278 // Duplicate multiple commits with an ancestry relationship between an ancestor
2279 // commit and a descendant commit.
2280 let output = work_dir.run_jj(["duplicate", "a2", "a3", "--after", "a1", "--before", "a4"]);
2281 insta::assert_snapshot!(output, @r"
2282 ------- stderr -------
2283 Duplicated 47df67757a64 as nwmqwkzz 8517eaa7 a2
2284 Duplicated 17072aa2b823 as uwrrnrtx 3ce18231 a3
2285 Rebased 1 commits onto duplicated commits
2286 [EOF]
2287 ");
2288 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2289 @ 0cdd923e993a d2
2290 ○ 0f21c5e185c5 d1
2291 │ ○ 09560d60cac4 c2
2292 │ ○ b27346e9a9bd c1
2293 ├─╯
2294 │ ○ 7b44470918f4 b2
2295 │ ○ dcc98bc8bbea b1
2296 ├─╯
2297 │ ○ 0855137fa398 a4
2298 │ ├─╮
2299 │ │ ○ 3ce182317a5b a3
2300 │ │ ○ 8517eaa73536 a2
2301 │ ○ │ 17072aa2b823 a3
2302 │ ○ │ 47df67757a64 a2
2303 │ ├─╯
2304 │ ○ 9e85a474f005 a1
2305 ├─╯
2306 ◆ 000000000000
2307 [EOF]
2308 ");
2309 work_dir.run_jj(["op", "restore", &setup_opid]).success();
2310
2311 // Should error if a loop will be created.
2312 let output = work_dir.run_jj(["duplicate", "a1", "--after", "b2", "--before", "b1"]);
2313 insta::assert_snapshot!(output, @r"
2314 ------- stderr -------
2315 Error: Refusing to create a loop: commit 7b44470918f4 would be both an ancestor and a descendant of the duplicated commits
2316 [EOF]
2317 [exit status: 1]
2318 ");
2319}
2320
2321// https://github.com/jj-vcs/jj/issues/1050
2322#[test]
2323fn test_undo_after_duplicate() {
2324 let test_env = TestEnvironment::default();
2325 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
2326 let work_dir = test_env.work_dir("repo");
2327
2328 create_commit(&work_dir, "a", &[]);
2329 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2330 @ 2443ea76b0b1 a
2331 ◆ 000000000000
2332 [EOF]
2333 ");
2334
2335 let output = work_dir.run_jj(["duplicate", "a"]);
2336 insta::assert_snapshot!(output, @r"
2337 ------- stderr -------
2338 Duplicated 2443ea76b0b1 as mzvwutvl f5cefcbb a
2339 [EOF]
2340 ");
2341 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2342 @ 2443ea76b0b1 a
2343 │ ○ f5cefcbb65a4 a
2344 ├─╯
2345 ◆ 000000000000
2346 [EOF]
2347 ");
2348
2349 let output = work_dir.run_jj(["undo"]);
2350 insta::assert_snapshot!(output, @r"
2351 ------- stderr -------
2352 Undid operation: d64d953f7d2b (2001-02-03 08:05:11) duplicate 1 commit(s)
2353 [EOF]
2354 ");
2355 insta::assert_snapshot!(get_log_output(&work_dir), @r"
2356 @ 2443ea76b0b1 a
2357 ◆ 000000000000
2358 [EOF]
2359 ");
2360}
2361
2362// https://github.com/jj-vcs/jj/issues/694
2363#[test]
2364fn test_rebase_duplicates() {
2365 let test_env = TestEnvironment::default();
2366 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
2367 let work_dir = test_env.work_dir("repo");
2368
2369 create_commit(&work_dir, "a", &[]);
2370 create_commit(&work_dir, "b", &["a"]);
2371 create_commit(&work_dir, "c", &["b"]);
2372 // Test the setup
2373 insta::assert_snapshot!(get_log_output_with_ts(&work_dir), @r"
2374 @ 7e4fbf4f2759 c @ 2001-02-03 04:05:13.000 +07:00
2375 ○ 1394f625cbbd b @ 2001-02-03 04:05:11.000 +07:00
2376 ○ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
2377 ◆ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
2378 [EOF]
2379 ");
2380
2381 let output = work_dir.run_jj(["duplicate", "c"]);
2382 insta::assert_snapshot!(output, @r"
2383 ------- stderr -------
2384 Duplicated 7e4fbf4f2759 as yostqsxw 0ac2063b c
2385 [EOF]
2386 ");
2387 let output = work_dir.run_jj(["duplicate", "c"]);
2388 insta::assert_snapshot!(output, @r"
2389 ------- stderr -------
2390 Duplicated 7e4fbf4f2759 as znkkpsqq ce5f4eeb c
2391 [EOF]
2392 ");
2393 insta::assert_snapshot!(get_log_output_with_ts(&work_dir), @r"
2394 @ 7e4fbf4f2759 c @ 2001-02-03 04:05:13.000 +07:00
2395 │ ○ ce5f4eeb69d1 c @ 2001-02-03 04:05:16.000 +07:00
2396 ├─╯
2397 │ ○ 0ac2063b1bee c @ 2001-02-03 04:05:15.000 +07:00
2398 ├─╯
2399 ○ 1394f625cbbd b @ 2001-02-03 04:05:11.000 +07:00
2400 ○ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
2401 ◆ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
2402 [EOF]
2403 ");
2404
2405 let output = work_dir.run_jj(["rebase", "-s", "b", "-d", "root()"]);
2406 insta::assert_snapshot!(output, @r"
2407 ------- stderr -------
2408 Rebased 4 commits onto destination
2409 Working copy (@) now at: royxmykx ed671a3c c | c
2410 Parent commit (@-) : zsuskuln 4c6f1569 b | b
2411 Added 0 files, modified 0 files, removed 1 files
2412 [EOF]
2413 ");
2414 // Some of the duplicate commits' timestamps were changed a little to make them
2415 // have distinct commit ids.
2416 insta::assert_snapshot!(get_log_output_with_ts(&work_dir), @r"
2417 @ ed671a3cbf35 c @ 2001-02-03 04:05:18.000 +07:00
2418 │ ○ b86e9f27d085 c @ 2001-02-03 04:05:16.000 +07:00
2419 ├─╯
2420 │ ○ 8033590fe04d c @ 2001-02-03 04:05:17.000 +07:00
2421 ├─╯
2422 ○ 4c6f1569e2a9 b @ 2001-02-03 04:05:18.000 +07:00
2423 │ ○ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
2424 ├─╯
2425 ◆ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
2426 [EOF]
2427 ");
2428}
2429
2430#[must_use]
2431fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {
2432 let template = r#"commit_id.short() ++ " " ++ description.first_line()"#;
2433 work_dir.run_jj(["log", "-T", template])
2434}
2435
2436#[must_use]
2437fn get_log_output_with_ts(work_dir: &TestWorkDir) -> CommandOutput {
2438 let template = r#"
2439 commit_id.short() ++ " " ++ description.first_line() ++ " @ " ++ committer.timestamp()
2440 "#;
2441 work_dir.run_jj(["log", "-T", template])
2442}