#!/usr/bin/env bash . "test/testlib.sh" begin_test "track" ( set -e # no need to setup a remote repo, since this test doesn't need to push or pull mkdir track cd track git init echo "############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto #*.cs diff=csharp" > .gitattributes # track *.jpg once git lfs track "*.jpg" | grep "Tracking \"\*.jpg\"" assert_attributes_count "jpg" "filter=lfs" 1 # track *.jpg again git lfs track "*.jpg" | grep "\"*.jpg\" already supported" assert_attributes_count "jpg" "filter=lfs" 1 mkdir -p a/b .git/info echo "*.mov filter=lfs -text" > .git/info/attributes echo "*.gif filter=lfs -text" > a/.gitattributes echo "*.png filter=lfs -text" > a/b/.gitattributes git lfs track | tee track.log grep "Listing tracked patterns" track.log grep "*.mov ($(native_path_escaped ".git/info/attributes"))" track.log grep "*.jpg (.gitattributes)" track.log grep "*.gif ($(native_path_escaped "a/.gitattributes"))" track.log grep "*.png ($(native_path_escaped "a/b/.gitattributes"))" track.log grep "Set default behavior" .gitattributes grep "############" .gitattributes grep "* text=auto" .gitattributes grep "diff=csharp" .gitattributes grep "*.jpg" .gitattributes ) end_test begin_test "track --verbose" ( set -e reponame="track_verbose_logs" mkdir "$reponame" cd "$reponame" git init touch foo.dat git add foo.dat git lfs track --verbose "foo.dat" 2>&1 > track.log grep "touching \"foo.dat\"" track.log ) end_test begin_test "track --dry-run" ( set -e reponame="track_dry_run" mkdir "$reponame" cd "$reponame" git init touch foo.dat git add foo.dat git lfs track --dry-run "foo.dat" 2>&1 > track.log grep "Tracking \"foo.dat\"" track.log grep "Git LFS: touching \"foo.dat\"" track.log git status --porcelain 2>&1 > status.log grep "A foo.dat" status.log ) end_test begin_test "track directory" ( set -e mkdir dir cd dir git init git lfs track "foo bar\\*" | tee track.txt [ "foo[[:space:]]bar/* filter=lfs diff=lfs merge=lfs -text" = "$(cat .gitattributes)" ] [ "Tracking \"foo bar/*\"" = "$(cat track.txt)" ] mkdir "foo bar" echo "a" > "foo bar/a" echo "b" > "foo bar/b" git add foo\ bar git commit -am "add foo bar" assert_pointer "master" "foo bar/a" "87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7" 2 assert_pointer "master" "foo bar/b" "0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f" 2 ) end_test begin_test "track without trailing linebreak" ( set -e mkdir no-linebreak cd no-linebreak git init printf "*.mov filter=lfs -text" > .gitattributes [ "*.mov filter=lfs -text" = "$(cat .gitattributes)" ] git lfs track "*.gif" expected="*.mov filter=lfs -text$(cat_end) *.gif filter=lfs diff=lfs merge=lfs -text$(cat_end)" [ "$expected" = "$(cat -e .gitattributes)" ] ) end_test begin_test "track with existing crlf" ( set -e mkdir existing-crlf cd existing-crlf git init git config core.autocrlf true git lfs track "*.mov" git lfs track "*.gif" expected="*.mov filter=lfs diff=lfs merge=lfs -text^M$ *.gif filter=lfs diff=lfs merge=lfs -text^M$" [ "$expected" = "$(cat -e .gitattributes)" ] git config core.autocrlf false git lfs track "*.jpg" expected="*.mov filter=lfs diff=lfs merge=lfs -text^M$ *.gif filter=lfs diff=lfs merge=lfs -text^M$ *.jpg filter=lfs diff=lfs merge=lfs -text^M$" [ "$expected" = "$(cat -e .gitattributes)" ] ) end_test begin_test "track with autocrlf=true" ( set -e mkdir autocrlf-true cd autocrlf-true git init git config core.autocrlf true printf "*.mov filter=lfs -text" > .gitattributes [ "*.mov filter=lfs -text" = "$(cat .gitattributes)" ] git lfs track "*.gif" expected="*.mov filter=lfs -text^M$ *.gif filter=lfs diff=lfs merge=lfs -text^M$" [ "$expected" = "$(cat -e .gitattributes)" ] ) end_test begin_test "track with autocrlf=input" ( set -e mkdir autocrlf-input cd autocrlf-input git init git config core.autocrlf input printf "*.mov filter=lfs -text" > .gitattributes [ "*.mov filter=lfs -text" = "$(cat .gitattributes)" ] git lfs track "*.gif" expected="*.mov filter=lfs -text^M$ *.gif filter=lfs diff=lfs merge=lfs -text^M$" [ "$expected" = "$(cat -e .gitattributes)" ] ) end_test begin_test "track outside git repo" ( set -e git lfs track "*.foo" || { # this fails if it's run outside of a git repo using GIT_LFS_TEST_DIR # git itself returns an exit status of 128 # $ git show # fatal: Not a git repository (or any of the parent directories): .git # $ echo "$?" # 128 [ "$?" = "128" ] exit 0 } if [ -n "$GIT_LFS_TEST_DIR" ]; then echo "GIT_LFS_TEST_DIR should be set outside of any Git repository" exit 1 fi git init track-outside cd track-outside git lfs track "*.file" git lfs track "../*.foo" || { # git itself returns an exit status of 128 # $ git add ../test.foo # fatal: ../test.foo: '../test.foo' is outside repository # $ echo "$?" # 128 [ "$?" = "128" ] exit 0 } exit 1 ) end_test begin_test "track representation" ( set -e git init track-representation cd track-representation git lfs track "*.jpg" mkdir a git lfs track "a/test.file" cd a out3=$(git lfs track "test.file") if [ "$out3" != "\"test.file\" already supported" ]; then echo "Track didn't recognize duplicate path" cat .gitattributes exit 1 fi git lfs track "file.bin" cd .. out4=$(git lfs track "a/file.bin") if [ "$out4" != "\"a/file.bin\" already supported" ]; then echo "Track didn't recognize duplicate path" cat .gitattributes exit 1 fi ) end_test begin_test "track absolute" ( # MinGW bash intercepts '/images' and passes 'C:/Program Files/Git/images' as arg! if [[ $(uname) == *"MINGW"* ]]; then echo "Skipping track absolute on Windows" exit 0 fi set -e git init track-absolute cd track-absolute git lfs track "/images" cat .gitattributes grep "^/images" .gitattributes ) end_test begin_test "track in gitDir" ( set -e git init track-in-dot-git cd track-in-dot-git echo "some content" > test.file cd .git git lfs track "../test.file" || { # this fails if it's run inside a .git directory # git itself returns an exit status of 128 # $ git add ../test.file # fatal: This operation must be run in a work tree # $ echo "$?" # 128 [ "$?" = "128" ] exit 0 } # fail if track passed exit 1 ) end_test begin_test "track in symlinked dir" ( set -e git init track-symlinkdst ln -s track-symlinkdst track-symlinksrc cd track-symlinksrc git lfs track "*.png" grep "^*.png" .gitattributes || { echo ".gitattributes doesn't contain the expected relative path *.png:" cat .gitattributes exit 1 } ) end_test begin_test "track blocklisted files by name" ( set -e repo="track_blocklisted_by_name" mkdir "$repo" cd "$repo" git init touch .gitattributes git add .gitattributes git lfs track .gitattributes 2>&1 > track.log grep "Pattern .gitattributes matches forbidden file .gitattributes" track.log ) end_test begin_test "track blocklisted files with glob" ( set -e repo="track_blocklisted_glob" mkdir "$repo" cd "$repo" git init touch .gitattributes git add .gitattributes git lfs track ".git*" 2>&1 > track.log grep "Pattern .git\* matches forbidden file" track.log ) end_test begin_test "track lockable" ( set -e repo="track_lockable" mkdir "$repo" cd "$repo" git init # track *.jpg once, lockable git lfs track --lockable "*.jpg" | grep "Tracking \"\*.jpg\"" assert_attributes_count "jpg" "lockable" 1 # track *.jpg again, don't change anything. Should retain lockable git lfs track "*.jpg" | grep "\"*.jpg\" already supported" assert_attributes_count "jpg" "lockable" 1 # track *.png once, not lockable yet git lfs track "*.png" | grep "Tracking \"\*.png\"" assert_attributes_count "png" "filter=lfs" 1 assert_attributes_count "png" "lockable" 0 # track png again, enable lockable, should replace git lfs track --lockable "*.png" | grep "Tracking \"\*.png\"" assert_attributes_count "png" "filter=lfs" 1 assert_attributes_count "png" "lockable" 1 # track png again, disable lockable, should replace git lfs track --not-lockable "*.png" | grep "Tracking \"\*.png\"" assert_attributes_count "png" "filter=lfs" 1 assert_attributes_count "png" "lockable" 0 # check output reflects lockable out=$(git lfs track) echo "$out" | grep "Listing tracked patterns" echo "$out" | grep "*.jpg \[lockable\] (.gitattributes)" echo "$out" | grep "*.png (.gitattributes)" ) end_test begin_test "track lockable read-only/read-write" ( set -e repo="track_lockable_ro_rw" mkdir "$repo" cd "$repo" git init echo "blah blah" > test.bin echo "foo bar" > test.dat mkdir subfolder echo "sub blah blah" > subfolder/test.bin echo "sub foo bar" > subfolder/test.dat # should start writeable assert_file_writeable test.bin assert_file_writeable test.dat assert_file_writeable subfolder/test.bin assert_file_writeable subfolder/test.dat # track *.bin, not lockable yet git lfs track "*.bin" | grep "Tracking \"\*.bin\"" # track *.dat, lockable immediately git lfs track --lockable "*.dat" | grep "Tracking \"\*.dat\"" # bin should remain writeable, dat should have been made read-only assert_file_writeable test.bin refute_file_writeable test.dat assert_file_writeable subfolder/test.bin refute_file_writeable subfolder/test.dat git add .gitattributes test.bin test.dat git commit -m "First commit" # bin should still be writeable assert_file_writeable test.bin assert_file_writeable subfolder/test.bin # now make bin lockable git lfs track --lockable "*.bin" | grep "Tracking \"\*.bin\"" # bin should now be read-only refute_file_writeable test.bin refute_file_writeable subfolder/test.bin # remove lockable again git lfs track --not-lockable "*.bin" | grep "Tracking \"\*.bin\"" # bin should now be writeable again assert_file_writeable test.bin assert_file_writeable subfolder/test.bin ) end_test begin_test "track escaped pattern" ( set -e reponame="track-escaped-pattern" git init "$reponame" cd "$reponame" git lfs track " " | grep "Tracking \" \"" assert_attributes_count "[[:space:]]" "filter=lfs" 1 git lfs track "#" | grep "Tracking \"#\"" assert_attributes_count "\\#" "filter=lfs" 1 ) end_test begin_test "track (symlinked repository)" ( set -e reponame="tracked-symlinked-repository" git init "$reponame" cd "$reponame" touch a.dat pushd .. > /dev/null dir="tracked-symlinked-repository-tmp" mkdir -p "$dir" ln -s "../$reponame" "./$dir" cd "$dir/$reponame" [ "Tracking \"a.dat\"" = "$(git lfs track "a.dat")" ] [ "\"a.dat\" already supported" = "$(git lfs track "a.dat")" ] popd > /dev/null ) end_test begin_test "track (\$GIT_LFS_TRACK_NO_INSTALL_HOOKS)" ( set -e reponame="track-no-setup-hooks" git init "$reponame" cd "$reponame" [ ! -f .git/hooks/pre-push ] [ ! -f .git/hooks/post-checkout ] [ ! -f .git/hooks/post-commit ] [ ! -f .git/hooks/post-merge ] GIT_LFS_TRACK_NO_INSTALL_HOOKS=1 git lfs track [ ! -f .git/hooks/pre-push ] [ ! -f .git/hooks/post-checkout ] [ ! -f .git/hooks/post-commit ] [ ! -f .git/hooks/post-merge ] ) end_test begin_test "track (with comments)" ( set -e reponame="track-with=comments" git init "$reponame" cd "$reponame" echo "*.jpg filter=lfs diff=lfs merge=lfs -text" >> .gitattributes echo "# *.png filter=lfs diff=lfs merge=lfs -text" >> .gitattributes echo "*.pdf filter=lfs diff=lfs merge=lfs -text" >> .gitattributes git add .gitattributes git commit -m "initial commit" git lfs track 2>&1 | tee track.log if [ "0" -ne "${PIPESTATUS[0]}" ]; then echo >&2 "expected \`git lfs track\` command to exit cleanly, didn't" exit 1 fi [ "1" -eq "$(grep -c "\.jpg" track.log)" ] [ "1" -eq "$(grep -c "\.pdf" track.log)" ] [ "0" -eq "$(grep -c "\.png" track.log)" ] ) end_test begin_test "track (with current-directory prefix)" ( set -e reponame="track-with-current-directory-prefix" git init "$reponame" cd "$reponame" git lfs track "./a.dat" printf "a" > a.dat git add .gitattributes a.dat git commit -m "initial commit" grep -e "^a.dat" .gitattributes ) end_test begin_test "track (global gitattributes)" ( set -e reponame="track-global-gitattributes" git init "$reponame" cd "$reponame" global="$(cd .. && pwd)/gitattributes-global" echo "*.dat filter=lfs diff=lfs merge=lfs -text" > "$global" git config --local core.attributesfile "$global" git lfs track 2>&1 | tee track.log grep "*.dat" track.log ) end_test begin_test "track (system gitattributes)" ( set -e reponame="track-system-gitattributes" git init "$reponame" cd "$reponame" pushd "$TRASHDIR" > /dev/null mkdir -p "prefix/${reponame}/etc" cd "prefix/${reponame}/etc" echo "*.dat filter=lfs diff=lfs merge=lfs -text" > gitattributes popd > /dev/null PREFIX="${TRASHDIR}/prefix/${reponame}" git lfs track 2>&1 | tee track.log grep "*.dat" track.log ) end_test