Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/build-oci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ permissions:
packages: write
id-token: write
jobs:
build:
build-oci-image:
runs-on: edera-large
strategy:
fail-fast: false
Expand All @@ -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
Expand Down
92 changes: 92 additions & 0 deletions unabsorb.sh
Original file line number Diff line number Diff line change
@@ -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
Loading