just playing with tangled
at diffedit3 782 lines 30 kB view raw
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 regex::Regex; 16 17use crate::common::TestEnvironment; 18 19#[test] 20fn test_log_parents() { 21 let test_env = TestEnvironment::default(); 22 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 23 let repo_path = test_env.env_root().join("repo"); 24 25 test_env.jj_cmd_ok(&repo_path, &["new"]); 26 test_env.jj_cmd_ok(&repo_path, &["new", "@-"]); 27 test_env.jj_cmd_ok(&repo_path, &["new", "@", "@-"]); 28 29 let template = 30 r#"commit_id ++ "\nP: " ++ parents.len() ++ " " ++ parents.map(|c| c.commit_id()) ++ "\n""#; 31 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", template]); 32 insta::assert_snapshot!(stdout, @r###" 33 @ c067170d4ca1bc6162b64f7550617ec809647f84 34 ├─╮ P: 2 4db490c88528133d579540b6900b8098f0c17701 230dd059e1b059aefc0da06a2e5a7dbf22362f22 35 ◉ │ 4db490c88528133d579540b6900b8098f0c17701 36 ├─╯ P: 1 230dd059e1b059aefc0da06a2e5a7dbf22362f22 37 ◉ 230dd059e1b059aefc0da06a2e5a7dbf22362f22 38 │ P: 1 0000000000000000000000000000000000000000 39 ◉ 0000000000000000000000000000000000000000 40 P: 0 41 "###); 42 43 let template = r#"parents.map(|c| c.commit_id().shortest(4))"#; 44 let stdout = test_env.jj_cmd_success( 45 &repo_path, 46 &["log", "-T", template, "-r@", "--color=always"], 47 ); 48 insta::assert_snapshot!(stdout, @r###" 49 @ 4db4 230d 50 51 ~ 52 "###); 53 54 // Commit object isn't printable 55 let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-T", "parents"]); 56 insta::assert_snapshot!(stderr, @r###" 57 Error: Failed to parse template: Expected expression of type "Template", but actual type is "List<Commit>" 58 Caused by: --> 1:1 59 | 60 1 | parents 61 | ^-----^ 62 | 63 = Expected expression of type "Template", but actual type is "List<Commit>" 64 "###); 65 66 // Redundant argument passed to keyword method 67 let template = r#"parents.map(|c| c.commit_id(""))"#; 68 let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-T", template]); 69 insta::assert_snapshot!(stderr, @r###" 70 Error: Failed to parse template: Function "commit_id": Expected 0 arguments 71 Caused by: --> 1:29 72 | 73 1 | parents.map(|c| c.commit_id("")) 74 | ^^ 75 | 76 = Function "commit_id": Expected 0 arguments 77 "###); 78} 79 80#[test] 81fn test_log_author_timestamp() { 82 let test_env = TestEnvironment::default(); 83 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 84 let repo_path = test_env.env_root().join("repo"); 85 86 test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "first"]); 87 test_env.jj_cmd_ok(&repo_path, &["new", "-m", "second"]); 88 89 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "author.timestamp()"]); 90 insta::assert_snapshot!(stdout, @r###" 91 @ 2001-02-03 04:05:09.000 +07:00 92 ◉ 2001-02-03 04:05:07.000 +07:00 93 ◉ 1970-01-01 00:00:00.000 +00:00 94 "###); 95} 96 97#[test] 98fn test_log_author_timestamp_ago() { 99 let test_env = TestEnvironment::default(); 100 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 101 let repo_path = test_env.env_root().join("repo"); 102 103 test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "first"]); 104 test_env.jj_cmd_ok(&repo_path, &["new", "-m", "second"]); 105 106 let template = r#"author.timestamp().ago() ++ "\n""#; 107 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--no-graph", "-T", template]); 108 let line_re = Regex::new(r"[0-9]+ years ago").unwrap(); 109 assert!( 110 stdout.lines().all(|x| line_re.is_match(x)), 111 "expected every line to match regex" 112 ); 113} 114 115#[test] 116fn test_log_author_timestamp_utc() { 117 let test_env = TestEnvironment::default(); 118 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 119 let repo_path = test_env.env_root().join("repo"); 120 121 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "author.timestamp().utc()"]); 122 insta::assert_snapshot!(stdout, @r###" 123 @ 2001-02-02 21:05:07.000 +00:00 124 ◉ 1970-01-01 00:00:00.000 +00:00 125 "###); 126} 127 128#[cfg(unix)] 129#[test] 130fn test_log_author_timestamp_local() { 131 let mut test_env = TestEnvironment::default(); 132 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 133 let repo_path = test_env.env_root().join("repo"); 134 135 test_env.add_env_var("TZ", "UTC-05:30"); 136 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "author.timestamp().local()"]); 137 insta::assert_snapshot!(stdout, @r###" 138 @ 2001-02-03 08:05:07.000 +11:00 139 ◉ 1970-01-01 11:00:00.000 +11:00 140 "###); 141 test_env.add_env_var("TZ", "UTC+10:00"); 142 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", "author.timestamp().local()"]); 143 insta::assert_snapshot!(stdout, @r###" 144 @ 2001-02-03 08:05:07.000 +11:00 145 ◉ 1970-01-01 11:00:00.000 +11:00 146 "###); 147} 148 149#[test] 150fn test_mine_is_true_when_author_is_user() { 151 let test_env = TestEnvironment::default(); 152 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 153 let repo_path = test_env.env_root().join("repo"); 154 test_env.jj_cmd_ok( 155 &repo_path, 156 &[ 157 "--config-toml=user.email='johndoe@example.com'", 158 "--config-toml=user.name='John Doe'", 159 "new", 160 ], 161 ); 162 163 let stdout = test_env.jj_cmd_success( 164 &repo_path, 165 &[ 166 "log", 167 "-T", 168 r#"coalesce(if(mine, "mine"), author.email(), email_placeholder)"#, 169 ], 170 ); 171 insta::assert_snapshot!(stdout, @r###" 172 @ johndoe@example.com 173 ◉ mine 174 ◉ (no email set) 175 "###); 176} 177 178#[test] 179fn test_log_default() { 180 let test_env = TestEnvironment::default(); 181 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 182 let repo_path = test_env.env_root().join("repo"); 183 184 std::fs::write(repo_path.join("file1"), "foo\n").unwrap(); 185 test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "add a file"]); 186 test_env.jj_cmd_ok(&repo_path, &["new", "-m", "description 1"]); 187 test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]); 188 189 // Test default log output format 190 let stdout = test_env.jj_cmd_success(&repo_path, &["log"]); 191 insta::assert_snapshot!(stdout, @r###" 192 @ kkmpptxz test.user@example.com 2001-02-03 08:05:09 my-branch 9de54178 193 │ (empty) description 1 194 ◉ qpvuntsm test.user@example.com 2001-02-03 08:05:08 4291e264 195 │ add a file 196 ◉ zzzzzzzz root() 00000000 197 "###); 198 199 // Color 200 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always"]); 201 insta::assert_snapshot!(stdout, @r###" 202 @ kkmpptxz test.user@example.com 2001-02-03 08:05:09 my-branch 9de54178 203 │ (empty) description 1 204 ◉ qpvuntsm test.user@example.com 2001-02-03 08:05:08 4291e264 205 │ add a file 206 ◉ zzzzzzzz root() 00000000 207 "###); 208 209 // Color without graph 210 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always", "--no-graph"]); 211 insta::assert_snapshot!(stdout, @r###" 212 kkmpptxz test.user@example.com 2001-02-03 08:05:09 my-branch 9de54178 213 (empty) description 1 214 qpvuntsm test.user@example.com 2001-02-03 08:05:08 4291e264 215 add a file 216 zzzzzzzz root() 00000000 217 "###); 218} 219 220#[test] 221fn test_log_builtin_templates() { 222 let test_env = TestEnvironment::default(); 223 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 224 let repo_path = test_env.env_root().join("repo"); 225 // Render without graph and append "[EOF]" marker to test line ending 226 let render = |template| { 227 test_env.jj_cmd_success(&repo_path, &["log", "-T", template, "--no-graph"]) + "[EOF]\n" 228 }; 229 230 test_env.jj_cmd_ok( 231 &repo_path, 232 &[ 233 "--config-toml=user.email=''", 234 "--config-toml=user.name=''", 235 "new", 236 ], 237 ); 238 test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]); 239 240 insta::assert_snapshot!(render(r#"builtin_log_oneline"#), @r###" 241 rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 (empty) (no description set) 242 qpvuntsm test.user 2001-02-03 08:05:07 230dd059 (empty) (no description set) 243 zzzzzzzz root() 00000000 244 [EOF] 245 "###); 246 247 insta::assert_snapshot!(render(r#"builtin_log_compact"#), @r###" 248 rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 249 (empty) (no description set) 250 qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059 251 (empty) (no description set) 252 zzzzzzzz root() 00000000 253 [EOF] 254 "###); 255 256 insta::assert_snapshot!(render(r#"builtin_log_comfortable"#), @r###" 257 rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 258 (empty) (no description set) 259 260 qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059 261 (empty) (no description set) 262 263 zzzzzzzz root() 00000000 264 265 [EOF] 266 "###); 267 268 insta::assert_snapshot!(render(r#"builtin_log_detailed"#), @r###" 269 Commit ID: dc31539712c7294d1d712cec63cef4504b94ca74 270 Change ID: rlvkpnrzqnoowoytxnquwvuryrwnrmlp 271 Branches: my-branch 272 Author: (no name set) <(no email set)> (2001-02-03 08:05:08) 273 Committer: (no name set) <(no email set)> (2001-02-03 08:05:08) 274 275 (no description set) 276 277 Commit ID: 230dd059e1b059aefc0da06a2e5a7dbf22362f22 278 Change ID: qpvuntsmwlqtpsluzzsnyyzlmlwvmlnu 279 Author: Test User <test.user@example.com> (2001-02-03 08:05:07) 280 Committer: Test User <test.user@example.com> (2001-02-03 08:05:07) 281 282 (no description set) 283 284 Commit ID: 0000000000000000000000000000000000000000 285 Change ID: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 286 Author: (no name set) <(no email set)> (1970-01-01 11:00:00) 287 Committer: (no name set) <(no email set)> (1970-01-01 11:00:00) 288 289 (no description set) 290 291 [EOF] 292 "###); 293} 294 295#[test] 296fn test_log_builtin_templates_colored() { 297 let test_env = TestEnvironment::default(); 298 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 299 let repo_path = test_env.env_root().join("repo"); 300 let render = 301 |template| test_env.jj_cmd_success(&repo_path, &["--color=always", "log", "-T", template]); 302 303 test_env.jj_cmd_ok( 304 &repo_path, 305 &[ 306 "--config-toml=user.email=''", 307 "--config-toml=user.name=''", 308 "new", 309 ], 310 ); 311 test_env.jj_cmd_ok(&repo_path, &["branch", "create", "my-branch"]); 312 313 insta::assert_snapshot!(render(r#"builtin_log_oneline"#), @r###" 314 @ rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 (empty) (no description set) 315 ◉ qpvuntsm test.user 2001-02-03 08:05:07 230dd059 (empty) (no description set) 316 ◉ zzzzzzzz root() 00000000 317 "###); 318 319 insta::assert_snapshot!(render(r#"builtin_log_compact"#), @r###" 320 @ rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 321 │ (empty) (no description set) 322 ◉ qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059 323 │ (empty) (no description set) 324 ◉ zzzzzzzz root() 00000000 325 "###); 326 327 insta::assert_snapshot!(render(r#"builtin_log_comfortable"#), @r###" 328 @ rlvkpnrz (no email set) 2001-02-03 08:05:08 my-branch dc315397 329 │ (empty) (no description set) 330331 ◉ qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059 332 │ (empty) (no description set) 333334 ◉ zzzzzzzz root() 00000000 335 "###); 336 337 insta::assert_snapshot!(render(r#"builtin_log_detailed"#), @r###" 338 @ Commit ID: dc31539712c7294d1d712cec63cef4504b94ca74 339 │ Change ID: rlvkpnrzqnoowoytxnquwvuryrwnrmlp 340 │ Branches: my-branch 341 │ Author: (no name set) <(no email set)> (2001-02-03 08:05:08) 342 │ Committer: (no name set) <(no email set)> (2001-02-03 08:05:08) 343344 │  (no description set) 345346 ◉ Commit ID: 230dd059e1b059aefc0da06a2e5a7dbf22362f22 347 │ Change ID: qpvuntsmwlqtpsluzzsnyyzlmlwvmlnu 348 │ Author: Test User <test.user@example.com> (2001-02-03 08:05:07) 349 │ Committer: Test User <test.user@example.com> (2001-02-03 08:05:07) 350351 │  (no description set) 352353 ◉ Commit ID: 0000000000000000000000000000000000000000 354 Change ID: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 355 Author: (no name set) <(no email set)> (1970-01-01 11:00:00) 356 Committer: (no name set) <(no email set)> (1970-01-01 11:00:00) 357 358  (no description set) 359 360 "###); 361} 362 363#[test] 364fn test_log_obslog_divergence() { 365 let test_env = TestEnvironment::default(); 366 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 367 let repo_path = test_env.env_root().join("repo"); 368 369 std::fs::write(repo_path.join("file"), "foo\n").unwrap(); 370 test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "description 1"]); 371 let stdout = test_env.jj_cmd_success(&repo_path, &["log"]); 372 // No divergence 373 insta::assert_snapshot!(stdout, @r###" 374 @ qpvuntsm test.user@example.com 2001-02-03 08:05:08 7a17d52e 375 │ description 1 376 ◉ zzzzzzzz root() 00000000 377 "###); 378 379 // Create divergence 380 test_env.jj_cmd_ok( 381 &repo_path, 382 &["describe", "-m", "description 2", "--at-operation", "@-"], 383 ); 384 let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["log"]); 385 insta::assert_snapshot!(stdout, @r###" 386 ◉ qpvuntsm?? test.user@example.com 2001-02-03 08:05:10 8979953d 387 │ description 2 388 │ @ qpvuntsm?? test.user@example.com 2001-02-03 08:05:08 7a17d52e 389 ├─╯ description 1 390 ◉ zzzzzzzz root() 00000000 391 "###); 392 insta::assert_snapshot!(stderr, @r###" 393 Concurrent modification detected, resolving automatically. 394 "###); 395 396 // Color 397 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always"]); 398 insta::assert_snapshot!(stdout, @r###" 399 ◉ qpvuntsm?? test.user@example.com 2001-02-03 08:05:10 8979953d 400 │ description 2 401 │ @ qpvuntsm?? test.user@example.com 2001-02-03 08:05:08 7a17d52e 402 ├─╯ description 1 403 ◉ zzzzzzzz root() 00000000 404 "###); 405 406 // Obslog and hidden divergent 407 let stdout = test_env.jj_cmd_success(&repo_path, &["obslog"]); 408 insta::assert_snapshot!(stdout, @r###" 409 @ qpvuntsm?? test.user@example.com 2001-02-03 08:05:08 7a17d52e 410 │ description 1 411 ◉ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:08 3b68ce25 412 │ (no description set) 413 ◉ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059 414 (empty) (no description set) 415 "###); 416 417 // Colored obslog 418 let stdout = test_env.jj_cmd_success(&repo_path, &["obslog", "--color=always"]); 419 insta::assert_snapshot!(stdout, @r###" 420 @ qpvuntsm?? test.user@example.com 2001-02-03 08:05:08 7a17d52e 421 │ description 1 422 ◉ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:08 3b68ce25 423 │ (no description set) 424 ◉ qpvuntsm hidden test.user@example.com 2001-02-03 08:05:07 230dd059 425 (empty) (no description set) 426 "###); 427} 428 429#[test] 430fn test_log_branches() { 431 let test_env = TestEnvironment::default(); 432 test_env.add_config("git.auto-local-branch = true"); 433 test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#); 434 435 test_env.jj_cmd_ok(test_env.env_root(), &["init", "--git", "origin"]); 436 let origin_path = test_env.env_root().join("origin"); 437 let origin_git_repo_path = origin_path 438 .join(".jj") 439 .join("repo") 440 .join("store") 441 .join("git"); 442 443 // Created some branches on the remote 444 test_env.jj_cmd_ok(&origin_path, &["describe", "-m=description 1"]); 445 test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch1"]); 446 test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 2"]); 447 test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch2", "unchanged"]); 448 test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 3"]); 449 test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch3"]); 450 test_env.jj_cmd_ok(&origin_path, &["git", "export"]); 451 test_env.jj_cmd_ok( 452 test_env.env_root(), 453 &[ 454 "git", 455 "clone", 456 origin_git_repo_path.to_str().unwrap(), 457 "local", 458 ], 459 ); 460 let workspace_root = test_env.env_root().join("local"); 461 462 // Rewrite branch1, move branch2 forward, create conflict in branch3, add 463 // new-branch 464 test_env.jj_cmd_ok( 465 &workspace_root, 466 &["describe", "branch1", "-m", "modified branch1 commit"], 467 ); 468 test_env.jj_cmd_ok(&workspace_root, &["new", "branch2"]); 469 test_env.jj_cmd_ok(&workspace_root, &["branch", "set", "branch2"]); 470 test_env.jj_cmd_ok(&workspace_root, &["branch", "create", "new-branch"]); 471 test_env.jj_cmd_ok(&workspace_root, &["describe", "branch3", "-m=local"]); 472 test_env.jj_cmd_ok(&origin_path, &["describe", "branch3", "-m=origin"]); 473 test_env.jj_cmd_ok(&origin_path, &["git", "export"]); 474 test_env.jj_cmd_ok(&workspace_root, &["git", "fetch"]); 475 476 let template = r#"commit_id.short() ++ " " ++ if(branches, branches, "(no branches)")"#; 477 let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]); 478 insta::assert_snapshot!(output, @r###" 479 ◉ fed794e2ba44 branch3?? branch3@origin 480 │ ◉ b1bb3766d584 branch3?? 481 ├─╯ 482 │ ◉ 21c33875443e branch1* 483 ├─╯ 484 │ @ a5b4d15489cc branch2* new-branch 485 │ ◉ 8476341eb395 branch2@origin unchanged 486 ├─╯ 487 ◉ 000000000000 (no branches) 488 "###); 489 490 let template = r#"branches.map(|b| separate("/", b.remote(), b.name())).join(", ")"#; 491 let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]); 492 insta::assert_snapshot!(output, @r###" 493 ◉ branch3, origin/branch3 494 │ ◉ branch3 495 ├─╯ 496 │ ◉ branch1 497 ├─╯ 498 │ @ branch2, new-branch 499 │ ◉ origin/branch2, unchanged 500 ├─╯ 501502 "###); 503 504 let template = r#"separate(" ", "L:", local_branches, "R:", remote_branches)"#; 505 let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]); 506 insta::assert_snapshot!(output, @r###" 507 ◉ L: branch3?? R: branch3@origin 508 │ ◉ L: branch3?? R: 509 ├─╯ 510 │ ◉ L: branch1* R: 511 ├─╯ 512 │ @ L: branch2* new-branch R: 513 │ ◉ L: unchanged R: branch2@origin unchanged@origin 514 ├─╯ 515 ◉ L: R: 516 "###); 517} 518 519#[test] 520fn test_log_git_head() { 521 let test_env = TestEnvironment::default(); 522 let repo_path = test_env.env_root().join("repo"); 523 git2::Repository::init(&repo_path).unwrap(); 524 test_env.jj_cmd_ok(&repo_path, &["init", "--git-repo=."]); 525 526 test_env.jj_cmd_ok(&repo_path, &["new", "-m=initial"]); 527 std::fs::write(repo_path.join("file"), "foo\n").unwrap(); 528 529 let template = r#" 530 separate(", ", 531 if(git_head, "name: " ++ git_head.name()), 532 "remote: " ++ git_head.remote(), 533 ) ++ "\n" 534 "#; 535 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", template]); 536 insta::assert_snapshot!(stdout, @r###" 537 @ remote: <Error: No RefName available> 538 ◉ name: HEAD, remote: git 539 ◉ remote: <Error: No RefName available> 540 "###); 541 542 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "--color=always"]); 543 insta::assert_snapshot!(stdout, @r###" 544 @ rlvkpnrz test.user@example.com 2001-02-03 08:05:09 50aaf475 545 │ initial 546 ◉ qpvuntsm test.user@example.com 2001-02-03 08:05:07 HEAD@git 230dd059 547 │ (empty) (no description set) 548 ◉ zzzzzzzz root() 00000000 549 "###); 550} 551 552#[test] 553fn test_log_customize_short_id() { 554 let test_env = TestEnvironment::default(); 555 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 556 let repo_path = test_env.env_root().join("repo"); 557 558 test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "first"]); 559 560 // Customize both the commit and the change id 561 let decl = "template-aliases.'format_short_id(id)'"; 562 let stdout = test_env.jj_cmd_success( 563 &repo_path, 564 &[ 565 "log", 566 "--config-toml", 567 &format!(r#"{decl}='id.shortest(5).prefix().upper() ++ "_" ++ id.shortest(5).rest()'"#), 568 ], 569 ); 570 insta::assert_snapshot!(stdout, @r###" 571 @ Q_pvun test.user@example.com 2001-02-03 08:05:08 6_9542 572 │ (empty) first 573 ◉ Z_zzzz root() 0_0000 574 "###); 575 576 // Customize only the change id 577 let stdout = test_env.jj_cmd_success( 578 &repo_path, 579 &[ 580 "log", 581 "--config-toml", 582 r#" 583 [template-aliases] 584 'format_short_change_id(id)'='format_short_id(id).upper()' 585 "#, 586 ], 587 ); 588 insta::assert_snapshot!(stdout, @r###" 589 @ QPVUNTSM test.user@example.com 2001-02-03 08:05:08 69542c19 590 │ (empty) first 591 ◉ ZZZZZZZZ root() 00000000 592 "###); 593} 594 595#[test] 596fn test_log_immutable() { 597 let test_env = TestEnvironment::default(); 598 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 599 let repo_path = test_env.env_root().join("repo"); 600 test_env.jj_cmd_ok(&repo_path, &["new", "-mA", "root()"]); 601 test_env.jj_cmd_ok(&repo_path, &["new", "-mB"]); 602 test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]); 603 test_env.jj_cmd_ok(&repo_path, &["new", "-mC"]); 604 test_env.jj_cmd_ok(&repo_path, &["new", "-mD", "root()"]); 605 606 let template = r#" 607 separate(" ", 608 description.first_line(), 609 branches, 610 if(immutable, "[immutable]"), 611 ) ++ "\n" 612 "#; 613 614 test_env.add_config("revset-aliases.'immutable_heads()' = 'main'"); 615 let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-r::", "-T", template]); 616 insta::assert_snapshot!(stdout, @r###" 617 @ D 618 │ ◉ C 619 │ ◉ B main [immutable] 620 │ ◉ A [immutable] 621 ├─╯ 622 ◉ [immutable] 623 "###); 624 625 // Suppress error that could be detected earlier 626 test_env.add_config("revsets.short-prefixes = ''"); 627 628 test_env.add_config("revset-aliases.'immutable_heads()' = 'unknown_fn()'"); 629 let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r::", "-T", template]); 630 insta::assert_snapshot!(stderr, @r###" 631 Error: Failed to parse template: Failed to parse revset 632 Caused by: 633 1: --> 5:10 634 | 635 5 | if(immutable, "[immutable]"), 636 | ^-------^ 637 | 638 = Failed to parse revset 639 2: --> 1:1 640 | 641 1 | unknown_fn() 642 | ^--------^ 643 | 644 = Function "unknown_fn" doesn't exist 645 "###); 646 647 test_env.add_config("revset-aliases.'immutable_heads()' = 'unknown_symbol'"); 648 let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r::", "-T", template]); 649 insta::assert_snapshot!(stderr, @r###" 650 Error: Failed to parse template: Failed to evaluate revset 651 Caused by: 652 1: --> 5:10 653 | 654 5 | if(immutable, "[immutable]"), 655 | ^-------^ 656 | 657 = Failed to evaluate revset 658 2: Revision "unknown_symbol" doesn't exist 659 "###); 660} 661 662#[test] 663fn test_log_contained_in() { 664 let test_env = TestEnvironment::default(); 665 test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]); 666 let repo_path = test_env.env_root().join("repo"); 667 test_env.jj_cmd_ok(&repo_path, &["new", "-mA", "root()"]); 668 test_env.jj_cmd_ok(&repo_path, &["new", "-mB"]); 669 test_env.jj_cmd_ok(&repo_path, &["branch", "create", "main"]); 670 test_env.jj_cmd_ok(&repo_path, &["new", "-mC"]); 671 test_env.jj_cmd_ok(&repo_path, &["new", "-mD", "root()"]); 672 673 let template_for_revset = |revset: &str| { 674 format!( 675 r#" 676 separate(" ", 677 description.first_line(), 678 branches, 679 if(self.contained_in("{revset}"), "[contained_in]"), 680 ) ++ "\n" 681 "# 682 ) 683 }; 684 685 let stdout = test_env.jj_cmd_success( 686 &repo_path, 687 &[ 688 "log", 689 "-r::", 690 "-T", 691 &template_for_revset(r#"description(A)::"#), 692 ], 693 ); 694 insta::assert_snapshot!(stdout, @r###" 695 @ D 696 │ ◉ C [contained_in] 697 │ ◉ B main [contained_in] 698 │ ◉ A [contained_in] 699 ├─╯ 700701 "###); 702 703 let stdout = test_env.jj_cmd_success( 704 &repo_path, 705 &[ 706 "log", 707 "-r::", 708 "-T", 709 &template_for_revset(r#"visible_heads()"#), 710 ], 711 ); 712 insta::assert_snapshot!(stdout, @r###" 713 @ D [contained_in] 714 │ ◉ C [contained_in] 715 │ ◉ B main 716 │ ◉ A 717 ├─╯ 718719 "###); 720 721 // Suppress error that could be detected earlier 722 let stderr = test_env.jj_cmd_failure( 723 &repo_path, 724 &["log", "-r::", "-T", &template_for_revset("unknown_fn()")], 725 ); 726 insta::assert_snapshot!(stderr, @r###" 727 Error: Failed to parse template: Failed to parse revset 728 Caused by: 729 1: --> 5:28 730 | 731 5 | if(self.contained_in("unknown_fn()"), "[contained_in]"), 732 | ^------------^ 733 | 734 = Failed to parse revset 735 2: --> 1:1 736 | 737 1 | unknown_fn() 738 | ^--------^ 739 | 740 = Function "unknown_fn" doesn't exist 741 "###); 742 743 let stderr = test_env.jj_cmd_failure( 744 &repo_path, 745 &["log", "-r::", "-T", &template_for_revset("author(x:'y')")], 746 ); 747 insta::assert_snapshot!(stderr, @r###" 748 Error: Failed to parse template: Failed to parse revset 749 Caused by: 750 1: --> 5:28 751 | 752 5 | if(self.contained_in("author(x:'y')"), "[contained_in]"), 753 | ^-------------^ 754 | 755 = Failed to parse revset 756 2: --> 1:8 757 | 758 1 | author(x:'y') 759 | ^---^ 760 | 761 = Function "author": Invalid string pattern 762 3: Invalid string pattern kind "x:" 763 Hint: Try prefixing with one of `exact:`, `glob:` or `substring:` 764 "###); 765 766 let stderr = test_env.jj_cmd_failure( 767 &repo_path, 768 &["log", "-r::", "-T", &template_for_revset("maine")], 769 ); 770 insta::assert_snapshot!(stderr, @r###" 771 Error: Failed to parse template: Failed to evaluate revset 772 Caused by: 773 1: --> 5:28 774 | 775 5 | if(self.contained_in("maine"), "[contained_in]"), 776 | ^-----^ 777 | 778 = Failed to evaluate revset 779 2: Revision "maine" doesn't exist 780 Hint: Did you mean "main"? 781 "###); 782}