#!/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())
