Skip to content

Add XDG user directories mapping to Windows Library folders#459

Open
Copilot wants to merge 7 commits intodevelopmentfrom
copilot/add-xdg-user-dirs-mapping
Open

Add XDG user directories mapping to Windows Library folders#459
Copilot wants to merge 7 commits intodevelopmentfrom
copilot/add-xdg-user-dirs-mapping

Conversation

Copy link
Contributor

Copilot AI commented Feb 6, 2026

  • Create the main installer script pengwin-setup.d/xdg-user-dirs.sh that:
    • Installs xdg-user-dirs package
    • Runs xdg-user-dirs-update to generate XDG dirs config
    • Maps XDG directories to Windows folders using wslvar -L and wslvar -S
    • Converts Windows paths to Linux using wslpath -u
    • Removes empty matched directories and creates symbolic links
    • Uses XDG constants (XDG_DESKTOP_DIR, etc.) as keys
    • Reads directory names from $XDG_CONFIG_HOME/user-dirs.dirs to support localization
    • Caches wslvar results to avoid expensive repeated calls
    • Uses helper function to reduce code duplication
  • Add the option to pengwin-setup.d/settings.sh menu
  • Create uninstaller script pengwin-setup.d/uninstall/xdg-user-dirs.sh
    • Only removes symlinks (doesn't recreate directories)
    • Deletes the user-dirs.dirs file only when uninstalling the package
    • Runs xdg-user-dirs-update to regenerate folders only when keeping the package
  • Add to pengwin-setup.d/uninstall.sh menu
  • Update completions/pengwin-setup with new option
  • Create unit test tests/xdg-user-dirs.sh
  • Add test to tests/run_tests.sh
  • Run shellcheck on new scripts
  • Run code review and address comments
Original prompt

create a new option in the pengwin-setup can be in SETTINGS that will map default XDG user dirs with the corresponding Libraries in Windows. the idea is first to be sure that the package xdg-user-dirs is installed, then run the command xdg-user-dirs-update to generate the file $XDG_CONFIG_HOME/user-dirs.dirs which should have a content like:

XDG_DESKTOP_DIR="$HOME/Desktop"
XDG_TEMPLATES_DIR="$HOME/Templates"
XDG_PUBLICSHARE_DIR="$HOME/Public"
XDG_DOCUMENTS_DIR="$HOME/Documents"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Pictures"
XDG_VIDEOS_DIR="$HOME/Videos"
XDG_DOWNLOAD_DIR="$HOME/Downloads"

then ussing the command wslvar -L look for the match in windows. the output of this command is like:

AppData                                : C:\Users\winuser\AppData\Roaming
Cache                                  : C:\Users\winuser\AppData\Local\Microsoft\Windows\INetCache
Cookies                                : C:\Users\winuser\AppData\Local\Microsoft\Windows\INetCookies
Desktop                                : E:\OneDrive\Desktop
Favorites                              : C:\Users\winuser\Favorites
History                                : C:\Users\winuser\AppData\Local\Microsoft\Windows\History
Local AppData                          : C:\Users\winuser\AppData\Local
My Music                               : E:\OneDrive\Música
My Pictures                            : E:\OneDrive\Imágenes
My Video                               : E:\OneDrive\Videos
NetHood                                : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Network Shortcuts
Personal                               : E:\OneDrive\Documentos
PrintHood                              : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Printer Shortcuts
Programs                               : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Recent                                 : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Recent
SendTo                                 : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\SendTo
Start Menu                             : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Start Menu
Startup                                : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Templates                              : C:\Users\winuser\AppData\Roaming\Microsoft\Windows\Templates
{374DE290-123F-4565-9164-39C4925E467B} : E:\OneDrive\Downloads
{A52BBA46-E9E1-435F-B3D9-28DAA648C0F6} : E:\OneDrive
{C3F2459E-80D6-45DC-BFEF-1F769F2BE730} : E:\OneDrive\Música
{24D89E24-2F19-4534-9DDE-6A6671FBB8FE} : E:\OneDrive\Documentos
{F42EE2D3-909F-4907-8871-4C22FC0BF756} : E:\OneDrive\Documentos
{0DDD015D-B06C-45D5-8C4C-F59713854639} : E:\OneDrive\Imágenes
{AB5FB87B-7CE2-4F83-915D-550846C9537B} : E:\OneDrive\Imágenes\Álbum de cámara
{339719B5-8C47-4894-94C2-D8F77ADD44A6} : E:\OneDrive\Imágenes
{767E6811-49CB-4273-87C2-20F355E1085B} : E:\OneDrive\Imágenes\Álbum de cámara
{B7BEDE81-DF94-4682-A7D8-57A52620B86F} : E:\OneDrive\Imágenes\Screenshots 1
{A0C69A99-21C8-4671-8703-7934162FCF1D} : E:\OneDrive\Música
{35286A68-3C57-41A1-BBB1-0EAE73D76C95} : E:\OneDrive\Videos
{7D83EE9B-2244-4E70-B1F5-5393042AF1E4} : E:\OneDrive\Downloads

the XDG_DOWNLOAD_DIR can be found in the key {374DE290-123F-4565-9164-39C4925E467B} or {7D83EE9B-2244-4E70-B1F5-5393042AF1E4}

the XDG_PUBLICSHARE_DIR can be found with wslvar -S using the key PUBLIC

check the microsoft documentation if any doubt.

then once you have the match, convert the windows paths to linux ones using wslpath -u
then delete the matched directories in the home folder if they are empty and create a symbolic link to the windows folder.

This feature helps to integrate better wsl specially GUI apps into the Windows environment


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits February 6, 2026 18:40
Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Copilot AI changed the title [WIP] Add option to map XDG user dirs to Windows libraries Add XDG user directories mapping to Windows Library folders Feb 6, 2026
Copilot AI requested a review from crramirez February 6, 2026 18:43
…var, fix uninstall

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
@crramirez crramirez marked this pull request as ready for review February 6, 2026 20:48
Copilot AI review requested due to automatic review settings February 6, 2026 20:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Settings option to pengwin-setup to map Linux XDG user directories (Desktop, Documents, Downloads, etc.) onto the corresponding Windows Library folders (via symlinks), improving WSL/GUI app integration with Windows file locations.

Changes:

  • Introduces an installer script to install xdg-user-dirs, generate user-dirs.dirs, resolve Windows Library locations, and create symlinks.
  • Adds an uninstaller to remove only the created symlinks, with optional removal of the xdg-user-dirs package.
  • Wires the feature into Settings/Uninstall menus, bash completion, and CI test execution.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pengwin-setup.d/xdg-user-dirs.sh New installer/mapping logic for XDG dirs → Windows folders (wslvar/wslpath, symlink creation).
pengwin-setup.d/uninstall/xdg-user-dirs.sh New uninstaller to remove symlinks and optionally uninstall xdg-user-dirs.
pengwin-setup.d/settings.sh Adds USERDIRS entry to Settings menu and dispatch to the installer script.
pengwin-setup.d/uninstall.sh Adds USERDIRS entry to Uninstall menu and dispatch to the new uninstaller script.
completions/pengwin-setup Adds USERDIRS to SETTINGS and UNINSTALL bash completion options.
tests/xdg-user-dirs.sh Adds a basic install/uninstall shunit2 test for the new feature.
tests/run_tests.sh Includes the new test in the test runner.

Comment on lines +307 to +316
if [[ -n "${target_path}" ]]; then
create_xdg_symlink "${xdg_dir_path}" "${target_path}"
else
echo "Could not find Windows path for ${xdg_const}"
fi
done

echo "XDG user directories mapped successfully!"
return 0
}
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map_xdg_dirs() always prints a success message and returns 0 even if no directories were actually mapped (e.g., wslvar/wslpath unavailable, or create_xdg_symlink() fails because the target path is missing/non-empty). Consider tracking per-directory failures/successes and returning non-zero (and/or a more accurate summary) when nothing is mapped or any mapping fails.

