diff --git a/src/wine/install.sh b/src/wine/install.sh index 883c25d..5b1117f 100644 --- a/src/wine/install.sh +++ b/src/wine/install.sh @@ -1,26 +1,32 @@ #!/bin/sh set -e -echo "Activating feature 'color'" -echo "The provided favorite color is: ${FAVORITE}" +WINEVERSION=$WINEVERSION +WINEHOME="/home/root" +WINEPREFIX="$WINEHOME/.wine32" +WINEARCH="win32" +WINEDEBUG=-all +ensure_nanolayer nanolayer_location "v0.5.0" -# The 'install.sh' entrypoint script is always executed as the root user. -# -# These following environment variables are passed in by the dev container CLI. -# These may be useful in instances where the context of the final -# remoteUser or containerUser is useful. -# For more details, see https://containers.dev/implementors/features#user-env-var -echo "The effective dev container remoteUser is '$_REMOTE_USER'" -echo "The effective dev container remoteUser's home directory is '$_REMOTE_USER_HOME'" +$nanolayer_location \ + install \ + apt-get \ + apt-transport-https \ + ca-certificates \ + telnet \ + cabextract \ + gnupg2 \ + wget -echo "The effective dev container containerUser is '$_CONTAINER_USER'" -echo "The effective dev container containerUser's home directory is '$_CONTAINER_USER_HOME'" +wget https://dl.winehq.org/wine-builds/winehq.key -O - | apt-key add - +echo "deb https://dl.winehq.org/wine-builds/debian bookworm main" > /etc/apt/sources.list.d/winehq.list +{ \ + echo "Package: *wine* *wine*:i386"; \ + echo "Pin: version $WINEVERSION~bookworm"; \ + echo "Pin-Priority: 1001"; \ +} > /etc/apt/preferences.d/winehq.pref -cat > /usr/local/bin/color \ -<< EOF -#!/bin/sh -echo "my favorite color is ${FAVORITE}" -EOF - -chmod +x /usr/local/bin/color +$nanolayer_location install apt-get winehq-stable +wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks -O /usr/bin/winetricks +chmod +rx /usr/bin/winetricks \ No newline at end of file diff --git a/src/wine/library_scripts.sh b/src/wine/library_scripts.sh new file mode 100644 index 0000000..87874f5 --- /dev/null +++ b/src/wine/library_scripts.sh @@ -0,0 +1,172 @@ +// https://github.com/devcontainers-contrib/features/blob/696aa94479697cf701c559ef17d4f0bbb86bd00c/src/bikeshed/library_scripts.sh + +clean_download() { + # The purpose of this function is to download a file with minimal impact on container layer size + # this means if no valid downloader is found (curl or wget) then we install a downloader (currently wget) in a + # temporary manner, and making sure to + # 1. uninstall the downloader at the return of the function + # 2. revert back any changes to the package installer database/cache (for example apt-get lists) + # The above steps will minimize the leftovers being created while installing the downloader + # Supported distros: + # debian/ubuntu/alpine + + url=$1 + output_location=$2 + tempdir=$(mktemp -d) + downloader_installed="" + + _apt_get_install() { + tempdir=$1 + + # copy current state of apt list - in order to revert back later (minimize contianer layer size) + cp -p -R /var/lib/apt/lists $tempdir + apt-get update -y + apt-get -y install --no-install-recommends wget ca-certificates + } + + _apt_get_cleanup() { + tempdir=$1 + + echo "removing wget" + apt-get -y purge wget --auto-remove + + echo "revert back apt lists" + rm -rf /var/lib/apt/lists/* + rm -r /var/lib/apt/lists && mv $tempdir/lists /var/lib/apt/lists + } + + _apk_install() { + tempdir=$1 + # copy current state of apk cache - in order to revert back later (minimize contianer layer size) + cp -p -R /var/cache/apk $tempdir + + apk add --no-cache wget + } + + _apk_cleanup() { + tempdir=$1 + + echo "removing wget" + apk del wget + } + # try to use either wget or curl if one of them already installer + if type curl >/dev/null 2>&1; then + downloader=curl + elif type wget >/dev/null 2>&1; then + downloader=wget + else + downloader="" + fi + + # in case none of them is installed, install wget temporarly + if [ -z $downloader ] ; then + if [ -x "/usr/bin/apt-get" ] ; then + _apt_get_install $tempdir + elif [ -x "/sbin/apk" ] ; then + _apk_install $tempdir + else + echo "distro not supported" + exit 1 + fi + downloader="wget" + downloader_installed="true" + fi + + if [ $downloader = "wget" ] ; then + wget -q $url -O $output_location + else + curl -sfL $url -o $output_location + fi + + # NOTE: the cleanup procedure was not implemented using `trap X RETURN` only because + # alpine lack bash, and RETURN is not a valid signal under sh shell + if ! [ -z $downloader_installed ] ; then + if [ -x "/usr/bin/apt-get" ] ; then + _apt_get_cleanup $tempdir + elif [ -x "/sbin/apk" ] ; then + _apk_cleanup $tempdir + else + echo "distro not supported" + exit 1 + fi + fi + +} + + +ensure_nanolayer() { + # Ensure existance of the nanolayer cli program + local variable_name=$1 + + local required_version=$2 + + local __nanolayer_location="" + + # If possible - try to use an already installed nanolayer + if [ -z "${NANOLAYER_FORCE_CLI_INSTALLATION}" ]; then + if [ -z "${NANOLAYER_CLI_LOCATION}" ]; then + if type nanolayer >/dev/null 2>&1; then + echo "Found a pre-existing nanolayer in PATH" + __nanolayer_location=nanolayer + fi + elif [ -f "${NANOLAYER_CLI_LOCATION}" ] && [ -x "${NANOLAYER_CLI_LOCATION}" ] ; then + __nanolayer_location=${NANOLAYER_CLI_LOCATION} + echo "Found a pre-existing nanolayer which were given in env variable: $__nanolayer_location" + fi + + # make sure its of the required version + if ! [ -z "${__nanolayer_location}" ]; then + local current_version + current_version=$($__nanolayer_location --version) + + + if ! [ $current_version == $required_version ]; then + echo "skipping usage of pre-existing nanolayer. (required version $required_version does not match existing version $current_version)" + __nanolayer_location="" + fi + fi + + fi + + # If not previuse installation found, download it temporarly and delete at the end of the script + if [ -z "${__nanolayer_location}" ]; then + + if [ "$(uname -sm)" = 'Linux x86_64' ] || [ "$(uname -sm)" = "Linux aarch64" ]; then + tmp_dir=$(mktemp -d -t nanolayer-XXXXXXXXXX) + + clean_up () { + ARG=$? + rm -rf $tmp_dir + exit $ARG + } + trap clean_up EXIT + + + if [ -x "/sbin/apk" ] ; then + clib_type=musl + else + clib_type=gnu + fi + + tar_filename=nanolayer-"$(uname -m)"-unknown-linux-$clib_type.tgz + + # clean download will minimize leftover in case a downloaderlike wget or curl need to be installed + clean_download https://github.com/devcontainers-contrib/cli/releases/download/$required_version/$tar_filename $tmp_dir/$tar_filename + + tar xfzv $tmp_dir/$tar_filename -C "$tmp_dir" + chmod a+x $tmp_dir/nanolayer + __nanolayer_location=$tmp_dir/nanolayer + + + else + echo "No binaries compiled for non-x86-linux architectures yet: $(uname -m)" + exit 1 + fi + fi + + # Expose outside the resolved location + export ${variable_name}=$__nanolayer_location + +} + + diff --git a/test/wine/scenarios.json b/test/wine/scenarios.json new file mode 100644 index 0000000..af19cd3 --- /dev/null +++ b/test/wine/scenarios.json @@ -0,0 +1,10 @@ +{ + "hello": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "wine": { + "version": "8.15" + } + } + } +} diff --git a/test/wine/test.sh b/test/wine/test.sh new file mode 100644 index 0000000..d8efd31 --- /dev/null +++ b/test/wine/test.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# This test file will be executed against an auto-generated devcontainer.json that +# includes the 'hello' Feature with no options. +# +# For more information, see: https://github.com/devcontainers/cli/blob/main/docs/features/test.md +# +# Eg: +# { +# "image": "<..some-base-image...>", +# "features": { +# "hello": {} +# }, +# "remoteUser": "root" +# } +# +# Thus, the value of all options will fall back to the default value in +# the Feature's 'devcontainer-feature.json'. +# For the 'hello' feature, that means the default favorite greeting is 'hey'. +# +# These scripts are run as 'root' by default. Although that can be changed +# with the '--remote-user' flag. +# +# This test can be run with the following command: +# +# devcontainer features test \ +# --features hello \ +# --remote-user root \ +# --skip-scenarios \ +# --base-image mcr.microsoft.com/devcontainers/base:ubuntu \ +# /path/to/this/repo + +set -e + +# Optional: Import test library bundled with the devcontainer CLI +# See https://github.com/devcontainers/cli/blob/HEAD/docs/features/test.md#dev-container-features-test-lib +# Provides the 'check' and 'reportResults' commands. +source dev-container-features-test-lib + +# Feature-specific tests +# The 'check' command comes from the dev-container-features-test-lib. Syntax is... +# check