just playing with tangled
1// Copyright 2025 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_with_files;
16use crate::common::CommandOutput;
17use crate::common::TestEnvironment;
18use crate::common::TestWorkDir;
19
20#[test]
21fn test_revert() {
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_with_files(&work_dir, "a", &[], &[("a", "a\n")]);
27 create_commit_with_files(&work_dir, "b", &["a"], &[]);
28 create_commit_with_files(&work_dir, "c", &["b"], &[]);
29 create_commit_with_files(&work_dir, "d", &["c"], &[]);
30 // Test the setup
31 insta::assert_snapshot!(get_log_output(&work_dir), @r"
32 @ cf3ddd838fd1 d
33 ○ 14e954305d4b c
34 ○ aa48676d4a49 b
35 ○ 2443ea76b0b1 a
36 ◆ 000000000000
37 [EOF]
38 ");
39 let output = work_dir.run_jj(["diff", "-ra", "-s"]);
40 insta::assert_snapshot!(output, @r"
41 A a
42 [EOF]
43 ");
44 let setup_opid = work_dir.current_operation_id();
45
46 // Reverting without a location is an error
47 let output = work_dir.run_jj(["revert", "-ra"]);
48 insta::assert_snapshot!(output, @r"
49 ------- stderr -------
50 error: the following required arguments were not provided:
51 <--destination <REVSETS>|--insert-after <REVSETS>|--insert-before <REVSETS>>
52
53 Usage: jj revert --revisions <REVSETS> <--destination <REVSETS>|--insert-after <REVSETS>|--insert-before <REVSETS>>
54
55 For more information, try '--help'.
56 [EOF]
57 [exit status: 2]
58 ");
59
60 // Revert the commit with `--destination`
61 let output = work_dir.run_jj(["revert", "-ra", "-d@"]);
62 insta::assert_snapshot!(output, @r#"
63 ------- stderr -------
64 Reverted 1 commits as follows:
65 lylxulpl f844336e Revert "a"
66 [EOF]
67 "#);
68 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
69 ○ f844336ef2a5 Revert "a"
70 │
71 │ This reverts commit 2443ea76b0b1c531326908326aab7020abab8e6c.
72 @ cf3ddd838fd1 d
73 ○ 14e954305d4b c
74 ○ aa48676d4a49 b
75 ○ 2443ea76b0b1 a
76 ◆ 000000000000
77 [EOF]
78 "#);
79 let output = work_dir.run_jj(["diff", "-s", "-r@+"]);
80 insta::assert_snapshot!(output, @r"
81 D a
82 [EOF]
83 ");
84
85 // Revert the new reverted commit
86 let output = work_dir.run_jj(["revert", "-r@+", "-d@+"]);
87 insta::assert_snapshot!(output, @r#"
88 ------- stderr -------
89 Reverted 1 commits as follows:
90 uyznsvlq 57fb197b Revert "Revert "a""
91 [EOF]
92 "#);
93 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
94 ○ 57fb197b953f Revert "Revert "a""
95 │
96 │ This reverts commit f844336ef2a54f4499a5efefa1a9549451276316.
97 ○ f844336ef2a5 Revert "a"
98 │
99 │ This reverts commit 2443ea76b0b1c531326908326aab7020abab8e6c.
100 @ cf3ddd838fd1 d
101 ○ 14e954305d4b c
102 ○ aa48676d4a49 b
103 ○ 2443ea76b0b1 a
104 ◆ 000000000000
105 [EOF]
106 "#);
107 let output = work_dir.run_jj(["diff", "-s", "-r@++"]);
108 insta::assert_snapshot!(output, @r"
109 A a
110 [EOF]
111 ");
112 work_dir.run_jj(["op", "restore", &setup_opid]).success();
113
114 // Revert the commit with `--insert-after`
115 let output = work_dir.run_jj(["revert", "-ra", "-Ab"]);
116 insta::assert_snapshot!(output, @r#"
117 ------- stderr -------
118 Reverted 1 commits as follows:
119 tlkvzzqu ff67400f Revert "a"
120 Rebased 2 descendant commits
121 Working copy (@) now at: vruxwmqv 37ad0315 d | (empty) d
122 Parent commit (@-) : royxmykx ca80e93f c | (empty) c
123 Added 0 files, modified 0 files, removed 1 files
124 [EOF]
125 "#);
126 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
127 @ 37ad03151aa7 d
128 ○ ca80e93fdef9 c
129 ○ ff67400f3e1f Revert "a"
130 │
131 │ This reverts commit 2443ea76b0b1c531326908326aab7020abab8e6c.
132 ○ aa48676d4a49 b
133 ○ 2443ea76b0b1 a
134 ◆ 000000000000
135 [EOF]
136 "#);
137 let output = work_dir.run_jj(["diff", "-s", "-rb+"]);
138 insta::assert_snapshot!(output, @r"
139 D a
140 [EOF]
141 ");
142 work_dir.run_jj(["op", "restore", &setup_opid]).success();
143
144 // Revert the commit with `--insert-before`
145 let output = work_dir.run_jj(["revert", "-ra", "-Bd"]);
146 insta::assert_snapshot!(output, @r#"
147 ------- stderr -------
148 Reverted 1 commits as follows:
149 xlzxqlsl 0b91fe42 Revert "a"
150 Rebased 1 descendant commits
151 Working copy (@) now at: vruxwmqv 3a8a8069 d | (empty) d
152 Parent commit (@-) : xlzxqlsl 0b91fe42 Revert "a"
153 Added 0 files, modified 0 files, removed 1 files
154 [EOF]
155 "#);
156 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
157 @ 3a8a80692ac3 d
158 ○ 0b91fe42616d Revert "a"
159 │
160 │ This reverts commit 2443ea76b0b1c531326908326aab7020abab8e6c.
161 ○ 14e954305d4b c
162 ○ aa48676d4a49 b
163 ○ 2443ea76b0b1 a
164 ◆ 000000000000
165 [EOF]
166 "#);
167 let output = work_dir.run_jj(["diff", "-s", "-rd-"]);
168 insta::assert_snapshot!(output, @r"
169 D a
170 [EOF]
171 ");
172 work_dir.run_jj(["op", "restore", &setup_opid]).success();
173
174 // Revert the commit with `--insert-after` and `--insert-before`
175 let output = work_dir.run_jj(["revert", "-ra", "-Aa", "-Bd"]);
176 insta::assert_snapshot!(output, @r#"
177 ------- stderr -------
178 Reverted 1 commits as follows:
179 pkstwlsy 29508aef Revert "a"
180 Rebased 1 descendant commits
181 Working copy (@) now at: vruxwmqv 3489c981 d | (empty) d
182 Parent commit (@-) : royxmykx 14e95430 c | (empty) c
183 Parent commit (@-) : pkstwlsy 29508aef Revert "a"
184 Added 0 files, modified 0 files, removed 1 files
185 [EOF]
186 "#);
187 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
188 @ 3489c98177aa d
189 ├─╮
190 │ ○ 29508aefc220 Revert "a"
191 │ │
192 │ │ This reverts commit 2443ea76b0b1c531326908326aab7020abab8e6c.
193 ○ │ 14e954305d4b c
194 ○ │ aa48676d4a49 b
195 ├─╯
196 ○ 2443ea76b0b1 a
197 ◆ 000000000000
198 [EOF]
199 "#);
200 let output = work_dir.run_jj(["diff", "-s", "-r", "a+ & d-"]);
201 insta::assert_snapshot!(output, @r"
202 D a
203 [EOF]
204 ");
205 work_dir.run_jj(["op", "restore", &setup_opid]).success();
206}
207
208#[test]
209fn test_revert_multiple() {
210 let test_env = TestEnvironment::default();
211 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
212 let work_dir = test_env.work_dir("repo");
213
214 create_commit_with_files(&work_dir, "a", &[], &[("a", "a\n")]);
215 create_commit_with_files(&work_dir, "b", &["a"], &[("a", "a\nb\n")]);
216 create_commit_with_files(&work_dir, "c", &["b"], &[("a", "a\nb\n"), ("b", "b\n")]);
217 create_commit_with_files(&work_dir, "d", &["c"], &[]);
218 create_commit_with_files(&work_dir, "e", &["d"], &[("a", "a\nb\nc\n")]);
219
220 // Test the setup
221 insta::assert_snapshot!(get_log_output(&work_dir), @r"
222 @ 208f8612074a e
223 ○ ceeec03be46b d
224 ○ 413337bbd11f c
225 ○ 46cc97af6802 b
226 ○ 2443ea76b0b1 a
227 ◆ 000000000000
228 [EOF]
229 ");
230
231 // Revert multiple commits
232 let output = work_dir.run_jj(["revert", "-rb", "-rc", "-re", "-d@"]);
233 insta::assert_snapshot!(output, @r#"
234 ------- stderr -------
235 Reverted 3 commits as follows:
236 wqnwkozp 05f5fa79 Revert "e"
237 mouksmqu f5d9e8b2 Revert "c"
238 tqvpomtp fb78f44d Revert "b"
239 [EOF]
240 "#);
241 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
242 ○ fb78f44decd2 Revert "b"
243 │
244 │ This reverts commit 46cc97af6802301d8db381386e8485ff3ff24ae6.
245 ○ f5d9e8b20bd1 Revert "c"
246 │
247 │ This reverts commit 413337bbd11f7a6636c010d9e196acf801d8df2f.
248 ○ 05f5fa79161a Revert "e"
249 │
250 │ This reverts commit 208f8612074af4c219d06568a8e1f04f2e80dc25.
251 @ 208f8612074a e
252 ○ ceeec03be46b d
253 ○ 413337bbd11f c
254 ○ 46cc97af6802 b
255 ○ 2443ea76b0b1 a
256 ◆ 000000000000
257 [EOF]
258 "#);
259 // View the output of each reverted commit
260 let output = work_dir.run_jj(["show", "@+"]);
261 insta::assert_snapshot!(output, @r#"
262 Commit ID: 05f5fa79161a41b9ed3dc11e156d18de8abc7907
263 Change ID: wqnwkozpkustnxypnnntnykwrqrkrpvv
264 Author : Test User <test.user@example.com> (2001-02-03 08:05:19)
265 Committer: Test User <test.user@example.com> (2001-02-03 08:05:19)
266
267 Revert "e"
268
269 This reverts commit 208f8612074af4c219d06568a8e1f04f2e80dc25.
270
271 Modified regular file a:
272 1 1: a
273 2 2: b
274 3 : c
275 [EOF]
276 "#);
277 let output = work_dir.run_jj(["show", "@++"]);
278 insta::assert_snapshot!(output, @r#"
279 Commit ID: f5d9e8b20bd1c5c7485e8baab4b287759c717a52
280 Change ID: mouksmquosnpvwqrpsvvxtxpywpnxlss
281 Author : Test User <test.user@example.com> (2001-02-03 08:05:19)
282 Committer: Test User <test.user@example.com> (2001-02-03 08:05:19)
283
284 Revert "c"
285
286 This reverts commit 413337bbd11f7a6636c010d9e196acf801d8df2f.
287
288 Removed regular file b:
289 1 : b
290 [EOF]
291 "#);
292 let output = work_dir.run_jj(["show", "@+++"]);
293 insta::assert_snapshot!(output, @r#"
294 Commit ID: fb78f44decd2082bc2a6940624744c90b20635a8
295 Change ID: tqvpomtpwrqsylrpsxknultrymmqxmxv
296 Author : Test User <test.user@example.com> (2001-02-03 08:05:19)
297 Committer: Test User <test.user@example.com> (2001-02-03 08:05:19)
298
299 Revert "b"
300
301 This reverts commit 46cc97af6802301d8db381386e8485ff3ff24ae6.
302
303 Modified regular file a:
304 1 1: a
305 2 : b
306 [EOF]
307 "#);
308}
309
310#[test]
311fn test_revert_description_template() {
312 let test_env = TestEnvironment::default();
313 test_env.run_jj_in(".", ["git", "init", "repo"]).success();
314 test_env.add_config(
315 r#"
316 [templates]
317 revert_description = '''
318 separate(" ",
319 "Revert commit",
320 commit_id.short(),
321 '"' ++ description.first_line() ++ '"',
322 )
323 '''
324 "#,
325 );
326 let work_dir = test_env.work_dir("repo");
327 create_commit_with_files(&work_dir, "a", &[], &[("a", "a\n")]);
328
329 // Test the setup
330 insta::assert_snapshot!(get_log_output(&work_dir), @r"
331 @ 2443ea76b0b1 a
332 ◆ 000000000000
333 [EOF]
334 ");
335 let output = work_dir.run_jj(["diff", "-s"]);
336 insta::assert_snapshot!(output, @r"
337 A a
338 [EOF]
339 ");
340
341 // Verify that message of reverted commit follows the template
342 let output = work_dir.run_jj(["revert", "-r@", "-d@"]);
343 insta::assert_snapshot!(output, @r#"
344 ------- stderr -------
345 Reverted 1 commits as follows:
346 royxmykx 1db880a5 Revert commit 2443ea76b0b1 "a"
347 [EOF]
348 "#);
349 insta::assert_snapshot!(get_log_output(&work_dir), @r#"
350 ○ 1db880a5204e Revert commit 2443ea76b0b1 "a"
351 @ 2443ea76b0b1 a
352 ◆ 000000000000
353 [EOF]
354 "#);
355}
356
357#[must_use]
358fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {
359 let template = r#"commit_id.short() ++ " " ++ description"#;
360 work_dir.run_jj(["log", "-T", template])
361}