just playing with tangled
at ig/vimdiffwarn 849 lines 25 kB view raw
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::TestEnvironment; 16 17#[test] 18fn test_syntax_error() { 19 let test_env = TestEnvironment::default(); 20 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 21 let work_dir = test_env.work_dir("repo"); 22 23 let output = work_dir.run_jj(["log", "-r", ":x"]); 24 insta::assert_snapshot!(output, @r" 25 ------- stderr ------- 26 Error: Failed to parse revset: `:` is not a prefix operator 27 Caused by: --> 1:1 28 | 29 1 | :x 30 | ^ 31 | 32 = `:` is not a prefix operator 33 Hint: Did you mean `::` for ancestors? 34 [EOF] 35 [exit status: 1] 36 "); 37 38 let output = work_dir.run_jj(["log", "-r", "x &"]); 39 insta::assert_snapshot!(output, @r" 40 ------- stderr ------- 41 Error: Failed to parse revset: Syntax error 42 Caused by: --> 1:4 43 | 44 1 | x & 45 | ^--- 46 | 47 = expected `::`, `..`, `~`, or <primary> 48 Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for revsets syntax and how to quote symbols. 49 [EOF] 50 [exit status: 1] 51 "); 52 53 let output = work_dir.run_jj(["log", "-r", "x - y"]); 54 insta::assert_snapshot!(output, @r" 55 ------- stderr ------- 56 Error: Failed to parse revset: `-` is not an infix operator 57 Caused by: --> 1:3 58 | 59 1 | x - y 60 | ^ 61 | 62 = `-` is not an infix operator 63 Hint: Did you mean `~` for difference? 64 [EOF] 65 [exit status: 1] 66 "); 67 68 let output = work_dir.run_jj(["log", "-r", "HEAD^"]); 69 insta::assert_snapshot!(output, @r" 70 ------- stderr ------- 71 Error: Failed to parse revset: `^` is not a postfix operator 72 Caused by: --> 1:5 73 | 74 1 | HEAD^ 75 | ^ 76 | 77 = `^` is not a postfix operator 78 Hint: Did you mean `-` for parents? 79 [EOF] 80 [exit status: 1] 81 "); 82} 83 84#[test] 85fn test_bad_function_call() { 86 let test_env = TestEnvironment::default(); 87 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 88 let work_dir = test_env.work_dir("repo"); 89 90 let output = work_dir.run_jj(["log", "-r", "all(or::nothing)"]); 91 insta::assert_snapshot!(output, @r" 92 ------- stderr ------- 93 Error: Failed to parse revset: Function `all`: Expected 0 arguments 94 Caused by: --> 1:5 95 | 96 1 | all(or::nothing) 97 | ^---------^ 98 | 99 = Function `all`: Expected 0 arguments 100 [EOF] 101 [exit status: 1] 102 "); 103 104 let output = work_dir.run_jj(["log", "-r", "parents()"]); 105 insta::assert_snapshot!(output, @r" 106 ------- stderr ------- 107 Error: Failed to parse revset: Function `parents`: Expected 1 arguments 108 Caused by: --> 1:9 109 | 110 1 | parents() 111 | ^ 112 | 113 = Function `parents`: Expected 1 arguments 114 [EOF] 115 [exit status: 1] 116 "); 117 118 let output = work_dir.run_jj(["log", "-r", "parents(foo, bar)"]); 119 insta::assert_snapshot!(output, @r" 120 ------- stderr ------- 121 Error: Failed to parse revset: Function `parents`: Expected 1 arguments 122 Caused by: --> 1:9 123 | 124 1 | parents(foo, bar) 125 | ^------^ 126 | 127 = Function `parents`: Expected 1 arguments 128 [EOF] 129 [exit status: 1] 130 "); 131 132 let output = work_dir.run_jj(["log", "-r", "heads(foo, bar)"]); 133 insta::assert_snapshot!(output, @r" 134 ------- stderr ------- 135 Error: Failed to parse revset: Function `heads`: Expected 1 arguments 136 Caused by: --> 1:7 137 | 138 1 | heads(foo, bar) 139 | ^------^ 140 | 141 = Function `heads`: Expected 1 arguments 142 [EOF] 143 [exit status: 1] 144 "); 145 146 let output = work_dir.run_jj(["log", "-r", "latest(a, not_an_integer)"]); 147 insta::assert_snapshot!(output, @r" 148 ------- stderr ------- 149 Error: Failed to parse revset: Expected expression of type integer 150 Caused by: --> 1:11 151 | 152 1 | latest(a, not_an_integer) 153 | ^------------^ 154 | 155 = Expected expression of type integer 156 [EOF] 157 [exit status: 1] 158 "); 159 160 // "N to M arguments" 161 let output = work_dir.run_jj(["log", "-r", "ancestors()"]); 162 insta::assert_snapshot!(output, @r" 163 ------- stderr ------- 164 Error: Failed to parse revset: Function `ancestors`: Expected 1 to 2 arguments 165 Caused by: --> 1:11 166 | 167 1 | ancestors() 168 | ^ 169 | 170 = Function `ancestors`: Expected 1 to 2 arguments 171 [EOF] 172 [exit status: 1] 173 "); 174 175 let output = work_dir.run_jj(["log", "-r", "files(not::a-fileset)"]); 176 insta::assert_snapshot!(output, @r" 177 ------- stderr ------- 178 Error: Failed to parse revset: In fileset expression 179 Caused by: 180 1: --> 1:7 181 | 182 1 | files(not::a-fileset) 183 | ^------------^ 184 | 185 = In fileset expression 186 2: --> 1:5 187 | 188 1 | not::a-fileset 189 | ^--- 190 | 191 = expected <identifier>, <string_literal>, or <raw_string_literal> 192 Hint: See https://jj-vcs.github.io/jj/latest/filesets/ or use `jj help -k filesets` for filesets syntax and how to match file paths. 193 [EOF] 194 [exit status: 1] 195 "); 196 197 let output = work_dir.run_jj(["log", "-r", r#"files(foo:"bar")"#]); 198 insta::assert_snapshot!(output, @r#" 199 ------- stderr ------- 200 Error: Failed to parse revset: In fileset expression 201 Caused by: 202 1: --> 1:7 203 | 204 1 | files(foo:"bar") 205 | ^-------^ 206 | 207 = In fileset expression 208 2: --> 1:1 209 | 210 1 | foo:"bar" 211 | ^-------^ 212 | 213 = Invalid file pattern 214 3: Invalid file pattern kind `foo:` 215 Hint: See https://jj-vcs.github.io/jj/latest/filesets/#file-patterns or `jj help -k filesets` for valid prefixes. 216 [EOF] 217 [exit status: 1] 218 "#); 219 220 let output = work_dir.run_jj(["log", "-r", r#"files("../out")"#]); 221 insta::assert_snapshot!(output.normalize_backslash(), @r#" 222 ------- stderr ------- 223 Error: Failed to parse revset: In fileset expression 224 Caused by: 225 1: --> 1:7 226 | 227 1 | files("../out") 228 | ^------^ 229 | 230 = In fileset expression 231 2: --> 1:1 232 | 233 1 | "../out" 234 | ^------^ 235 | 236 = Invalid file pattern 237 3: Path "../out" is not in the repo "." 238 4: Invalid component ".." in repo-relative path "../out" 239 [EOF] 240 [exit status: 1] 241 "#); 242 243 let output = work_dir.run_jj(["log", "-r", "bookmarks(bad:pattern)"]); 244 insta::assert_snapshot!(output, @r" 245 ------- stderr ------- 246 Error: Failed to parse revset: Invalid string pattern 247 Caused by: 248 1: --> 1:11 249 | 250 1 | bookmarks(bad:pattern) 251 | ^---------^ 252 | 253 = Invalid string pattern 254 2: Invalid string pattern kind `bad:` 255 Hint: Try prefixing with one of `exact:`, `glob:`, `regex:`, `substring:`, or one of these with `-i` suffix added (e.g. `glob-i:`) for case-insensitive matching 256 [EOF] 257 [exit status: 1] 258 "); 259 260 let output = work_dir.run_jj(["log", "-r", "bookmarks(regex:'(')"]); 261 insta::assert_snapshot!(output, @r" 262 ------- stderr ------- 263 Error: Failed to parse revset: Invalid string pattern 264 Caused by: 265 1: --> 1:11 266 | 267 1 | bookmarks(regex:'(') 268 | ^-------^ 269 | 270 = Invalid string pattern 271 2: regex parse error: 272 ( 273 ^ 274 error: unclosed group 275 [EOF] 276 [exit status: 1] 277 "); 278 279 let output = work_dir.run_jj(["log", "-r", "root()::whatever()"]); 280 insta::assert_snapshot!(output, @r" 281 ------- stderr ------- 282 Error: Failed to parse revset: Function `whatever` doesn't exist 283 Caused by: --> 1:9 284 | 285 1 | root()::whatever() 286 | ^------^ 287 | 288 = Function `whatever` doesn't exist 289 [EOF] 290 [exit status: 1] 291 "); 292 293 let output = work_dir.run_jj(["log", "-r", "remote_bookmarks(a, b, remote=c)"]); 294 insta::assert_snapshot!(output, @r#" 295 ------- stderr ------- 296 Error: Failed to parse revset: Function `remote_bookmarks`: Got multiple values for keyword "remote" 297 Caused by: --> 1:24 298 | 299 1 | remote_bookmarks(a, b, remote=c) 300 | ^------^ 301 | 302 = Function `remote_bookmarks`: Got multiple values for keyword "remote" 303 [EOF] 304 [exit status: 1] 305 "#); 306 307 let output = work_dir.run_jj(["log", "-r", "remote_bookmarks(remote=a, b)"]); 308 insta::assert_snapshot!(output, @r" 309 ------- stderr ------- 310 Error: Failed to parse revset: Function `remote_bookmarks`: Positional argument follows keyword argument 311 Caused by: --> 1:28 312 | 313 1 | remote_bookmarks(remote=a, b) 314 | ^ 315 | 316 = Function `remote_bookmarks`: Positional argument follows keyword argument 317 [EOF] 318 [exit status: 1] 319 "); 320 321 let output = work_dir.run_jj(["log", "-r", "remote_bookmarks(=foo)"]); 322 insta::assert_snapshot!(output, @r" 323 ------- stderr ------- 324 Error: Failed to parse revset: Syntax error 325 Caused by: --> 1:18 326 | 327 1 | remote_bookmarks(=foo) 328 | ^--- 329 | 330 = expected <strict_identifier> or <expression> 331 Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for revsets syntax and how to quote symbols. 332 [EOF] 333 [exit status: 1] 334 "); 335 336 let output = work_dir.run_jj(["log", "-r", "remote_bookmarks(remote=)"]); 337 insta::assert_snapshot!(output, @r" 338 ------- stderr ------- 339 Error: Failed to parse revset: Syntax error 340 Caused by: --> 1:25 341 | 342 1 | remote_bookmarks(remote=) 343 | ^--- 344 | 345 = expected <expression> 346 Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for revsets syntax and how to quote symbols. 347 [EOF] 348 [exit status: 1] 349 "); 350} 351 352#[test] 353fn test_function_name_hint() { 354 let test_env = TestEnvironment::default(); 355 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 356 let work_dir = test_env.work_dir("repo"); 357 let evaluate = |expr| work_dir.run_jj(["log", "-r", expr]); 358 359 test_env.add_config( 360 r###" 361 [revset-aliases] 362 'bookmarks(x)' = 'x' # override builtin function 363 'my_author(x)' = 'author(x)' # similar name to builtin function 364 'author_sym' = 'x' # not a function alias 365 'my_bookmarks' = 'bookmark()' # typo in alias 366 "###, 367 ); 368 369 // The suggestion "bookmarks" shouldn't be duplicated 370 insta::assert_snapshot!(evaluate("bookmark()"), @r" 371 ------- stderr ------- 372 Error: Failed to parse revset: Function `bookmark` doesn't exist 373 Caused by: --> 1:1 374 | 375 1 | bookmark() 376 | ^------^ 377 | 378 = Function `bookmark` doesn't exist 379 Hint: Did you mean `bookmarks`, `remote_bookmarks`? 380 [EOF] 381 [exit status: 1] 382 "); 383 384 // Both builtin function and function alias should be suggested 385 insta::assert_snapshot!(evaluate("author_()"), @r" 386 ------- stderr ------- 387 Error: Failed to parse revset: Function `author_` doesn't exist 388 Caused by: --> 1:1 389 | 390 1 | author_() 391 | ^-----^ 392 | 393 = Function `author_` doesn't exist 394 Hint: Did you mean `author`, `author_date`, `author_email`, `author_name`, `my_author`? 395 [EOF] 396 [exit status: 1] 397 "); 398 399 insta::assert_snapshot!(evaluate("my_bookmarks"), @r" 400 ------- stderr ------- 401 Error: Failed to parse revset: In alias `my_bookmarks` 402 Caused by: 403 1: --> 1:1 404 | 405 1 | my_bookmarks 406 | ^----------^ 407 | 408 = In alias `my_bookmarks` 409 2: --> 1:1 410 | 411 1 | bookmark() 412 | ^------^ 413 | 414 = Function `bookmark` doesn't exist 415 Hint: Did you mean `bookmarks`, `remote_bookmarks`? 416 [EOF] 417 [exit status: 1] 418 "); 419} 420 421#[test] 422fn test_alias() { 423 let test_env = TestEnvironment::default(); 424 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 425 let work_dir = test_env.work_dir("repo"); 426 427 test_env.add_config( 428 r###" 429 [revset-aliases] 430 'my-root' = 'root()' 431 'syntax-error' = 'whatever &' 432 'recurse' = 'recurse1' 433 'recurse1' = 'recurse2()' 434 'recurse2()' = 'recurse' 435 'identity(x)' = 'x' 436 'my_author(x)' = 'author(x)' 437 "###, 438 ); 439 440 let output = work_dir.run_jj(["log", "-r", "my-root"]); 441 insta::assert_snapshot!(output, @r" 442 ◆ zzzzzzzz root() 00000000 443 [EOF] 444 "); 445 446 let output = work_dir.run_jj(["log", "-r", "identity(my-root)"]); 447 insta::assert_snapshot!(output, @r" 448 ◆ zzzzzzzz root() 00000000 449 [EOF] 450 "); 451 452 let output = work_dir.run_jj(["log", "-r", "root() & syntax-error"]); 453 insta::assert_snapshot!(output, @r" 454 ------- stderr ------- 455 Error: Failed to parse revset: In alias `syntax-error` 456 Caused by: 457 1: --> 1:10 458 | 459 1 | root() & syntax-error 460 | ^----------^ 461 | 462 = In alias `syntax-error` 463 2: --> 1:11 464 | 465 1 | whatever & 466 | ^--- 467 | 468 = expected `::`, `..`, `~`, or <primary> 469 Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for revsets syntax and how to quote symbols. 470 [EOF] 471 [exit status: 1] 472 "); 473 474 let output = work_dir.run_jj(["log", "-r", "identity()"]); 475 insta::assert_snapshot!(output, @r" 476 ------- stderr ------- 477 Error: Failed to parse revset: Function `identity`: Expected 1 arguments 478 Caused by: --> 1:10 479 | 480 1 | identity() 481 | ^ 482 | 483 = Function `identity`: Expected 1 arguments 484 [EOF] 485 [exit status: 1] 486 "); 487 488 let output = work_dir.run_jj(["log", "-r", "my_author(none())"]); 489 insta::assert_snapshot!(output, @r" 490 ------- stderr ------- 491 Error: Failed to parse revset: In alias `my_author(x)` 492 Caused by: 493 1: --> 1:1 494 | 495 1 | my_author(none()) 496 | ^---------------^ 497 | 498 = In alias `my_author(x)` 499 2: --> 1:8 500 | 501 1 | author(x) 502 | ^ 503 | 504 = In function parameter `x` 505 3: --> 1:11 506 | 507 1 | my_author(none()) 508 | ^----^ 509 | 510 = Expected expression of string pattern 511 [EOF] 512 [exit status: 1] 513 "); 514 515 let output = work_dir.run_jj(["log", "-r", "root() & recurse"]); 516 insta::assert_snapshot!(output, @r" 517 ------- stderr ------- 518 Error: Failed to parse revset: In alias `recurse` 519 Caused by: 520 1: --> 1:10 521 | 522 1 | root() & recurse 523 | ^-----^ 524 | 525 = In alias `recurse` 526 2: --> 1:1 527 | 528 1 | recurse1 529 | ^------^ 530 | 531 = In alias `recurse1` 532 3: --> 1:1 533 | 534 1 | recurse2() 535 | ^--------^ 536 | 537 = In alias `recurse2()` 538 4: --> 1:1 539 | 540 1 | recurse 541 | ^-----^ 542 | 543 = Alias `recurse` expanded recursively 544 [EOF] 545 [exit status: 1] 546 "); 547} 548 549#[test] 550fn test_alias_override() { 551 let test_env = TestEnvironment::default(); 552 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 553 let work_dir = test_env.work_dir("repo"); 554 555 test_env.add_config( 556 r###" 557 [revset-aliases] 558 'f(x)' = 'user' 559 "###, 560 ); 561 562 // 'f(x)' should be overridden by --config 'f(a)'. If aliases were sorted 563 // purely by name, 'f(a)' would come first. 564 let output = work_dir.run_jj(["log", "-r", "f(_)", "--config=revset-aliases.'f(a)'=arg"]); 565 insta::assert_snapshot!(output, @r" 566 ------- stderr ------- 567 Error: Revision `arg` doesn't exist 568 [EOF] 569 [exit status: 1] 570 "); 571} 572 573#[test] 574fn test_bad_alias_decl() { 575 let test_env = TestEnvironment::default(); 576 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 577 let work_dir = test_env.work_dir("repo"); 578 579 test_env.add_config( 580 r#" 581 [revset-aliases] 582 'my-root' = 'root()' 583 '"bad"' = 'root()' 584 'badfn(a, a)' = 'root()' 585 "#, 586 ); 587 588 // Invalid declaration should be warned and ignored. 589 let output = work_dir.run_jj(["log", "-r", "my-root"]); 590 insta::assert_snapshot!(output, @r#" 591 ◆ zzzzzzzz root() 00000000 592 [EOF] 593 ------- stderr ------- 594 Warning: Failed to load `revset-aliases."bad"`: --> 1:1 595 | 596 1 | "bad" 597 | ^--- 598 | 599 = expected <strict_identifier> or <function_name> 600 Warning: Failed to load `revset-aliases.badfn(a, a)`: --> 1:7 601 | 602 1 | badfn(a, a) 603 | ^--^ 604 | 605 = Redefinition of function parameter 606 [EOF] 607 "#); 608} 609 610#[test] 611fn test_all_modifier() { 612 let test_env = TestEnvironment::default(); 613 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 614 let work_dir = test_env.work_dir("repo"); 615 616 // Command that accepts single revision by default 617 let output = work_dir.run_jj(["new", "all()"]); 618 insta::assert_snapshot!(output, @r" 619 ------- stderr ------- 620 Error: Revset `all()` resolved to more than one revision 621 Hint: The revset `all()` resolved to these revisions: 622 qpvuntsm 230dd059 (empty) (no description set) 623 zzzzzzzz 00000000 (empty) (no description set) 624 Hint: Prefix the expression with `all:` to allow any number of revisions (i.e. `all:all()`). 625 [EOF] 626 [exit status: 1] 627 "); 628 let output = work_dir.run_jj(["new", "all:all()"]); 629 insta::assert_snapshot!(output, @r" 630 ------- stderr ------- 631 Error: The Git backend does not support creating merge commits with the root commit as one of the parents. 632 [EOF] 633 [exit status: 1] 634 "); 635 636 // Command that accepts multiple revisions by default 637 let output = work_dir.run_jj(["log", "-rall:all()"]); 638 insta::assert_snapshot!(output, @r" 639 @ qpvuntsm test.user@example.com 2001-02-03 08:05:07 230dd059 640 │ (empty) (no description set) 641 ◆ zzzzzzzz root() 00000000 642 [EOF] 643 "); 644 645 // Command that accepts only single revision 646 let output = work_dir.run_jj(["bookmark", "create", "-rall:@", "x"]); 647 insta::assert_snapshot!(output, @r" 648 ------- stderr ------- 649 Created 1 bookmarks pointing to qpvuntsm 230dd059 x | (empty) (no description set) 650 [EOF] 651 "); 652 let output = work_dir.run_jj(["bookmark", "set", "-rall:all()", "x"]); 653 insta::assert_snapshot!(output, @r" 654 ------- stderr ------- 655 Error: Revset `all:all()` resolved to more than one revision 656 Hint: The revset `all:all()` resolved to these revisions: 657 qpvuntsm 230dd059 x | (empty) (no description set) 658 zzzzzzzz 00000000 (empty) (no description set) 659 [EOF] 660 [exit status: 1] 661 "); 662 663 // Template expression that accepts multiple revisions by default 664 let output = work_dir.run_jj(["log", "-Tself.contained_in('all:all()')"]); 665 insta::assert_snapshot!(output, @r" 666 @ true 667 ◆ true 668 [EOF] 669 "); 670 671 // Typo 672 let output = work_dir.run_jj(["new", "ale:x"]); 673 insta::assert_snapshot!(output, @r" 674 ------- stderr ------- 675 Error: Failed to parse revset: Modifier `ale` doesn't exist 676 Caused by: --> 1:1 677 | 678 1 | ale:x 679 | ^-^ 680 | 681 = Modifier `ale` doesn't exist 682 [EOF] 683 [exit status: 1] 684 "); 685 686 // Modifier shouldn't be allowed in sub expression 687 let output = work_dir.run_jj(["new", "x..", "--config=revset-aliases.x='all:@'"]); 688 insta::assert_snapshot!(output, @r" 689 ------- stderr ------- 690 Error: Failed to parse revset: In alias `x` 691 Caused by: 692 1: --> 1:1 693 | 694 1 | x.. 695 | ^ 696 | 697 = In alias `x` 698 2: --> 1:1 699 | 700 1 | all:@ 701 | ^-^ 702 | 703 = Modifier `all:` is not allowed in sub expression 704 [EOF] 705 [exit status: 1] 706 "); 707 708 // immutable_heads() alias may be parsed as a top-level expression, but 709 // still, modifier shouldn't be allowed there. 710 let output = work_dir.run_jj([ 711 "new", 712 "--config=revset-aliases.'immutable_heads()'='all:@'", 713 "--config=revsets.short-prefixes='none()'", 714 ]); 715 insta::assert_snapshot!(output, @r" 716 ------- stderr ------- 717 Config error: Invalid `revset-aliases.immutable_heads()` 718 Caused by: --> 1:1 719 | 720 1 | all:@ 721 | ^-^ 722 | 723 = Modifier `all:` is not allowed in sub expression 724 For help, see https://jj-vcs.github.io/jj/latest/config/ or use `jj help -k config`. 725 [EOF] 726 [exit status: 1] 727 "); 728} 729 730/// Verifies that the committer_date revset honors the local time zone. 731/// This test cannot run on Windows because The TZ env var does not control 732/// chrono::Local on that platform. 733#[test] 734#[cfg(not(target_os = "windows"))] 735fn test_revset_committer_date_with_time_zone() { 736 // Use these for the test instead of tzdb identifiers like America/New_York 737 // because the tz database may not be installed on some build servers 738 const NEW_YORK: &str = "EST+5EDT+4,M3.1.0,M11.1.0"; 739 const CHICAGO: &str = "CST+6CDT+5,M3.1.0,M11.1.0"; 740 const AUSTRALIA: &str = "AEST-10"; 741 let mut test_env = TestEnvironment::default(); 742 test_env.add_env_var("TZ", NEW_YORK); 743 test_env.run_jj_in(".", ["git", "init", "repo"]).success(); 744 let work_dir = test_env.work_dir("repo"); 745 746 work_dir 747 .run_jj([ 748 "--config=debug.commit-timestamp=2023-01-25T11:30:00-05:00", 749 "describe", 750 "-m", 751 "first", 752 ]) 753 .success(); 754 work_dir 755 .run_jj([ 756 "--config=debug.commit-timestamp=2023-01-25T12:30:00-05:00", 757 "new", 758 "-m", 759 "second", 760 ]) 761 .success(); 762 work_dir 763 .run_jj([ 764 "--config=debug.commit-timestamp=2023-01-25T13:30:00-05:00", 765 "new", 766 "-m", 767 "third", 768 ]) 769 .success(); 770 771 let mut log_commits_before_and_after = |committer_date: &str, now: &str, tz: &str| { 772 test_env.add_env_var("TZ", tz); 773 let config = format!("debug.commit-timestamp={now}"); 774 let work_dir = test_env.work_dir("repo"); 775 let before_log = work_dir.run_jj([ 776 "--config", 777 config.as_str(), 778 "log", 779 "--no-graph", 780 "-T", 781 "description.first_line() ++ ' ' ++ committer.timestamp() ++ '\n'", 782 "-r", 783 format!("committer_date(before:'{committer_date}') ~ root()").as_str(), 784 ]); 785 let after_log = work_dir.run_jj([ 786 "--config", 787 config.as_str(), 788 "log", 789 "--no-graph", 790 "-T", 791 "description.first_line() ++ ' ' ++ committer.timestamp() ++ '\n'", 792 "-r", 793 format!("committer_date(after:'{committer_date}')").as_str(), 794 ]); 795 (before_log, after_log) 796 }; 797 798 let (before_log, after_log) = 799 log_commits_before_and_after("2023-01-25 12:00", "2023-02-01T00:00:00-05:00", NEW_YORK); 800 insta::assert_snapshot!(before_log, @r" 801 first 2023-01-25 11:30:00.000 -05:00 802 [EOF] 803 "); 804 insta::assert_snapshot!(after_log, @r" 805 third 2023-01-25 13:30:00.000 -05:00 806 second 2023-01-25 12:30:00.000 -05:00 807 [EOF] 808 "); 809 810 // Switch to DST and ensure we get the same results, because it should 811 // evaluate 12:00 on commit date, not the current date 812 let (before_log, after_log) = 813 log_commits_before_and_after("2023-01-25 12:00", "2023-06-01T00:00:00-04:00", NEW_YORK); 814 insta::assert_snapshot!(before_log, @r" 815 first 2023-01-25 11:30:00.000 -05:00 816 [EOF] 817 "); 818 insta::assert_snapshot!(after_log, @r" 819 third 2023-01-25 13:30:00.000 -05:00 820 second 2023-01-25 12:30:00.000 -05:00 821 [EOF] 822 "); 823 824 // Change the local time zone and ensure the result changes 825 let (before_log, after_log) = 826 log_commits_before_and_after("2023-01-25 12:00", "2023-06-01T00:00:00-06:00", CHICAGO); 827 insta::assert_snapshot!(before_log, @r" 828 second 2023-01-25 12:30:00.000 -05:00 829 first 2023-01-25 11:30:00.000 -05:00 830 [EOF] 831 "); 832 insta::assert_snapshot!(after_log, @r" 833 third 2023-01-25 13:30:00.000 -05:00 834 [EOF] 835 "); 836 837 // Time zone far outside USA with no DST 838 let (before_log, after_log) = 839 log_commits_before_and_after("2023-01-26 03:00", "2023-06-01T00:00:00+10:00", AUSTRALIA); 840 insta::assert_snapshot!(before_log, @r" 841 first 2023-01-25 11:30:00.000 -05:00 842 [EOF] 843 "); 844 insta::assert_snapshot!(after_log, @r" 845 third 2023-01-25 13:30:00.000 -05:00 846 second 2023-01-25 12:30:00.000 -05:00 847 [EOF] 848 "); 849}