| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='test git rev-parse' |
| 4 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| 5 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 6 | |
| 7 | . ./test-lib.sh |
| 8 | |
| 9 | test_one () { |
| 10 | dir="$1" && |
| 11 | expect="$2" && |
| 12 | shift && |
| 13 | shift && |
| 14 | echo "$expect" >expect && |
| 15 | git -C "$dir" rev-parse "$@" >actual && |
| 16 | test_cmp expect actual |
| 17 | } |
| 18 | |
| 19 | # usage: [options] label is-bare is-inside-git is-inside-work prefix git-dir absolute-git-dir |
| 20 | test_rev_parse () { |
| 21 | d= |
| 22 | bare= |
| 23 | gitdir= |
| 24 | while : |
| 25 | do |
| 26 | case "$1" in |
| 27 | -C) d="$2"; shift; shift ;; |
| 28 | -b) case "$2" in |
| 29 | [tfu]*) bare="$2"; shift; shift ;; |
| 30 | *) error "test_rev_parse: bogus core.bare value '$2'" ;; |
| 31 | esac ;; |
| 32 | -g) gitdir="$2"; shift; shift ;; |
| 33 | -*) error "test_rev_parse: unrecognized option '$1'" ;; |
| 34 | *) break ;; |
| 35 | esac |
| 36 | done |
| 37 | |
| 38 | name=$1 |
| 39 | shift |
| 40 | |
| 41 | for o in --is-bare-repository \ |
| 42 | --is-inside-git-dir \ |
| 43 | --is-inside-work-tree \ |
| 44 | --show-prefix \ |
| 45 | --git-dir \ |
| 46 | --absolute-git-dir |
| 47 | do |
| 48 | test $# -eq 0 && break |
| 49 | expect="$1" |
| 50 | test_expect_success "$name: $o" ' |
| 51 | if test -n "$gitdir" |
| 52 | then |
| 53 | test_when_finished "unset GIT_DIR" && |
| 54 | GIT_DIR="$gitdir" && |
| 55 | export GIT_DIR |
| 56 | fi && |
| 57 | |
| 58 | case "$bare" in |
| 59 | t*) test_config ${d:+-C} ${d:+"$d"} core.bare true ;; |
| 60 | f*) test_config ${d:+-C} ${d:+"$d"} core.bare false ;; |
| 61 | u*) test_unconfig ${d:+-C} ${d:+"$d"} core.bare ;; |
| 62 | esac && |
| 63 | |
| 64 | echo "$expect" >expect && |
| 65 | git ${d:+-C} ${d:+"$d"} rev-parse $o >actual && |
| 66 | test_cmp expect actual |
| 67 | ' |
| 68 | shift |
| 69 | done |
| 70 | } |
| 71 | |
| 72 | ROOT=$(pwd) |
| 73 | |
| 74 | test_expect_success 'setup' ' |
| 75 | mkdir -p sub/dir work && |
| 76 | cp -R .git repo.git && |
| 77 | git checkout -B main && |
| 78 | test_commit abc && |
| 79 | git checkout -b side && |
| 80 | test_commit def && |
| 81 | git checkout main && |
| 82 | git worktree add worktree side |
| 83 | ' |
| 84 | |
| 85 | test_rev_parse toplevel false false true '' .git "$ROOT/.git" |
| 86 | |
| 87 | test_rev_parse -C .git .git/ false true false '' . "$ROOT/.git" |
| 88 | test_rev_parse -C .git/objects .git/objects/ false true false '' "$ROOT/.git" "$ROOT/.git" |
| 89 | |
| 90 | test_rev_parse -C sub/dir subdirectory false false true sub/dir/ "$ROOT/.git" "$ROOT/.git" |
| 91 | |
| 92 | test_rev_parse -b t 'core.bare = true' true false false |
| 93 | |
| 94 | test_rev_parse -b u 'core.bare undefined' false false true |
| 95 | |
| 96 | |
| 97 | test_rev_parse -C work -g ../.git -b f 'GIT_DIR=../.git, core.bare = false' false false true '' "../.git" "$ROOT/.git" |
| 98 | |
| 99 | test_rev_parse -C work -g ../.git -b t 'GIT_DIR=../.git, core.bare = true' true false false '' |
| 100 | |
| 101 | test_rev_parse -C work -g ../.git -b u 'GIT_DIR=../.git, core.bare undefined' false false true '' |
| 102 | |
| 103 | |
| 104 | test_rev_parse -C work -g ../repo.git -b f 'GIT_DIR=../repo.git, core.bare = false' false false true '' "../repo.git" "$ROOT/repo.git" |
| 105 | |
| 106 | test_rev_parse -C work -g ../repo.git -b t 'GIT_DIR=../repo.git, core.bare = true' true false false '' |
| 107 | |
| 108 | test_rev_parse -C work -g ../repo.git -b u 'GIT_DIR=../repo.git, core.bare undefined' false false true '' |
| 109 | |
| 110 | test_expect_success 'rev-parse --path-format=absolute' ' |
| 111 | test_one "." "$ROOT/.git" --path-format=absolute --git-dir && |
| 112 | test_one "." "$ROOT/.git" --path-format=absolute --git-common-dir && |
| 113 | test_one "sub/dir" "$ROOT/.git" --path-format=absolute --git-dir && |
| 114 | test_one "sub/dir" "$ROOT/.git" --path-format=absolute --git-common-dir && |
| 115 | test_one "worktree" "$ROOT/.git/worktrees/worktree" --path-format=absolute --git-dir && |
| 116 | test_one "worktree" "$ROOT/.git" --path-format=absolute --git-common-dir && |
| 117 | test_one "." "$ROOT" --path-format=absolute --show-toplevel && |
| 118 | test_one "." "$ROOT/.git/objects" --path-format=absolute --git-path objects && |
| 119 | test_one "." "$ROOT/.git/objects/foo/bar/baz" --path-format=absolute --git-path objects/foo/bar/baz |
| 120 | ' |
| 121 | |
| 122 | test_expect_success 'rev-parse --path-format=relative' ' |
| 123 | test_one "." ".git" --path-format=relative --git-dir && |
| 124 | test_one "." ".git" --path-format=relative --git-common-dir && |
| 125 | test_one "sub/dir" "../../.git" --path-format=relative --git-dir && |
| 126 | test_one "sub/dir" "../../.git" --path-format=relative --git-common-dir && |
| 127 | test_one "worktree" "../.git/worktrees/worktree" --path-format=relative --git-dir && |
| 128 | test_one "worktree" "../.git" --path-format=relative --git-common-dir && |
| 129 | test_one "." "./" --path-format=relative --show-toplevel && |
| 130 | test_one "." ".git/objects" --path-format=relative --git-path objects && |
| 131 | test_one "." ".git/objects/foo/bar/baz" --path-format=relative --git-path objects/foo/bar/baz |
| 132 | ' |
| 133 | |
| 134 | test_expect_success '--path-format=relative does not affect --absolute-git-dir' ' |
| 135 | git rev-parse --path-format=relative --absolute-git-dir >actual && |
| 136 | echo "$ROOT/.git" >expect && |
| 137 | test_cmp expect actual |
| 138 | ' |
| 139 | |
| 140 | test_expect_success '--path-format can change in the middle of the command line' ' |
| 141 | git rev-parse --path-format=absolute --git-dir --path-format=relative --git-path objects/foo/bar >actual && |
| 142 | cat >expect <<-EOF && |
| 143 | $ROOT/.git |
| 144 | .git/objects/foo/bar |
| 145 | EOF |
| 146 | test_cmp expect actual |
| 147 | ' |
| 148 | |
| 149 | test_expect_success '--path-format does not segfault without an argument' ' |
| 150 | test_must_fail git rev-parse --path-format |
| 151 | ' |
| 152 | |
| 153 | test_expect_success 'git-common-dir from worktree root' ' |
| 154 | echo .git >expect && |
| 155 | git rev-parse --git-common-dir >actual && |
| 156 | test_cmp expect actual |
| 157 | ' |
| 158 | |
| 159 | test_expect_success 'git-common-dir inside sub-dir' ' |
| 160 | mkdir -p path/to/child && |
| 161 | test_when_finished "rm -rf path" && |
| 162 | echo "$(git -C path/to/child rev-parse --show-cdup).git" >expect && |
| 163 | git -C path/to/child rev-parse --git-common-dir >actual && |
| 164 | test_cmp expect actual |
| 165 | ' |
| 166 | |
| 167 | test_expect_success 'git-path from worktree root' ' |
| 168 | echo .git/objects >expect && |
| 169 | git rev-parse --git-path objects >actual && |
| 170 | test_cmp expect actual |
| 171 | ' |
| 172 | |
| 173 | test_expect_success 'git-path inside sub-dir' ' |
| 174 | mkdir -p path/to/child && |
| 175 | test_when_finished "rm -rf path" && |
| 176 | echo "$(git -C path/to/child rev-parse --show-cdup).git/objects" >expect && |
| 177 | git -C path/to/child rev-parse --git-path objects >actual && |
| 178 | test_cmp expect actual |
| 179 | ' |
| 180 | |
| 181 | test_expect_success 'rev-parse --is-shallow-repository in shallow repo' ' |
| 182 | test_commit test_commit && |
| 183 | echo true >expect && |
| 184 | git clone --depth 1 --no-local . shallow && |
| 185 | test_when_finished "rm -rf shallow" && |
| 186 | git -C shallow rev-parse --is-shallow-repository >actual && |
| 187 | test_cmp expect actual |
| 188 | ' |
| 189 | |
| 190 | test_expect_success 'rev-parse --is-shallow-repository in non-shallow repo' ' |
| 191 | echo false >expect && |
| 192 | git rev-parse --is-shallow-repository >actual && |
| 193 | test_cmp expect actual |
| 194 | ' |
| 195 | |
| 196 | test_expect_success 'rev-parse --show-object-format in repo' ' |
| 197 | test_oid algo >expect && |
| 198 | git rev-parse --show-object-format >actual && |
| 199 | test_cmp expect actual && |
| 200 | git rev-parse --show-object-format=storage >actual && |
| 201 | test_cmp expect actual && |
| 202 | git rev-parse --show-object-format=input >actual && |
| 203 | test_cmp expect actual && |
| 204 | git rev-parse --show-object-format=output >actual && |
| 205 | test_cmp expect actual && |
| 206 | test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err && |
| 207 | grep "unknown mode for --show-object-format: squeamish-ossifrage" err |
| 208 | ' |
| 209 | |
| 210 | |
| 211 | test_expect_success RUST 'rev-parse --show-object-format in repo with compat mode' ' |
| 212 | mkdir repo && |
| 213 | ( |
| 214 | sane_unset GIT_DEFAULT_HASH && |
| 215 | cd repo && |
| 216 | git init --object-format=sha256 && |
| 217 | git config extensions.compatobjectformat sha1 && |
| 218 | echo sha256 >expect && |
| 219 | git rev-parse --show-object-format >actual && |
| 220 | test_cmp expect actual && |
| 221 | git rev-parse --show-object-format=storage >actual && |
| 222 | test_cmp expect actual && |
| 223 | git rev-parse --show-object-format=input >actual && |
| 224 | test_cmp expect actual && |
| 225 | git rev-parse --show-object-format=output >actual && |
| 226 | test_cmp expect actual && |
| 227 | echo sha1 >expect && |
| 228 | git rev-parse --show-object-format=compat >actual && |
| 229 | test_cmp expect actual && |
| 230 | test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err && |
| 231 | grep "unknown mode for --show-object-format: squeamish-ossifrage" err |
| 232 | ) && |
| 233 | mkdir repo2 && |
| 234 | ( |
| 235 | sane_unset GIT_DEFAULT_HASH && |
| 236 | cd repo2 && |
| 237 | git init --object-format=sha256 && |
| 238 | echo >expect && |
| 239 | git rev-parse --show-object-format=compat >actual && |
| 240 | test_cmp expect actual |
| 241 | ) |
| 242 | ' |
| 243 | |
| 244 | test_expect_success 'rev-parse --show-ref-format' ' |
| 245 | test_detect_ref_format >expect && |
| 246 | git rev-parse --show-ref-format >actual && |
| 247 | test_cmp expect actual |
| 248 | ' |
| 249 | |
| 250 | test_expect_success 'rev-parse --show-ref-format with invalid storage' ' |
| 251 | test_when_finished "rm -rf repo" && |
| 252 | git init repo && |
| 253 | ( |
| 254 | cd repo && |
| 255 | git config extensions.refstorage broken && |
| 256 | test_must_fail git rev-parse --show-ref-format 2>err && |
| 257 | grep "error: invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}broken${SQ}" err |
| 258 | ) |
| 259 | ' |
| 260 | |
| 261 | test_expect_success '--show-toplevel from subdir of working tree' ' |
| 262 | pwd >expect && |
| 263 | git -C sub/dir rev-parse --show-toplevel >actual && |
| 264 | test_cmp expect actual |
| 265 | ' |
| 266 | |
| 267 | test_expect_success '--show-toplevel from inside .git' ' |
| 268 | test_must_fail git -C .git rev-parse --show-toplevel |
| 269 | ' |
| 270 | |
| 271 | test_expect_success 'showing the superproject correctly' ' |
| 272 | git rev-parse --show-superproject-working-tree >out && |
| 273 | test_must_be_empty out && |
| 274 | |
| 275 | test_create_repo super && |
| 276 | test_commit -C super test_commit && |
| 277 | test_create_repo sub && |
| 278 | test_commit -C sub test_commit && |
| 279 | git -c protocol.file.allow=always \ |
| 280 | -C super submodule add ../sub dir/sub && |
| 281 | echo $(pwd)/super >expect && |
| 282 | git -C super/dir/sub rev-parse --show-superproject-working-tree >out && |
| 283 | test_cmp expect out && |
| 284 | |
| 285 | test_commit -C super submodule_add && |
| 286 | git -C super checkout -b branch1 && |
| 287 | git -C super/dir/sub checkout -b branch1 && |
| 288 | test_commit -C super/dir/sub branch1_commit && |
| 289 | git -C super add dir/sub && |
| 290 | test_commit -C super branch1_commit && |
| 291 | git -C super checkout -b branch2 main && |
| 292 | git -C super/dir/sub checkout -b branch2 main && |
| 293 | test_commit -C super/dir/sub branch2_commit && |
| 294 | git -C super add dir/sub && |
| 295 | test_commit -C super branch2_commit && |
| 296 | test_must_fail git -C super merge branch1 && |
| 297 | |
| 298 | git -C super/dir/sub rev-parse --show-superproject-working-tree >out && |
| 299 | test_cmp expect out |
| 300 | ' |
| 301 | |
| 302 | # at least one external project depends on this behavior: |
| 303 | test_expect_success 'rev-parse --since= unsqueezed ordering' ' |
| 304 | x1=--since=1970-01-01T00:00:01Z && |
| 305 | x2=--since=1970-01-01T00:00:02Z && |
| 306 | x3=--since=1970-01-01T00:00:03Z && |
| 307 | git rev-parse $x1 $x1 $x3 $x2 >actual && |
| 308 | cat >expect <<-EOF && |
| 309 | --max-age=1 |
| 310 | --max-age=1 |
| 311 | --max-age=3 |
| 312 | --max-age=2 |
| 313 | EOF |
| 314 | test_cmp expect actual |
| 315 | ' |
| 316 | |
| 317 | test_expect_success 'rev-parse --bisect includes bad, excludes good' ' |
| 318 | test_commit_bulk 6 && |
| 319 | |
| 320 | git update-ref refs/bisect/bad-1 HEAD~1 && |
| 321 | git update-ref refs/bisect/b HEAD~2 && |
| 322 | git update-ref refs/bisect/bad-3 HEAD~3 && |
| 323 | git update-ref refs/bisect/good-3 HEAD~3 && |
| 324 | git update-ref refs/bisect/bad-4 HEAD~4 && |
| 325 | git update-ref refs/bisect/go HEAD~4 && |
| 326 | |
| 327 | # Note: refs/bisect/b and refs/bisect/go should be ignored because they |
| 328 | # do not match the refs/bisect/bad or refs/bisect/good prefixes. |
| 329 | cat >expect <<-EOF && |
| 330 | refs/bisect/bad-1 |
| 331 | refs/bisect/bad-3 |
| 332 | refs/bisect/bad-4 |
| 333 | ^refs/bisect/good-3 |
| 334 | EOF |
| 335 | |
| 336 | git rev-parse --symbolic-full-name --bisect >actual && |
| 337 | test_cmp expect actual |
| 338 | ' |
| 339 | |
| 340 | test_expect_success 'rev-parse --bisect works with alternate terms' ' |
| 341 | test_commit_bulk 6 && |
| 342 | |
| 343 | git bisect start --term-old=known --term-new=curious && |
| 344 | |
| 345 | git update-ref refs/bisect/curious-1 HEAD~1 && |
| 346 | git update-ref refs/bisect/bad HEAD~2 && |
| 347 | git update-ref refs/bisect/curious-3 HEAD~3 && |
| 348 | git update-ref refs/bisect/known-3 HEAD~3 && |
| 349 | git update-ref refs/bisect/curious-4 HEAD~4 && |
| 350 | git update-ref refs/bisect/good HEAD~4 && |
| 351 | |
| 352 | # Note: refs/bisect/bad and refs/bisect/goood should be ignored because this |
| 353 | # is a bisect with custom terms (known/curious) |
| 354 | cat >expect <<-EOF && |
| 355 | refs/bisect/curious-1 |
| 356 | refs/bisect/curious-3 |
| 357 | refs/bisect/curious-4 |
| 358 | ^refs/bisect/known-3 |
| 359 | EOF |
| 360 | |
| 361 | git rev-parse --symbolic-full-name --bisect >actual && |
| 362 | test_cmp expect actual |
| 363 | ' |
| 364 | |
| 365 | test_expect_success '--short= truncates to the actual hash length' ' |
| 366 | git rev-parse HEAD >expect && |
| 367 | git rev-parse --short=100 HEAD >actual && |
| 368 | test_cmp expect actual |
| 369 | ' |
| 370 | |
| 371 | test_expect_success ':/ and HEAD^{/} favor more recent matching commits' ' |
| 372 | test_when_finished "rm -rf repo" && |
| 373 | git init repo && |
| 374 | ( |
| 375 | cd repo && |
| 376 | test_commit common-old && |
| 377 | test_commit --no-tag common-new && |
| 378 | git rev-parse HEAD >expect && |
| 379 | git rev-parse :/common >actual && |
| 380 | test_cmp expect actual && |
| 381 | git rev-parse HEAD^{/common} >actual && |
| 382 | test_cmp expect actual |
| 383 | ) |
| 384 | ' |
| 385 | |
| 386 | test_done |