Loading...
No commits yet
Not committed History
Blame
process_diff.sh • 6.8 KB
#!/bin/bash
# -*- coding: utf-8 -*-
# Timestamp: "2026-01-19 (ywatanabe)"
# File: ./scripts/shell/modules/process_diff.sh
# Description: Generate diff between current and previous git commit (or arbitrary commits)

ORIG_DIR="$(pwd)"
THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENGINES_DIR="${THIS_DIR}/engines"
LOG_PATH="$THIS_DIR/.$(basename "$0").log"
echo >"$LOG_PATH"

GRAY='\033[0;90m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
NC='\033[0m'

echo_info() { echo -e "${GRAY}INFO: $1${NC}"; }
log_info() {
    if [ "${SCITEX_LOG_LEVEL:-1}" -ge 2 ]; then
        echo -e "  \033[0;90m→ $1\033[0m"
    fi
}
echo_success() { echo -e "${GREEN}SUCC: $1${NC}"; }
echo_warning() { echo -e "${YELLOW}WARN: $1${NC}"; }
echo_error() { echo -e "${RED}ERRO: $1${NC}"; }

# shellcheck source=../../../config/load_config.sh
source ./config/load_config.sh "$SCITEX_WRITER_DOC_TYPE"

# shellcheck source=./command_switching.src
source "$(dirname "${BASH_SOURCE[0]}")/command_switching.src"

touch "$LOG_PATH" >/dev/null 2>&1
echo
log_info "Running $0 ..."

# Get .tex content from a specific git commit
# Usage: get_tex_from_commit <commit> <tex_path>
get_tex_from_commit() {
    local commit="$1"
    local tex_path="$2"
    git show "${commit}:${tex_path}" 2>/dev/null
}

# Get the previous commit that modified the compiled .tex file
# Returns the commit hash, or empty if no previous commit
get_previous_commit() {
    local tex_path="$1"
    # Get the second-to-last commit that touched this file (skip HEAD)
    git log --format="%H" -n 2 -- "$tex_path" 2>/dev/null | tail -n 1
}

# Create a temporary file with .tex content from a git commit
# Usage: create_temp_tex_from_commit <commit> <tex_path>
# Returns: path to temp file
create_temp_tex_from_commit() {
    local commit="$1"
    local tex_path="$2"
    local temp_file
    temp_file=$(mktemp --suffix=.tex)

    if get_tex_from_commit "$commit" "$tex_path" >"$temp_file" 2>/dev/null; then
        echo "$temp_file"
    else
        rm -f "$temp_file"
        echo ""
    fi
}

# Get short commit hash for display
get_short_hash() {
    local commit="${1:-HEAD}"
    git rev-parse --short=7 "$commit" 2>/dev/null || echo "unknown"
}

