Skip to content

Move .purr folder from the home folder to the correct folder for the host OS#5

Open
carson-coder wants to merge 5 commits intomainfrom
change_purr_path
Open

Move .purr folder from the home folder to the correct folder for the host OS#5
carson-coder wants to merge 5 commits intomainfrom
change_purr_path

Conversation

@carson-coder
Copy link
Member

@carson-coder carson-coder commented Feb 26, 2026

Moves the .purr folder to $XDG_DATA_HOME/purr on linux (if XDG_DATA_HOME is null then it defaults to ~/.local/share), %LOCALAPPDATA%/purr on windows, and on mac os nothing changes because I do not know the correct path for on macos.

I tried to update as much documentation. I searched the repo for .purr and replace references to the .purr folder. I also added PURR_BIN_DIR as a env var for install scripts which points to <purr_folder>/bin

fixes #4

Copy link

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

Moves the purr data directory from the legacy ~/.purr location to OS-appropriate per-user data locations (XDG on Linux, LocalAppData on Windows), and updates installer scripts/docs to use a PURR_BIN_DIR environment variable.

Changes:

  • Update CLI data-root resolution to use XDG data dir on Linux and %LOCALAPPDATA% on Windows, and adjust paths used for bin/ and packages/.
  • Add PURR_BIN_DIR to the environment for installer/uninstaller scripts and update sample package installers accordingly.
  • Refresh documentation and website pages to reflect the new directory layout and PATH instructions.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
purr/Services/PackageManager.cs Implements new purr data-root resolution and updates internal references to bin/ + packages/; adds PURR_BIN_DIR.
purr/README.md Updates CLI docs for directory layout, PATH setup, and installer env vars.
purr-packages/dev/raylib/installer.sh Switches install destination to PURR_BIN_DIR.
purr-packages/dev/raylib/installer.ps1 Switches install destination to PURR_BIN_DIR.
purr-packages/dev/cmake/installer.sh Switches install destination to PURR_BIN_DIR.
purr-packages/dev/cmake/installer.ps1 Switches install destination to PURR_BIN_DIR.
documentation/installer-scripts.md Updates PATH guidance to XDG/LocalAppData locations.
documentation/install-packages.md Updates install-path references to XDG/LocalAppData locations.
documentation/directory-layout.md Updates documented directory layout to XDG/LocalAppData locations.
PurrNet/wwwroot/install.sh Removes a now-unused .purr target-dir reference (left as a comment).
PurrNet/Pages/Documentation/SubmitPackage.cshtml Updates examples to use PURR_BIN_DIR and new directory paths.
PurrNet/Pages/Documentation/InstallerScripts.cshtml Updates PATH setup docs to XDG/LocalAppData locations.
PurrNet/Pages/Documentation/InstallPackages.cshtml Updates install-path references to XDG/LocalAppData locations.
PurrNet/Pages/Documentation/DirectoryLayout.cshtml Updates directory-layout docs (with one remaining Windows path reference).
PurrLauncher/Services/PackageInstallService.cs Updates Windows package directory path to %LOCALAPPDATA%\\purr\\packages.
Comments suppressed due to low confidence (7)

purr/README.md:90

  • purr_folder is described as $XDG_DATA_DIR/purr here, but the XDG base directory variable is XDG_DATA_HOME (and the code uses XDG_DATA_HOME). Please update this line to avoid pointing users at a non-standard environment variable.
## Directory Layout
purr_folder is `$XDG_DATA_DIR/purr` (Linux), `~/.purr` (MacOS) or `%LOCALAPPDATA%\purr` (Windows)

purr/README.md:372

  • Typo in the new env var table entry: "binarys" → "binaries".
| `PURR_BIN_DIR`        | The directory to place package binarys                    |

purr/README.md:152

  • The note says release-asset-installed binaries are not removed by uninstall, but PackageManager.UninstallPackageAsync now deletes candidate binaries from <purr_folder>/bin. Please update this note to match actual behavior (or clarify the remaining limitations, if any).
> **Note:** Release-asset-installed binaries are not currently removed by `uninstall`. Delete them manually if needed.

purr/README.md:399

  • The PATH examples use XDG_DATA_DIR, but the standard variable is XDG_DATA_HOME (and other docs in this repo use XDG_DATA_HOME). Also the current-session example prepends the bin dir while the persist example appends it; please make these consistent and prefer the same variable name as the implementation.
