Repository: hyprwm/Hyprland
File: start/src/helpers/Nix.cpp (C++)

Code before:

    CVarList2       paths(PATHENV, 0, ':', true);
    std::error_code ec;

    for (const auto& PATH : paths) {
        std::filesystem::path candidate = std::filesystem::path(PATH) / exe;
        if (!std::filesystem::exists(candidate, ec) || ec)
            continue;
        if (!std::filesystem::is_regular_file(candidate, ec) || ec)
            continue;
        auto perms = std::filesystem::status(candidate, ec).permissions();
        if (ec)
            continue;
        if ((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
            return true;
    }

    return false;
}

std::expected<void, std::string> Nix::nixEnvironmentOk() {
    if (!shouldUseNixGL())
        return {};

    if (!executableExistsInPath("nixGL"))
        return std::unexpected("Hyprland was pulled from Nix, which requires nixGL to be installed as well.\nYou can install nixGL by running \"nix profile install "
                               "github:guibou/nixGL --impure\" in your terminal.");

    return {};
}

bool Nix::shouldUseNixGL() {
    // check if installed hyprland is nix'd
    CProcess proc("Hyprland", {"--version"});
    if (!proc.runSync()) {
        g_logger->log(Hyprutils::CLI::LOG_ERR, "failed to obtain hyprland version string");
        return false;
    }

    CVarList2  lines(std::string{proc.stdOut()}, '\n', true);
    const bool IS_NIX = std::ranges::any_of(lines, [](const auto& l) { return l == "nix"; });

    if (IS_NIX) {
        const auto NAME = getFromEtcOsRelease("NAME");
        return !NAME || *NAME != "NixOS";
    }

    return false;
}


Review comment (suggestion):
```suggestion
        return std::unexpected("Hyprland was installed using Nix, but you're not on NixOS. This requires nixGL to be installed as well.\nYou can install nixGL by running \"nix profile install "
```

Code after:
    const char* PATHENV = std::getenv("PATH");
    if (!PATHENV)
        return false;

    CVarList2       paths(PATHENV, 0, ':', true);
    std::error_code ec;

    for (const auto& PATH : paths) {
        std::filesystem::path candidate = std::filesystem::path(PATH) / exe;
        if (!std::filesystem::exists(candidate, ec) || ec)
            continue;
        if (!std::filesystem::is_regular_file(candidate, ec) || ec)
            continue;
        auto perms = std::filesystem::status(candidate, ec).permissions();
        if (ec)
            continue;
        if ((perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none)
            return true;
    }

    return false;
}

std::expected<void, std::string> Nix::nixEnvironmentOk() {
    if (!shouldUseNixGL())
        return {};

    if (!executableExistsInPath("nixGL"))
        return std::unexpected(
            "Hyprland was installed using Nix, but you're not on NixOS. This requires nixGL to be installed as well.\nYou can install nixGL by running \"nix profile install "
            "github:guibou/nixGL --impure\" in your terminal.");

    return {};
}

bool Nix::shouldUseNixGL() {
    if (g_state->noNixGl)
        return false;

    // check if installed hyprland is nix'd
    CProcess proc("Hyprland", {"--version-json"});
    if (!proc.runSync()) {
        g_logger->log(Hyprutils::CLI::LOG_ERR, "failed to obtain hyprland version string");
        return false;
    }

    auto json = glz::read_json<glz::generic>(proc.stdOut());
    if (!json) {
        g_logger->log(Hyprutils::CLI::LOG_ERR, "failed to obtain hyprland version string (bad json)");
        return false;
    }