#!/usr/bin/env bash # integrate-redbear.sh — Prepare Red Bear OS custom work for standard builds. # # Usage: # ./local/scripts/integrate-redbear.sh # REDBEAR_TAG=build/x86_64-unknown-redox/redbear.tag ./local/scripts/integrate-redbear.sh # # This script is idempotent and safe to run repeatedly. It ensures the Red Bear OS overlay # is wired into the main build tree, stages branding assets and firmware into local # recipe sources, and updates a tag file consumed by the build system. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" REDBEAR_TAG="${REDBEAR_TAG:-build/redbear.tag}" if [ -t 1 ]; then GREEN='\033[1;32m' YELLOW='\033[1;33m' CYAN='\033[1;36m' RESET='\033[0m' else GREEN='' YELLOW='' CYAN='' RESET='' fi cd "$PROJECT_ROOT" status() { echo -e "${GREEN}✅${RESET} $1" } warn() { echo -e "${YELLOW}⚠️${RESET} $1" } section() { echo -e "${CYAN}==>${RESET} $1" } require_repo_relative_path() { local path="$1" case "$path" in /*|../*|*/../*|..) warn "Refusing unsafe path outside repo: $path" return 1 ;; esac } require_real_parent_dirs() { local path="$1" local parent="$(dirname "$path")" require_repo_relative_path "$path" while [ "$parent" != "." ] && [ "$parent" != "/" ]; do if [ -L "$parent" ]; then warn "Refusing path with symlink parent: $path" return 1 fi parent="$(dirname "$parent")" done } symlink() { local target="$1" local link="$2" local current="" require_real_parent_dirs "$link" mkdir -p "$(dirname "$link")" if [ -L "$link" ]; then current="$(readlink "$link")" if [ "$current" = "$target" ]; then return 0 fi fi if [ -d "$link" ] && [ ! -L "$link" ]; then warn "Refusing to replace directory $link" return 1 fi if [ -e "$link" ] || [ -L "$link" ]; then rm -f "$link" ln -s "$target" "$link" status "Refreshed $link -> $target" else ln -s "$target" "$link" status "Linked $link -> $target" fi } stage_file() { local source_path="$1" local dest_path="$2" local label="$3" if [ ! -f "$source_path" ]; then warn "$label missing at ${source_path#$PROJECT_ROOT/}; skipping" return 0 fi require_real_parent_dirs "$dest_path" if [ -L "$dest_path" ]; then warn "$label destination is a symlink at ${dest_path#$PROJECT_ROOT/}; refusing to overwrite" return 1 fi mkdir -p "$(dirname "$dest_path")" if [ -f "$dest_path" ] && cmp -s "$source_path" "$dest_path"; then status "$label already staged" return 0 fi cp "$source_path" "$dest_path" status "Staged $label" } echo "========================================" echo " Red Bear OS Pre-Build Integration" echo "========================================" echo "Root: ${PROJECT_ROOT##*/}" echo "Tag: $REDBEAR_TAG" echo "" section "Ensuring custom recipe symlinks..." # Auto-discover all local/recipes/// directories and symlink # into recipes//. This replaces the previous 95-line manual # symlink list which was perpetually out of sync with local/recipes/. linked_count=0 skipped_count=0 while IFS= read -r -d '' recipe_dir; do rel_path="${recipe_dir#local/recipes/}" category="${rel_path%%/*}" name="${rel_path#*/}" link="recipes/${category}/${name}" # Compute relative path from link to target # recipes// → ../../local/recipes// target="../../local/recipes/${rel_path}" if symlink "$target" "$link"; then linked_count=$((linked_count + 1)) else skipped_count=$((skipped_count + 1)) fi done < <(find local/recipes -mindepth 2 -maxdepth 2 -type d -print0 2>/dev/null | sort -z) # Special alias: kf6-kirigami → kirigami (KDE expects both names) symlink "../../local/recipes/kde/kirigami" "recipes/kde/kf6-kirigami" # WIP compat: qt6-wayland-smoke lives under wayland/ but historically # was also linked under recipes/wip/wayland/ mkdir -p recipes/wip/wayland symlink "../../../../local/recipes/wayland/qt6-wayland-smoke" "recipes/wip/wayland/qt6-wayland-smoke" status "Custom recipe symlinks ready (${linked_count} linked, ${skipped_count} skipped)" echo "" section "Ensuring recipe patch symlinks..." # Auto-discover patches from local/patches// and create/refresh # symlinks in the corresponding recipe directories. This replaces the # previous hardcoded-per-patch approach which went stale whenever patches # were reorganized (e.g. moved to absorbed/ subdirectories). declare -A PATCH_COMPONENT_TO_RECIPE=( [kernel]="recipes/core/kernel" [base]="recipes/core/base" [relibc]="recipes/core/relibc" [bootloader]="recipes/core/bootloader" [installer]="recipes/core/installer" [userutils]="recipes/core/userutils" ) linked=0 skipped=0 for component in "${!PATCH_COMPONENT_TO_RECIPE[@]}"; do recipe_dir="${PATCH_COMPONENT_TO_RECIPE[$component]}" [ -d "$recipe_dir" ] || continue patch_dir="local/patches/${component}" # Collect all .patch files from the component dir (skip absorbed/ subdirs). find "$patch_dir" -maxdepth 1 -name "*.patch" -type f 2>/dev/null | while read patch_file; do patch_name="$(basename "$patch_file")" # Resolve the relative path from recipe dir to patch file. # recipe_dir is e.g. recipes/core/base (2 levels deep) # patch_file is e.g. local/patches/base/absorbed/P0-foo.patch # We need to go up from recipe_dir to repo root, then into local/patches/... # For recipes/core/base → ../../.. → repo root → local/patches/base/absorbed/... # Number of directory components = slashes + 1 depth=$(($(echo "$recipe_dir" | tr -cd '/' | wc -c) + 1)) up="" for ((i=0; i