| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='git command aliasing' |
| 4 | |
| 5 | . ./test-lib.sh |
| 6 | |
| 7 | test_expect_success 'nested aliases - internal execution' ' |
| 8 | git config alias.nested-internal-1 nested-internal-2 && |
| 9 | git config alias.nested-internal-2 status && |
| 10 | git nested-internal-1 >output && |
| 11 | test_grep "^On branch " output |
| 12 | ' |
| 13 | |
| 14 | test_expect_success 'nested aliases - mixed execution' ' |
| 15 | git config alias.nested-external-1 nested-external-2 && |
| 16 | git config alias.nested-external-2 "!git nested-external-3" && |
| 17 | git config alias.nested-external-3 status && |
| 18 | git nested-external-1 >output && |
| 19 | test_grep "^On branch " output |
| 20 | ' |
| 21 | |
| 22 | test_expect_success 'looping aliases - internal execution' ' |
| 23 | git config alias.loop-internal-1 loop-internal-2 && |
| 24 | git config alias.loop-internal-2 loop-internal-3 && |
| 25 | git config alias.loop-internal-3 loop-internal-2 && |
| 26 | test_must_fail git loop-internal-1 2>output && |
| 27 | test_grep "^fatal: alias loop detected: expansion of" output |
| 28 | ' |
| 29 | |
| 30 | test_expect_success 'looping aliases - deprecated builtins' ' |
| 31 | test_config alias.whatchanged pack-redundant && |
| 32 | test_config alias.pack-redundant whatchanged && |
| 33 | cat >expect <<-EOF && |
| 34 | ${SQ}whatchanged${SQ} is aliased to ${SQ}pack-redundant${SQ} |
| 35 | ${SQ}pack-redundant${SQ} is aliased to ${SQ}whatchanged${SQ} |
| 36 | fatal: alias loop detected: expansion of ${SQ}whatchanged${SQ} does not terminate: |
| 37 | whatchanged <== |
| 38 | pack-redundant ==> |
| 39 | EOF |
| 40 | test_must_fail git whatchanged -h 2>actual && |
| 41 | test_cmp expect actual |
| 42 | ' |
| 43 | |
| 44 | # This test is disabled until external loops are fixed, because would block |
| 45 | # the test suite for a full minute. |
| 46 | # |
| 47 | #test_expect_failure 'looping aliases - mixed execution' ' |
| 48 | # git config alias.loop-mixed-1 loop-mixed-2 && |
| 49 | # git config alias.loop-mixed-2 "!git loop-mixed-1" && |
| 50 | # test_must_fail git loop-mixed-1 2>output && |
| 51 | # test_grep "^fatal: alias loop detected: expansion of" output |
| 52 | #' |
| 53 | |
| 54 | test_expect_success 'run-command formats empty args properly' ' |
| 55 | test_must_fail env GIT_TRACE=1 git frotz a "" b " " c 2>actual.raw && |
| 56 | sed -ne "/run_command:/s/.*trace: run_command: //p" actual.raw >actual && |
| 57 | echo "git-frotz a '\'''\'' b '\'' '\'' c" >expect && |
| 58 | test_cmp expect actual |
| 59 | ' |
| 60 | |
| 61 | test_expect_success 'tracing a shell alias with arguments shows trace of prepared command' ' |
| 62 | cat >expect <<-EOF && |
| 63 | trace: start_command: SHELL -c ${SQ}echo \$* "\$@"${SQ} ${SQ}echo \$*${SQ} arg |
| 64 | EOF |
| 65 | git config alias.echo "!echo \$*" && |
| 66 | env GIT_TRACE=1 git echo arg 2>output && |
| 67 | # redact platform differences |
| 68 | sed -n -e "s/^\(trace: start_command:\) .* -c /\1 SHELL -c /p" output >actual && |
| 69 | test_cmp expect actual |
| 70 | ' |
| 71 | |
| 72 | can_alias_deprecated_builtin () { |
| 73 | cmd="$1" && |
| 74 | # some git(1) commands will fail for `-h` (the case for |
| 75 | # git-status as of 2025-09-07) |
| 76 | test_might_fail git status -h >expect && |
| 77 | test_file_not_empty expect && |
| 78 | test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual && |
| 79 | test_cmp expect actual |
| 80 | } |
| 81 | |
| 82 | test_expect_success 'can alias-shadow deprecated builtins' ' |
| 83 | for cmd in $(git --list-cmds=deprecated) |
| 84 | do |
| 85 | can_alias_deprecated_builtin "$cmd" || return 1 |
| 86 | done |
| 87 | ' |
| 88 | |
| 89 | test_expect_success 'can alias-shadow via two deprecated builtins' ' |
| 90 | # some git(1) commands will fail... (see above) |
| 91 | test_might_fail git status -h >expect && |
| 92 | test_file_not_empty expect && |
| 93 | test_might_fail git -c alias.whatchanged=pack-redundant \ |
| 94 | -c alias.pack-redundant=status whatchanged -h >actual && |
| 95 | test_cmp expect actual |
| 96 | ' |
| 97 | |
| 98 | cannot_alias_regular_builtin () { |
| 99 | cmd="$1" && |
| 100 | # some git(1) commands will fail... (see above) |
| 101 | test_might_fail git "$cmd" -h >expect && |
| 102 | test_file_not_empty expect && |
| 103 | test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual && |
| 104 | test_cmp expect actual |
| 105 | } |
| 106 | |
| 107 | test_expect_success 'cannot alias-shadow a sample of regular builtins' ' |
| 108 | for cmd in grep check-ref-format interpret-trailers \ |
| 109 | checkout-index fast-import diagnose rev-list prune |
| 110 | do |
| 111 | cannot_alias_regular_builtin "$cmd" || return 1 |
| 112 | done |
| 113 | ' |
| 114 | |
| 115 | test_expect_success 'alias without value reports error' ' |
| 116 | test_when_finished "git config --unset alias.noval" && |
| 117 | cat >>.git/config <<-\EOF && |
| 118 | [alias] |
| 119 | noval |
| 120 | EOF |
| 121 | test_must_fail git noval 2>error && |
| 122 | test_grep "alias.noval" error |
| 123 | ' |
| 124 | |
| 125 | test_expect_success 'subsection syntax works' ' |
| 126 | test_config alias.testnew.command "!echo ran-subsection" && |
| 127 | git testnew >output && |
| 128 | test_grep "ran-subsection" output |
| 129 | ' |
| 130 | |
| 131 | test_expect_success 'simple dotted alias syntax still works' ' |
| 132 | test_config alias.simple.dotted "!echo ran-simple-dotted" && |
| 133 | git simple.dotted >output && |
| 134 | test_grep "ran-simple-dotted" output |
| 135 | ' |
| 136 | |
| 137 | test_expect_success 'subsection syntax only accepts command key' ' |
| 138 | test_config alias.invalid.notcommand value && |
| 139 | test_must_fail git invalid 2>error && |
| 140 | test_grep -i "not a git command" error |
| 141 | ' |
| 142 | |
| 143 | test_expect_success 'subsection syntax requires value for command' ' |
| 144 | test_when_finished "git config --remove-section alias.noval" && |
| 145 | cat >>.git/config <<-\EOF && |
| 146 | [alias "noval"] |
| 147 | command |
| 148 | EOF |
| 149 | test_must_fail git noval 2>error && |
| 150 | test_grep "alias.noval.command" error |
| 151 | ' |
| 152 | |
| 153 | test_expect_success 'simple syntax is case-insensitive' ' |
| 154 | test_config alias.LegacyCase "!echo ran-legacy" && |
| 155 | git legacycase >output && |
| 156 | test_grep "ran-legacy" output |
| 157 | ' |
| 158 | |
| 159 | test_expect_success 'subsection syntax is case-sensitive' ' |
| 160 | test_config alias.SubCase.command "!echo ran-upper" && |
| 161 | test_config alias.subcase.command "!echo ran-lower" && |
| 162 | git SubCase >upper.out && |
| 163 | git subcase >lower.out && |
| 164 | test_grep "ran-upper" upper.out && |
| 165 | test_grep "ran-lower" lower.out |
| 166 | ' |
| 167 | |
| 168 | test_expect_success 'UTF-8 alias with Swedish characters' ' |
| 169 | test_config alias."förgrena".command "!echo ran-swedish" && |
| 170 | git förgrena >output && |
| 171 | test_grep "ran-swedish" output |
| 172 | ' |
| 173 | |
| 174 | test_expect_success 'UTF-8 alias with CJK characters' ' |
| 175 | test_config alias."分支".command "!echo ran-cjk" && |
| 176 | git 分支 >output && |
| 177 | test_grep "ran-cjk" output |
| 178 | ' |
| 179 | |
| 180 | test_expect_success 'alias with spaces in name' ' |
| 181 | test_config alias."test name".command "!echo ran-spaces" && |
| 182 | git "test name" >output && |
| 183 | test_grep "ran-spaces" output |
| 184 | ' |
| 185 | |
| 186 | test_expect_success 'subsection aliases listed in help -a' ' |
| 187 | test_config alias."förgrena".command "!echo test" && |
| 188 | git help -a >output && |
| 189 | test_grep "förgrena" output |
| 190 | ' |
| 191 | |
| 192 | test_expect_success 'simple dotted aliases listed in help -a' ' |
| 193 | test_config alias.simple.listed "!echo test" && |
| 194 | git help -a >output && |
| 195 | test_grep "simple.listed" output |
| 196 | ' |
| 197 | |
| 198 | test_expect_success 'empty subsection treated as no subsection' ' |
| 199 | test_config "alias..something" "!echo foobar" && |
| 200 | git something >actual && |
| 201 | echo foobar >expect && |
| 202 | test_cmp expect actual |
| 203 | ' |
| 204 | |
| 205 | test_expect_success 'alias with leading dot via subsection syntax' ' |
| 206 | test_config alias.".something".command "!echo foobar" && |
| 207 | git .something >actual && |
| 208 | echo foobar >expect && |
| 209 | test_cmp expect actual |
| 210 | ' |
| 211 | |
| 212 | test_done |