2

I'm trying to listen file changes in a folder except .gitignore to trigger rebuild.

It seems like using inotifywait with --exclude option is the right way to do. Does anyone know a good way to convert .gitignore to regex such that inotifywait --exclude can accept correctly?

Kibeom Kim
  • 379
  • 3
  • 9

2 Answers2

3

Don't try to tell inotifywait ahead of time, it's better to run the modified paths through git check-ignore -nv --stdin. Spend more time with the gitignore docs, you'll see why, the patterns come from multiple sources and they're context-sensitive and they just stop things being automatically tracked, they don't prevent you specifically tracking a file anyway.

jthill
  • 42,819
  • 4
  • 65
  • 113
1

Here is a full example that watches for changes on non-gitignored files in the current directory, and runs ./build if any file changes.

One important thing is that .git/ is not .gitignored, so we check and ignore it as well.

inotifywait --event close_write --monitor --recursive . |
  while read -r directory events filename; do
    echo "directory events filename: \"${directory}\" \"${events}\" \"${filename}\""
    if ! echo "$directory" | grep -Eq '^\.\/\.git' &&
       ! git check-ignore --non-matching --verbose "${directory}/${filename}" >/dev/null 2>&1
    then
      echo 'will build'
      ./build
    fi
  done

GitHub upstream.

If you are a Vim user, you will also want the configs:

set backupcopy=no
set noswapfile
set nowritebackup

In Vim 8.1, set backupcopy=no prevents events of type:

directory events filename: "./" "CLOSE_WRITE,CLOSE" "4913"

The annoying 4913 is mentioned at:

(TODO minimize with vim -u NONE) prevents the creation of .swp files: How to prevent vim from creating (and leaving) temporary files?

Ideally we would also have --event moved_to,create but Vim generates 3 events per :w in that case, even though I tried to turn off all temporary files (TODO minimize example config with vim -u NONE):

directory events filename: "./" "MOVED_TO" "README.adoc~"
directory events filename: "./" "CREATE" "README.adoc"
directory events filename: "./" "CLOSE_WRITE,CLOSE" "README.adoc"

You could also consider to check if the file is git tracked to automatically include the .git: How to tell if a file is git tracked (by shell exit code)? but this approach is better as it uses the new files that you are testing even before they start being tracked.