**Bash / Zsh (one-time, current session):**
```bash
export PATH="${XDG_DATA_DIR:-~/.local/share}/purr/bin:$PATH"

Persist in Bash (~/.bashrc) or Zsh (~/.zshrc):

echo 'export PATH="$PATH:${XDG_DATA_DIR:-~/.local/share}/purr/bin"' >> ~/.bashrc
source ~/.bashrc

PurrNet/Pages/Documentation/DirectoryLayout.cshtml:24

  • This Windows path example still references %USERPROFILE%\.purr\bin, but the CLI has moved to %LOCALAPPDATA%\purr\bin on Windows. Please update this to match the new location.
    <li>Release-asset-installed executables are placed in <code>$XDG_DATA_HOME/purr/bin</code> (or <code>%USERPROFILE%\.purr\bin</code> on Windows).</li>

documentation/installer-scripts.md:19

  • The Fish PATH instruction hardcodes $HOME/.local/share/purr/bin. If the user has XDG_DATA_HOME set to a non-default location, this will be wrong. Consider using the same ${XDG_DATA_HOME:-~/.local/share}/purr/bin pattern here too.
- Persist in `~/.bashrc` / `~/.zshrc` by echoing the export line and sourcing the file.
- Fish: use `set -U fish_user_paths $HOME/.local/share/purr/bin $fish_user_paths`.
- PowerShell: add `%LOCALAPPDATA%\purr\bin` to `PATH` for session or persist via `setx`.

purr/Services/PackageManager.cs:15

  • The new field name _purr_folder (and related locals like xdg_data_home, legacy_path) uses snake_case, but the rest of this class uses the C# convention _camelCase (e.g. _apiService, _packagesDirectory). Renaming to _purrFolder / xdgDataHome / legacyPath will keep naming consistent and avoid mixed styles in the same file.
    private readonly string _purr_folder;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +49
string legacy_path = Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr"));
Directory.Move(legacy_path, _purr_folder);
File.CreateSymbolicLink(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _purr_folder);
}

_packagesDirectory = Path.Combine(purr_folder, "packages");
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

purr_folder is not defined here, so this line will not compile. It looks like this should use the _purr_folder field computed above (or the renamed _purrFolder).

Suggested change
string legacy_path = Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr"));
Directory.Move(legacy_path, _purr_folder);
File.CreateSymbolicLink(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _purr_folder);
}
_packagesDirectory = Path.Combine(purr_folder, "packages");
string legacy_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr");
Directory.Move(legacy_path, _purr_folder);
File.CreateSymbolicLink(legacy_path, _purr_folder);
}
_packagesDirectory = Path.Combine(_purr_folder, "packages");

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +49
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr")))
{
string legacy_path = Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr"));
Directory.Move(legacy_path, _purr_folder);
File.CreateSymbolicLink(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _purr_folder);
}

_packagesDirectory = Path.Combine(purr_folder, "packages");
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

This legacy-migration block is currently broken and unsafe:

  • Directory.Exists(...) returns a bool, so assigning it to string legacy_path will not compile.
  • File.CreateSymbolicLink(Environment.GetFolderPath(UserProfile), _purr_folder) attempts to create a symlink at the home directory path, and also uses the file API for what should be a directory link.
    Use a legacyPath = Path.Combine(UserProfile, ".purr"), guard against _purr_folder == legacyPath / destination existing, and create a directory symlink at legacyPath pointing to _purr_folder (handling platforms/permissions).
Suggested change
if (Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr")))
{
string legacy_path = Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".purr"));
Directory.Move(legacy_path, _purr_folder);
File.CreateSymbolicLink(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _purr_folder);
}
_packagesDirectory = Path.Combine(purr_folder, "packages");
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var legacyPath = Path.Combine(userProfile, ".purr");
if (Directory.Exists(legacyPath))
{
// Avoid migrating if the legacy path and target path are the same
var legacyFullPath = Path.GetFullPath(legacyPath);
var targetFullPath = Path.GetFullPath(_purr_folder);
if (!string.Equals(legacyFullPath, targetFullPath, StringComparison.OrdinalIgnoreCase))
{
// Only move if the new target does not already exist
if (!Directory.Exists(_purr_folder))
{
Directory.Move(legacyPath, _purr_folder);
}
// Attempt to create a directory symlink at legacyPath pointing to _purr_folder
try
{
if (!Directory.Exists(legacyPath) && !File.Exists(legacyPath))
{
Directory.CreateSymbolicLink(legacyPath, _purr_folder);
}
}
catch (IOException) when (!_verbose)
{
// Ignore migration symlink failures silently when not verbose
}
catch (UnauthorizedAccessException) when (!_verbose)
{
// Ignore permission issues silently when not verbose
}
catch (PlatformNotSupportedException) when (!_verbose)
{
// Ignore platforms that do not support directory symlinks when not verbose
}
catch (Exception ex) when (_verbose)
{
ConsoleHelper.WriteWarning($"Failed to create legacy symlink at '{legacyPath}': {ex.Message}");
}
}
}
_packagesDirectory = Path.Combine(_purr_folder, "packages");

Copilot uses AI. Check for mistakes.
@carson-coder
Copy link
Member Author

I do still need to test this before we merge

@carson-coder
Copy link
Member Author

image everything seems to work good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.purr folder is not placed in the correct folder

3 participants