# Justfile for bootc reverse dependency testing
# Invoked via: just bootc/<target>
#
# This builds and tests bootc against the local composefs-rs checkout
# using bootc's auto-detection of path dependencies via `cargo xtask local-rust-deps`.
# --------------------------------------------------------------------

# Configuration variables (override via environment or command line)
# Example: COMPOSEFS_BOOTC_REF=v1.0.0 just bootc/build

# Path to bootc checkout (will be cloned if it doesn't exist)
# Note: Use source_directory() not justfile_directory() so paths resolve correctly
# when invoked as a submodule (just bootc::test) vs directly (cd bootc && just test)
export COMPOSEFS_BOOTC_PATH := env("COMPOSEFS_BOOTC_PATH", source_directory() + "/../target/bootc")
# Git ref to checkout for bootc (branch, tag, or PR ref)
export COMPOSEFS_BOOTC_REF := env("COMPOSEFS_BOOTC_REF", "main")
# Remote repository for bootc
export COMPOSEFS_BOOTC_REPO := env("COMPOSEFS_BOOTC_REPO", "https://github.com/bootc-dev/bootc")

# Internal: absolute path to the composefs-rs checkout (parent of this Justfile)
export _COMPOSEFS_SRC := canonicalize(source_directory() + "/..")

# Clone or update bootc repository
clone:
    #!/bin/bash
    set -euo pipefail
    if [ -d "$COMPOSEFS_BOOTC_PATH/.git" ]; then
        echo "bootc already cloned at $COMPOSEFS_BOOTC_PATH"
        echo "To update: cd $COMPOSEFS_BOOTC_PATH && git fetch && git checkout <ref>"
    else
        echo "Cloning bootc from $COMPOSEFS_BOOTC_REPO (ref: $COMPOSEFS_BOOTC_REF) to $COMPOSEFS_BOOTC_PATH"
        mkdir -p "$(dirname "$COMPOSEFS_BOOTC_PATH")"
        # Use --no-checkout with --filter for efficient cloning, then fetch the specific ref
        # This handles PR refs (refs/pull/123/head) correctly
        git clone "$COMPOSEFS_BOOTC_REPO" "$COMPOSEFS_BOOTC_PATH" --no-checkout --filter=blob:none
        cd "$COMPOSEFS_BOOTC_PATH"
        git fetch --depth=1 origin "$COMPOSEFS_BOOTC_REF"
        git checkout FETCH_HEAD
    fi

# Patch bootc's Cargo.toml to use the local composefs-rs checkout.
#
# The workspace dependency already has a `git` + `rev` pointing at the
# composefs-rs commit this bootc branch is compatible with.  Bumping that
# `rev` (done when the bootc branch is updated) busts the podman build
# cache.  This recipe just adds a [patch] override so Cargo resolves from
# the bind-mounted local source instead of fetching from git.
#
# Errors if the composefs-rs tree has uncommitted changes.
patch: clone
    #!/bin/bash
    set -euo pipefail

    # Require a clean composefs-rs working tree so we test a real commit.
    # Only tracked files matter; untracked files are allowed.
    # git diff HEAD already excludes untracked files.
    if ! git -C "$_COMPOSEFS_SRC" diff --quiet HEAD 2>/dev/null; then
        echo "error: composefs-rs has uncommitted changes — commit or stash first" >&2
        git -C "$_COMPOSEFS_SRC" diff --stat HEAD >&2
        exit 1
    fi

    cfs_path="$_COMPOSEFS_SRC/crates/composefs-ctl"

    cd "$COMPOSEFS_BOOTC_PATH"

    # Add or update the [patch] section with a path override
    patch_value="composefs-ctl = { path = \"${cfs_path}\" } # Patched by composefs-rs"
    if grep -q '^[[:space:]]*\[patch\."https://github.com/composefs/composefs-rs"\]' Cargo.toml; then
        # Patch section already exists (uncommented) — replace the composefs-ctl line
        sed -i '/^[[:space:]]*\[patch\."https:\/\/github.com\/composefs\/composefs-rs"\]/,/^$\|^\[/{
            s|^composefs-ctl = .*|'"$patch_value"'|
        }' Cargo.toml
    else
        # No patch section yet — append one
        {
            echo ''
            echo '# Patched by composefs-rs CI to test against local composefs-rs'
            echo '[patch."https://github.com/composefs/composefs-rs"]'
            echo "$patch_value"
        } >> Cargo.toml
    fi

    # Patch the workspace lints to allow missing_docs for composefs-rs crates
    # bootc has workspace.lints.rust.missing_docs = "deny" but composefs-rs has undocumented items
    sed -i 's/missing_docs = "deny"/missing_docs = "allow"/' Cargo.toml

    # Update the rev comment in the [patch] section so Cargo.toml actually
    # changes when composefs-rs moves to a new commit.  Since the file is
    # part of the podman build context this busts the layer cache.
    _rev=$(git -C "$_COMPOSEFS_SRC" rev-parse HEAD)
    sed -i "s/^# Patched by composefs-rs.*/# Patched by composefs-rs at ${_rev}/" Cargo.toml
    echo "bootc patched for composefs-rs at ${_rev}"

