Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 5 additions & 26 deletions scripts/actions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,32 +120,11 @@ case "$1" in
# This script creates symbolic links to the shared working directories.
# 1. Get the path of the private config of the cluster
# 2. Read the yaml and extract the path of the shared conf
# This uses the yq command. It is a python package so uvx (bundled with uv) will donwload and create the right venv
export working_dir=$(cat $("$PRIVATE_REPO_PATH"/hpc/platform-env.py hpc-config) | uvx yq .path_shared_working_dir)
# Remove quotes
export working_dir=$(echo "$working_dir" | sed 's/[\"\x27]//g')
# If the working directory does not exist, exit with an error
if [ ! -d "$working_dir" ]; then
echo "Working directory $working_dir does not exist. Please check the configuration."
exit 1
fi
# Ensure the working directory ends with a slash
if [[ "$working_dir" != */ ]]; then
working_dir="$working_dir/"
fi
echo "Working directory: $working_dir"
# Create all the links
for d in "logs" "models" "output" "plots" "results"
do
# If the link already exists, do nothing
# If a file with the same name exists, skip it
if [ -e "$d" ]; then
echo "'$d' already exists, skipping. The results in $d will not be linked to the shared working directory."
continue
fi
echo "$d -> $working_dir$d"
ln -s "$working_dir$d" "$d"
done
# A new --fix flag is supported by the Python script to remove incorrect
# symlinks automatically; pass it after the command name below.
# The Python helper handles config lookup and symlink validation/creation.
shift # consume the "create-links" argument and forward remaining args
uv run --no-project python scripts/check_symlinks.py "$@"
)
;;
create-jupyter-kernel)
Expand Down
102 changes: 102 additions & 0 deletions scripts/check_symlinks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env -S uv run
# /// script
# dependencies = [ "PyYAML", "GitPython"
# ]
# [tool.uv]
# exclude-newer = "2025-01-01T00:00:00Z"
# ///

import argparse
import logging
import os
import subprocess
import sys

import yaml

# parse command-line options
parser = argparse.ArgumentParser(description="Create symlinks to shared directories")
parser.add_argument(
"--fix",
action="store_true",
help="automatically remove and recreate any incorrect symlinks",
)
args = parser.parse_args()

logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)

# Change to the repo root directory (parent of scripts/)
script_dir = os.path.dirname(os.path.abspath(__file__))
repo_root = os.path.dirname(script_dir)
os.chdir(repo_root)

# This script creates symbolic links to the shared working directories.
# 1. Get the path of the private config of the cluster
# 2. Read the yaml and extract the path of the shared conf
# This uses the yq command equivalent in Python with PyYAML

# Run the command to get the config file path
try:
result = subprocess.run(
["../WeatherGenerator-private/hpc/platform-env.py", "hpc-config"],
capture_output=True,
text=True,
check=True,
)
config_file = result.stdout.strip()
except subprocess.CalledProcessError as e:
logger.error(f"Error running platform-env.py: {e}")
sys.exit(1)

# Read the YAML file
try:
with open(config_file) as f:
data = yaml.safe_load(f)
working_dir = data["path_shared_working_dir"]
except (FileNotFoundError, yaml.YAMLError) as e:
logger.error(f"Error reading config file {config_file}: {e}")
sys.exit(1)

# Remove quotes
working_dir = working_dir.strip("\"'").strip()

# If the working directory does not exist, exit with an error
if not os.path.isdir(working_dir):
logger.error(f"Working directory {working_dir} does not exist. Please check the configuration.")
sys.exit(1)

# Ensure the working directory ends with a slash
if not working_dir.endswith("/"):
working_dir += "/"

logger.info(f"Working directory: {working_dir}")

# Create all the links
for d in ["logs", "models", "plots", "results"]:
target = working_dir + d
# Check if something exists at this path (including broken symlinks)
if os.path.islink(d):
# It's a symlink - check if it points to the correct target
if os.readlink(d) == target and os.path.exists(target):
logger.info(f"'{d}' already correctly linked to {target}, skipping.")
continue
else:
logger.warning(f"'{d}' is a symlink BUT IS NOT correctly linked to {target}.")
if args.fix:
logger.info(f"Removing incorrect symlink '{d}' and recreating it.")
os.remove(d)
# fall through to create the correct link below
else:
logger.warning("Run this script with --fix to remove it automatically.")
continue
elif os.path.exists(d):
# It exists but is not a symlink (regular file or directory)
logger.warning(
f"'{d}' exists as a file/directory (not a symlink), PLEASE REMOVE IT MANUALLY."
)
continue

# create link if we didn't continue above
logger.info(f"{d} -> {target}")
os.symlink(target, d)
Loading