diff --git a/.github/workflows/build-oci.yml b/.github/workflows/build-oci.yml index 6f433e3..0febc47 100644 --- a/.github/workflows/build-oci.yml +++ b/.github/workflows/build-oci.yml @@ -6,7 +6,7 @@ permissions: packages: write id-token: write jobs: - build: + build-oci-image: runs-on: edera-large strategy: fail-fast: false @@ -18,6 +18,8 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: submodules: recursive + - run: ./unabsorb.sh + shell: bash - uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 - uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 diff --git a/unabsorb.sh b/unabsorb.sh new file mode 100755 index 0000000..a9cff46 --- /dev/null +++ b/unabsorb.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +set -euo pipefail + +super_top="$(git rev-parse --show-toplevel 2>/dev/null)" || { + echo "error: not inside a git worktree" >&2 + exit 1 +} + +cd "${super_top}" + +# Collect all submodule paths first, recursively, then process deepest-first. +mapfile -t submodules < <( + git submodule foreach --quiet --recursive 'printf "%s\n" "$displaypath"' \ + | awk '{ depth=gsub(/\//, "/"); printf "%d\t%s\n", depth, $0 }' \ + | sort -r -n -k1,1 \ + | cut -f2- +) + +if [[ ${#submodules[@]} -eq 0 ]]; then + echo "No submodules found." + exit 0 +fi + +for path in "${submodules[@]}"; do + echo "Processing ${path}" + + cd "${super_top}/${path}" + + if [[ ! -f .git ]]; then + echo " skipping: .git is not a gitfile stub" + continue + fi + + gitfile="$(< .git)" + case "${gitfile}" in + "gitdir: "*) + gitdir="${gitfile#gitdir: }" + ;; + *) + echo " skipping: .git is not a recognized gitfile stub" + continue + ;; + esac + + if [[ "${gitdir}" = /* ]]; then + src_gitdir="${gitdir}" + else + src_gitdir="$(realpath -m "${PWD}/${gitdir}")" + fi + + if [[ ! -d "${src_gitdir}" ]]; then + echo " error: source gitdir does not exist: ${src_gitdir}" >&2 + exit 1 + fi + + rm -f .git + mv "${src_gitdir}" .git + + # Remove core.worktree directly from config to avoid Git trying to + # resolve the stale absorbed worktree path during `git config`. + if [[ -f .git/config ]]; then + python3 - "$PWD/.git/config" <<'PY' +import configparser +import io +import os +import sys + +path = sys.argv[1] + +cp = configparser.RawConfigParser() +cp.optionxform = str + +with open(path, "r", encoding="utf-8") as f: + data = f.read() + +cp.read_file(io.StringIO(data)) + +changed = False +if cp.has_section("core") and cp.has_option("core", "worktree"): + cp.remove_option("core", "worktree") + changed = True + if not cp.items("core"): + cp.remove_section("core") + +if changed: + with open(path, "w", encoding="utf-8") as f: + cp.write(f) +PY + fi + + echo " moved ${src_gitdir} -> ${PWD}/.git" +done