take_diff_tex() {
    local diff_from="${SCITEX_DIFF_FROM:-}"
    local diff_to="${SCITEX_DIFF_TO:-HEAD}"

    log_info "    Creating diff document..."

    if [ ! -f "$SCITEX_WRITER_COMPILED_TEX" ]; then
        echo_warning "    $SCITEX_WRITER_COMPILED_TEX not found."
        return 1
    fi

    # Determine the "from" commit
    local previous_tex=""
    local old_hash=""
    local new_hash=""

    if [ -n "$diff_from" ]; then
        # Explicit --diff-from specified
        old_hash=$(get_short_hash "$diff_from")
        previous_tex=$(create_temp_tex_from_commit "$diff_from" "$SCITEX_WRITER_COMPILED_TEX")
    else
        # Default: diff from last commit
        local prev_commit
        prev_commit=$(get_previous_commit "$SCITEX_WRITER_COMPILED_TEX")
        if [ -n "$prev_commit" ]; then
            old_hash=$(get_short_hash "$prev_commit")
            previous_tex=$(create_temp_tex_from_commit "$prev_commit" "$SCITEX_WRITER_COMPILED_TEX")
        fi
    fi

    # Determine the "to" version
    if [ "$diff_to" = "HEAD" ]; then
        new_hash=$(get_short_hash HEAD)
        # Check for uncommitted changes
        if ! git diff --quiet HEAD -- 2>/dev/null; then
            new_hash="${new_hash}+"
        fi
    else
        new_hash=$(get_short_hash "$diff_to")
    fi

    # If no previous version found, use current as both (no diff)
    if [ -z "$previous_tex" ] || [ ! -f "$previous_tex" ]; then
        echo_warning "    No previous version found in git history"
        echo_warning "    Creating empty diff (current vs current)"
        previous_tex="$SCITEX_WRITER_COMPILED_TEX"
        old_hash="none"
    fi

    # Get latexdiff command
    local latexdiff_cmd
    latexdiff_cmd=$(get_cmd_latexdiff "$ORIG_DIR")

    if [ -z "$latexdiff_cmd" ]; then
        echo_error "    latexdiff not found (native, module, or container)"
        [ -f "$previous_tex" ] && [ "$previous_tex" != "$SCITEX_WRITER_COMPILED_TEX" ] && rm -f "$previous_tex"
        return 1
    fi

    # Run latexdiff
    $latexdiff_cmd \
        --encoding=utf8 \
        --type=CULINECHBAR \
        --disable-citation-markup \
        --append-safecmd="cite,cite,citet" \
        "$previous_tex" "$SCITEX_WRITER_COMPILED_TEX" 2> >(grep -v 'gocryptfs not found' | grep -v 'Wide character in print' >&2) >"$SCITEX_WRITER_DIFF_TEX"

    # Cleanup temp file
    [ -f "$previous_tex" ] && [ "$previous_tex" != "$SCITEX_WRITER_COMPILED_TEX" ] && rm -f "$previous_tex"

    if [ -f "$SCITEX_WRITER_DIFF_TEX" ] && [ -s "$SCITEX_WRITER_DIFF_TEX" ]; then
        echo_success "    $SCITEX_WRITER_DIFF_TEX created (${old_hash} → ${new_hash})"

        # Add signature with git commit metadata
        if [ -f "./scripts/shell/modules/add_diff_signature.sh" ]; then
            # shellcheck source=./add_diff_signature.sh
            source ./scripts/shell/modules/add_diff_signature.sh
            add_diff_signature "$SCITEX_WRITER_DIFF_TEX" "$old_hash" "$new_hash"
        fi

        return 0
    else
        echo_warning "    $SCITEX_WRITER_DIFF_TEX not created or is empty"
        return 1
    fi
}

compile_diff_tex() {
    log_info "    Compiling diff document..."

    local tex_file="$SCITEX_WRITER_DIFF_TEX"

    # shellcheck source=./engines/compile_tectonic.sh
    source "${ENGINES_DIR}/compile_tectonic.sh"
    # shellcheck source=./engines/compile_latexmk.sh
    source "${ENGINES_DIR}/compile_latexmk.sh"
    # shellcheck source=./engines/compile_3pass.sh
    source "${ENGINES_DIR}/compile_3pass.sh"

    local engine="${SCITEX_WRITER_SELECTED_ENGINE:-latexmk}"

    log_info "    Using engine: $engine"

    case "$engine" in
    tectonic)
        compile_with_tectonic "$tex_file"
        ;;
    latexmk)
        compile_with_latexmk "$tex_file"
        ;;
    3pass)
        compile_with_3pass "$tex_file"
        ;;
    *)
        echo_warning "    Unknown engine '$engine', using latexmk"
        compile_with_latexmk "$tex_file"
        ;;
    esac
}

cleanup() {
    local pdf_basename
    pdf_basename=$(basename "$SCITEX_WRITER_DIFF_PDF")
    local pdf_in_logs="${LOG_DIR}/${pdf_basename}"

    if [ -f "$pdf_in_logs" ]; then
        mv "$pdf_in_logs" "$SCITEX_WRITER_DIFF_PDF"
        echo_info "    Moved PDF: $pdf_in_logs -> $SCITEX_WRITER_DIFF_PDF"
    fi

    if [ -f "$SCITEX_WRITER_DIFF_PDF" ]; then
        local size
        size=$(du -h "$SCITEX_WRITER_DIFF_PDF" | cut -f1)
        echo_success "    $SCITEX_WRITER_DIFF_PDF ready (${size})"
        sleep 1
    else
        echo_warning "    $SCITEX_WRITER_DIFF_PDF not created"
    fi
}

main() {
    local start_time
    start_time=$(date +%s)

    if take_diff_tex; then
        compile_diff_tex
    fi

    cleanup
    echo_info "    Total time: $(($(date +%s) - start_time))s"
}

main "$@"

# EOF