1#!/bin/bash
2
3#
4# DOCKER_CMD should be either `docker` or `podman`.
5#
6# if using (rootless) podman, remember to set /etc/subuid
7# and /etc/subgid.
8#
9docker_cmd=${DOCKER_CMD:-"docker"}
10[ "$DOCKER_CMD" = "podman" ] && userns_podman="--userns=keep-id" selinux=",z"
11
12einfo() {
13    echo "$*" >&2
14}
15
16die() {
17    echo "$*" >&2
18    exit 1
19}
20
21#
22# The caller is expected to override the CONTAINER environment
23# variable with the container they wish to launch.
24#
25BASE="registry.gitlab.com/xen-project/xen"
26case "_${CONTAINER}" in
27    _alpine) CONTAINER="${BASE}/alpine:3.18" ;;
28    _alpine-arm64v8) CONTAINER="${BASE}/alpine:3.18-arm64v8" ;;
29    _archlinux|_arch) CONTAINER="${BASE}/archlinux:current" ;;
30    _centos7) CONTAINER="${BASE}/centos:7" ;;
31    _fedora) CONTAINER="${BASE}/fedora:29";;
32    _bullseye-ppc64le) CONTAINER="${BASE}/debian:11-ppc64le" ;;
33    _bookworm-ppc64le) CONTAINER="${BASE}/debian:12-ppc64le" ;;
34    _bullseye-riscv64) CONTAINER="${BASE}/debian:11-riscv64" ;;
35    _bookworm-riscv64) CONTAINER="${BASE}/debian:12-riscv64" ;;
36    _bookworm-x86_64-gcc-ibt) CONTAINER="${BASE}/debian:12-x86_64-gcc-ibt" ;;
37    _bookworm|_) CONTAINER="${BASE}/debian:bookworm" ;;
38    _bookworm-i386) CONTAINER="${BASE}/debian:bookworm-i386" ;;
39    _bookworm-arm64v8-arm32-gcc) CONTAINER="${BASE}/debian:bookworm-arm64v8-arm32-gcc" ;;
40    _bookworm-arm64v8) CONTAINER="${BASE}/debian:bookworm-arm64v8" ;;
41    _bookworm-cppcheck) CONTAINER="${BASE}/debian:bookworm-cppcheck" ;;
42    _opensuse-leap|_leap) CONTAINER="${BASE}/opensuse:leap-15.6-x86_64" ;;
43    _opensuse-tumbleweed|_tumbleweed) CONTAINER="${BASE}/opensuse:tumbleweed-x86_64" ;;
44    _xenial) CONTAINER="${BASE}/ubuntu:16.04-x86_64" ;;
45    _bionic) CONTAINER="${BASE}/ubuntu:18.04-x86_64" ;;
46    _focal)  CONTAINER="${BASE}/ubuntu:20.04-x86_64" ;;
47    _jammy)  CONTAINER="${BASE}/ubuntu:22.04-x86_64" ;;
48    _noble)  CONTAINER="${BASE}/ubuntu:24.04-x86_64" ;;
49esac
50
51# Use this variable to control whether root should be used
52case "_${CONTAINER_UID0}" in
53    _1)   userarg="-u 0" ;;
54    _0|_) userarg="-u $(id -u) $userns_podman" ;;
55esac
56
57# Save the commands for future use
58cmd=("$@")
59
60# If no command was specified, just drop us into a shell if we're interactive
61[ $# -eq 0 ] && tty -s && cmd=("/bin/bash")
62
63# Are we in an interactive terminal?
64tty -s && termint=t
65
66#
67# Fetch the latest version of the container in hub.docker.com,
68# unless it's a newly created local copy.
69#
70if [[ "_${CONTAINER_NO_PULL}" != "_1" ]]; then
71    einfo "*** Ensuring ${CONTAINER} is up to date"
72    ${docker_cmd} pull ${CONTAINER} > /dev/null ||     \
73        die "Failed to update container"
74fi
75
76if hash greadlink > /dev/null 2>&1; then
77    READLINK=greadlink
78elif [[ $(uname -s) == "Darwin" ]]; then
79    echo "Unable to forward SSH agent without coreutils installed"
80    unset SSH_AUTH_SOCK
81else
82    READLINK=readlink
83fi
84
85# Ensure we've got what we need for SSH_AUTH_SOCK
86if [[ -n ${SSH_AUTH_SOCK} ]]; then
87    fullpath_sock=$(${READLINK} -f ${SSH_AUTH_SOCK} 2> /dev/null)
88    if [ $? -ne 0 ]; then
89        echo "Invalid SSH_AUTH_SOCK: ${SSH_AUTH_SOCK}"
90        unset SSH_AUTH_SOCK
91    else
92        SSH_AUTH_DIR=$(dirname ${fullpath_sock})
93        SSH_AUTH_NAME=$(basename ${fullpath_sock})
94    fi
95fi
96
97# Figure out the base of what we want as our sources
98# by using the top of the git repo
99if [[ -z ${CONTAINER_PATH} ]]; then
100    CONTAINER_PATH=$(git rev-parse --show-toplevel)
101fi
102
103# Kick off Docker
104einfo "*** Launching container ..."
105exec ${docker_cmd} run \
106    ${userarg} \
107    ${SSH_AUTH_SOCK:+-e SSH_AUTH_SOCK="/tmp/ssh-agent/${SSH_AUTH_NAME}"} \
108    -v "${CONTAINER_PATH}":/build:rw${selinux} \
109    -v "${HOME}/.ssh":/root/.ssh:ro \
110    ${SSH_AUTH_DIR:+-v "${SSH_AUTH_DIR}":/tmp/ssh-agent${selinux}} \
111    ${CONTAINER_ARGS} \
112    -${termint}i --rm -- \
113    ${CONTAINER} \
114    "${cmd[@]}"
115