# Build sealed bootc image using local composefs-rs
# The path dependency is auto-detected and bind-mounted by bootc's Justfile
build: patch
    #!/bin/bash
    set -euo pipefail
    cd "$COMPOSEFS_BOOTC_PATH"
    echo "Building sealed bootc image with local composefs-rs from $_COMPOSEFS_SRC"
    just build-sealed

# Run bootc composefs tests using local composefs-rs
# Since the patch uses real local paths, no symlinks or special env vars needed
# Parameters match bootc's test-composefs target signature
test bootloader="systemd" filesystem="ext4" boot_type="uki" seal_state="sealed": build
    #!/bin/bash
    set -euo pipefail
    cd "$COMPOSEFS_BOOTC_PATH"
    echo "Running bootc composefs tests (bootloader={{bootloader}}, filesystem={{filesystem}}, boot_type={{boot_type}}, seal_state={{seal_state}})..."
    # Export as env vars so they propagate through @just sub-invocations
    # (just variable overrides don't propagate to child `just` processes,
    # but bootc's Justfile reads these from BOOTC_* env vars)
    export BOOTC_boot_type={{boot_type}}
    export BOOTC_seal_state={{seal_state}}
    just test-composefs {{bootloader}} {{filesystem}} {{boot_type}} {{seal_state}}

# Clean the bootc checkout and any patches.
# Refuses to delete if there are any uncommitted changes (tracked, untracked,
# or ignored) to prevent accidentally losing work.
clean:
    #!/bin/bash
    set -euo pipefail
    if [ ! -d "$COMPOSEFS_BOOTC_PATH" ]; then
        echo "No bootc checkout found at $COMPOSEFS_BOOTC_PATH"
        exit 0
    fi
    cd "$COMPOSEFS_BOOTC_PATH"
    if [ ! -d .git ]; then
        echo "Not a git repo: $COMPOSEFS_BOOTC_PATH — removing"
        rm -rf "$COMPOSEFS_BOOTC_PATH"
        exit 0
    fi
    # Check for ANY local state: staged, unstaged, untracked, or ignored files
    if ! git diff --quiet HEAD -- 2>/dev/null || \
       ! git diff --cached --quiet HEAD -- 2>/dev/null || \
       [ -n "$(git ls-files --others 2>/dev/null)" ]; then
        echo "error: bootc checkout at $COMPOSEFS_BOOTC_PATH has uncommitted changes" >&2
        echo "       Commit, stash, or manually 'rm -rf' if you're sure." >&2
        git status --short
        exit 1
    fi
    echo "Removing bootc checkout at $COMPOSEFS_BOOTC_PATH"
    rm -rf "$COMPOSEFS_BOOTC_PATH"

# Show current bootc integration configuration
config:
    #!/bin/bash
    cat <<EOF
    Bootc Integration Configuration
    ================================
    path:  $COMPOSEFS_BOOTC_PATH
    ref:   $COMPOSEFS_BOOTC_REF
    repo:  $COMPOSEFS_BOOTC_REPO

    composefs-rs source: $_COMPOSEFS_SRC

    Environment Variables:
      COMPOSEFS_BOOTC_PATH - Override bootc checkout path
      COMPOSEFS_BOOTC_REF  - Override bootc git ref (branch/tag/PR)
      COMPOSEFS_BOOTC_REPO - Override bootc git repository

    Test Parameters:
      just bootc/test                                        # Default: systemd + ext4 + uki + sealed
      just bootc/test grub ext4 bls unsealed                 # grub + ext4 + BLS (unsealed)
      just bootc/test systemd btrfs uki sealed               # systemd-boot + btrfs + UKI (sealed)

    Example Usage:
      just bootc/build                                      # Clone main, patch, and build
      COMPOSEFS_BOOTC_REF=v1.0.0 just bootc/build           # Use specific tag
      COMPOSEFS_BOOTC_REF=refs/pull/1791/head just bootc/build  # Use PR
    EOF
