Skip to content

Commit 4eb11cd

Browse files
chapterjasonclaude
andcommitted
home-persist: merge dir-vs-dir collisions instead of nesting symlink (1.2.0)
When $HOME/<p>/ existed as a real directory AND the volume already had the same path populated, the seeding mv was skipped and `ln -sfn $target $link` landed *inside* the existing directory — producing e.g. $HOME/.claude/.claude instead of $HOME/.claude → /mnt/home-persist/.claude. Detect the dir-vs-dir collision, merge home → volume without clobbering (volume wins, matching the stated model), then drop the home dir so the symlink replaces it cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f180997 commit 4eb11cd

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

src/home-persist/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "home-persist",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"name": "home-persist",
55
"description": "Symlinks selected paths under $HOME into a per-owner persistence volume mounted at /mnt/home-persist. Features and users declare paths via JSON manifests in /etc/devcontainer-persist.d/, and an onCreateCommand materializes the symlinks on every create. Requires the consumer to bind-mount a persistent source to /mnt/home-persist in devcontainer.json.",
66
"documentationURL": "https://github.com/SoureCode/devcontainer-features/tree/master/src/home-persist",

src/home-persist/resolve.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,19 @@ for mf in "${manifests[@]}"; do
7373
target="$STATE/$rel"
7474
mkdir -p "$(dirname "$target")" "$(dirname "$link")"
7575

76-
if [ -e "$link" ] && [ ! -L "$link" ] && [ ! -e "$target" ]; then
77-
mv "$link" "$target"
76+
if [ -e "$link" ] && [ ! -L "$link" ]; then
77+
if [ ! -e "$target" ]; then
78+
mv "$link" "$target"
79+
elif [ -d "$link" ] && [ -d "$target" ]; then
80+
# Both sides are directories and the volume is already populated. Merge
81+
# home into the volume without clobbering (volume wins, per the stated
82+
# model), then drop the now-redundant home dir so `ln -sfn` below
83+
# replaces it with the symlink. Without this branch, `ln -sfn` against
84+
# a real directory creates the link *inside* it — that's how we ended
85+
# up with $HOME/.claude/.claude.
86+
cp -an "$link"/. "$target"/
87+
rm -rf "$link"
88+
fi
7889
fi
7990

8091
# Pre-create directory targets so the symlink isn't dangling — consumer

0 commit comments

Comments
 (0)