diff --git a/src/persistence/README.md b/src/persistence/README.md index fa9ea72..652a756 100644 --- a/src/persistence/README.md +++ b/src/persistence/README.md @@ -15,7 +15,8 @@ Store data you with to persist between cntainer rebuilds. | Options Id | Description | Type | Default Value | |-----|-----|-----|-----| -| paths | Colon separated list of directory paths to persist. | string | - | +| directories | Colon separated list of directory paths to persist. | string | - | +| files | Colon separated list of file paths to persist. | string | - | diff --git a/src/persistence/devcontainer-feature.json b/src/persistence/devcontainer-feature.json index 0216a98..fd7bfba 100755 --- a/src/persistence/devcontainer-feature.json +++ b/src/persistence/devcontainer-feature.json @@ -1,14 +1,19 @@ { "id": "persistence", - "version": "1.0.15", + "version": "1.1.2", "name": "Persistance", "documentationURL": "http://github.com/lugoues/devcontainers-features/tree/main/src/persistence", "description": "Store data you with to persist between cntainer rebuilds.", "options": { - "paths": { + "directories": { "default": "", "description": "Colon separated list of directory paths to persist.", "type": "string" + }, + "files": { + "default": "", + "description": "Colon separated list of file paths to persist.", + "type": "string" } }, "mounts": [ diff --git a/src/persistence/install.sh b/src/persistence/install.sh index 9da60a5..382abd9 100644 --- a/src/persistence/install.sh +++ b/src/persistence/install.sh @@ -6,44 +6,81 @@ PERSIST_DIR="/mnt/persistence-data" PERSIST_POST_CREATE="/usr/local/share/persistence_post_create" cat > "$PERSIST_POST_CREATE" << EOF -#!/usr/bin/env bash +#!/bin/sh +set -ex SUDO_CMD="" [ "\${USER}" != "root" ] && SUDO_CMD="sudo" EOF -chmod +x "${PERSIST_POST_CREATE}" -IFS=':' read -ra PATH_ARRAY <<< "${PATHS}" -for path in "${PATH_ARRAY[@]}"; do - [[ -z "${path}" ]] && continue +chmod +x "${PERSIST_POST_CREATE}" +expand_path() { + local path="$1" path="${path/#\~/${_REMOTE_USER_HOME}}" path="${path/#\$HOME/${_REMOTE_USER_HOME}}" + echo "$(realpath -m "${path}")" +} - original_path=$(realpath -m "${path}") - safe_name="${original_path//\//_}" - persist_path="${PERSIST_DIR}/${safe_name#_}" +append_post_create() { + echo "$1" >> "${PERSIST_POST_CREATE}" +} - # Add directory creation to post-create - echo "echo \"Setting up ${path}\"" >> "${PERSIST_POST_CREATE}" - echo "\${SUDO_CMD} mkdir -p \"${persist_path}\"" >> "${PERSIST_POST_CREATE}" +create_symlink() { + local original_path="$1" + local persist_path="$2" + local parent_dir="$(dirname "${original_path}")" - parent_dir="$(dirname "${original_path}")" mkdir -p "${parent_dir}" - if [[ -d "${original_path}" ]]; then + if [[ -e "${original_path}" ]]; then mv "${original_path}" "${original_path}.backup" fi ln -s "${persist_path}" "${original_path}" - echo "\${SUDO_CMD} chown -R \$USER \"${parent_dir}\"" >> "${PERSIST_POST_CREATE}" -done + append_post_create "\${SUDO_CMD} chown -R \$USER \"${parent_dir}\"" +} + +# Process directories +if [[ -n "${DIRECTORIES:-}" ]]; then + IFS=':' read -ra DIR_ARRAY <<< "${DIRECTORIES}" + for path in "${DIR_ARRAY[@]}"; do + [[ -z "${path}" ]] && continue + + original_path=$(expand_path "${path}") + safe_name="${original_path//\//_}" + persist_path="${PERSIST_DIR}/${safe_name#_}" + + append_post_create "echo \"Setting up persistent directory: ${path}\"" + append_post_create "\${SUDO_CMD} mkdir -p \"${persist_path}\"" + append_post_create "\${SUDO_CMD} chown -R \$USER \"${persist_path}\"" + + create_symlink "${original_path}" "${persist_path}" + done +fi + +# Process files +if [[ -n "${FILES:-}" ]]; then + IFS=':' read -ra FILE_ARRAY <<< "${FILES}" + for path in "${FILE_ARRAY[@]}"; do + [[ -z "${path}" ]] && continue + + original_path=$(expand_path "${path}") + safe_name="${original_path//\//_}" + persist_path="${PERSIST_DIR}/${safe_name#_}" + + persist_parent="$(dirname "${persist_path}")" -cat >> "$PERSIST_POST_CREATE" << EOF + append_post_create "echo \"Setting up persistent file: ${path}\"" + append_post_create "\${SUDO_CMD} mkdir -p \"${persist_parent}\"" + append_post_create "\${SUDO_CMD} touch \"${persist_path}\"" + append_post_create "\${SUDO_CMD} chown \$USER \"${persist_path}\"" -echo "Setting owner for ${PERSIST_DIR} to \${USER}" -\${SUDO_CMD} chown -R \$USER "${PERSIST_DIR}" + create_symlink "${original_path}" "${persist_path}" + done +fi -EOF \ No newline at end of file +append_post_create "echo "Setting owner for ${PERSIST_DIR} to \${USER}"" +append_post_create "\${SUDO_CMD} chown -R \$USER "${PERSIST_DIR}"" diff --git a/test/persistence/persitence_single_link.sh b/test/persistence/persitence_single_dir.sh similarity index 100% rename from test/persistence/persitence_single_link.sh rename to test/persistence/persitence_single_dir.sh diff --git a/test/persistence/persitence_single_file.sh b/test/persistence/persitence_single_file.sh new file mode 100644 index 0000000..b903c8f --- /dev/null +++ b/test/persistence/persitence_single_file.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -ex + +source dev-container-features-test-lib + +# from scenario +source="/mnt/persistence-data" +home="/home/vscode" +string="testing" + +check "source exists" test -d "${source}" +check "target symlink" test -L "${home}/.zshrc" +check "write test file to new linked dir" bash -xc "echo ${string} >| ${home}/.zshrc" +check "ensure it exists in target" bash -xc "[[ \$(cat ${source}/home_vscode_.zshrc) == ${string} ]]" +check "ensure user owns target" bash -xc "[[ \$(stat -c '%U' ${source}/home_vscode_.zshrc) == vscode ]]" + +reportResults diff --git a/test/persistence/scenarios.json b/test/persistence/scenarios.json index fec8b65..fb5d6f1 100644 --- a/test/persistence/scenarios.json +++ b/test/persistence/scenarios.json @@ -1,9 +1,19 @@ { - "persitence_single_link": { + "persitence_single_dir": { "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "features": { "persistence": { - "paths": "~/.config/tests/nested/deep" + "directories": "~/.config/tests/nested/deep" + } + }, + "containerUser": "vscode", + "onCreateCommand": "mkdir -p /mnt/persistence-data" + }, + "persitence_single_file": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "persistence": { + "files": "~/.zshrc" } }, "containerUser": "vscode",