#!/usr/bin/env python3
# Copyright (c) 2007-2011 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

import pty, os, select, sys, time
import optparse # pylint: disable=deprecated-module

op = optparse.OptionParser( usage="%prog [OPTIONS] DIRECTORY" )
op.add_option( "-c", "--command", action="store",
               help="run COMMAND when anything in DIRECTORY changes" )
op.add_option( "--ratelimit", action="store", type="float", metavar="PERIOD",
               help="run COMMAND at most once every PERIOD seconds " \
                  "(default=%default)" )
op.add_option( "-d", "--daemon", action="store_true",
               help="daemonize and return immediately" )
op.add_option( "--logfile", action="store",
               help="write output to LOGFILE (default=%default)" )
op.add_option( "--pidfile", action="store",
               help="write process ID to PIDFILE (default=%default)" )
op.add_option( "--debug", action="store_true",
               help="show inotifywait output" )
op.set_defaults( ratelimit=0 )
opts, args = op.parse_args()

if len( args ) != 1:
   op.error( "expected one argument" )

dir = args[0] # pylint: disable=redefined-builtin

if opts.daemon:
   if os.fork() != 0:
      sys.exit()
   os.setsid()
   if os.fork() != 0:
      os._exit( 0 ) # pylint: disable=protected-access
   os.umask( 0 )

with open( os.devnull, 'r' ) as f:
   os.dup2( f.fileno(), 0 )

if opts.logfile:
   with open( opts.logfile, 'a+' ) as f:
      os.dup2( f.fileno(), 1 )
      os.dup2( f.fileno(), 2 )

if opts.pidfile:
   with open( opts.pidfile, "w" ) as fd:
      fd.write( f"{os.getpid()}\n" )

os.chdir( dir )
pid, fd = pty.fork()
if pid == 0:
   x = [ "inotifywait", "-m", "-r", "-e", "modify", "-e", "create",
         "-e", "delete", "-e", "attrib", "-e", "move", "." ]
   os.execvp( x[0], x )
else:
   while True:
      if opts.command:
         os.spawnvp( os.P_WAIT, "sh", ["sh", "-c", opts.command] )
      select.select( [fd], [], [] )
      time.sleep( opts.ratelimit )
      try:
         while fd in select.select( [fd], [], [], 0 )[0]:
            x = os.read( fd, 1024 )
            if opts.debug:
               sys.stdout.buffer.write( x )
               sys.stdout.flush()
      except OSError: break # pylint: disable=multiple-statements

sys.exit( os.waitpid( pid, 0 )[1] )