Copilot uses AI. Check for mistakes.
Comment on lines +241 to +248
elif [[ -d "${xdg_path}" ]]; then
if [[ -z "$(ls -A "${xdg_path}" 2>/dev/null)" ]]; then
echo "Removing empty directory: ${xdg_path}"
rmdir "${xdg_path}"
else
echo "Directory not empty, cannot replace: ${xdg_path}"
return 1
fi
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty-directory check uses ls -A and then rmdir, which introduces a TOCTOU race and unnecessary process spawning. Since rmdir already fails on non-empty directories, prefer attempting rmdir directly and checking its exit status (and only erroring if it fails for non-empty).

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +52
while IFS= read -r line; do
# Parse "Key : Value" format
key=$(echo "${line}" | cut -d':' -f1 | sed 's/[[:space:]]*$//')
value=$(echo "${line}" | cut -d':' -f2- | sed 's/^[[:space:]]*//' | tr -d '\r')
if [[ -n "${key}" && -n "${value}" ]]; then
WSLVAR_L_CACHE["${key}"]="${value}"
fi
done < <(wslvar -L 2>/dev/null)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_wslvar_*_cache() assumes every output line contains a ':' separator. If wslvar outputs an error/placeholder line (or localized output), the current parsing can create bogus cache entries. Consider skipping lines that don't match the expected key : value format before populating the cache.

Copilot uses AI. Check for mistakes.
Comment on lines +199 to +202
# Replace $HOME with actual home directory
dir_value="${dir_value/\$HOME/${HOME}}"

echo "${dir_value}"
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $HOME substitution only replaces the first occurrence (${dir_value/\$HOME/...}); if the value contains $HOME more than once, the path will be partially expanded. Consider using the global replacement form and (optionally) handling ${HOME} too for robustness.

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +31
# Replace $HOME with actual home directory
dir_value="${dir_value/\$HOME/${HOME}}"

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $HOME substitution only replaces the first occurrence (${dir_value/\$HOME/...}); if the value contains $HOME more than once, the path will be partially expanded. Consider using the global replacement form and (optionally) handling ${HOME} too for robustness.

Copilot uses AI. Check for mistakes.
Comment on lines 34 to 37
# After uninstall, user-dirs.dirs should be deleted and regenerated
# by xdg-user-dirs-update
run test -f "$HOME/.config/user-dirs.dirs"
assertFalse "user-dirs.dirs file should be deleted after uninstall" "$?"
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says user-dirs.dirs is "deleted and regenerated", but the test asserts the file is absent after uninstall. Please update the comment to match the actual expected behavior (or adjust the assertion if regeneration is intended).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c9f7b45. Updated the comment to accurately describe that when the package is removed, the user-dirs.dirs file is deleted (not regenerated).

Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants