[PR #9223] [MERGED] When launching wsl, promote the starting directory to --cd #27481

Open
opened 2026-01-31 09:22:13 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/9223
Author: @DHowett
Created: 2/19/2021
Status: ✅ Merged
Merged: 8/2/2021
Merged by: @undefined

Base: main ← Head: dev/duhowett/wsl_--cd


📝 Commits (6)

  • b3bbacf When launching wsl, promote the starting directory to --cd
  • 7bb34c3 Merge remote-tracking branch 'origin/main' into dev/duhowett/wsl_--cd
  • ad7b736 fix the speeling
  • 5c53dca Don't try to relative-resolve paths if they look WSLy
  • 4c82087 til::at doesn't work for hstring, and well... hstring's operators are already checked operators
  • 13a16f9 Expand env using wil helpers

📊 Changes

3 files changed (+80 additions, -12 deletions)

View changed files

📝 src/cascadia/TerminalApp/TerminalPage.cpp (+10 -4)
📝 src/cascadia/TerminalConnection/ConptyConnection.cpp (+69 -2)
📝 src/cascadia/TerminalSettingsModel/Profile.cpp (+1 -6)

📄 Description

This commit introduces a hack to ConptyConnection for launching WSL.
When we detect that WSL is being launched (either "wsl" or "wsl.exe",
unqialified or specifically from the current OS's System32 directory),
we will promote the startingDirectory specified at launch time into a
commandline argument.

Why do we want to switch to --cd?
With the current design of ConptyConnection and WSL, there are some
significant limitations:

  • startingDirectory cannot be a WSL path, which forces users to
    use weird tricks such as setting the starting directory to
    \\wsl$\Distro\home\user.
  • WSL occasionally fails to launch in time to handle a \\wsl$ path,
    which makes us spawn in a strange location (or no location at all).

(This fix will only address the second one until a WSL update is
released that adds support for --cd $LINUX_PATH.)

We will not do the promotion if any of the following are true:

  • the commandline contains --cd already
  • the commandline contains a bare ~
    • This was a commonly-used workaround that forced wsl to start in the
      user's home directory. It conflicts with --cd.
  • wsl is not spelled properly (WSL and WSL.EXE are unacceptable)
  • an absolute path to wsl outside the system32 directory is provided

We chose the do this trick in the connection layer, the latest possible
point, because it captures the most use cases.

We could have done it earlier, but the options were quite limiting.
They are:

  • Generate WSL profiles with startingDirectory set to the home folder
    • We can't do this because we do not know the user's home folder
      path.
  • Generate WSL profiles with --cd in them.
    • This only works for unmodified profiles.
    • This only works for generated profiles.
    • Users cannot override the commandline without breaking it.
    • Users cannot specify a startingDirectory (!) since the one on the
      commandline wins.
  • Set a flag on generated WSL profiles to request this trick
    • This only works for generated profiles. Users who create their own
      WSL profiles couldn't set startingDirectory and have it work the
      same.

Patching the commandline, hacky though it may be, seemed to be the most
compatible option. Eventually, we can even support wt -d ~ wsl!

Validation Steps Performed

Manual validation for the following cases:

// MUST MANGLE
auto a01 = _tryMangleStartingDirectoryForWSL(LR"(wsl)", L"SENTINEL");
auto a02 = _tryMangleStartingDirectoryForWSL(LR"(wsl -d X)", L"SENTINEL");
auto a03 = _tryMangleStartingDirectoryForWSL(LR"(wsl -d X ~/bin/sh)", L"SENTINEL");
auto a04 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe)", L"SENTINEL");
auto a05 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe -d X)", L"SENTINEL");
auto a06 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe -d X ~/bin/sh)", L"SENTINEL");
auto a07 = _tryMangleStartingDirectoryForWSL(LR"("wsl")", L"SENTINEL");
auto a08 = _tryMangleStartingDirectoryForWSL(LR"("wsl.exe")", L"SENTINEL");
auto a09 = _tryMangleStartingDirectoryForWSL(LR"("wsl" -d X)", L"SENTINEL");
auto a10 = _tryMangleStartingDirectoryForWSL(LR"("wsl.exe" -d X)", L"SENTINEL");
auto a11 = _tryMangleStartingDirectoryForWSL(LR"("C:\Windows\system32\wsl.exe" -d X)", L"SENTINEL");
auto a12 = _tryMangleStartingDirectoryForWSL(LR"("C:\windows\system32\wsl" -d X)", L"SENTINEL");
auto a13 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~/bin)", L"SENTINEL");

// MUST NOT MANGLE
auto a14 = _tryMangleStartingDirectoryForWSL(LR"("C:\wsl.exe" -d X)", L"SENTINEL");
auto a15 = _tryMangleStartingDirectoryForWSL(LR"(C:\wsl.exe)", L"SENTINEL");
auto a16 = _tryMangleStartingDirectoryForWSL(LR"(wsl --cd C:\)", L"SENTINEL");
auto a17 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~)", L"SENTINEL");
auto a18 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~ -d Ubuntu)", L"SENTINEL");

We don't have anywhere to put TerminalConnection unit tests :|

