diff --git a/.gitignore b/.gitignore index ccab439..8db1792 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,7 @@ compile CMakeCache.txt cmake_install.cmake src/intern/.dirstamp + +# Docker build outputs +*.tar.gz +dxfrw-*.tar.gz diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 92c81aa..0000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM centos:7 - -MAINTAINER CodeLibs Project - -RUN yum -y groupinstall base "Development tools" --setopt=group_package_types=mandatory,default,optional -RUN yum clean all - -RUN mkdir /work -WORKDIR /work - -CMD ["sh", "/opt/bin/run.sh"] - diff --git a/README.md b/README.md index 221e3ae..87c2eb2 100644 --- a/README.md +++ b/README.md @@ -145,25 +145,45 @@ cmake --build . --config Release --target install ### Docker Build -#### Build Docker Image: +Build portable binaries for multiple OS distributions using Docker. + +> **Note:** Dockerfiles are in `docker/` directory. Build process updated from CentOS 7 (EOL) to AlmaLinux 9. + +**Available OS Distributions:** + +| OS | Tag | Use Case | +|----|-----|----------| +| AlmaLinux 9 | `almalinux` | RHEL/CentOS compatible (CentOS successor) | +| Ubuntu 22.04 LTS | `ubuntu` | Debian/Ubuntu compatible | +| Amazon Linux 2023 | `amazonlinux` | AWS optimized | +| Alpine Linux | `alpine` | Lightweight musl-based | + +**Quick Start:** ```bash -docker build --rm -t codelibs/libdxfrw . +# Build for single OS (creates dxfrw-{os}.tar.gz) +./docker/build-docker.sh run almalinux +./docker/build-docker.sh run ubuntu + +# Build for all OS distributions +./docker/build-docker.sh run all-os + +# Extract and install +sudo tar xzf dxfrw-almalinux.tar.gz -C /opt ``` -#### Build Library Using Docker: +**Manual Docker Commands (if needed):** ```bash -docker run -t --rm -v `pwd`:/work codelibs/libdxfrw:latest /work/build.sh +# Build image and library +docker build -t codelibs/libdxfrw:ubuntu -f docker/Dockerfile.ubuntu . +docker run -t --rm -v `pwd`:/work codelibs/libdxfrw:ubuntu /work/build.sh ``` -This creates `dxfrw.tar.gz`. Extract it under `/opt` or your preferred location. - -#### Push Docker Image: +**Push to Docker Hub:** ```bash -docker tag codelibs/libdxfrw codelibs/libdxfrw:centos7 -docker push codelibs/libdxfrw:centos7 +./docker/build-docker.sh push almalinux ``` ## Installation @@ -302,6 +322,59 @@ The source code in `dwg2dxf/` serves as a comprehensive reference implementation Extracts text information from DWG files. +## Utility Scripts + +The library includes utility scripts in the `bin/` directory for extracting text content from DXF/DWG files. + +### dwg2txt - DWG to Text Converter + +Extracts text entities from DWG files: + +```bash +# Usage +./bin/dwg2txt + +# Example +./bin/dwg2txt drawing.dwg output.txt +``` + +**Requirements:** +- `dwg2text` executable (built with the library) + +### dxf2txt - DXF to Text Converter + +Extracts text entities from DXF files: + +```bash +# Usage +./bin/dxf2txt + +# Example +./bin/dxf2txt drawing.dxf output.txt +``` + +**Requirements:** +- Python 3.9 or later (minimum version across all Docker build environments) +- `ezdxf` Python package: `pip install ezdxf` + +**Features:** +- Supports both TEXT and MTEXT entities +- Handles multiple DXF versions (R12 through 2018+) +- Automatic encoding detection (UTF-8, CP932/Shift-JIS) +- Preserves multi-line text formatting + +### Direct Python Usage + +You can also use the Python script directly: + +```bash +# Install ezdxf if not already installed +pip install ezdxf + +# Run the script +python3 bin/dxf2txt.py input.dxf output.txt +``` + ## Testing The library includes comprehensive tests covering various aspects: diff --git a/bin/dwg2txt b/bin/dwg2txt index 185a022..3403b25 100755 --- a/bin/dwg2txt +++ b/bin/dwg2txt @@ -1,9 +1,60 @@ #!/bin/bash +# +# dwg2txt - Convert DWG files to text format +# Uses dwg2text utility to extract text content from DWG files +# -INPUT_FILE=$1 -OUTPUT_FILE=$2 +set -e -`dirname $0`/dwg2text $INPUT_FILE > $OUTPUT_FILE -if [ $? != 0 ] ; then - echo > $OUTPUT_FILE +# Get script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Function to show usage +usage() { + cat << EOF +Usage: $0 + +Convert DWG file to text format by extracting text entities. + +Arguments: + input.dwg Input DWG file path + output.txt Output text file path + +Example: + $0 drawing.dwg output.txt + +EOF + exit 1 +} + +# Check arguments +if [ $# -ne 2 ]; then + echo "Error: Invalid number of arguments" + usage +fi + +INPUT_FILE="$1" +OUTPUT_FILE="$2" + +# Check if input file exists +if [ ! -f "$INPUT_FILE" ]; then + echo "Error: Input file does not exist: $INPUT_FILE" + exit 1 +fi + +# Check if dwg2text exists +DWG2TEXT="${SCRIPT_DIR}/dwg2text" +if [ ! -x "$DWG2TEXT" ]; then + echo "Error: dwg2text utility not found or not executable: $DWG2TEXT" + exit 1 +fi + +# Convert DWG to text +if "$DWG2TEXT" "$INPUT_FILE" > "$OUTPUT_FILE" 2>&1; then + echo "✓ Successfully converted: $OUTPUT_FILE" + exit 0 +else + echo "⚠ Warning: dwg2text failed, creating empty output file" + echo "" > "$OUTPUT_FILE" + exit 1 fi diff --git a/bin/dxf2txt b/bin/dxf2txt index 8db738a..dd7cea5 100755 --- a/bin/dxf2txt +++ b/bin/dxf2txt @@ -1,7 +1,74 @@ #!/bin/bash +# +# dxf2txt - Convert DXF files to text format +# Uses Python script to extract text content from DXF files +# -INPUT_FILE=$1 -OUTPUT_FILE=$2 +set -e -python `dirname $0`/dxf2txt.py $INPUT_FILE $OUTPUT_FILE +# Get script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Function to show usage +usage() { + cat << EOF +Usage: $0 + +Convert DXF file to text format by extracting text entities. + +Arguments: + input.dxf Input DXF file path + output.txt Output text file path + +Example: + $0 drawing.dxf output.txt + +Requirements: + - Python 3 + - ezdxf Python package (pip install ezdxf) + +EOF + exit 1 +} + +# Check arguments +if [ $# -ne 2 ]; then + echo "Error: Invalid number of arguments" + usage +fi + +INPUT_FILE="$1" +OUTPUT_FILE="$2" + +# Check if input file exists +if [ ! -f "$INPUT_FILE" ]; then + echo "Error: Input file does not exist: $INPUT_FILE" + exit 1 +fi + +# Find Python interpreter +PYTHON="" +for cmd in python3 python; do + if command -v $cmd >/dev/null 2>&1; then + PYTHON=$cmd + break + fi +done + +if [ -z "$PYTHON" ]; then + echo "Error: Python not found. Please install Python 3." + exit 1 +fi + +# Check if ezdxf is available +if ! $PYTHON -c "import ezdxf" 2>/dev/null; then + echo "Error: ezdxf package not found. Please install it:" + echo " pip install ezdxf" + exit 1 +fi + +# Convert DXF to text +$PYTHON "${SCRIPT_DIR}/dxf2txt.py" "$INPUT_FILE" "$OUTPUT_FILE" + +echo "✓ Successfully converted: $OUTPUT_FILE" diff --git a/bin/dxf2txt.py b/bin/dxf2txt.py index 68db0fe..30331fc 100644 --- a/bin/dxf2txt.py +++ b/bin/dxf2txt.py @@ -1,35 +1,107 @@ +#!/usr/bin/env python3 # -*- coding: utf-8 -*- -from __future__ import print_function -from __future__ import unicode_literals -from __future__ import absolute_import -from __future__ import generators -from __future__ import division +""" +dxf2txt.py - Extract text content from DXF files + +This script reads a DXF file and extracts all text entities (TEXT and MTEXT) +to a text file. It handles different DXF versions and character encodings. + +Usage: + python3 dxf2txt.py + +Requirements: + - Python 3.9+ (minimum version available across all supported OS distributions) + - ezdxf package (pip install ezdxf) + +Supported OS and their Python versions: + - Ubuntu 22.04 LTS: Python 3.10 + - AlmaLinux 9: Python 3.9 + - Amazon Linux 2023: Python 3.9 + - Alpine Linux 3.19: Python 3.11 + +Author: CodeLibs Project +""" import re import sys import ezdxf +from pathlib import Path + + +def show_usage(): + """Display usage information""" + print(__doc__) + sys.exit(1) + + +def extract_text_from_dxf(input_file, output_file): + """ + Extract text entities from DXF file and save to text file + + Args: + input_file: Path to input DXF file + output_file: Path to output text file + """ + # Check if input file exists + if not Path(input_file).exists(): + print(f"Error: Input file not found: {input_file}", file=sys.stderr) + sys.exit(1) + + try: + # Try reading with UTF-8 encoding first + dwg = ezdxf.readfile(input_file, encoding='utf-8') + + # For older DXF versions, try CP932 encoding (Japanese Shift-JIS) + old_enc_versions = ['AC1009', 'AC1015', 'AC1018'] + if dwg.dxfversion in old_enc_versions: + try: + dwg = ezdxf.readfile(input_file, encoding='cp932') + except: + pass # Keep UTF-8 version if CP932 fails + + # Extract text entities + texts = [] + modelspace = dwg.modelspace() + + for entity in modelspace: + if entity.dxftype() == 'TEXT': + # Simple text entity + texts.append(entity.dxf.text) + elif entity.dxftype() == 'MTEXT': + # Multi-line text entity + # Remove formatting codes and convert \P to newlines + text = re.sub(r'\{\\f[^;]+;([^}]+)\}', r'\1', entity.plain_text()) + text = text.replace('\\P', '\n') + texts.append(text) + + # Write extracted text to output file + with open(output_file, 'w', encoding='utf-8') as f: + for text in texts: + f.write(text + '\n') + + print(f"Extracted {len(texts)} text entities from {dwg.dxfversion} format DXF") + + except ezdxf.DXFError as e: + print(f"Error: Failed to read DXF file: {e}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def main(): + """Main entry point""" + # Check arguments + if len(sys.argv) != 3: + print(f"Error: Invalid arguments", file=sys.stderr) + show_usage() + + input_file = sys.argv[1] + output_file = sys.argv[2] + + extract_text_from_dxf(input_file, output_file) + -if len(sys.argv) != 3: - print("Invalid arguments: " + str(sys.argv)) - exit(1) - -dwg = ezdxf.readfile(sys.argv[1], encoding='utf-8') - -print(dwg.dxfversion) -old_enc_versions = ['AC1009', 'AC1015', 'AC1018'] -if dwg.dxfversion in old_enc_versions: - dwg = ezdxf.readfile(sys.argv[1], encoding='cp932') - -texts = [] -block_pattern = r'\{\f.*;([^}]+)\}' -modelspace = dwg.modelspace() -for e in modelspace: - if e.dxftype() == 'TEXT': - texts.append(e.dxf.text) - elif e.dxftype() == 'MTEXT': - v = re.sub(r'\{\\f[^;]+;([^}]+)\}', r'\1', e.plain_text()).replace('\\P', '\n') - texts.append(v) - -with open(sys.argv[2], 'w', encoding='utf-8') as f: - f.writelines([(t+'\n') for t in texts]) +if __name__ == '__main__': + main() diff --git a/build.sh b/build.sh index 56243cf..099245b 100755 --- a/build.sh +++ b/build.sh @@ -1,11 +1,87 @@ #!/bin/bash +# +# Build script for libdxfrw +# This script is designed to run inside Docker containers +# and creates a distributable tar.gz archive +# +# Robust error handling +# -e: Exit on error +# -u: Exit on undefined variable +# -o pipefail: Fail on pipe errors +set -euo pipefail + +echo "==========================================" +echo "libdxfrw Build Script" +echo "==========================================" + +# Configuration +PREFIX="/opt/dxfrw" +OUTPUT_DIR="/work" +OUTPUT_FILE="dxfrw.tar.gz" + +# Start timer +START_TIME=$(date +%s) + +# Step 1: Generate configure script +echo "" +echo "[1/6] Generating configure script..." autoreconf -vfi -./configure --prefix=/opt/dxfrw -make + +# Step 2: Configure build +echo "" +echo "[2/6] Configuring build..." +./configure --prefix="${PREFIX}" + +# Step 3: Build library +echo "" +echo "[3/6] Building library..." +make -j$(nproc) + +# Step 4: Install to prefix +echo "" +echo "[4/6] Installing to ${PREFIX}..." make install -make clean -cp bin/* /opt/dxfrw/bin + +# Step 5: Copy additional binaries if they exist +echo "" +echo "[5/6] Copying additional binaries..." +if [ -d "bin" ] && [ "$(ls -A bin 2>/dev/null)" ]; then + mkdir -p "${PREFIX}/bin" + cp -v bin/* "${PREFIX}/bin/" || true +else + echo "No additional binaries found in bin/ directory" +fi + +# Step 6: Create distributable archive +echo "" +echo "[6/6] Creating distributable archive..." cd /opt -tar zcvf /work/dxfrw.tar.gz dxfrw -chmod 777 /work/dxfrw.tar.gz +tar czf "${OUTPUT_DIR}/${OUTPUT_FILE}" dxfrw + +# Set permissions to allow host user access when running in Docker +# 666 (rw-rw-rw-) ensures the file can be accessed even if Docker runs as different UID +chmod 666 "${OUTPUT_DIR}/${OUTPUT_FILE}" + +# Calculate elapsed time +END_TIME=$(date +%s) +ELAPSED=$((END_TIME - START_TIME)) + +# Show summary +echo "" +echo "==========================================" +echo "✓ Build completed successfully!" +echo "==========================================" +echo "Output file: ${OUTPUT_DIR}/${OUTPUT_FILE}" +echo "File size: $(du -h "${OUTPUT_DIR}/${OUTPUT_FILE}" | cut -f1)" +echo "Build time: ${ELAPSED} seconds" +echo "==========================================" +echo "" +echo "To extract the archive:" +echo " tar xzf ${OUTPUT_FILE} -C /opt" +echo "" + +# Clean up build artifacts +echo "Cleaning up build artifacts..." +cd /work +make clean 2>/dev/null || true diff --git a/docker/Dockerfile.almalinux b/docker/Dockerfile.almalinux new file mode 100644 index 0000000..8b57c6e --- /dev/null +++ b/docker/Dockerfile.almalinux @@ -0,0 +1,22 @@ +# AlmaLinux 9 Dockerfile for libdxfrw +# Use this for building RHEL/CentOS compatible binaries +# AlmaLinux is the successor to CentOS + +FROM almalinux:9 + +LABEL maintainer="CodeLibs Project" +LABEL description="Build environment for libdxfrw on AlmaLinux 9" + +# Install build dependencies +RUN dnf -y groupinstall "Development Tools" && \ + dnf -y install \ + autoconf \ + automake \ + libtool \ + pkg-config \ + && dnf clean all + +WORKDIR /work + +# Default command +CMD ["sh", "/work/build.sh"] diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine new file mode 100644 index 0000000..091f1a5 --- /dev/null +++ b/docker/Dockerfile.alpine @@ -0,0 +1,24 @@ +# Alpine Linux Dockerfile for libdxfrw +# Use this for building lightweight musl-based binaries + +FROM alpine:3.19 + +LABEL maintainer="CodeLibs Project" +LABEL description="Build environment for libdxfrw on Alpine Linux (musl-based)" + +# Install build dependencies +# Note: Alpine uses musl libc instead of glibc +RUN apk add --no-cache \ + build-base \ + autoconf \ + automake \ + libtool \ + pkgconfig \ + bash \ + tar \ + gzip + +WORKDIR /work + +# Default command +CMD ["sh", "/work/build.sh"] diff --git a/docker/Dockerfile.amazonlinux b/docker/Dockerfile.amazonlinux new file mode 100644 index 0000000..66f9cec --- /dev/null +++ b/docker/Dockerfile.amazonlinux @@ -0,0 +1,23 @@ +# Amazon Linux 2023 Dockerfile for libdxfrw +# Use this for building AWS/Amazon Linux compatible binaries + +FROM amazonlinux:2023 + +LABEL maintainer="CodeLibs Project" +LABEL description="Build environment for libdxfrw on Amazon Linux 2023" + +# Install build dependencies +RUN dnf -y groupinstall "Development Tools" && \ + dnf -y install \ + autoconf \ + automake \ + libtool \ + pkg-config \ + tar \ + gzip \ + && dnf clean all + +WORKDIR /work + +# Default command +CMD ["sh", "/work/build.sh"] diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu new file mode 100644 index 0000000..7a3466a --- /dev/null +++ b/docker/Dockerfile.ubuntu @@ -0,0 +1,27 @@ +# Ubuntu 22.04 LTS Dockerfile for libdxfrw +# Use this for building Debian/Ubuntu compatible binaries + +FROM ubuntu:22.04 AS builder + +LABEL maintainer="CodeLibs Project" +LABEL description="Build environment for libdxfrw on Ubuntu 22.04 LTS" + +# Avoid interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Install build dependencies +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + autoconf \ + automake \ + libtool \ + pkg-config \ + libiconv-hook-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /work + +# Default command +CMD ["sh", "/work/build.sh"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..671d89b --- /dev/null +++ b/docker/README.md @@ -0,0 +1,55 @@ +# Docker Build Configuration + +This directory contains Docker build configurations for libdxfrw supporting multiple OS distributions. + +## Files + +- **`Dockerfile.ubuntu`** - Ubuntu 22.04 LTS (Debian-based) +- **`Dockerfile.almalinux`** - AlmaLinux 9 (RHEL/CentOS compatible, CentOS successor) +- **`Dockerfile.amazonlinux`** - Amazon Linux 2023 (AWS optimized) +- **`Dockerfile.alpine`** - Alpine Linux (lightweight, musl-based) +- **`build-docker.sh`** - Automated build script for all distributions + +## Quick Usage + +```bash +# Build for single OS +./build-docker.sh run almalinux + +# Build for all OS +./build-docker.sh run all-os + +# See all options +./build-docker.sh +``` + +## Output + +Each build creates a tar.gz archive in the project root: +- `dxfrw-ubuntu.tar.gz` +- `dxfrw-almalinux.tar.gz` +- `dxfrw-amazonlinux.tar.gz` +- `dxfrw-alpine.tar.gz` + +## OS Selection Guide + +| Choose | When you need | +|--------|---------------| +| **AlmaLinux** | RHEL/CentOS/Fedora compatible binaries | +| **Ubuntu** | Debian/Ubuntu compatible binaries | +| **Amazon Linux** | AWS EC2 or AWS environment deployment | +| **Alpine** | Minimal footprint, container-optimized builds | + +## Manual Build + +If you need to customize the build: + +```bash +# Build image +docker build -t codelibs/libdxfrw:ubuntu -f Dockerfile.ubuntu .. + +# Run build +docker run -t --rm -v $(pwd)/..:/work codelibs/libdxfrw:ubuntu /work/build.sh +``` + +Note: Manual builds should be run from the project root, not from this directory. diff --git a/docker/build-docker.sh b/docker/build-docker.sh new file mode 100755 index 0000000..660d13c --- /dev/null +++ b/docker/build-docker.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# +# Docker build script for libdxfrw +# Supports multiple OS/distributions +# +# Usage: +# ./docker/build-docker.sh [options] [os] +# +# Options: +# build - Build Docker image only +# run - Build library using Docker +# push - Push image to Docker Hub +# all - Build image, run build, and push (default) +# +# OS options: +# ubuntu - Ubuntu 22.04 LTS +# almalinux - AlmaLinux 9 (CentOS successor) +# amazonlinux - Amazon Linux 2023 +# alpine - Alpine Linux (musl-based) +# all-os - Build for all OS distributions +# +# Examples: +# ./docker/build-docker.sh build ubuntu +# ./docker/build-docker.sh run almalinux +# ./docker/build-docker.sh all amazonlinux +# ./docker/build-docker.sh run all-os +# + +# Robust error handling +# -e: Exit on error +# -u: Exit on undefined variable +# -o pipefail: Fail on pipe errors +set -euo pipefail + +# Configuration +IMAGE_NAME="codelibs/libdxfrw" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Available OS distributions +declare -A OS_LIST=( + ["ubuntu"]="Dockerfile.ubuntu" + ["almalinux"]="Dockerfile.almalinux" + ["amazonlinux"]="Dockerfile.amazonlinux" + ["alpine"]="Dockerfile.alpine" +) + +# Function to print usage +usage() { + cat << EOF +Usage: $0 [action] [os] + +Actions: + build Build Docker image only + run Build library using Docker (creates tar.gz) + push Push image to Docker Hub + all Build image, run build, and push (default) + +OS Distributions: + ubuntu Ubuntu 22.04 LTS (Debian-based) + almalinux AlmaLinux 9 (RHEL-based, CentOS successor) + amazonlinux Amazon Linux 2023 (AWS optimized) + alpine Alpine Linux (lightweight, musl-based) + all-os Build for all distributions + +Examples: + $0 build ubuntu # Build Ubuntu image only + $0 run almalinux # Build library on AlmaLinux + $0 all amazonlinux # Build image, library, and push + $0 run all-os # Build library for all OS distributions + +EOF + exit 1 +} + +# Function to build Docker image +build_image() { + local os=$1 + local dockerfile=$2 + local tag="${IMAGE_NAME}:${os}" + + echo "==========================================" + echo "Building Docker image: ${tag}" + echo "Dockerfile: ${dockerfile}" + echo "==========================================" + + docker build --rm -t "${tag}" -f "${SCRIPT_DIR}/${dockerfile}" "${PROJECT_ROOT}" + + echo "✓ Image built successfully: ${tag}" +} + +# Function to run build inside Docker +run_build() { + local os=$1 + local tag="${IMAGE_NAME}:${os}" + local output_file="dxfrw-${os}.tar.gz" + + echo "==========================================" + echo "Building library using: ${tag}" + echo "Output: ${output_file}" + echo "==========================================" + + docker run -t --rm -v "${PROJECT_ROOT}:/work" "${tag}" /work/build.sh + + # Rename output file to include OS name + if [ -f "${PROJECT_ROOT}/dxfrw.tar.gz" ]; then + mv "${PROJECT_ROOT}/dxfrw.tar.gz" "${PROJECT_ROOT}/${output_file}" + echo "✓ Build completed: ${output_file}" + else + echo "✗ Error: Build output not found" + return 1 + fi +} + +# Function to push Docker image +push_image() { + local os=$1 + local tag="${IMAGE_NAME}:${os}" + + echo "==========================================" + echo "Pushing Docker image: ${tag}" + echo "==========================================" + + docker push "${tag}" + + echo "✓ Image pushed successfully: ${tag}" +} + +# Function to process single OS +process_os() { + local action=$1 + local os=$2 + local dockerfile=${OS_LIST[$os]} + + if [ -z "$dockerfile" ]; then + echo "Error: Unknown OS '${os}'" + echo "Available OS: ${!OS_LIST[@]}" + exit 1 + fi + + case $action in + build) + build_image "$os" "$dockerfile" + ;; + run) + build_image "$os" "$dockerfile" + run_build "$os" + ;; + push) + push_image "$os" + ;; + all) + build_image "$os" "$dockerfile" + run_build "$os" + push_image "$os" + ;; + *) + echo "Error: Unknown action '${action}'" + usage + ;; + esac +} + +# Main script +ACTION=${1:-all} +OS=${2:-almalinux} + +# Handle special case: all-os +if [ "$OS" = "all-os" ]; then + echo "==========================================" + echo "Processing all OS distributions" + echo "==========================================" + + for os in "${!OS_LIST[@]}"; do + echo "" + process_os "$ACTION" "$os" + done + + echo "" + echo "==========================================" + echo "✓ All OS distributions processed" + echo "==========================================" + ls -lh "${PROJECT_ROOT}"/dxfrw-*.tar.gz 2>/dev/null || true +else + process_os "$ACTION" "$OS" +fi