Skip to content
Snippets Groups Projects
watcher.py 3.86 KiB
Newer Older
#!/usr/bin/env python3.10
#
# Copyright (C) 2021 Associated Universities, Inc. Washington DC, USA.
#
# This file is part of NRAO Workspaces.
#
# Workspaces is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Workspaces is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Workspaces.  If not, see <https://www.gnu.org/licenses/>.

import re
import subprocess
import sys
import time

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer


class PexHandler(FileSystemEventHandler):
    event_cache = {}

    def on_modified(self, event):
        print(event)
        if event.is_directory or event.src_path.endswith(".py~"):
            return

        seconds = int(time.time())
        key = (seconds, event.src_path)

        # check for identical events
        if key in self.event_cache:
            return

        # don't handle events if they happen quickly after another event
        if self.event_cache.__len__() != 0:
            previous_entry = list(self.event_cache)[-1]
            elapsed_time = seconds - previous_entry[0]
            print(f"elapsed_time between events: {elapsed_time}")
            if elapsed_time < 10:
                print(f"Too little time between events, Skipping...")
                return

        self.event_cache[key] = True

        # Only build pex if changes are made to files that end in ".py"
        if event.src_path.endswith(".py"):
            pexable = re.search("/pexable/(.*?)/", event.src_path).group(1)
            print(f"******************** Building pex - {pexable} ********************")
            # run local-build-pexables.sh
            sp = subprocess.run(
                ["./bin/local-build-pexables.sh", f"{pexable}"],
                stdout=subprocess.PIPE,
                universal_newlines=True,
            )
            print(f"{sp.stdout}")
            print(f"*********************** {pexable} finished ***********************")
        print("Modification event handled.")


def build_missing_pexes(path_to_sbin, path_to_pexables):
    sbin_content = os.listdir(path_to_sbin)
    pexables = os.listdir(path_to_pexables)
    existing_pexes_in_sbin = set(sbin_content).intersection(set(pexables))
    if len(pexables) > len(existing_pexes_in_sbin):
        missing_pexables = set(pexables).difference(existing_pexes_in_sbin)
        print(
            f"There {'is' if len(missing_pexables) == 1 else 'are'} "
            f"{len(missing_pexables)} pex{'' if len(missing_pexables) == 1 else 'es'} "
            f"missing from your sbin area: \n{missing_pexables}"
        )
        for pex in missing_pexables:
            print(f"Building {pex}")
            sp = subprocess.run(
                ["./bin/local-build-pexables.sh", f"{pex}"],
                stdout=subprocess.PIPE,
                universal_newlines=True,
            )
            print(f"{sp.stdout}")
    else:
        print("There are no missing pexes.")


if __name__ == "__main__":
    path_to_sbin = "/lustre/aoc/cluster/pipeline/docker/workspaces/sbin"
    path_to_pexables = sys.argv[1] if len(sys.argv) > 1 else "./apps/cli/executables/pexable/"

    build_missing_pexes(path_to_sbin, path_to_pexables)
    print("Starting Pex Watcher...")

    event_handler = PexHandler()
    observer = Observer()
    observer.schedule(event_handler, path_to_pexables, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    finally:
        observer.stop()
        observer.join()