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 std::path::Path;
16
17use crate::common::TestEnvironment;
18
19fn create_commit(test_env: &TestEnvironment, repo_path: &Path, name: &str, parents: &[&str]) {
20 if parents.is_empty() {
21 test_env.jj_cmd_ok(repo_path, &["new", "root()", "-m", name]);
22 } else {
23 let mut args = vec!["new", "-m", name];
24 args.extend(parents);
25 test_env.jj_cmd_ok(repo_path, &args);
26 }
27 std::fs::write(repo_path.join(name), format!("{name}\n")).unwrap();
28 test_env.jj_cmd_ok(repo_path, &["branch", "create", name]);
29}
30
31#[test]
32fn test_duplicate() {
33 let test_env = TestEnvironment::default();
34 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
35 let repo_path = test_env.env_root().join("repo");
36
37 create_commit(&test_env, &repo_path, "a", &[]);
38 create_commit(&test_env, &repo_path, "b", &[]);
39 create_commit(&test_env, &repo_path, "c", &["a", "b"]);
40 // Test the setup
41 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
42 @ 17a00fc21654 c
43 ├─╮
44 │ ◉ d370aee184ba b
45 ◉ │ 2443ea76b0b1 a
46 ├─╯
47 ◉ 000000000000
48 "###);
49
50 let stderr = test_env.jj_cmd_failure(&repo_path, &["duplicate", "all()"]);
51 insta::assert_snapshot!(stderr, @r###"
52 Error: Cannot duplicate the root commit
53 "###);
54
55 let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "none()"]);
56 insta::assert_snapshot!(stderr, @r###"
57 No revisions to duplicate.
58 "###);
59
60 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "a"]);
61 insta::assert_snapshot!(stdout, @"");
62 insta::assert_snapshot!(stderr, @r###"
63 Duplicated 2443ea76b0b1 as kpqxywon f5b1e687 a
64 "###);
65 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
66 ◉ f5b1e68729d6 a
67 │ @ 17a00fc21654 c
68 │ ├─╮
69 │ │ ◉ d370aee184ba b
70 ├───╯
71 │ ◉ 2443ea76b0b1 a
72 ├─╯
73 ◉ 000000000000
74 "###);
75
76 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["undo"]);
77 insta::assert_snapshot!(stdout, @"");
78 insta::assert_snapshot!(stderr, @"");
79 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate" /* duplicates `c` */]);
80 insta::assert_snapshot!(stdout, @"");
81 insta::assert_snapshot!(stderr, @r###"
82 Duplicated 17a00fc21654 as lylxulpl ef3b0f3d c
83 "###);
84 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
85 ◉ ef3b0f3d1046 c
86 ├─╮
87 │ │ @ 17a00fc21654 c
88 ╭─┬─╯
89 │ ◉ d370aee184ba b
90 ◉ │ 2443ea76b0b1 a
91 ├─╯
92 ◉ 000000000000
93 "###);
94}
95
96#[test]
97fn test_duplicate_many() {
98 let test_env = TestEnvironment::default();
99 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
100 let repo_path = test_env.env_root().join("repo");
101
102 create_commit(&test_env, &repo_path, "a", &[]);
103 create_commit(&test_env, &repo_path, "b", &["a"]);
104 create_commit(&test_env, &repo_path, "c", &["a"]);
105 create_commit(&test_env, &repo_path, "d", &["c"]);
106 create_commit(&test_env, &repo_path, "e", &["b", "d"]);
107 // Test the setup
108 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
109 @ 921dde6e55c0 e
110 ├─╮
111 │ ◉ ebd06dba20ec d
112 │ ◉ c0cb3a0b73e7 c
113 ◉ │ 1394f625cbbd b
114 ├─╯
115 ◉ 2443ea76b0b1 a
116 ◉ 000000000000
117 "###);
118
119 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "b::"]);
120 insta::assert_snapshot!(stdout, @"");
121 insta::assert_snapshot!(stderr, @r###"
122 Duplicated 1394f625cbbd as wqnwkozp 3b74d969 b
123 Duplicated 921dde6e55c0 as mouksmqu 8348ddce e
124 "###);
125 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
126 ◉ 8348ddcec733 e
127 ├─╮
128 ◉ │ 3b74d9691015 b
129 │ │ @ 921dde6e55c0 e
130 │ ╭─┤
131 │ ◉ │ ebd06dba20ec d
132 │ ◉ │ c0cb3a0b73e7 c
133 ├─╯ │
134 │ ◉ 1394f625cbbd b
135 ├───╯
136 ◉ 2443ea76b0b1 a
137 ◉ 000000000000
138 "###);
139
140 // Try specifying the same commit twice directly
141 test_env.jj_cmd_ok(&repo_path, &["undo"]);
142 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "b", "b"]);
143 insta::assert_snapshot!(stdout, @"");
144 insta::assert_snapshot!(stderr, @r###"
145 Duplicated 1394f625cbbd as nkmrtpmo 0276d3d7 b
146 "###);
147 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
148 ◉ 0276d3d7c24d b
149 │ @ 921dde6e55c0 e
150 │ ├─╮
151 │ │ ◉ ebd06dba20ec d
152 │ │ ◉ c0cb3a0b73e7 c
153 ├───╯
154 │ ◉ 1394f625cbbd b
155 ├─╯
156 ◉ 2443ea76b0b1 a
157 ◉ 000000000000
158 "###);
159
160 // Try specifying the same commit twice indirectly
161 test_env.jj_cmd_ok(&repo_path, &["undo"]);
162 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "b::", "d::"]);
163 insta::assert_snapshot!(stdout, @"");
164 insta::assert_snapshot!(stderr, @r###"
165 Duplicated 1394f625cbbd as xtnwkqum fa167d18 b
166 Duplicated ebd06dba20ec as pqrnrkux 2181781b d
167 Duplicated 921dde6e55c0 as ztxkyksq 0f7430f2 e
168 "###);
169 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
170 ◉ 0f7430f2727a e
171 ├─╮
172 │ ◉ 2181781b4f81 d
173 ◉ │ fa167d18a83a b
174 │ │ @ 921dde6e55c0 e
175 │ │ ├─╮
176 │ │ │ ◉ ebd06dba20ec d
177 │ ├───╯
178 │ ◉ │ c0cb3a0b73e7 c
179 ├─╯ │
180 │ ◉ 1394f625cbbd b
181 ├───╯
182 ◉ 2443ea76b0b1 a
183 ◉ 000000000000
184 "###);
185
186 test_env.jj_cmd_ok(&repo_path, &["undo"]);
187 // Reminder of the setup
188 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
189 @ 921dde6e55c0 e
190 ├─╮
191 │ ◉ ebd06dba20ec d
192 │ ◉ c0cb3a0b73e7 c
193 ◉ │ 1394f625cbbd b
194 ├─╯
195 ◉ 2443ea76b0b1 a
196 ◉ 000000000000
197 "###);
198 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "d::", "a"]);
199 insta::assert_snapshot!(stdout, @"");
200 insta::assert_snapshot!(stderr, @r###"
201 Duplicated 2443ea76b0b1 as nlrtlrxv c6f7f8c4 a
202 Duplicated ebd06dba20ec as plymsszl d94e4c55 d
203 Duplicated 921dde6e55c0 as urrlptpw 9bd4389f e
204 "###);
205 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
206 ◉ 9bd4389f5d47 e
207 ├─╮
208 │ ◉ d94e4c55a68b d
209 │ │ @ 921dde6e55c0 e
210 ╭───┤
211 │ │ ◉ ebd06dba20ec d
212 │ ├─╯
213 │ ◉ c0cb3a0b73e7 c
214 ◉ │ 1394f625cbbd b
215 ├─╯
216 ◉ 2443ea76b0b1 a
217 │ ◉ c6f7f8c4512e a
218 ├─╯
219 ◉ 000000000000
220 "###);
221
222 // Check for BUG -- makes too many 'a'-s, etc.
223 test_env.jj_cmd_ok(&repo_path, &["undo"]);
224 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "a::"]);
225 insta::assert_snapshot!(stdout, @"");
226 insta::assert_snapshot!(stderr, @r###"
227 Duplicated 2443ea76b0b1 as uuuvxpvw 0fe67a05 a
228 Duplicated 1394f625cbbd as nmpuuozl e13ac0ad b
229 Duplicated c0cb3a0b73e7 as kzpokyyw df53fa58 c
230 Duplicated ebd06dba20ec as yxrlprzz 2f2442db d
231 Duplicated 921dde6e55c0 as mvkzkxrl ee8fe64e e
232 "###);
233 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
234 ◉ ee8fe64ed254 e
235 ├─╮
236 │ ◉ 2f2442db08eb d
237 │ ◉ df53fa589286 c
238 ◉ │ e13ac0adabdf b
239 ├─╯
240 ◉ 0fe67a05989e a
241 │ @ 921dde6e55c0 e
242 │ ├─╮
243 │ │ ◉ ebd06dba20ec d
244 │ │ ◉ c0cb3a0b73e7 c
245 │ ◉ │ 1394f625cbbd b
246 │ ├─╯
247 │ ◉ 2443ea76b0b1 a
248 ├─╯
249 ◉ 000000000000
250 "###);
251}
252
253// https://github.com/martinvonz/jj/issues/1050
254#[test]
255fn test_undo_after_duplicate() {
256 let test_env = TestEnvironment::default();
257 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
258 let repo_path = test_env.env_root().join("repo");
259
260 create_commit(&test_env, &repo_path, "a", &[]);
261 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
262 @ 2443ea76b0b1 a
263 ◉ 000000000000
264 "###);
265
266 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "a"]);
267 insta::assert_snapshot!(stdout, @"");
268 insta::assert_snapshot!(stderr, @r###"
269 Duplicated 2443ea76b0b1 as mzvwutvl f5cefcbb a
270 "###);
271 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
272 ◉ f5cefcbb65a4 a
273 │ @ 2443ea76b0b1 a
274 ├─╯
275 ◉ 000000000000
276 "###);
277
278 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["undo"]);
279 insta::assert_snapshot!(stdout, @"");
280 insta::assert_snapshot!(stderr, @"");
281 insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
282 @ 2443ea76b0b1 a
283 ◉ 000000000000
284 "###);
285}
286
287// https://github.com/martinvonz/jj/issues/694
288#[test]
289fn test_rebase_duplicates() {
290 let test_env = TestEnvironment::default();
291 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
292 let repo_path = test_env.env_root().join("repo");
293
294 create_commit(&test_env, &repo_path, "a", &[]);
295 create_commit(&test_env, &repo_path, "b", &["a"]);
296 create_commit(&test_env, &repo_path, "c", &["b"]);
297 // Test the setup
298 insta::assert_snapshot!(get_log_output_with_ts(&test_env, &repo_path), @r###"
299 @ 7e4fbf4f2759 c @ 2001-02-03 04:05:13.000 +07:00
300 ◉ 1394f625cbbd b @ 2001-02-03 04:05:11.000 +07:00
301 ◉ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
302 ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
303 "###);
304
305 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "c"]);
306 insta::assert_snapshot!(stdout, @"");
307 insta::assert_snapshot!(stderr, @r###"
308 Duplicated 7e4fbf4f2759 as yostqsxw 0ac2063b c
309 "###);
310 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate", "c"]);
311 insta::assert_snapshot!(stdout, @"");
312 insta::assert_snapshot!(stderr, @r###"
313 Duplicated 7e4fbf4f2759 as znkkpsqq ce5f4eeb c
314 "###);
315 insta::assert_snapshot!(get_log_output_with_ts(&test_env, &repo_path), @r###"
316 ◉ ce5f4eeb69d1 c @ 2001-02-03 04:05:16.000 +07:00
317 │ ◉ 0ac2063b1bee c @ 2001-02-03 04:05:15.000 +07:00
318 ├─╯
319 │ @ 7e4fbf4f2759 c @ 2001-02-03 04:05:13.000 +07:00
320 ├─╯
321 ◉ 1394f625cbbd b @ 2001-02-03 04:05:11.000 +07:00
322 ◉ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
323 ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
324 "###);
325
326 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-s", "b", "-d", "root()"]);
327 insta::assert_snapshot!(stdout, @"");
328 insta::assert_snapshot!(stderr, @r###"
329 Rebased 4 commits
330 Working copy now at: royxmykx ed671a3c c | c
331 Parent commit : zsuskuln 4c6f1569 b | b
332 Added 0 files, modified 0 files, removed 1 files
333 "###);
334 // Some of the duplicate commits' timestamps were changed a little to make them
335 // have distinct commit ids.
336 insta::assert_snapshot!(get_log_output_with_ts(&test_env, &repo_path), @r###"
337 ◉ b86e9f27d085 c @ 2001-02-03 04:05:16.000 +07:00
338 │ ◉ 8033590fe04d c @ 2001-02-03 04:05:17.000 +07:00
339 ├─╯
340 │ @ ed671a3cbf35 c @ 2001-02-03 04:05:18.000 +07:00
341 ├─╯
342 ◉ 4c6f1569e2a9 b @ 2001-02-03 04:05:18.000 +07:00
343 │ ◉ 2443ea76b0b1 a @ 2001-02-03 04:05:09.000 +07:00
344 ├─╯
345 ◉ 000000000000 @ 1970-01-01 00:00:00.000 +00:00
346 "###);
347}
348
349fn get_log_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
350 let template = r#"commit_id.short() ++ " " ++ description.first_line()"#;
351 test_env.jj_cmd_success(repo_path, &["log", "-T", template])
352}
353
354fn get_log_output_with_ts(test_env: &TestEnvironment, repo_path: &Path) -> String {
355 let template = r#"
356 commit_id.short() ++ " " ++ description.first_line() ++ " @ " ++ committer.timestamp()
357 "#;
358 test_env.jj_cmd_success(repo_path, &["log", "-T", template])
359}