commit 3d6bc4b0dd4a879b9a5b9795e82419b459516434
Author: David Sorber <david.sorber@gmail.com>
Date:   Wed Jun 13 09:46:20 2018 -0400

    Adding git monitor script.

diff --git a/software/misc/git_monitor.py b/software/misc/git_monitor.py
new file mode 100755
index 0000000..9e16bd2
--- /dev/null
+++ b/software/misc/git_monitor.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python3
+
+import logging
+import subprocess
+import sys
+import time
+
+# --- Config ---
+
+# Polling duration in seconds
+POLLING_PERIOD = 15
+
+# Upstream branch identification
+UPSTREAM = 'origin/master'
+
+# Full path to cloned git repository
+GIT_DIR = '/home/dsorber/dev/repo'
+
+# Full path to "action" script to be executed after any changes have been 
+# pulled
+ACTION_SCRIPT = '/home/dsorber/Desktop/post_pull_action.sh'
+
+# Full path of file in which to log output. If empty log output will be written
+# to stdout.
+LOGFILE_PATH = ''
+
+
+def execute_command(command_str, quiet=True):
+    error = False
+    try:
+        output = subprocess.check_output(command_str, shell=True, 
+                                         stderr=subprocess.STDOUT)
+        output = output.decode('utf-8').strip()
+        if output and not quiet:
+            logging.debug(output)
+    except subprocess.CalledProcessError:
+        error = True
+        if output:
+            logging.error(output)
+        else:
+            logging.error('An error occurred while attempting to execute '
+                          '"{:s}"'.format(command_str))
+
+    return (error, output)
+
+def main():
+    logging.info('{:s} starting'.format(sys.argv[0].startswith('./') and 
+                                        sys.argv[0][2:] or sys.argv[0]))
+    
+    while True:
+        # Git fetch first so we can compare reivsions
+        logging.info('Fetching remote history')
+        cmd = 'cd {:s}; git fetch'.format(GIT_DIR)
+        error, _ = execute_command(cmd)
+        if error:
+            logging.warn('Script terminating due to previous error')
+            break
+        
+        # Get local revision 
+        cmd = 'cd {:s}; git rev-parse @'.format(GIT_DIR)
+        error, local_rev = execute_command(cmd)
+        if error:
+            logging.warn('Script terminating due to previous error')
+            break
+        
+        # Get remote revision
+        cmd = 'cd {:s}; git rev-parse "{:s}"'.format(GIT_DIR, UPSTREAM)
+        error, remote_rev = execute_command(cmd)
+        if error:
+            logging.warn('Script terminating due to previous error')
+            break
+        
+        # Get merge base revision
+        cmd = 'cd {:s}; git merge-base @ "{:s}"'.format(GIT_DIR, UPSTREAM)
+        error, base_rev = execute_command(cmd)
+        if error:
+            logging.warn('Script terminating due to previous error')
+            break
+        
+        # Now decide what to do
+        if local_rev == remote_rev:
+            logging.info('Up-to-date with "{:s}"'.format(UPSTREAM))
+        elif remote_rev == base_rev:
+            logging.warn('Local changes found, need to push them')
+        elif local_rev == base_rev:
+            logging.info('Remote changes found, preparing to pull them')
+            
+            # Pull remote changes
+            cmd = 'cd {:s}; git pull'.format(GIT_DIR)
+            error, _ = execute_command(cmd, False)
+            if error:
+                logging.warn('Script terminating due to previous error')
+                break
+                
+            # Now execute "action" script if one has been specified
+            if ACTION_SCRIPT:
+                cmd = '{:s}'.format(ACTION_SCRIPT)
+                error, script_output = execute_command(cmd)
+                if error:
+                    logging.warn('Script terminating due to previous error')
+                    break
+        
+        # Sleep for a while
+        time.sleep(POLLING_PERIOD)
+        
+    logging.info('{:s} stopping'.format(sys.argv[0]))
+     
+if __name__ == '__main__':
+    if LOGFILE_PATH:
+        logging.basicConfig(format='%(asctime)s|%(levelname)s|%(message)s', 
+                            datefmt='%a %b %d %H:%M:%S %Y', 
+                            filename=LOGFILE_PATH, level=logging.DEBUG)
+    else:
+        logging.basicConfig(format='%(asctime)s|%(levelname)s|%(message)s', 
+                            datefmt='%a %b %d %H:%M:%S %Y', 
+                            level=logging.DEBUG)
+    sys.exit(main())
