Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
## Unreleased

- Add `csharprepl inspect list`, which lists the running, inspector-enabled processes you can attach to, so you no longer have to find the process id by hand.
- Fix `inspect init` printing `cmd` syntax (`set "..."`) instead of PowerShell syntax when the RID-specific tool is run from PowerShell. The `.cmd` tool shim makes Windows insert a transient `cmd.exe /c` between PowerShell and the tool; shell detection now walks past such a cmd when its own parent is itself a recognized shell.
- On Windows, new installations store the config file, prompt history, and NuGet/symbol caches in the local profile (`%LOCALAPPDATA%\.csharprepl`) instead of the roaming profile (`%APPDATA%`), so the package cache is no longer synchronized across machines.
- Existing installations keep using their current (roaming) location; macOS and Linux are unaffected ([#391](https://github.com/waf/CSharpRepl/issues/391)).
- Support native assets in Nuget packages and improve assembly version conflict resolution (use highest) ([#483](https://github.com/waf/CSharpRepl/issues/483)).
- Add `csharprepl inspect list`, which lists the running, inspector-enabled processes you can attach to, so you no longer have to find the process id by hand ([#482](https://github.com/waf/CSharpRepl/issues/482))..
- Fix `inspect init` printing `cmd` syntax (`set "..."`) instead of PowerShell syntax when the RID-specific tool is run from PowerShell. The `.cmd` tool shim makes Windows insert a transient `cmd.exe /c` between PowerShell and the tool; shell detection now walks past such a cmd when its own parent is itself a recognized shell. ([#481](https://github.com/waf/CSharpRepl/pull/481)).

## Release 0.8.0

Expand Down
23 changes: 19 additions & 4 deletions CSharpRepl.Services/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,27 @@ public sealed class Configuration
public static readonly string DefaultThemeRelativePath = Path.Combine("themes", "VisualStudio_Dark.json");

public const string PromptDefault = "> ";

public const string KeyBindingPatternDescription =
"Key pattern is a key with optional modifiers (Alt/Shift/Control) e.g. 'Enter', 'Control+A'";

public static readonly string ApplicationDirectory =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".csharprepl");

/// <summary>
/// The directory where csharprepl stores its config file, prompt history, and the (potentially large)
/// NuGet package and symbol caches.
/// </summary>
/// <remarks>
/// On Windows this historically lived in the roaming profile (%APPDATA%>), but new csharprepl installations use
/// the local profile (%LOCALAPPDATA%>) instead. To avoid orphaning existing users' configuration and caches, we
/// keep using the roaming location when it already exists.
/// </remarks>
public static readonly string ApplicationDirectory = GetApplicationDirectory(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".csharprepl"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ".csharprepl"),
Directory.Exists,
OperatingSystem.IsWindows());

internal static string GetApplicationDirectory(string roamingDirectory, string localDirectory, Func<string, bool> directoryExists, bool isWindows)
=> !isWindows || directoryExists(roamingDirectory) ? roamingDirectory : localDirectory;

public static readonly string ExecutableDirectory =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ??
Expand Down
2 changes: 1 addition & 1 deletion CSharpRepl/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ private static bool TryParseArguments(string[] args, string configFilePath, ICon
/// </summary>
private static string CreateApplicationStorageDirectory()
{
var appStorage = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".csharprepl");
var appStorage = Configuration.ApplicationDirectory;
Directory.CreateDirectory(appStorage);
return appStorage;
}
Expand Down
25 changes: 25 additions & 0 deletions Tests/CSharpRepl.Tests/ConfigurationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,29 @@ public void ParseKeyPressPattern_KeyChar(string pattern, char keyChar)
Assert.Equal(keyChar, parsed.Character);
Assert.Equal(default, parsed.Modifiers);
}

[Fact]
public void GetApplicationDirectory_WindowsRoamingExists_KeepsRoaming()
{
// Existing Windows installations keep their (roaming) directory so config and caches aren't orphaned.
var result = Configuration.GetApplicationDirectory("roaming", "local", directoryExists: dir => dir == "roaming", isWindows: true);
Assert.Equal("roaming", result);
}

[Fact]
public void GetApplicationDirectory_WindowsRoamingMissing_UsesLocal()
{
// New Windows installations prefer the local directory so the package cache isn't synced across machines.
var result = Configuration.GetApplicationDirectory("roaming", "local", directoryExists: _ => false, isWindows: true);
Assert.Equal("local", result);
}

[Fact]
public void GetApplicationDirectory_NonWindows_AlwaysUsesRoaming()
{
// The roaming-profile sync problem only exists on Windows, so Unix behavior is left unchanged
// (ApplicationData), regardless of whether that directory already exists.
Assert.Equal("roaming", Configuration.GetApplicationDirectory("roaming", "local", directoryExists: _ => false, isWindows: false));
Assert.Equal("roaming", Configuration.GetApplicationDirectory("roaming", "local", directoryExists: _ => true, isWindows: false));
}
}
Loading