just playing with tangled
1// Copyright 2022 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::common::to_toml_value;
16use crate::common::TestEnvironment;
17
18#[test]
19fn test_evolog_with_or_without_diff() {
20 let test_env = TestEnvironment::default();
21 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
22 let work_dir = test_env.work_dir("repo");
23
24 work_dir.write_file("file1", "foo\n");
25 work_dir.run_jj(["new", "-m", "my description"]).success();
26 work_dir.write_file("file1", "foo\nbar\n");
27 work_dir.write_file("file2", "foo\n");
28 work_dir
29 .run_jj(["rebase", "-r", "@", "-d", "root()"])
30 .success();
31 work_dir.write_file("file1", "resolved\n");
32
33 let output = work_dir.run_jj(["evolog"]);
34 insta::assert_snapshot!(output, @r"
35 @ rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
36 │ my description
37 × rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
38 │ my description
39 ○ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 068224a7
40 │ my description
41 ○ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:08 2b023b5f
42 (empty) my description
43 [EOF]
44 ");
45
46 // Color
47 let output = work_dir.run_jj(["--color=always", "evolog"]);
48 insta::assert_snapshot!(output, @r"
49 [1m[38;5;2m@[0m [1m[38;5;13mr[38;5;8mlvkpnrz[39m [38;5;3mtest.user@example.com[39m [38;5;14m2001-02-03 08:05:10[39m [38;5;12m6[38;5;8m6b42ad3[39m[0m
50 │ [1mmy description[0m
51 [1m[38;5;1m×[0m [1m[39mr[0m[38;5;8mlvkpnrz[39m hidden [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:09[39m [1m[38;5;4m07[0m[38;5;8mb18245[39m [38;5;1mconflict[39m
52 │ my description
53 ○ [1m[39mr[0m[38;5;8mlvkpnrz[39m hidden [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:09[39m [1m[38;5;4m06[0m[38;5;8m8224a7[39m
54 │ my description
55 ○ [1m[39mr[0m[38;5;8mlvkpnrz[39m hidden [38;5;3mtest.user@example.com[39m [38;5;6m2001-02-03 08:05:08[39m [1m[38;5;4m2b[0m[38;5;8m023b5f[39m
56 [38;5;2m(empty)[39m my description
57 [EOF]
58 ");
59
60 // There should be no diff caused by the rebase because it was a pure rebase
61 // (even even though it resulted in a conflict).
62 let output = work_dir.run_jj(["evolog", "-p"]);
63 insta::assert_snapshot!(output, @r"
64 @ rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
65 │ my description
66 │ Resolved conflict in file1:
67 │ 1 : <<<<<<< Conflict 1 of 1
68 │ 2 : %%%%%%% Changes from base to side #1
69 │ 3 : -foo
70 │ 4 : +++++++ Contents of side #2
71 │ 5 : foo
72 │ 6 : bar
73 │ 7 1: >>>>>>> Conflict 1 of 1 endsresolved
74 × rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
75 │ my description
76 ○ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 068224a7
77 │ my description
78 │ Modified regular file file1:
79 │ 1 1: foo
80 │ 2: bar
81 │ Added regular file file2:
82 │ 1: foo
83 ○ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:08 2b023b5f
84 (empty) my description
85 [EOF]
86 ");
87
88 // Test `--limit`
89 let output = work_dir.run_jj(["evolog", "--limit=2"]);
90 insta::assert_snapshot!(output, @r"
91 @ rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
92 │ my description
93 × rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
94 │ my description
95 [EOF]
96 ");
97
98 // Test `--no-graph`
99 let output = work_dir.run_jj(["evolog", "--no-graph"]);
100 insta::assert_snapshot!(output, @r"
101 rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
102 my description
103 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
104 my description
105 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 068224a7
106 my description
107 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:08 2b023b5f
108 (empty) my description
109 [EOF]
110 ");
111
112 // Test `--git` format, and that it implies `-p`
113 let output = work_dir.run_jj(["evolog", "--no-graph", "--git"]);
114 insta::assert_snapshot!(output, @r"
115 rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
116 my description
117 diff --git a/file1 b/file1
118 index 0000000000..2ab19ae607 100644
119 --- a/file1
120 +++ b/file1
121 @@ -1,7 +1,1 @@
122 -<<<<<<< Conflict 1 of 1
123 -%%%%%%% Changes from base to side #1
124 --foo
125 -+++++++ Contents of side #2
126 -foo
127 -bar
128 ->>>>>>> Conflict 1 of 1 ends
129 +resolved
130 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
131 my description
132 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 068224a7
133 my description
134 diff --git a/file1 b/file1
135 index 257cc5642c..3bd1f0e297 100644
136 --- a/file1
137 +++ b/file1
138 @@ -1,1 +1,2 @@
139 foo
140 +bar
141 diff --git a/file2 b/file2
142 new file mode 100644
143 index 0000000000..257cc5642c
144 --- /dev/null
145 +++ b/file2
146 @@ -0,0 +1,1 @@
147 +foo
148 rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:08 2b023b5f
149 (empty) my description
150 [EOF]
151 ");
152}
153
154#[test]
155fn test_evolog_with_custom_symbols() {
156 let test_env = TestEnvironment::default();
157 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
158 let work_dir = test_env.work_dir("repo");
159
160 work_dir.write_file("file1", "foo\n");
161 work_dir.run_jj(["new", "-m", "my description"]).success();
162 work_dir.write_file("file1", "foo\nbar\n");
163 work_dir.write_file("file2", "foo\n");
164 work_dir
165 .run_jj(["rebase", "-r", "@", "-d", "root()"])
166 .success();
167 work_dir.write_file("file1", "resolved\n");
168
169 let config = "templates.log_node='if(current_working_copy, \"$\", \"┝\")'";
170 let output = work_dir.run_jj(["evolog", "--config", config]);
171
172 insta::assert_snapshot!(output, @r"
173 $ rlvkpnrz test.user@example.com 2001-02-03 08:05:10 66b42ad3
174 │ my description
175 ┝ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 07b18245 conflict
176 │ my description
177 ┝ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:09 068224a7
178 │ my description
179 ┝ rlvkpnrz hidden test.user@example.com 2001-02-03 08:05:08 2b023b5f
180 (empty) my description
181 [EOF]
182 ");
183}
184
185#[test]
186fn test_evolog_word_wrap() {
187 let test_env = TestEnvironment::default();
188 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
189 let work_dir = test_env.work_dir("repo");
190 let render = |args: &[&str], columns: u32, word_wrap: bool| {
191 let word_wrap = to_toml_value(word_wrap);
192 work_dir.run_jj_with(|cmd| {
193 cmd.args(args)
194 .arg(format!("--config=ui.log-word-wrap={word_wrap}"))
195 .env("COLUMNS", columns.to_string())
196 })
197 };
198
199 work_dir.run_jj(["describe", "-m", "first"]).success();
200
201 // ui.log-word-wrap option applies to both graph/no-graph outputs
202 insta::assert_snapshot!(render(&["evolog"], 40, false), @r"
203 @ qpvuntsm test.user@example.com 2001-02-03 08:05:08 fa15625b
204 │ (empty) first
205 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059
206 (empty) (no description set)
207 [EOF]
208 ");
209 insta::assert_snapshot!(render(&["evolog"], 40, true), @r"
210 @ qpvuntsm test.user@example.com
211 │ 2001-02-03 08:05:08 fa15625b
212 │ (empty) first
213 ○ qpvuntsm hidden test.user@example.com
214 2001-02-03 08:05:07 230dd059
215 (empty) (no description set)
216 [EOF]
217 ");
218 insta::assert_snapshot!(render(&["evolog", "--no-graph"], 40, false), @r"
219 qpvuntsm test.user@example.com 2001-02-03 08:05:08 fa15625b
220 (empty) first
221 qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059
222 (empty) (no description set)
223 [EOF]
224 ");
225 insta::assert_snapshot!(render(&["evolog", "--no-graph"], 40, true), @r"
226 qpvuntsm test.user@example.com
227 2001-02-03 08:05:08 fa15625b
228 (empty) first
229 qpvuntsm hidden test.user@example.com
230 2001-02-03 08:05:07 230dd059
231 (empty) (no description set)
232 [EOF]
233 ");
234}
235
236#[test]
237fn test_evolog_squash() {
238 let test_env = TestEnvironment::default();
239 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
240 let work_dir = test_env.work_dir("repo");
241
242 work_dir.run_jj(["describe", "-m", "first"]).success();
243 work_dir.write_file("file1", "foo\n");
244 work_dir.run_jj(["new", "-m", "second"]).success();
245 work_dir.write_file("file1", "foo\nbar\n");
246
247 // not partial
248 work_dir.run_jj(["squash", "-m", "squashed 1"]).success();
249
250 work_dir.run_jj(["describe", "-m", "third"]).success();
251 work_dir.write_file("file1", "foo\nbar\nbaz\n");
252 work_dir.write_file("file2", "foo2\n");
253 work_dir.write_file("file3", "foo3\n");
254
255 // partial
256 work_dir
257 .run_jj(["squash", "-m", "squashed 2", "file1"])
258 .success();
259
260 work_dir.run_jj(["new", "-m", "fourth"]).success();
261 work_dir.write_file("file4", "foo4\n");
262
263 work_dir.run_jj(["new", "-m", "fifth"]).success();
264 work_dir.write_file("file5", "foo5\n");
265
266 // multiple sources
267 work_dir
268 .run_jj([
269 "squash",
270 "-msquashed 3",
271 "--from=description('fourth')|description('fifth')",
272 "--into=description('squash')",
273 ])
274 .success();
275
276 let output = work_dir.run_jj(["evolog", "-p", "-r", "description('squash')"]);
277 insta::assert_snapshot!(output, @r"
278 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:15 d49749bf
279 ├─┬─╮ squashed 3
280 │ │ ○ vruxwmqv hidden test.user@example.com 2001-02-03 08:05:15 8f2ae2b5
281 │ │ │ fifth
282 │ │ │ Added regular file file5:
283 │ │ │ 1: foo5
284 │ │ ○ vruxwmqv hidden test.user@example.com 2001-02-03 08:05:14 04d28ca9
285 │ │ (empty) fifth
286 │ ○ yqosqzyt hidden test.user@example.com 2001-02-03 08:05:14 c5801e10
287 │ │ fourth
288 │ │ Added regular file file4:
289 │ │ 1: foo4
290 │ ○ yqosqzyt hidden test.user@example.com 2001-02-03 08:05:13 bb54a199
291 │ (empty) fourth
292 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:12 1408a0a7
293 ├─╮ squashed 2
294 │ │ Removed regular file file2:
295 │ │ 1 : foo2
296 │ │ Removed regular file file3:
297 │ │ 1 : foo3
298 │ ○ zsuskuln hidden test.user@example.com 2001-02-03 08:05:12 c9460789
299 │ │ third
300 │ │ Modified regular file file1:
301 │ │ 1 1: foo
302 │ │ 2 2: bar
303 │ │ 3: baz
304 │ │ Added regular file file2:
305 │ │ 1: foo2
306 │ │ Added regular file file3:
307 │ │ 1: foo3
308 │ ○ zsuskuln hidden test.user@example.com 2001-02-03 08:05:11 66645763
309 │ │ (empty) third
310 │ ○ zsuskuln hidden test.user@example.com 2001-02-03 08:05:10 1c7afcb4
311 │ (empty) (no description set)
312 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:10 e3c2a446
313 ├─╮ squashed 1
314 │ ○ kkmpptxz hidden test.user@example.com 2001-02-03 08:05:10 46acd22a
315 │ │ second
316 │ │ Modified regular file file1:
317 │ │ 1 1: foo
318 │ │ 2: bar
319 │ ○ kkmpptxz hidden test.user@example.com 2001-02-03 08:05:09 cba41deb
320 │ (empty) second
321 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:09 766420db
322 │ first
323 │ Added regular file file1:
324 │ 1: foo
325 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:08 fa15625b
326 │ (empty) first
327 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059
328 (empty) (no description set)
329 [EOF]
330 ");
331}
332
333#[test]
334fn test_evolog_with_no_template() {
335 let test_env = TestEnvironment::default();
336 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
337 let work_dir = test_env.work_dir("repo");
338
339 let output = work_dir.run_jj(["evolog", "-T"]);
340 insta::assert_snapshot!(output, @r"
341 ------- stderr -------
342 error: a value is required for '--template <TEMPLATE>' but none was supplied
343
344 For more information, try '--help'.
345 Hint: The following template aliases are defined:
346 - builtin_config_list
347 - builtin_config_list_detailed
348 - builtin_draft_commit_description
349 - builtin_log_comfortable
350 - builtin_log_compact
351 - builtin_log_compact_full_description
352 - builtin_log_detailed
353 - builtin_log_node
354 - builtin_log_node_ascii
355 - builtin_log_oneline
356 - builtin_op_log_comfortable
357 - builtin_op_log_compact
358 - builtin_op_log_node
359 - builtin_op_log_node_ascii
360 - builtin_op_log_oneline
361 - commit_summary_separator
362 - description_placeholder
363 - email_placeholder
364 - name_placeholder
365 [EOF]
366 [exit status: 2]
367 ");
368}
369
370#[test]
371fn test_evolog_reversed_no_graph() {
372 let test_env = TestEnvironment::default();
373 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
374 let work_dir = test_env.work_dir("repo");
375
376 work_dir.run_jj(["describe", "-m", "a"]).success();
377 work_dir.run_jj(["describe", "-m", "b"]).success();
378 work_dir.run_jj(["describe", "-m", "c"]).success();
379 let output = work_dir.run_jj(["evolog", "--reversed", "--no-graph"]);
380 insta::assert_snapshot!(output, @r"
381 qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059
382 (empty) (no description set)
383 qpvuntsm hidden test.user@example.com 2001-02-03 08:05:08 d8d5f980
384 (empty) a
385 qpvuntsm hidden test.user@example.com 2001-02-03 08:05:09 b4584f54
386 (empty) b
387 qpvuntsm test.user@example.com 2001-02-03 08:05:10 5cb22a87
388 (empty) c
389 [EOF]
390 ");
391
392 let output = work_dir.run_jj(["evolog", "--limit=2", "--reversed", "--no-graph"]);
393 insta::assert_snapshot!(output, @r"
394 qpvuntsm hidden test.user@example.com 2001-02-03 08:05:09 b4584f54
395 (empty) b
396 qpvuntsm test.user@example.com 2001-02-03 08:05:10 5cb22a87
397 (empty) c
398 [EOF]
399 ");
400}
401
402#[test]
403fn test_evolog_reverse_with_graph() {
404 let test_env = TestEnvironment::default();
405 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
406 let work_dir = test_env.work_dir("repo");
407
408 work_dir.run_jj(["describe", "-m", "a"]).success();
409 work_dir.run_jj(["describe", "-m", "b"]).success();
410 work_dir.run_jj(["describe", "-m", "c"]).success();
411 work_dir
412 .run_jj(["new", "-r", "description(c)", "-m", "d"])
413 .success();
414 work_dir
415 .run_jj(["new", "-r", "description(c)", "-m", "e"])
416 .success();
417 work_dir
418 .run_jj([
419 "squash",
420 "--from",
421 "description(d)|description(e)",
422 "--to",
423 "description(c)",
424 "-m",
425 "c+d+e",
426 ])
427 .success();
428 let output = work_dir.run_jj(["evolog", "-r", "description(c+d+e)", "--reversed"]);
429 insta::assert_snapshot!(output, @r"
430 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059
431 │ (empty) (no description set)
432 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:08 d8d5f980
433 │ (empty) a
434 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:09 b4584f54
435 │ (empty) b
436 ○ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:10 5cb22a87
437 │ (empty) c
438 │ ○ mzvwutvl hidden test.user@example.com 2001-02-03 08:05:11 280cbb6e
439 ├─╯ (empty) d
440 │ ○ royxmykx hidden test.user@example.com 2001-02-03 08:05:12 031df638
441 ├─╯ (empty) e
442 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:13 a177c2f2
443 (empty) c+d+e
444 [EOF]
445 ");
446
447 let output = work_dir.run_jj(["evolog", "-rdescription(c+d+e)", "--limit=3", "--reversed"]);
448 insta::assert_snapshot!(output, @r"
449 ○ mzvwutvl hidden test.user@example.com 2001-02-03 08:05:11 280cbb6e
450 │ (empty) d
451 │ ○ royxmykx hidden test.user@example.com 2001-02-03 08:05:12 031df638
452 ├─╯ (empty) e
453 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:13 a177c2f2
454 (empty) c+d+e
455 [EOF]
456 ");
457}