Closes #592.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/9223 **Author:** [@DHowett](https://github.com/DHowett) **Created:** 2/19/2021 **Status:** ✅ Merged **Merged:** 8/2/2021 **Merged by:** [@undefined](undefined) **Base:** `main` ← **Head:** `dev/duhowett/wsl_--cd` --- ### 📝 Commits (6) - [`b3bbacf`](https://github.com/microsoft/terminal/commit/b3bbacfe310d4a25c7e64ab1334c1705ab5dc8bf) When launching wsl, promote the starting directory to --cd - [`7bb34c3`](https://github.com/microsoft/terminal/commit/7bb34c3bf35ea477cd85a17671cf02ff998bf82f) Merge remote-tracking branch 'origin/main' into dev/duhowett/wsl_--cd - [`ad7b736`](https://github.com/microsoft/terminal/commit/ad7b736dcc69666e22e3a1c2a99b6e0d00d612d8) fix the speeling - [`5c53dca`](https://github.com/microsoft/terminal/commit/5c53dcad53634198a7ce803731a02f45b1b0e0be) Don't try to relative-resolve paths if they look WSLy - [`4c82087`](https://github.com/microsoft/terminal/commit/4c820872a582b04e5d87bf5f62196d03ab7bb392) til::at doesn't work for hstring, and well... hstring's operators are already checked operators - [`13a16f9`](https://github.com/microsoft/terminal/commit/13a16f90c6f97bdf7e8f454569466cae3bf5d989) Expand env using wil helpers ### 📊 Changes **3 files changed** (+80 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `src/cascadia/TerminalApp/TerminalPage.cpp` (+10 -4) 📝 `src/cascadia/TerminalConnection/ConptyConnection.cpp` (+69 -2) 📝 `src/cascadia/TerminalSettingsModel/Profile.cpp` (+1 -6) </details> ### 📄 Description This commit introduces a hack to ConptyConnection for launching WSL. When we detect that WSL is being launched (either "wsl" or "wsl.exe", unqialified or _specifically_ from the current OS's System32 directory), we will promote the startingDirectory specified at launch time into a commandline argument. Why do we want to switch to `--cd`? With the current design of ConptyConnection and WSL, there are some significant limitations: * `startingDirectory` cannot be a WSL path, which forces users to use weird tricks such as setting the starting directory to `\\wsl$\Distro\home\user`. * WSL occasionally fails to launch in time to handle a `\\wsl$` path, which makes us spawn in a strange location (or no location at all). (This fix will only address the second one until a WSL update is released that adds support for `--cd $LINUX_PATH`.) We will not do the promotion if any of the following are true: * the commandline contains `--cd` already * the commandline contains a bare `~` * This was a commonly-used workaround that forced wsl to start in the user's home directory. It conflicts with --cd. * wsl is not spelled properly (`WSL` and `WSL.EXE` are unacceptable) * an absolute path to wsl outside the system32 directory is provided We chose the do this trick in the connection layer, the latest possible point, because it captures the most use cases. We could have done it earlier, but the options were quite limiting. They are: * Generate WSL profiles with startingDirectory set to the home folder * We can't do this because we do not know the user's home folder path. * Generate WSL profiles with `--cd` in them. * This only works for unmodified profiles. * This only works for generated profiles. * Users cannot override the commandline without breaking it. * Users cannot specify a startingDirectory (!) since the one on the commandline wins. * Set a flag on generated WSL profiles to request this trick * This only works for generated profiles. Users who create their own WSL profiles couldn't set startingDirectory and have it work the same. Patching the commandline, hacky though it may be, seemed to be the most compatible option. Eventually, we can even support `wt -d ~ wsl`! ## Validation Steps Performed Manual validation for the following cases: ```c++ // MUST MANGLE auto a01 = _tryMangleStartingDirectoryForWSL(LR"(wsl)", L"SENTINEL"); auto a02 = _tryMangleStartingDirectoryForWSL(LR"(wsl -d X)", L"SENTINEL"); auto a03 = _tryMangleStartingDirectoryForWSL(LR"(wsl -d X ~/bin/sh)", L"SENTINEL"); auto a04 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe)", L"SENTINEL"); auto a05 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe -d X)", L"SENTINEL"); auto a06 = _tryMangleStartingDirectoryForWSL(LR"(wsl.exe -d X ~/bin/sh)", L"SENTINEL"); auto a07 = _tryMangleStartingDirectoryForWSL(LR"("wsl")", L"SENTINEL"); auto a08 = _tryMangleStartingDirectoryForWSL(LR"("wsl.exe")", L"SENTINEL"); auto a09 = _tryMangleStartingDirectoryForWSL(LR"("wsl" -d X)", L"SENTINEL"); auto a10 = _tryMangleStartingDirectoryForWSL(LR"("wsl.exe" -d X)", L"SENTINEL"); auto a11 = _tryMangleStartingDirectoryForWSL(LR"("C:\Windows\system32\wsl.exe" -d X)", L"SENTINEL"); auto a12 = _tryMangleStartingDirectoryForWSL(LR"("C:\windows\system32\wsl" -d X)", L"SENTINEL"); auto a13 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~/bin)", L"SENTINEL"); // MUST NOT MANGLE auto a14 = _tryMangleStartingDirectoryForWSL(LR"("C:\wsl.exe" -d X)", L"SENTINEL"); auto a15 = _tryMangleStartingDirectoryForWSL(LR"(C:\wsl.exe)", L"SENTINEL"); auto a16 = _tryMangleStartingDirectoryForWSL(LR"(wsl --cd C:\)", L"SENTINEL"); auto a17 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~)", L"SENTINEL"); auto a18 = _tryMangleStartingDirectoryForWSL(LR"(wsl ~ -d Ubuntu)", L"SENTINEL"); ``` We don't have anywhere to put TerminalConnection unit tests :| Closes #592. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:22:13 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#27481