github.com/catandhorse/git-lfs@v2.5.2+incompatible/t/testhelpers.sh (about) 1 #!/usr/bin/env bash 2 3 # assert_pointer confirms that the pointer in the repository for $path in the 4 # given $ref matches the given $oid and $size. 5 # 6 # $ assert_pointer "master" "path/to/file" "some-oid" 123 7 assert_pointer() { 8 local ref="$1" 9 local path="$2" 10 local oid="$3" 11 local size="$4" 12 13 gitblob=$(git ls-tree -lrz "$ref" | 14 while read -r -d $'\0' x; do 15 echo $x 16 done | 17 grep "$path" | cut -f 3 -d " ") 18 19 actual=$(git cat-file -p $gitblob) 20 expected=$(pointer $oid $size) 21 22 if [ "$expected" != "$actual" ]; then 23 exit 1 24 fi 25 } 26 27 # refute_pointer confirms that the file in the repository for $path in the 28 # given $ref is _not_ a pointer. 29 # 30 # $ refute_pointer "master" "path/to/file" 31 refute_pointer() { 32 local ref="$1" 33 local path="$2" 34 35 gitblob=$(git ls-tree -lrz "$ref" | 36 while read -r -d $'\0' x; do 37 echo $x 38 done | 39 grep "$path" | cut -f 3 -d " ") 40 41 file=$(git cat-file -p $gitblob) 42 version="version https://git-lfs.github.com/spec/v[0-9]" 43 oid="oid sha256:[0-9a-f]\{64\}" 44 size="size [0-9]*" 45 regex="$version.*$oid.*$size" 46 47 if echo $file | grep -q "$regex"; then 48 exit 1 49 fi 50 } 51 52 # assert_local_object confirms that an object file is stored for the given oid & 53 # has the correct size 54 # $ assert_local_object "some-oid" size 55 assert_local_object() { 56 local oid="$1" 57 local size="$2" 58 local cfg=`git lfs env | grep LocalMediaDir` 59 local f="${cfg:14}/${oid:0:2}/${oid:2:2}/$oid" 60 actualsize=$(wc -c <"$f" | tr -d '[[:space:]]') 61 if [ "$size" != "$actualsize" ]; then 62 exit 1 63 fi 64 } 65 66 # refute_local_object confirms that an object file is NOT stored for an oid. 67 # If "$size" is given as the second argument, assert that the file exists _and_ 68 # that it does _not_ the expected size 69 # 70 # $ refute_local_object "some-oid" 71 # $ refute_local_object "some-oid" "123" 72 refute_local_object() { 73 local oid="$1" 74 local size="$2" 75 local cfg=`git lfs env | grep LocalMediaDir` 76 local regex="LocalMediaDir=(\S+)" 77 local f="${cfg:14}/${oid:0:2}/${oid:2:2}/$oid" 78 if [ -e $f ]; then 79 if [ -z "$size" ]; then 80 exit 1 81 fi 82 83 actual_size="$(wc -c < "$f" | awk '{ print $1 }')" 84 if [ "$size" -eq "$actual_size" ]; then 85 echo >&2 "fatal: expected object $oid not to have size: $size" 86 exit 1 87 fi 88 fi 89 } 90 91 # delete_local_object deletes the local storage for an oid 92 # $ delete_local_object "some-oid" 93 delete_local_object() { 94 local oid="$1" 95 local cfg=`git lfs env | grep LocalMediaDir` 96 local f="${cfg:14}/${oid:0:2}/${oid:2:2}/$oid" 97 rm "$f" 98 } 99 100 # corrupt_local_object corrupts the local storage for an oid 101 # $ corrupt_local_object "some-oid" 102 corrupt_local_object() { 103 local oid="$1" 104 local cfg=`git lfs env | grep LocalMediaDir` 105 local f="${cfg:14}/${oid:0:2}/${oid:2:2}/$oid" 106 cp /dev/null "$f" 107 } 108 109 110 # check that the object does not exist in the git lfs server. HTTP log is 111 # written to http.log. JSON output is written to http.json. 112 # 113 # $ refute_server_object "reponame" "oid" 114 refute_server_object() { 115 local reponame="$1" 116 local oid="$2" 117 curl -v "$GITSERVER/$reponame.git/info/lfs/objects/batch" \ 118 -u "user:pass" \ 119 -o http.json \ 120 -d "{\"operation\":\"download\",\"objects\":[{\"oid\":\"$oid\"}]}" \ 121 -H "Accept: application/vnd.git-lfs+json" \ 122 -H "X-Check-Object: 1" \ 123 -H "X-Ignore-Retries: true" 2>&1 | 124 tee http.log 125 126 [ "0" = "$(grep -c "download" http.json)" ] || { 127 cat http.json 128 exit 1 129 } 130 } 131 132 # Delete an object on the lfs server. HTTP log is 133 # written to http.log. JSON output is written to http.json. 134 # 135 # $ delete_server_object "reponame" "oid" 136 delete_server_object() { 137 local reponame="$1" 138 local oid="$2" 139 curl -v "$GITSERVER/$reponame.git/info/lfs/objects/$oid" \ 140 -X DELETE \ 141 -u "user:pass" \ 142 -o http.json \ 143 -H "Accept: application/vnd.git-lfs+json" 2>&1 | 144 tee http.log 145 146 grep "200 OK" http.log 147 } 148 149 # check that the object does exist in the git lfs server. HTTP log is written 150 # to http.log. JSON output is written to http.json. 151 assert_server_object() { 152 local reponame="$1" 153 local oid="$2" 154 local refspec="$3" 155 curl -v "$GITSERVER/$reponame.git/info/lfs/objects/batch" \ 156 -u "user:pass" \ 157 -o http.json \ 158 -d "{\"operation\":\"download\",\"objects\":[{\"oid\":\"$oid\"}],\"ref\":{\"name\":\"$refspec\"}}" \ 159 -H "Accept: application/vnd.git-lfs+json" \ 160 -H "X-Check-Object: 1" \ 161 -H "X-Ignore-Retries: true" 2>&1 | 162 tee http.log 163 grep "200 OK" http.log 164 165 grep "download" http.json || { 166 cat http.json 167 exit 1 168 } 169 } 170 171 # This asserts the lock path and returns the lock ID by parsing the response of 172 # 173 # git lfs lock --json <path> 174 assert_lock() { 175 local log="$1" 176 local path="$2" 177 178 if [ $(grep -c "\"path\":\"$path\"" "$log") -eq 0 ]; then 179 echo "path '$path' not found in:" 180 cat "$log" 181 exit 1 182 fi 183 184 local jsonid=$(grep -oh "\"id\":\"\w\+\"" "$log") 185 echo "${jsonid:3}" | tr -d \"\: 186 } 187 188 # assert that a lock with the given ID exists on the test server 189 assert_server_lock() { 190 local reponame="$1" 191 local id="$2" 192 local refspec="$3" 193 194 curl -v "$GITSERVER/$reponame.git/info/lfs/locks?refspec=$refspec" \ 195 -u "user:pass" \ 196 -o http.json \ 197 -H "Accept:application/vnd.git-lfs+json" 2>&1 | 198 tee http.log 199 200 grep "200 OK" http.log 201 grep "$id" http.json || { 202 cat http.json 203 exit 1 204 } 205 } 206 207 # refute that a lock with the given ID exists on the test server 208 refute_server_lock() { 209 local reponame="$1" 210 local id="$2" 211 local refspec="$3" 212 213 curl -v "$GITSERVER/$reponame.git/info/lfs/locks?refspec=$refspec" \ 214 -u "user:pass" \ 215 -o http.json \ 216 -H "Accept:application/vnd.git-lfs+json" 2>&1 | tee http.log 217 218 grep "200 OK" http.log 219 220 [ $(grep -c "$id" http.json) -eq 0 ] 221 } 222 223 # Assert that .gitattributes contains a given attribute N times 224 assert_attributes_count() { 225 local fileext="$1" 226 local attrib="$2" 227 local count="$3" 228 229 pattern="\(*.\)\?$fileext\(.*\)$attrib" 230 actual=$(grep -e "$pattern" .gitattributes | wc -l) 231 if [ "$(printf "%d" "$actual")" != "$count" ]; then 232 echo "wrong number of $attrib entries for $fileext" 233 echo "expected: $count actual: $actual" 234 cat .gitattributes 235 exit 1 236 fi 237 } 238 239 assert_file_writeable() { 240 ls -l "$1" | grep -e "^-rw" 241 } 242 243 refute_file_writeable() { 244 ls -l "$1" | grep -e "^-r-" 245 } 246 247 git_root() { 248 git rev-parse --show-toplevel 2>/dev/null 249 } 250 251 dot_git_dir() { 252 echo "$(git_root)/.git" 253 } 254 255 assert_hooks() { 256 local git_root="$1" 257 258 if [ -z "$git_root" ]; then 259 echo >&2 "fatal: (assert_hooks) not in git repository" 260 exit 1 261 fi 262 263 [ -x "$git_root/hooks/post-checkout" ] 264 [ -x "$git_root/hooks/post-commit" ] 265 [ -x "$git_root/hooks/post-merge" ] 266 [ -x "$git_root/hooks/pre-push" ] 267 } 268 269 assert_clean_status() { 270 status="$(git status)" 271 echo "$status" | grep "working tree clean" || { 272 echo $status 273 git lfs status 274 } 275 } 276 277 # pointer returns a string Git LFS pointer file. 278 # 279 # $ pointer abc-some-oid 123 <version> 280 # > version ... 281 pointer() { 282 local oid=$1 283 local size=$2 284 local version=${3:-https://git-lfs.github.com/spec/v1} 285 printf "version %s 286 oid sha256:%s 287 size %s 288 " "$version" "$oid" "$size" 289 } 290 291 # wait_for_file simply sleeps until a file exists. 292 # 293 # $ wait_for_file "path/to/upcoming/file" 294 wait_for_file() { 295 local filename="$1" 296 n=0 297 wait_time=1 298 while [ $n -lt 17 ]; do 299 if [ -s $filename ]; then 300 return 0 301 fi 302 303 sleep $wait_time 304 n=`expr $n + 1` 305 if [ $wait_time -lt 4 ]; then 306 wait_time=`expr $wait_time \* 2` 307 fi 308 done 309 310 echo "$filename did not appear after 60 seconds." 311 return 1 312 } 313 314 # setup_remote_repo initializes a bare Git repository that is accessible through 315 # the test Git server. The `pwd` is set to the repository's directory, in case 316 # further commands need to be run. This server is running for every test in an 317 # integration run, so every test file should setup its own remote repository to 318 # avoid conflicts. 319 # 320 # $ setup_remote_repo "some-name" 321 # 322 setup_remote_repo() { 323 local reponame="$1" 324 echo "set up remote git repository: $reponame" 325 repodir="$REMOTEDIR/$reponame.git" 326 mkdir -p "$repodir" 327 cd "$repodir" 328 git init --bare 329 git config http.receivepack true 330 git config receive.denyCurrentBranch ignore 331 } 332 333 # creates a bare remote repository for a local clone. Useful to test pushing to 334 # a fresh remote server. 335 # 336 # $ setup_alternate_remote "$reponame-whatever" 337 # $ setup_alternate_remote "$reponame-whatever" "other-remote-name" 338 # 339 setup_alternate_remote() { 340 local newRemoteName=$1 341 local remote=${2:-origin} 342 343 wd=`pwd` 344 345 setup_remote_repo "$newRemoteName" 346 cd $wd 347 git remote rm "$remote" 348 git remote add "$remote" "$GITSERVER/$newRemoteName" 349 } 350 351 # clone_repo clones a repository from the test Git server to the subdirectory 352 # $dir under $TRASHDIR. setup_remote_repo() needs to be run first. Output is 353 # written to clone.log. 354 clone_repo() { 355 cd "$TRASHDIR" 356 357 local reponame="$1" 358 local dir="$2" 359 echo "clone local git repository $reponame to $dir" 360 out=$(git clone "$GITSERVER/$reponame" "$dir" 2>&1) 361 cd "$dir" 362 363 git config credential.helper lfstest 364 echo "$out" > clone.log 365 echo "$out" 366 } 367 368 # clone_repo_url clones a Git repository to the subdirectory $dir under $TRASHDIR. 369 # setup_remote_repo() needs to be run first. Output is written to clone.log. 370 clone_repo_url() { 371 cd "$TRASHDIR" 372 373 local repo="$1" 374 local dir="$2" 375 echo "clone git repository $repo to $dir" 376 out=$(git clone "$repo" "$dir" 2>&1) 377 cd "$dir" 378 379 git config credential.helper lfstest 380 echo "$out" > clone.log 381 echo "$out" 382 } 383 384 # clone_repo_ssl clones a repository from the test Git server to the subdirectory 385 # $dir under $TRASHDIR, using the SSL endpoint. 386 # setup_remote_repo() needs to be run first. Output is written to clone_ssl.log. 387 clone_repo_ssl() { 388 cd "$TRASHDIR" 389 390 local reponame="$1" 391 local dir="$2" 392 echo "clone local git repository $reponame to $dir" 393 out=$(git clone "$SSLGITSERVER/$reponame" "$dir" 2>&1) 394 cd "$dir" 395 396 git config credential.helper lfstest 397 398 echo "$out" > clone_ssl.log 399 echo "$out" 400 } 401 402 # clone_repo_clientcert clones a repository from the test Git server to the subdirectory 403 # $dir under $TRASHDIR, using the client cert endpoint. 404 # setup_remote_repo() needs to be run first. Output is written to clone_client_cert.log. 405 clone_repo_clientcert() { 406 cd "$TRASHDIR" 407 408 local reponame="$1" 409 local dir="$2" 410 echo "clone $CLIENTCERTGITSERVER/$reponame to $dir" 411 set +e 412 out=$(git clone "$CLIENTCERTGITSERVER/$reponame" "$dir" 2>&1) 413 res="${PIPESTATUS[0]}" 414 set -e 415 416 if [ "0" -eq "$res" ]; then 417 cd "$dir" 418 echo "$out" > clone_client_cert.log 419 420 git config credential.helper lfstest 421 exit 0 422 fi 423 424 echo "$out" > clone_client_cert.log 425 if [ $(grep -c "NSInvalidArgumentException" clone_client_cert.log) -gt 0 ]; then 426 echo "client-cert-mac-openssl" > clone_client_cert.log 427 exit 0 428 fi 429 430 exit 1 431 } 432 433 # setup_remote_repo_with_file creates a remote repo, clones it locally, commits 434 # a file tracked by LFS, and pushes it to the remote: 435 # 436 # setup_remote_repo_with_file "reponame" "filename" 437 setup_remote_repo_with_file() { 438 local reponame="$1" 439 local filename="$2" 440 local dirname="$(dirname "$filename")" 441 442 setup_remote_repo "$reponame" 443 clone_repo "$reponame" "clone_$reponame" 444 445 mkdir -p "$dirname" 446 447 git lfs track "$filename" 448 echo "$filename" > "$filename" 449 git add .gitattributes $filename 450 git commit -m "add $filename" | tee commit.log 451 452 grep "master (root-commit)" commit.log 453 grep "2 files changed" commit.log 454 grep "create mode 100644 $filename" commit.log 455 grep "create mode 100644 .gitattributes" commit.log 456 457 git push origin master 2>&1 | tee push.log 458 grep "master -> master" push.log 459 } 460 461 # substring_position returns the position of a substring in a 1-indexed search 462 # space. 463 # 464 # [ "$(substring_position "foo bar baz" "baz")" -eq "9" ] 465 substring_position() { 466 local str="$1" 467 local substr="$2" 468 469 # 1) Print the string... 470 # 2) Remove the substring and everything after it 471 # 3) Count the number of characters (bytes) left, i.e., the offset of the 472 # string we were looking for. 473 474 echo "$str" \ 475 | sed "s/$substr.*$//" \ 476 | wc -c 477 } 478 479 # repo_endpoint returns the LFS endpoint for a given server and repository. 480 # 481 # [ "$GITSERVER/example/repo.git/info/lfs" = "$(repo_endpoint $GITSERVER example-repo)" ] 482 repo_endpoint() { 483 local server="$1" 484 local repo="$2" 485 486 echo "$server/$repo.git/info/lfs" 487 } 488 489 # setup initializes the clean, isolated environment for integration tests. 490 setup() { 491 cd "$ROOTDIR" 492 493 if [ ! -d "$REMOTEDIR" ]; then 494 mkdir "$REMOTEDIR" 495 fi 496 497 echo "# Git LFS: ${LFS_BIN:-$(which git-lfs)}" 498 git lfs version | sed -e 's/^/# /g' 499 git version | sed -e 's/^/# /g' 500 501 if [ -z "$GIT_LFS_NO_TEST_COUNT" ]; then 502 LFSTEST_URL="$LFS_URL_FILE" \ 503 LFSTEST_SSL_URL="$LFS_SSL_URL_FILE" \ 504 LFSTEST_CLIENT_CERT_URL="$LFS_CLIENT_CERT_URL_FILE" \ 505 LFSTEST_DIR="$REMOTEDIR" \ 506 LFSTEST_CERT="$LFS_CERT_FILE" \ 507 LFSTEST_CLIENT_CERT="$LFS_CLIENT_CERT_FILE" \ 508 LFSTEST_CLIENT_KEY="$LFS_CLIENT_KEY_FILE" \ 509 lfstest-count-tests increment 510 fi 511 512 wait_for_file "$LFS_URL_FILE" 513 wait_for_file "$LFS_SSL_URL_FILE" 514 wait_for_file "$LFS_CLIENT_CERT_URL_FILE" 515 wait_for_file "$LFS_CERT_FILE" 516 wait_for_file "$LFS_CLIENT_CERT_FILE" 517 wait_for_file "$LFS_CLIENT_KEY_FILE" 518 519 LFS_CLIENT_CERT_URL=`cat $LFS_CLIENT_CERT_URL_FILE` 520 521 # Set up the initial git config and osx keychain if applicable 522 HOME="$TESTHOME" 523 if [ ! -d "$HOME" ]; then 524 mkdir "$HOME" 525 fi 526 527 if [ ! -f $HOME/.gitconfig ]; then 528 git lfs install --skip-repo 529 git config --global credential.usehttppath true 530 git config --global credential.helper lfstest 531 git config --global user.name "Git LFS Tests" 532 git config --global user.email "git-lfs@example.com" 533 git config --global http.sslcainfo "$LFS_CERT_FILE" 534 git config --global http.$LFS_CLIENT_CERT_URL/.sslKey "$LFS_CLIENT_KEY_FILE" 535 git config --global http.$LFS_CLIENT_CERT_URL/.sslCert "$LFS_CLIENT_CERT_FILE" 536 git config --global http.$LFS_CLIENT_CERT_URL/.sslVerify "false" 537 fi | sed -e 's/^/# /g' 538 539 # setup the git credential password storage 540 mkdir -p "$CREDSDIR" 541 printf "user:pass" > "$CREDSDIR/127.0.0.1" 542 543 echo "#" 544 echo "# HOME: $HOME" 545 echo "# TMP: $TMPDIR" 546 echo "# CREDS: $CREDSDIR" 547 echo "# lfstest-gitserver:" 548 echo "# LFSTEST_URL=$LFS_URL_FILE" 549 echo "# LFSTEST_SSL_URL=$LFS_SSL_URL_FILE" 550 echo "# LFSTEST_CLIENT_CERT_URL=$LFS_CLIENT_CERT_URL_FILE ($LFS_CLIENT_CERT_URL)" 551 echo "# LFSTEST_CERT=$LFS_CERT_FILE" 552 echo "# LFSTEST_CLIENT_CERT=$LFS_CLIENT_CERT_FILE" 553 echo "# LFSTEST_CLIENT_KEY=$LFS_CLIENT_KEY_FILE" 554 echo "# LFSTEST_DIR=$REMOTEDIR" 555 } 556 557 # shutdown cleans the $TRASHDIR and shuts the test Git server down. 558 shutdown() { 559 # every t/t-*.sh file should cleanup its trashdir 560 [ -z "$KEEPTRASH" ] && rm -rf "$TRASHDIR" 561 562 if [ -z "$GIT_LFS_NO_TEST_COUNT" ]; then 563 LFSTEST_DIR="$REMOTEDIR" \ 564 LFS_URL_FILE="$LFS_URL_FILE" \ 565 lfstest-count-tests decrement 566 fi 567 } 568 569 tap_show_plan() { 570 local tests="$1" 571 572 printf "1..%i\n" "$tests" 573 } 574 575 ensure_git_version_isnt() { 576 local expectedComparison=$1 577 local version=$2 578 579 local gitVersion=$(git version | cut -d" " -f3) 580 581 set +e 582 compare_version $gitVersion $version 583 result=$? 584 set -e 585 586 if [[ $result == $expectedComparison ]]; then 587 echo "skip: $0 (git version $(comparison_to_operator $expectedComparison) $version)" 588 exit 589 fi 590 } 591 592 VERSION_EQUAL=0 593 VERSION_HIGHER=1 594 VERSION_LOWER=2 595 596 # Compare $1 and $2 and return VERSION_EQUAL / VERSION_LOWER / VERSION_HIGHER 597 compare_version() { 598 if [[ $1 == $2 ]] 599 then 600 return $VERSION_EQUAL 601 fi 602 local IFS=. 603 local i ver1=($1) ver2=($2) 604 # fill empty fields in ver1 with zeros 605 for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 606 do 607 ver1[i]=0 608 done 609 for ((i=0; i<${#ver1[@]}; i++)) 610 do 611 if [[ -z ${ver2[i]} ]] 612 then 613 # fill empty fields in ver2 with zeros 614 ver2[i]=0 615 fi 616 if ((10#${ver1[i]} > 10#${ver2[i]})) 617 then 618 return $VERSION_HIGHER 619 fi 620 if ((10#${ver1[i]} < 10#${ver2[i]})) 621 then 622 return $VERSION_LOWER 623 fi 624 done 625 return $VERSION_EQUAL 626 } 627 628 comparison_to_operator() { 629 local comparison=$1 630 if [[ $1 == $VERSION_EQUAL ]]; then 631 echo "==" 632 elif [[ $1 == $VERSION_HIGHER ]]; then 633 echo ">" 634 elif [[ $1 == $VERSION_LOWER ]]; then 635 echo "<" 636 else 637 echo "???" 638 fi 639 } 640 641 # Calculate the object ID from the string passed as the argument 642 calc_oid() { 643 printf "$1" | $SHASUM | cut -f 1 -d " " 644 } 645 646 # Calculate the object ID from the file passed as the argument 647 calc_oid_file() { 648 $SHASUM "$1" | cut -f 1 -d " " 649 } 650 651 # Get a date string with an offset 652 # Args: One or more date offsets of the form (regex) "[+-]\d+[dmyHM]" 653 # e.g. +1d = 1 day forward from today 654 # -5y = 5 years before today 655 # Example call: 656 # D=$(get_date +1y +1m -5H) 657 # returns date as string in RFC3339 format ccyy-mm-ddThh:MM:ssZ 658 # note returns in UTC time not local time hence Z and not +/- 659 get_date() { 660 # Wrapped because BSD (inc OSX) & GNU 'date' functions are different 661 # on Windows under Git Bash it's GNU 662 if date --version >/dev/null 2>&1 ; then # GNU 663 ARGS="" 664 for var in "$@" 665 do 666 # GNU offsets are more verbose 667 unit=${var: -1} 668 val=${var:0:${#var}-1} 669 case "$unit" in 670 d) unit="days" ;; 671 m) unit="months" ;; 672 y) unit="years" ;; 673 H) unit="hours" ;; 674 M) unit="minutes" ;; 675 esac 676 ARGS="$ARGS $val $unit" 677 done 678 date -d "$ARGS" -u +%Y-%m-%dT%TZ 679 else # BSD 680 ARGS="" 681 for var in "$@" 682 do 683 ARGS="$ARGS -v$var" 684 done 685 date $ARGS -u +%Y-%m-%dT%TZ 686 fi 687 } 688 689 # Convert potentially MinGW bash paths to native Windows paths 690 # Needed to match generic built paths in test scripts to native paths generated from Go 691 native_path() { 692 local arg=$1 693 if [ $IS_WINDOWS -eq 1 ]; then 694 # Use params form to avoid interpreting any '\' characters 695 printf '%s' "$(cygpath -w $arg)" 696 else 697 printf '%s' "$arg" 698 fi 699 } 700 701 # escape any instance of '\' with '\\' on Windows 702 escape_path() { 703 local unescaped="$1" 704 if [ $IS_WINDOWS -eq 1 ]; then 705 printf '%s' "${unescaped//\\/\\\\}" 706 else 707 printf '%s' "$unescaped" 708 fi 709 } 710 711 # As native_path but escape all backslash characters to "\\" 712 native_path_escaped() { 713 local unescaped=$(native_path "$1") 714 escape_path "$unescaped" 715 } 716 717 # native_path_list_separator prints the operating system-specific path list 718 # separator. 719 native_path_list_separator() { 720 if [ "$IS_WINDOWS" -eq 1 ]; then 721 printf ";"; 722 else 723 printf ":"; 724 fi 725 } 726 727 cat_end() { 728 if [ $IS_WINDOWS -eq 1 ]; then 729 printf '^M$' 730 else 731 printf '$' 732 fi 733 } 734 735 # Compare 2 lists which are newline-delimited in a string, ignoring ordering and blank lines 736 contains_same_elements() { 737 # Remove blank lines then sort 738 diff -u <(printf '%s' "$1" | grep -v '^$' | sort) <(printf '%s' "$2" | grep -v '^$' | sort) 739 } 740 741 is_stdin_attached() { 742 test -t0 743 echo $? 744 } 745 746 has_test_dir() { 747 if [ -z "$GIT_LFS_TEST_DIR" ]; then 748 echo "No GIT_LFS_TEST_DIR. Skipping..." 749 exit 0 750 fi 751 } 752 753 add_symlink() { 754 local src=$1 755 local dest=$2 756 757 prefix=`git rev-parse --show-prefix` 758 hashsrc=`printf "$src" | git hash-object -w --stdin` 759 760 git update-index --add --cacheinfo 120000 "$hashsrc" "$prefix$dest" 761 git checkout -- "$dest" 762 }