This is an automated email from the ASF dual-hosted git repository.
shuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/unomi.git
The following commit(s) were added to refs/heads/master by this push:
new 6d4525e1a Update documentation scripts to streamline generation and
publishing process
6d4525e1a is described below
commit 6d4525e1ae208ef7be63f67511853e13c8ac5f14
Author: Serge Huber <[email protected]>
AuthorDate: Thu Sep 25 11:45:02 2025 +0200
Update documentation scripts to streamline generation and publishing process
- Consolidated `generate-site.sh` and `generate-site-and-upload.sh` into a
single unified script `generate-manual.sh`.
- Improved readability, added enhanced options (e.g., simulation mode), and
better error handling.
- Updated to support multi-version documentation generation and automatic
publishing to Apache SVN, including manual and Javadoc uploads.
---
generate-manual-config.sh | 98 +++++++
generate-manual.sh | 684 ++++++++++++++++++++++++++++++++++++++++++++
generate-site-and-upload.sh | 64 -----
generate-site.sh | 67 -----
shell-utils.sh | 368 ++++++++++++++++++++++++
5 files changed, 1150 insertions(+), 131 deletions(-)
diff --git a/generate-manual-config.sh b/generate-manual-config.sh
new file mode 100755
index 000000000..a9ae9b10a
--- /dev/null
+++ b/generate-manual-config.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+################################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Generate Manual Configuration File
+# Edit these variables to configure which versions are generated
+# Part of the Apache Unomi Manual Generator toolkit
+
+# === VERSION CONFIGURATION ===
+# Latest version (master branch)
+LATEST_BRANCH="master"
+LATEST_VERSION="3.0.0-SNAPSHOT"
+LATEST_DIR="latest"
+
+# Stable version (release branch)
+STABLE_BRANCH="unomi-2.7.x"
+STABLE_VERSION="2.7.0"
+STABLE_DIR="2_7_x"
+
+# === INFRASTRUCTURE CONFIGURATION ===
+# Git repository URL
+GIT_REPO_URL="https://gitbox.apache.org/repos/asf/unomi.git"
+
+# SVN Base URLs
+SVN_WEBSITE_BASE="https://svn.apache.org/repos/asf/unomi/website"
+SVN_DIST_BASE="https://dist.apache.org/repos/dist/release/unomi"
+
+# Temporary directory base (will be created under target/)
+TEMP_DIR_BASE="target/generated-manual"
+
+# === SYSTEM REQUIREMENTS ===
+# Minimum system requirements for validation
+MIN_DISK_SPACE_MB=200
+MIN_MEMORY_MB=512
+JAVA_MIN_VERSION=11
+MAVEN_MIN_VERSION="3.6"
+
+# === LOGGING CONFIGURATION ===
+# Log file retention (days)
+LOG_RETENTION_DAYS=7
+
+# Log levels: DEBUG, INFO, WARN, ERROR
+DEFAULT_LOG_LEVEL="INFO"
+
+# === MAVEN CONFIGURATION ===
+# Maven profiles to use
+MAVEN_SIGN_PROFILE="sign"
+MAVEN_INTEGRATION_PROFILE="integration-tests"
+
+# Maven goals for different operations
+MAVEN_CLEAN_GOAL="clean"
+MAVEN_INSTALL_GOAL="install"
+MAVEN_JAVADOC_GOAL="javadoc:aggregate"
+
+# === DOCUMENTATION PATHS ===
+# These paths are relative to INDIVIDUAL GIT CLONE directories (not the
original project root)
+# Each temporary git clone will have these paths within it
+CLONE_MANUAL_SOURCE_DIR="manual/src/main/asciidoc"
+CLONE_MANUAL_TARGET_DIR="manual/target/generated-docs"
+CLONE_API_TARGET_DIR="target/site/apidocs"
+CLONE_STAGING_DIR="target/staging"
+
+# These paths are relative to the ORIGINAL PROJECT ROOT for aggregated results
+PROJECT_STAGING_DIR="target/staging"
+
+# === TIMEOUTS ===
+# Command timeouts in seconds
+MAVEN_TIMEOUT=1800 # 30 minutes
+GIT_TIMEOUT=300 # 5 minutes
+SVN_TIMEOUT=600 # 10 minutes
+
+# Export all configuration variables
+export LATEST_BRANCH LATEST_VERSION LATEST_DIR
+export STABLE_BRANCH STABLE_VERSION STABLE_DIR
+export GIT_REPO_URL SVN_WEBSITE_BASE SVN_DIST_BASE TEMP_DIR_BASE
+export MIN_DISK_SPACE_MB MIN_MEMORY_MB JAVA_MIN_VERSION MAVEN_MIN_VERSION
+export LOG_RETENTION_DAYS DEFAULT_LOG_LEVEL
+export MAVEN_SIGN_PROFILE MAVEN_INTEGRATION_PROFILE
+export MAVEN_CLEAN_GOAL MAVEN_INSTALL_GOAL MAVEN_JAVADOC_GOAL
+export CLONE_MANUAL_SOURCE_DIR CLONE_MANUAL_TARGET_DIR CLONE_API_TARGET_DIR
CLONE_STAGING_DIR
+export PROJECT_STAGING_DIR
+export MAVEN_TIMEOUT GIT_TIMEOUT SVN_TIMEOUT
\ No newline at end of file
diff --git a/generate-manual.sh b/generate-manual.sh
new file mode 100755
index 000000000..b891f0628
--- /dev/null
+++ b/generate-manual.sh
@@ -0,0 +1,684 @@
+#!/usr/bin/env bash
+################################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Load utility functions and configuration (can be used by other scripts)
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+if [ -f "$SCRIPT_DIR/generate-manual-config.sh" ]; then
+ source "$SCRIPT_DIR/generate-manual-config.sh"
+fi
+if [ -f "$SCRIPT_DIR/shell-utils.sh" ]; then
+ source "$SCRIPT_DIR/shell-utils.sh"
+fi
+
+# Configuration is now loaded from generate-manual-config.sh
+# Colors and utility functions are loaded from shell-utils.sh
+
+
+show_banner() {
+ clear
+ echo -e
"${CYAN}╔══════════════════════════════════════════════════════╗${NC}"
+ typewriter_effect "${CYAN}║${WHITE} 🚀 APACHE UNOMI MANUAL
GENERATOR 🚀 ${CYAN}║"
+ echo -e
"${CYAN}╚══════════════════════════════════════════════════════╝${NC}"
+ echo
+ rainbow_text " ✨ The Ultimate Documentation Tool ✨"
+ echo
+}
+
+show_usage() {
+ echo -e "${YELLOW}${BOLD}USAGE:${NC}"
+ echo -e "${WHITE} $0 ${GREEN}publish${NC} ${CYAN}<user> <pass>${NC}
${DIM}# Generate all 2 versions + publish to SVN${NC}"
+ echo -e "${WHITE} $0 ${GREEN}simulate${NC} ${CYAN}<user> <pass>${NC}
${DIM}# Simulate publish (dry-run)${NC}"
+ echo
+ echo
+ echo -e "${YELLOW}${BOLD}EXAMPLES:${NC}"
+ echo -e "${WHITE} $0 publish myuser mypass${NC}"
+ echo -e "${WHITE} $0 simulate myuser mypass${NC}"
+ echo
+ echo -e "${PURPLE}${BOLD}WHAT IT GENERATES:${NC}"
+ echo -e "${GREEN} Always generates exactly 2 versions:${NC}"
+ echo -e " ${CYAN}$LATEST_DIR/${NC} - From $LATEST_BRANCH branch
($LATEST_VERSION)"
+ echo -e " ${CYAN}$STABLE_DIR/${NC} - From $STABLE_BRANCH branch
($STABLE_VERSION)"
+ echo
+ echo -e "${PURPLE}${BOLD}MODES:${NC}"
+ echo -e "${GREEN} publish${NC} - Generate all documentation and publish
to Apache SVN"
+ echo -e " ${DIM}• Generates all 2 versions (latest +
stable)${NC}"
+ echo -e " ${DIM}• Uploads to $SVN_WEBSITE_BASE/manual${NC}"
+ echo -e " ${DIM}• Publishes API docs from master branch${NC}"
+ echo -e " ${DIM}• Uploads release packages (PDF/ZIP) to Apache
Dist SVN${NC}"
+ echo -e " ${DIM}• Removes any old versions automatically${NC}"
+ echo
+ echo -e "${GREEN} simulate${NC} - Preview what publish would do (dry-run)"
+ echo -e " ${DIM}• Shows all commands that would be executed${NC}"
+ echo -e " ${DIM}• Safe to test without making changes${NC}"
+ echo
+ echo -e "${CYAN}${BOLD}REQUIREMENTS:${NC}"
+ echo -e "${WHITE} • Maven 3.6+ with Java 11+${NC}"
+ echo -e "${WHITE} • Git with access to master and 2_7_x branches${NC}"
+ echo -e "${WHITE} • SVN client (for publish/simulate modes)${NC}"
+ echo -e "${WHITE} • bc command (for progress animations)${NC}"
+ echo
+ echo -e "${CYAN}${BOLD}NOTES:${NC}"
+ echo -e "${WHITE} • All temporary files are created in
$TEMP_DIR_BASE/${NC}"
+ echo -e "${WHITE} • Use 'mvn $MAVEN_CLEAN_GOAL' to remove all generated
files${NC}"
+ echo -e "${WHITE} • Always generates exactly 2 versions (latest,
2_7_x)${NC}"
+ echo -e "${WHITE} • Script works on macOS and Linux${NC}"
+ echo
+}
+
+execute_or_simulate_dist_svn() {
+ local simulate="$1"
+ local branch_name="$2"
+ local version="$3"
+ local manual_target_dir="$4"
+ local svn_username="$5"
+ local svn_password="$6"
+
+ local DIST_SVN_URL="$SVN_DIST_BASE/$version"
+
+ animate_loading "Preparing Apache Dist SVN upload" 2
+
+ pushd "$manual_target_dir" >/dev/null
+
+ log_info "Checking out Apache Dist SVN for version: ${GREEN}$version${NC}"
+ if ! run_svn_command "svn checkout \"$DIST_SVN_URL\""; then
+ log_error "Failed to checkout Apache Dist SVN for version $version"
+ popd >/dev/null
+ return 1
+ fi
+
+ log_info "Moving manual packages to dist directory..."
+
+ # Helper function for safe move with logging
+ move_file() {
+ local src="$1"
+ local dest="$2"
+ local desc="$3"
+
+ if [ -f "$src" ]; then
+ if mv "$src" "$dest" 2>/dev/null; then
+ log_info "Moved: $src → $dest"
+ else
+ log_warning "Failed to move $desc: $src → $dest"
+ fi
+ else
+ log_warning "$desc not found: $src"
+ fi
+ }
+
+ move_file "unomi-manual-$version.pdf" "$version/" "PDF file"
+ move_file "unomi-manual-$version.pdf.asc" "$version/" "PDF signature"
+ move_file "unomi-manual-$version.zip" "$version/" "ZIP file"
+ move_file "unomi-manual-$version.pdf.sha512" "$version/" "PDF checksum"
+ move_file "unomi-manual-$version.zip.asc" "$version/" "ZIP signature"
+ move_file "unomi-manual-$version.zip.sha512" "$version/" "ZIP checksum"
+
+ pushd "$version" >/dev/null
+
+ animate_loading "Adding manual packages to SVN" 1
+ # Extract function: add files to SVN but tolerate "already versioned"
cases.
+ add_manual_packages_to_svn_if_needed() {
+ # Uses current directory; expects logging helpers and run_svn_command
+ local pattern="unomi-manual*"
+ # Try the add; capture output and status
+ local output
+ output="$(svn add $pattern 2>&1)"
+ local status=$?
+
+ if [ $status -eq 0 ]; then
+ # Added successfully
+ return 0
+ fi
+
+ # If some targets are already versioned, warn and continue
+ if echo "$output" | grep -qE 'W150002|E200009|already under version
control|Could not add all targets'; then
+ log_warning "Manual packages already under version control;
continuing."
+ log_debug "svn add output: $output"
+ return 0
+ fi
+
+ # Unexpected failure: log and propagate error
+ log_error "Failed to add manual packages to SVN"
+ log_debug "svn add output: $output"
+ return 1
+ }
+
+ if ! add_manual_packages_to_svn_if_needed; then
+ popd >/dev/null
+ popd >/dev/null
+ return 1
+ fi
+ if [ "$simulate" = "true" ]; then
+ log_simulate "Would upload manual packages to Apache Dist SVN"
+ log_command "svn commit -m \"Update Unomi manual packages for version
$version\" --username=\"$svn_username\" --password=\"$svn_password\""
+ else
+ animate_loading "Committing manual packages to Apache Dist SVN" 2
+ if ! run_svn_command "svn commit -m \"Update Unomi manual packages for
version $version\" --username=\"$svn_username\" --password=\"$svn_password\"";
then
+ log_error "Failed to commit manual packages to Apache Dist SVN"
+ popd >/dev/null
+ popd >/dev/null
+ return 1
+ fi
+ fi
+ popd >/dev/null
+ popd >/dev/null
+
+ log_success "Manual packages uploaded to Apache Dist SVN! 📦"
+}
+
+check_requirements() {
+ local mode="$1"
+ local errors=0
+
+ log_step "🔍 Checking system requirements..."
+ echo
+
+ # Use utility functions from shell-utils.sh
+ check_command "java" "Java 11+" "true" || ((errors++))
+ check_command "mvn" "Maven 3.6+" "true" || ((errors++))
+ check_command "git" "Git" "true" || ((errors++))
+ check_git_repository || ((errors++))
+
+ # Check SVN based on mode
+ if [ "$mode" = "publish" ] || [ "$mode" = "multi" ]; then
+ check_command "svn" "SVN" "true" || ((errors++))
+ else
+ check_command "svn" "SVN" "false"
+ fi
+
+ check_command "bc" "bc (for enhanced animations)" "false"
+
+ echo
+ log_step "🔧 Additional environment checks..."
+
+ check_directory_writable "." || ((errors++))
+ check_disk_space "$MIN_DISK_SPACE_MB"
+ check_memory "$MIN_MEMORY_MB"
+
+ echo
+ if [ $errors -eq 0 ]; then
+ log_success "All required dependencies are available! 🎉"
+ echo
+ return 0
+ else
+ log_error "Found $errors requirement error(s). Please
$MAVEN_INSTALL_GOAL missing dependencies."
+ echo
+ log_info "Installation hints:"
+ echo -e "${DIM} • Java 11+: https://adoptopenjdk.net/${NC}"
+ echo -e "${DIM} • Maven 3.6+:
https://maven.apache.org/download.cgi${NC}"
+ echo -e "${DIM} • Git: https://git-scm.com/downloads${NC}"
+ if [ "$mode" = "publish" ] || [ "$mode" = "multi" ]; then
+ echo -e "${DIM} • SVN:
https://subversion.apache.org/download.cgi${NC}"
+ fi
+ echo -e "${DIM} • bc: Usually available via package manager (brew,
apt, yum)${NC}"
+ echo
+ return 1
+ fi
+}
+
+detect_javadoc_output_dir() {
+ local base_dir="${1:-.}"
+
+ # Check multiple possible Javadoc output directories
+ local possible_dirs=(
+ "$base_dir/target/site/apidocs" # Maven site plugin (classic)
+ "$base_dir/target/reports/apidocs" # Maven reporting plugin (newer)
+ "$base_dir/target/apidocs" # Direct javadoc plugin
+ )
+
+ for dir in "${possible_dirs[@]}"; do
+ if [ -d "$dir" ]; then
+ echo "$dir"
+ return 0
+ fi
+ done
+
+ # If none exist, check which one would be created based on POM
configuration
+ if grep -q "<reporting>" "$base_dir/pom.xml" 2>/dev/null; then
+ echo "$base_dir/target/site/apidocs" # Reporting section uses site
+ else
+ echo "$base_dir/target/reports/apidocs" # Modern default
+ fi
+}
+
+setup_environment() {
+ log_step "Setting up environment..."
+
+ DIRNAME=$(dirname "$0")
+
+ if [ -f "$DIRNAME/setenv.sh" ]; then
+ . "$DIRNAME/setenv.sh"
+ log_info "Loaded environment from setenv.sh"
+ fi
+
+ # Create target directory structure for temporary files and logs
+ mkdir -p "$TEMP_DIR_BASE/logs"
+ TEMP_DIR="$TEMP_DIR_BASE"
+ LOG_DIR="$TEMP_DIR/logs"
+
+ # Create timestamped log file with absolute path
+ TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
+ MAIN_LOG="$(pwd)/$LOG_DIR/generate-manual_$TIMESTAMP.log"
+ export MAIN_LOG
+
+ # Initialize log file
+ touch "$MAIN_LOG"
+
+ # Only show essential paths to user, details go to logs
+ log_info "Temporary directory: ${GREEN}$(basename "$TEMP_DIR")${NC}"
+ # Log full details to file only
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Full temporary directory
path: $(cd "$TEMP_DIR" && pwd)" >> "$MAIN_LOG"
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Log directory path: $(cd
"$LOG_DIR" && pwd)" >> "$MAIN_LOG"
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Main log file: $MAIN_LOG" >>
"$MAIN_LOG"
+ fi
+
+ set -e
+
+ LOCAL_BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
+ log_info "Current git branch: ${GREEN}${LOCAL_BRANCH_NAME}${NC}"
+}
+
+generate_docs_local() {
+ local branch_name="$1"
+ local version="$2"
+ local output_dir="$3"
+
+ log_step "🎯 Generating complete documentation for
${CYAN}${branch_name}${NC} version ${YELLOW}${version}${NC}"
+
+ # IMPORTANT PATH DISTINCTION:
+ # CLONE_* variables: Paths within the current temporary git clone directory
+ # PROJECT_* variables: Paths within the original project root directory
+ # This prevents confusion between temporary clone staging and project
staging
+
+ animate_loading "Cleaning previous builds" 1
+ if ! run_maven_command "mvn $MAVEN_CLEAN_GOAL"; then
+ log_error "Maven clean failed for $branch_name"
+ return 1
+ fi
+
+ log_step "📚 Building manual documentation (HTML, PDF, ZIP)..."
+ pushd manual >/dev/null
+
+ # Generate complete documentation set for all branches with versioned
output
+ animate_loading "Generating versioned PDF and HTML docs" 3
+ if ! run_maven_command "mvn -Ddoc.archive=true
-Ddoc.output.pdf=target/generated-docs/pdf/$branch_name
-Ddoc.output.html=target/generated-docs/html/$branch_name
-Ddoc.version=$version -P $MAVEN_SIGN_PROFILE $MAVEN_INSTALL_GOAL"; then
+ log_error "Maven versioned documentation build failed for $branch_name"
+ popd >/dev/null
+ return 1
+ fi
+
+ popd >/dev/null
+
+ log_step "📖 Generating Javadoc API documentation..."
+ animate_loading "Building aggregated Javadocs" 4
+ if ! run_maven_command "mvn -DskipTests $MAVEN_INSTALL_GOAL
$MAVEN_JAVADOC_GOAL -P $MAVEN_INTEGRATION_PROFILE"; then
+ log_warning "Maven Javadoc generation failed for $branch_name (likely
Java version issue)"
+ log_info "Continuing without API documentation..."
+ # Don't fail the entire process for Javadoc issues
+ else
+ log_success "Javadoc generation completed successfully"
+
+ # Dynamically detect the actual Javadoc output directory
+ ACTUAL_API_DIR=$(detect_javadoc_output_dir ".")
+ log_debug "Detected Javadoc directory: $(cd "$ACTUAL_API_DIR" && pwd)"
+
+ if [ -d "$ACTUAL_API_DIR" ]; then
+ log_info "Javadoc directory found with $(find "$ACTUAL_API_DIR"
-name "*.html" 2>/dev/null | wc -l) HTML files"
+ # Update CLONE_API_TARGET_DIR to the actual location for this
branch
+ CLONE_API_TARGET_DIR="$ACTUAL_API_DIR"
+ else
+ log_warning "Javadoc directory not found after generation: $(cd
"$(dirname "$ACTUAL_API_DIR")" && pwd)/$(basename "$ACTUAL_API_DIR")"
+ fi
+ fi
+
+ log_step "📦 Staging documentation files..."
+
+ # Create staging directories using output_dir for final directory structure
+ mkdir -p "$CLONE_STAGING_DIR/unomi-api/$output_dir"
+ mkdir -p "$CLONE_STAGING_DIR/manual/$output_dir"
+
+ animate_loading "Copying API documentation" 1
+ # Copy API docs - they are generated in target/site/apidocs
+ log_debug "Checking API docs in: $(cd "$CLONE_API_TARGET_DIR" && pwd)"
+ if [ -d "$CLONE_API_TARGET_DIR" ]; then
+ log_debug "API docs directory exists, copying $(find
"$CLONE_API_TARGET_DIR" -name "*.html" 2>/dev/null | wc -l) HTML files"
+ log_debug "Copying API docs: $(cd "$CLONE_API_TARGET_DIR" && pwd)/* →
$(cd "$CLONE_STAGING_DIR/unomi-api/$output_dir" && pwd)/"
+ if ! cp -R "$CLONE_API_TARGET_DIR"/*
"$CLONE_STAGING_DIR/unomi-api/$output_dir/" 2>/dev/null; then
+ log_warning "Failed to copy API documentation files: $(cd
"$CLONE_API_TARGET_DIR" && pwd)/* → $(cd
"$CLONE_STAGING_DIR/unomi-api/$output_dir" && pwd)/"
+ else
+ log_debug "Successfully copied API documentation files"
+ fi
+ else
+ log_warning "API docs directory does not exist: $(cd "$(dirname
"$CLONE_API_TARGET_DIR")" 2>/dev/null && pwd)/$(basename
"$CLONE_API_TARGET_DIR") (absolute path)"
+ fi
+
+ animate_loading "Copying manual documentation" 1
+ # Copy manual documentation from versioned directory
+ if [ -d "$CLONE_MANUAL_TARGET_DIR/html/$branch_name" ]; then
+ log_debug "Copying manual docs: $(cd
"$CLONE_MANUAL_TARGET_DIR/html/$branch_name" && pwd)/* → $(cd
"$CLONE_STAGING_DIR/manual/$output_dir" && pwd)/"
+ if cp -Rf "$CLONE_MANUAL_TARGET_DIR/html/$branch_name"/*
"$CLONE_STAGING_DIR/manual/$output_dir/"; then
+ log_debug "Successfully copied manual documentation files"
+ else
+ log_warning "Failed to copy manual documentation files: $(cd
"$CLONE_MANUAL_TARGET_DIR/html/$branch_name" 2>/dev/null && pwd)/* → $(cd
"$CLONE_STAGING_DIR/manual/$output_dir" && pwd)/"
+ fi
+ else
+ log_warning "Manual HTML not found in expected location: $(cd
"$CLONE_MANUAL_TARGET_DIR/html" 2>/dev/null && pwd)/$branch_name (absolute
path)"
+ fi
+
+ log_success "Complete documentation set generated! 🎉"
+ log_debug "Documentation staged in: $(cd "$CLONE_STAGING_DIR" && pwd)/"
+}
+
+multi_version_generate() {
+ local mode="$1" # "publish" or "simulate"
+ local svn_username="$2"
+ local svn_password="$3"
+ shift 3
+ local version_configs=("$@")
+
+ echo
+ if [ "$mode" = "simulate" ]; then
+ log_step "🎭 Simulating multi-version documentation generation"
+ else
+ log_step "🎯 Multi-version documentation generation"
+ fi
+ log_info "Processing ${#version_configs[@]} version configurations..."
+
+ local REPO_ROOT=$(pwd)
+ local DEBUG_TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
+ local TEMP_REPO_PREFIX="$TEMP_DIR/repo_${DEBUG_TIMESTAMP}"
+ local SVN_BASE_URL="$SVN_WEBSITE_BASE/manual"
+ local TEMP_CHECKOUT_DIR="$TEMP_DIR/svn-manual_${DEBUG_TIMESTAMP}"
+
+ animate_loading "Checking out SVN manual directory" 2
+ # if [ -d "$TEMP_CHECKOUT_DIR" ]; then
+ # rm -rf "$TEMP_CHECKOUT_DIR" # Commented out for debugging
+ # fi
+ log_debug "SVN checkout directory: $TEMP_CHECKOUT_DIR"
+ if ! run_svn_command "svn checkout \"$SVN_BASE_URL\"
\"$TEMP_CHECKOUT_DIR\" --username=\"$svn_username\"
--password=\"$svn_password\""; then
+ log_error "Failed to checkout SVN manual directory"
+ return 1
+ fi
+
+ local LATEST_VERSION=""
+ local GENERATED_VERSIONS=()
+
+ for config in "${version_configs[@]}"; do
+ IFS=':' read -r branch_name version_number target_dir is_latest <<<
"$config"
+
+ echo
+ log_step "🔄 Processing
${CYAN}$branch_name${NC}:${YELLOW}$version_number${NC} →
${GREEN}$target_dir${NC} (latest=$is_latest)"
+
+ local TEMP_REPO_DIR="${TEMP_REPO_PREFIX}_${branch_name}"
+
+ animate_loading "Creating temporary repository for branch
$branch_name" 1
+ # if [ -d "$TEMP_REPO_DIR" ]; then
+ # rm -rf "$TEMP_REPO_DIR" # Commented out for debugging
+ # fi
+ log_debug "Temporary repo directory: $TEMP_REPO_DIR"
+ log_info "Cloning from official repository: ${CYAN}$GIT_REPO_URL${NC}"
+
+ if ! run_git_command "git clone \"$GIT_REPO_URL\" \"$TEMP_REPO_DIR\"";
then
+ log_error "Git clone failed for $branch_name"
+ continue
+ fi
+
+ pushd "$TEMP_REPO_DIR" >/dev/null
+
+ if [ "$branch_name" != "master" ]; then
+ log_debug "Checking out branch: $branch_name"
+ if ! run_git_command "git checkout \"$branch_name\""; then
+ log_error "Git checkout failed for $branch_name"
+ popd >/dev/null
+ continue
+ fi
+ fi
+
+ animate_loading "Generating documentation for $branch_name" 3
+ generate_docs_local "$branch_name" "$version_number" "$target_dir"
+
+ if [ ! -d "$CLONE_STAGING_DIR/manual" ]; then
+ log_error "Documentation generation failed for $branch_name"
+ popd >/dev/null
+ continue
+ fi
+
+ popd >/dev/null
+
+ # Copy documentation from clone staging to main project staging area
(for all modes)
+ log_debug "Copying documentation to main staging area: $target_dir"
+ mkdir -p "$REPO_ROOT/$PROJECT_STAGING_DIR/manual/$target_dir"
+ mkdir -p "$REPO_ROOT/$PROJECT_STAGING_DIR/unomi-api/$target_dir"
+
+ if [ -d "$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir" ]; then
+ log_debug "Copying manual docs to main staging: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir" && pwd)/* → $(cd
"$REPO_ROOT/$PROJECT_STAGING_DIR/manual/$target_dir" && pwd)/"
+ if ! cp -Rf
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir"/*
"$REPO_ROOT/$PROJECT_STAGING_DIR/manual/$target_dir/" 2>/dev/null; then
+ log_warning "Failed to copy manual documentation files: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir" 2>/dev/null && pwd)/* →
$(cd "$REPO_ROOT/$PROJECT_STAGING_DIR/manual/$target_dir" && pwd)/"
+ else
+ log_debug "Successfully copied manual documentation to main
staging"
+ fi
+ fi
+
+ if [ -d "$TEMP_REPO_DIR/$CLONE_STAGING_DIR/unomi-api/$target_dir" ];
then
+ log_debug "Copying API docs to main staging: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/unomi-api/$target_dir" && pwd)/* → $(cd
"$REPO_ROOT/$PROJECT_STAGING_DIR/unomi-api/$target_dir" && pwd)/"
+ if ! cp -Rf
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/unomi-api/$target_dir"/*
"$REPO_ROOT/$PROJECT_STAGING_DIR/unomi-api/$target_dir/" 2>/dev/null; then
+ log_warning "Failed to copy API documentation files: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/unomi-api/$target_dir" 2>/dev/null && pwd)/*
→ $(cd "$REPO_ROOT/$PROJECT_STAGING_DIR/unomi-api/$target_dir" && pwd)/"
+ else
+ log_debug "Successfully copied API documentation to main
staging"
+ fi
+ fi
+
+ # Copy documentation to SVN directory
+ local TARGET_DIR="$TEMP_CHECKOUT_DIR/$target_dir"
+ log_debug "Copying documentation to SVN directory: $target_dir"
+
+ if [ ! -d "$TARGET_DIR" ]; then
+ mkdir -p "$TARGET_DIR"
+ pushd "$TEMP_CHECKOUT_DIR" >/dev/null
+ run_svn_command "svn add \"$target_dir\""
+ popd >/dev/null
+ fi
+
+ rm -rf "$TARGET_DIR"/*
+ log_debug "Copying to SVN: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir" && pwd)/* → $(cd
"$TARGET_DIR" && pwd)/"
+ if cp -R "$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual"/$target_dir/*
"$TARGET_DIR"/; then
+ log_debug "Successfully copied documentation to SVN directory"
+ else
+ log_warning "Failed to copy documentation to SVN directory: $(cd
"$TEMP_REPO_DIR/$CLONE_STAGING_DIR/manual/$target_dir" 2>/dev/null && pwd)/* →
$(cd "$TARGET_DIR" && pwd)/"
+ fi
+
+ pushd "$TEMP_CHECKOUT_DIR" >/dev/null
+ run_svn_command "svn add --force \"$target_dir\""
+ popd >/dev/null
+
+ GENERATED_VERSIONS+=("$target_dir")
+
+ if [ "$is_latest" = "true" ]; then
+ LATEST_VERSION="$target_dir"
+ fi
+
+ # Apache Dist SVN upload for all branches that generate release
artifacts
+ if [ "$branch_name" != "master" ]; then # Only upload to Dist SVN for
actual releases, not development snapshots
+ echo
+ local simulate_mode="false"
+ if [ "$mode" = "simulate" ]; then
+ simulate_mode="true"
+ log_step "🎭 Simulating Apache Dist SVN upload for $branch_name
and version $version_number..."
+ else
+ log_step "📦 Uploading release artifacts to Apache Dist SVN for
$branch_name and version $version_number..."
+ fi
+
+ local MANUAL_TARGET_DIR="$TEMP_REPO_DIR/manual/target"
+ if ! execute_or_simulate_dist_svn "$simulate_mode" "$branch_name"
"$version_number" "$MANUAL_TARGET_DIR" "$svn_username" "$svn_password"; then
+ # rm -rf "$TEMP_REPO_DIR" # Commented out for debugging
+ log_debug "Preserving temp directory for analysis:
$TEMP_REPO_DIR"
+ continue
+ fi
+ fi
+
+ # rm -rf "$TEMP_REPO_DIR" # Commented out for debugging
+ log_debug "Preserving temp directory for analysis: $TEMP_REPO_DIR"
+ done
+
+ log_step "🧹 Managing version retention..."
+ pushd "$TEMP_CHECKOUT_DIR" >/dev/null
+
+ # Always preserve the currently generated versions
+ local DIRS_TO_KEEP=("${GENERATED_VERSIONS[@]}")
+
+ log_info "Generated versions (preserved): ${GREEN}${DIRS_TO_KEEP[*]}${NC}"
+
+ for dir in */; do
+ dir_name="${dir%/}"
+
+ if [[ ! " ${DIRS_TO_KEEP[*]} " =~ " $dir_name " ]]; then
+ log_warning "Removing old version directory: $dir_name"
+ run_svn_command "svn remove \"$dir_name\""
+ else
+ log_info "Preserving directory: $dir_name"
+ fi
+ done
+
+ if [ "$mode" == "publish" ]; then
+ animate_loading "Committing all changes to SVN" 3
+ local COMMIT_MSG="Update manual documentation
+
+Generated versions: ${GENERATED_VERSIONS[*]}
+Latest version: $LATEST_VERSION
+Preserved versions: ${DIRS_TO_KEEP[*]}"
+
+ if ! run_svn_command "svn commit -m \"$COMMIT_MSG\"
--username=\"$svn_username\" --password=\"$svn_password\""; then
+ log_error "Failed to commit to SVN"
+ return 1
+ fi
+ else
+ animate_loading "Simulating committing all changes to SVN" 3
+ local COMMIT_MSG="Update manual documentation
+
+Generated versions: ${GENERATED_VERSIONS[*]}
+Latest version: $LATEST_VERSION
+Preserved versions: ${DIRS_TO_KEEP[*]}"
+
+ log_command "svn commit -m \"$COMMIT_MSG\"
--username=\"$svn_username\" --password=\"$svn_password\""
+ fi
+
+ popd >/dev/null
+ # rm -rf "$TEMP_CHECKOUT_DIR" # Commented out for debugging
+ log_debug "Preserving SVN checkout directory for analysis:
$TEMP_CHECKOUT_DIR"
+
+ if [ "$mode" = "simulate" ]; then
+ log_success "Multi-version documentation simulation completed! 🎊"
+ log_info "Generated versions: ${GREEN}${GENERATED_VERSIONS[*]}${NC}"
+ if [ -n "$LATEST_VERSION" ]; then
+ log_info "Latest version set to: ${GREEN}$LATEST_VERSION${NC}"
+ fi
+ # Count release branches (non-master) for dist upload summary
+ local RELEASE_BRANCHES=()
+ for version in "${GENERATED_VERSIONS[@]}"; do
+ if [ "$version" != "master" ]; then
+ RELEASE_BRANCHES+=("$version")
+ fi
+ done
+ if [ ${#RELEASE_BRANCHES[@]} -gt 0 ]; then
+ log_info "Would upload manual packages to Apache Dist SVN for:
${GREEN}${RELEASE_BRANCHES[*]}${NC}"
+ fi
+ else
+ log_success "Multi-version documentation generation completed! 🎊"
+ log_info "Generated versions: ${GREEN}${GENERATED_VERSIONS[*]}${NC}"
+ if [ -n "$LATEST_VERSION" ]; then
+ log_info "Latest version set to: ${GREEN}$LATEST_VERSION${NC}"
+ fi
+ # Count release branches (non-master) for dist upload summary
+ local RELEASE_BRANCHES=()
+ for version in "${GENERATED_VERSIONS[@]}"; do
+ if [ "$version" != "master" ]; then
+ RELEASE_BRANCHES+=("$version")
+ fi
+ done
+ if [ ${#RELEASE_BRANCHES[@]} -gt 0 ]; then
+ log_info "Manual packages uploaded to Apache Dist SVN for:
${GREEN}${RELEASE_BRANCHES[*]}${NC}"
+ fi
+ fi
+}
+
+celebrate_completion() {
+ echo
+ echo -e "${GREEN}${BOLD}🎉 SUCCESS! 🎉${NC}"
+ echo -e "${GREEN}Documentation generation completed successfully!${NC}"
+ echo
+ echo -e "${CYAN}Thanks for using the Unomi Manual Generator! 🚀${NC}"
+ echo
+}
+
+# Main script logic
+main() {
+ show_banner
+
+ if [ $# -eq 0 ]; then
+ show_usage
+ exit 1
+ fi
+
+ local mode="$1"
+
+ # Check requirements before proceeding
+ if ! check_requirements "$mode"; then
+ exit 1
+ fi
+
+ setup_environment
+ shift
+
+ case "$mode" in
+ "publish")
+ if [ $# -ne 2 ]; then
+ log_error "Publish mode requires exactly 2 arguments:
username, password"
+ show_usage
+ exit 1
+ fi
+
+ # Always generate and publish all 2 versions
+ multi_version_generate "publish" "$1" "$2"
"$LATEST_BRANCH:$LATEST_VERSION:$LATEST_DIR:true"
"$STABLE_BRANCH:$STABLE_VERSION:$STABLE_DIR:false"
+ celebrate_completion
+ ;;
+
+ "simulate")
+ if [ $# -ne 2 ]; then
+ log_error "Simulate mode requires exactly 2 arguments:
username, password"
+ show_usage
+ exit 1
+ fi
+
+ # Always simulate all 2 versions
+ multi_version_generate "simulate" "$1" "$2"
"$LATEST_BRANCH:$LATEST_VERSION:$LATEST_DIR:true"
"$STABLE_BRANCH:$STABLE_VERSION:$STABLE_DIR:false"
+ celebrate_completion
+ ;;
+
+ *)
+ log_error "Unknown mode: $mode"
+ show_usage
+ exit 1
+ ;;
+ esac
+
+}
+
+# Run the main function
+main "$@"
diff --git a/generate-site-and-upload.sh b/generate-site-and-upload.sh
deleted file mode 100755
index ec665b047..000000000
--- a/generate-site-and-upload.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env bash
-################################################################################
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-if [ $# -ne 4 ]
- then
- echo "Illegal number of arguments supplied. Syntax should be
generate-site-and-upload.sh X_X_X X.X.X SVNusername SVNpassword"
- echo "Where X_X_X is either the release branch name or master"
- echo "Example: ./generate-site-and-upload.sh 2_0_x 2.0.1 user password
./generate-site.sh master 2.3.0-SNAPSHOT user password for updating the master
snapshot version"
- exit 1
-fi
-echo Setting up environment...
-DIRNAME=`dirname "$0"`
-PROGNAME=`basename "$0"`
-if [ -f "$DIRNAME/setenv.sh" ]; then
- . "$DIRNAME/setenv.sh"
-fi
-set -e
-# keep track of the last executed command
-trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
-# echo an error message before exiting
-trap 'echo "\"${last_command}\" command filed with exit code $?."' EXIT
-BRANCH_NAME=$1
-VERSION=$2
-SVN_USERNAME=$3
-SVN_PASSWORD=$4
-LOCAL_BRANCH_NAME=`git rev-parse --abbrev-ref HEAD`
-echo Git local branch: ${LOCAL_BRANCH_NAME}
-bash generate-site.sh $BRANCH_NAME $VERSION
-echo Committing documentation to Apache SVN...
-mvn scm-publish:publish-scm
-Dscmpublish.pubScmUrl=scm:svn:https://svn.apache.org/repos/asf/unomi/website/manual
-Dscmpublish.content=target/staging/manual -Dusername=$SVN_USERNAME
-Dpassword=$SVN_PASSWORD
-if [ "$LOCAL_BRANCH_NAME" == "master" ]; then
- mvn scm-publish:publish-scm
-Dscmpublish.pubScmUrl=scm:svn:https://svn.apache.org/repos/asf/unomi/website/unomi-api
-Dscmpublish.content=target/staging/unomi-api -Dusername=$SVN_USERNAME
-Dpassword=$SVN_PASSWORD
-else
- echo "Committing manual to Apache Dist SVN..."
- pushd manual/target
- svn co https://dist.apache.org/repos/dist/release/unomi/$VERSION
- mv unomi-manual-$BRANCH_NAME.pdf $VERSION
- mv unomi-manual-$BRANCH_NAME.pdf.asc $VERSION
- mv unomi-manual-$BRANCH_NAME.zip $VERSION
- mv unomi-manual-$BRANCH_NAME.pdf.sha512 $VERSION
- mv unomi-manual-$BRANCH_NAME.zip.asc $VERSION
- mv unomi-manual-$BRANCH_NAME.zip.sha512 $VERSION
- cd $VERSION
- svn add unomi-manual*
- svn commit -m "Update Unomi manual packages for version ${VERSION}"
- popd
-fi
-echo Documentation generation and upload completed.
diff --git a/generate-site.sh b/generate-site.sh
deleted file mode 100755
index 8a3fca8ef..000000000
--- a/generate-site.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env bash
-################################################################################
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-if [ $# -ne 2 ]
- then
- echo "Illegal number of arguments supplied. Syntax should be
generate-site.sh X_X_X X.X.X"
- echo "Where X_X_X is either the release branch name or master"
- echo "Example: ./generate-site.sh 2_0_x 2.0.1 or ./generate-site.sh master
2.3.0-SNAPSHOT for updating the master snapshot version"
- exit 1
-fi
-echo Setting up environment...
-DIRNAME=`dirname "$0"`
-PROGNAME=`basename "$0"`
-if [ -f "$DIRNAME/setenv.sh" ]; then
- . "$DIRNAME/setenv.sh"
-fi
-set -e
-# keep track of the last executed command
-trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
-# echo an error message before exiting
-trap 'echo "\"${last_command}\" command filed with exit code $?."' EXIT
-RELEASE_BRANCH_NAME=$1
-RELEASE_VERSION=$2
-LOCAL_BRANCH_NAME=`git rev-parse --abbrev-ref HEAD`
-echo Git local branch: ${LOCAL_BRANCH_NAME}
-echo Generating manual for branch ${RELEASE_BRANCH_NAME} and version
${RELEASE_VERSION}...
-mvn clean
-pushd manual
-if [ "$RELEASE_BRANCH_NAME" != "master" ]; then
- mvn -Ddoc.archive=true
-Ddoc.output.pdf=target/generated-docs/pdf/$RELEASE_BRANCH_NAME
-Ddoc.output.html=target/generated-docs/html/$RELEASE_BRANCH_NAME
-Ddoc.version=$RELEASE_BRANCH_NAME -P sign install
-fi
-mvn -P sign install
-# If not on master branch we remove the latest directories
-if [ "$LOCAL_BRANCH_NAME" != "master" ]; then
- rm -rf target/generated-docs/html/latest
- rm -rf target/generated-docs/pdf/latest
-fi
-popd
-if [ "$LOCAL_BRANCH_NAME" == "master" ]; then
- echo Generating Javadoc...
- mvn javadoc:aggregate -P integration-tests
-else
- echo Not on master branch, skipping Javadoc generation
-fi
-mkdir -p target/staging/unomi-api
-mkdir -p target/staging/manual
-if [ "$LOCAL_BRANCH_NAME" == "master" ]; then
- cp -R target/site/apidocs target/staging/unomi-api
-fi
-cp -Rf manual/target/generated-docs/html/* target/staging/manual
-echo Documentation generation completed!
diff --git a/shell-utils.sh b/shell-utils.sh
new file mode 100755
index 000000000..ad25beb22
--- /dev/null
+++ b/shell-utils.sh
@@ -0,0 +1,368 @@
+#!/bin/bash
+################################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Shell Utility Functions
+# This file contains reusable shell functions that can be used by other scripts
+# Part of the Apache Unomi Manual Generator toolkit
+
+# Color and formatting constants
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[0;33m'
+BLUE='\033[0;34m'
+PURPLE='\033[0;35m'
+CYAN='\033[0;36m'
+WHITE='\033[0;37m'
+BOLD='\033[1m'
+DIM='\033[2m'
+UNDERLINE='\033[4m'
+BLINK='\033[5m'
+REVERSE='\033[7m'
+NC='\033[0m'
+
+# Logging functions
+log_info() {
+ echo -e "${BLUE}ℹ${NC} $1"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_success() {
+ echo -e "${GREEN}✅${NC} $1"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [SUCCESS] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_warning() {
+ echo -e "${YELLOW}⚠${NC} $1"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [WARNING] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_error() {
+ echo -e "${RED}❌${NC} $1"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_step() {
+ echo -e "${PURPLE}🔸${NC} ${BOLD}$1${NC}"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [STEP] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_simulate() {
+ echo -e "${CYAN}🎭${NC} $1"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [SIMULATE] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_command() {
+ echo -e "${YELLOW}\$${NC} ${DIM}$1${NC}"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [COMMAND] $1" >> "$MAIN_LOG"
+ fi
+}
+
+log_debug() {
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [DEBUG] $1" >> "$MAIN_LOG"
+ fi
+}
+
+# Progress animation functions
+animate_loading() {
+ local message="$1"
+ local duration="${2:-3}"
+ local frames="⣾⣽⣻⢿⡿⣟⣯⣷"
+ local frame_count=${#frames}
+ local delay=0.1
+
+ # Log the start of the loading animation
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [PROGRESS] Starting: $message" >>
"$MAIN_LOG"
+ fi
+
+ if ! command -v bc >/dev/null 2>&1; then
+ echo -e "${CYAN}⏳${NC} $message"
+ sleep "$duration"
+ echo -e "\r${GREEN}✅${NC} $message"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [PROGRESS] Completed: $message"
>> "$MAIN_LOG"
+ fi
+ return
+ fi
+
+ local total_iterations=$(echo "$duration / $delay" | bc -l)
+ total_iterations=${total_iterations%.*}
+
+ for (( i=0; i<total_iterations; i++ )); do
+ local frame_index=$((i % frame_count))
+ local frame=${frames:$frame_index:1}
+ echo -ne "\r${CYAN}$frame${NC} $message"
+ sleep "$delay"
+ done
+
+ echo -e "\r${GREEN}✅${NC} $message"
+ if [ -n "${MAIN_LOG:-}" ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [PROGRESS] Completed: $message" >>
"$MAIN_LOG"
+ fi
+}
+
+# Rainbow text animation
+rainbow_text() {
+ local text="$1"
+ local colors=("$RED" "$YELLOW" "$GREEN" "$CYAN" "$BLUE" "$PURPLE")
+ local color_count=${#colors[@]}
+
+ for (( i=0; i<${#text}; i++ )); do
+ local char="${text:$i:1}"
+ local color_index=$((i % color_count))
+ echo -ne "${colors[$color_index]}$char"
+ done
+ echo -e "${NC}"
+}
+
+# Typewriter effect animation with ANSI code support
+typewriter_effect() {
+ local text="$1"
+ local delay="${2:-0.01}"
+
+ # Use echo -e to interpret escape sequences, then process character by
character
+ local processed_text=$(echo -e "$text")
+
+ local i=0
+ while [ $i -lt ${#processed_text} ]; do
+ # Check if we're at the start of an ANSI escape sequence (\033[)
+ if [[ "${processed_text:$i:1}" == $'\033' ]]; then
+ # Find the end of the ANSI sequence (ends with a letter, usually
'm')
+ local ansi_seq=""
+ local j=$i
+ while [ $j -lt ${#processed_text} ]; do
+ ansi_seq+="${processed_text:$j:1}"
+ if [[ "${processed_text:$j:1}" =~ [a-zA-Z] ]]; then
+ break
+ fi
+ ((j++))
+ done
+ # Print the entire ANSI sequence at once (no delay)
+ echo -n "$ansi_seq"
+ i=$((j + 1))
+ else
+ # Regular character - print with delay
+ echo -n "${processed_text:$i:1}"
+ sleep "$delay"
+ ((i++))
+ fi
+ done
+ echo -e "${NC}"
+}
+
+# System requirements checking
+check_command() {
+ local cmd="$1"
+ local description="$2"
+ local required="${3:-true}"
+
+ if command -v "$cmd" >/dev/null 2>&1; then
+ local version=""
+ case "$cmd" in
+ "java")
+ version=$(java -version 2>&1 | head -n1 | cut -d'"' -f2 | cut
-d'.' -f1-2)
+ ;;
+ "mvn")
+ version=$(mvn --version 2>/dev/null | head -n1 | cut -d' ' -f3)
+ ;;
+ "git")
+ version=$(git --version | cut -d' ' -f3)
+ ;;
+ "svn")
+ version=$(svn --version --quiet 2>/dev/null)
+ ;;
+ *)
+ version="found"
+ ;;
+ esac
+ log_success "$description $version found"
+ return 0
+ else
+ if [ "$required" = "true" ]; then
+ log_error "$description not found"
+ return 1
+ else
+ log_info "$description not found (not required for local mode)"
+ return 0
+ fi
+ fi
+}
+
+# Git repository validation
+check_git_repository() {
+ if ! git rev-parse --git-dir >/dev/null 2>&1; then
+ log_error "Not in a git repository"
+ return 1
+ fi
+ log_success "Git repository detected"
+ return 0
+}
+
+# Disk space checking
+check_disk_space() {
+ local required_mb="${1:-100}"
+
+ if command -v df >/dev/null 2>&1; then
+ local available_kb
+ available_kb=$(df . | tail -1 | awk '{print $4}')
+ local available_mb=$((available_kb / 1024))
+
+ if [ "$available_mb" -lt "$required_mb" ]; then
+ log_warning "Low disk space: ${available_mb}MB available,
${required_mb}MB recommended"
+ return 1
+ else
+ log_success "Sufficient disk space available"
+ return 0
+ fi
+ else
+ log_info "Cannot check disk space (df command not available)"
+ return 0
+ fi
+}
+
+# Memory checking
+check_memory() {
+ local required_mb="${1:-512}"
+
+ if command -v free >/dev/null 2>&1; then
+ # Linux
+ local available_mb
+ available_mb=$(free -m | awk '/^Mem:/{print $7}')
+ if [ -z "$available_mb" ]; then
+ available_mb=$(free -m | awk '/^Mem:/{print $4}')
+ fi
+ elif command -v vm_stat >/dev/null 2>&1; then
+ # macOS
+ local page_size=4096
+ local free_pages
+ free_pages=$(vm_stat | grep "Pages free" | awk '{print $3}' | sed
's/\.//')
+ local available_mb=$((free_pages * page_size / 1024 / 1024))
+ else
+ log_info "Cannot check memory (free/vm_stat command not available)"
+ return 0
+ fi
+
+ if [ -n "$available_mb" ] && [ "$available_mb" -lt "$required_mb" ]; then
+ log_warning "Low available memory - at least ${required_mb}MB
recommended"
+ return 1
+ else
+ log_success "Sufficient memory available"
+ return 0
+ fi
+}
+
+# Directory validation
+check_directory_writable() {
+ local dir="${1:-.}"
+
+ if [ -w "$dir" ]; then
+ log_success "Current directory is writable"
+ return 0
+ else
+ log_error "Current directory is not writable"
+ return 1
+ fi
+}
+
+# Logging helper functions for command execution
+log_to_file() {
+ local log_file="$1"
+ local command="$2"
+ shift 2
+
+ echo
"==============================================================================="
>> "$log_file"
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - Executing: $command" >> "$log_file"
+ echo "Working directory: $(pwd)" >> "$log_file"
+ echo
"==============================================================================="
>> "$log_file"
+}
+
+run_git_command() {
+ local cmd="$*"
+ log_to_file "${MAIN_LOG:-/dev/null}" "$cmd"
+ echo "Command: $cmd" >> "${MAIN_LOG:-/dev/null}"
+ echo "Output:" >> "${MAIN_LOG:-/dev/null}"
+
+ if eval "$cmd" >> "${MAIN_LOG:-/dev/null}" 2>&1; then
+ echo "Status: SUCCESS" >> "${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return 0
+ else
+ local exit_code=$?
+ echo "Status: FAILED (exit code: $exit_code)" >>
"${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return $exit_code
+ fi
+}
+
+run_maven_command() {
+ local cmd="$*"
+ log_to_file "${MAIN_LOG:-/dev/null}" "$cmd"
+ echo "Command: $cmd" >> "${MAIN_LOG:-/dev/null}"
+ echo "Output:" >> "${MAIN_LOG:-/dev/null}"
+
+ if eval "$cmd" >> "${MAIN_LOG:-/dev/null}" 2>&1; then
+ echo "Status: SUCCESS" >> "${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return 0
+ else
+ local exit_code=$?
+ echo "Status: FAILED (exit code: $exit_code)" >>
"${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return $exit_code
+ fi
+}
+
+run_svn_command() {
+ local cmd="$*"
+ log_to_file "${MAIN_LOG:-/dev/null}" "$cmd"
+ echo "Command: $cmd" >> "${MAIN_LOG:-/dev/null}"
+ echo "Output:" >> "${MAIN_LOG:-/dev/null}"
+
+ if eval "$cmd" >> "${MAIN_LOG:-/dev/null}" 2>&1; then
+ echo "Status: SUCCESS" >> "${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return 0
+ else
+ local exit_code=$?
+ echo "Status: FAILED (exit code: $exit_code)" >>
"${MAIN_LOG:-/dev/null}"
+ echo "" >> "${MAIN_LOG:-/dev/null}"
+ return $exit_code
+ fi
+}
+
+# Export functions for use in other scripts
+export -f log_info log_success log_warning log_error log_step log_simulate
log_command log_debug
+export -f animate_loading rainbow_text typewriter_effect
+export -f check_command check_git_repository check_disk_space check_memory
check_directory_writable
+export -f log_to_file run_git_command run_maven_command run_svn_command