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