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?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Kibeom Kim
  • 471
  • 1
  • 5
  • 12

2 Answers2

4

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.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
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
  • 55,082
  • 5
  • 77
  • 137