fix(jobs): autodetectar distro WSL + normalizar separadores UNC (issue 0026)

El usuario reportaba "no enrichers for url" en Windows. Tres bugs:

1. resolve_registry_root tenia el fallback hardcoded a "Ubuntu" pero la
   distro real era "Ubuntu-22.04". Reemplazado por detect_wsl_distro()
   que sondea las distros comunes (Ubuntu, Ubuntu-24.04, Ubuntu-22.04,
   Ubuntu-20.04, Debian, kali-linux, Fedora, openSUSE-Tumbleweed) y se
   queda con la primera cuyo UNC tenga registry.db.
2. enrichers_load construia paths con mixed separators
   ("\\\\wsl.localhost\\Ubuntu-22.04\\...\\enrichers/foo/manifest.yaml")
   que confunden a opendir de MinGW. Ahora normaliza todo a backslashes
   en Windows antes de opendir + concatena con el separador nativo.
3. El menu "Run enricher" decia simplemente "(no enrichers para tipo X)"
   sin distinguir si era 0/N (no se carga ninguno) o N>0/M (existen pero
   ninguno aplica). Ahora muestra "(no enrichers cargados — revisa
   FN_REGISTRY_ROOT)" vs "(0/4 enrichers para tipo 'url')".

Si el usuario tiene una distro con nombre raro, sigue pudiendo setear
FN_REGISTRY_ROOT explicitamente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 19:27:28 +02:00
parent 598e6fcdd4
commit 4281f3ccb2
2 changed files with 63 additions and 17 deletions
+43 -12
View File
@@ -252,14 +252,35 @@ static bool load_input(bool first_load = true);
// Registry path resolution (issue 0026)
// ----------------------------------------------------------------------------
#ifdef _WIN32
// Detecta la distro WSL "default" buscando que UNC `\\wsl.localhost\<name>\`
// existe y contiene `home/lucas/fn_registry/registry.db`. Devuelve "" si no
// encuentra ninguna. Probamos las distros comunes — el usuario sobrescribe
// con FN_REGISTRY_ROOT si tiene una con nombre raro.
static std::string detect_wsl_distro() {
const char* candidates[] = {
"Ubuntu", "Ubuntu-24.04", "Ubuntu-22.04", "Ubuntu-20.04",
"Debian", "kali-linux", "Fedora", "openSUSE-Tumbleweed",
nullptr
};
for (int i = 0; candidates[i]; ++i) {
std::string probe = std::string("\\\\wsl.localhost\\") + candidates[i] +
"\\home\\lucas\\fn_registry\\registry.db";
FILE* f = std::fopen(probe.c_str(), "rb");
if (f) { std::fclose(f); return candidates[i]; }
}
return "";
}
#endif
// Devuelve el path absoluto al root de fn_registry. Estrategia:
// 1) FN_REGISTRY_ROOT env var (acepta path Linux o UNC Windows
// `\\\\wsl.localhost\\Ubuntu\\home\\...`).
// `\\\\wsl.localhost\\<distro>\\home\\...`).
// 2) Sube desde getcwd() buscando un dir con `registry.db`.
// 3) En Windows, fallback al UNC default `\\\\wsl.localhost\\Ubuntu\\home\\
// lucas\\fn_registry` (la build se distribuye al desktop fuera del
// arbol del registry, asi que getcwd nunca lo encuentra).
// 4) "" si no se encuentra.
// 3) En Windows, sondear UNCs de las distros comunes hasta encontrar
// una con `registry.db`. La build se distribuye al desktop fuera del
// arbol del registry, asi que getcwd nunca lo encuentra.
// 4) "" si no se encuentra (los enrichers quedan desactivados).
static std::string resolve_registry_root() {
if (const char* env = std::getenv("FN_REGISTRY_ROOT")) {
if (env && *env) return env;
@@ -268,7 +289,6 @@ static std::string resolve_registry_root() {
if (getcwd(cwd, sizeof(cwd)) != nullptr) {
std::string p = cwd;
#ifdef _WIN32
// Normalizar separadores para comparar.
for (char& c : p) if (c == '\\') c = '/';
#endif
for (int i = 0; i < 8; ++i) {
@@ -281,9 +301,15 @@ static std::string resolve_registry_root() {
}
}
#ifdef _WIN32
// Fallback Windows: el UNC apunta al WSL del usuario. Ajustar el nombre
// de la distro si no es "Ubuntu". La build Linux/WSL nunca llega aqui.
return "\\\\wsl.localhost\\Ubuntu\\home\\lucas\\fn_registry";
std::string distro = detect_wsl_distro();
if (!distro.empty()) {
return std::string("\\\\wsl.localhost\\") + distro +
"\\home\\lucas\\fn_registry";
}
std::fprintf(stderr,
"[graph_explorer] no se detecta la distro WSL — "
"setea FN_REGISTRY_ROOT con el UNC del registry.\n");
return "";
#else
return "";
#endif
@@ -676,18 +702,23 @@ static void render_context_menu() {
// issue 0026 — listamos enrichers cuyo applies_to incluye este type.
const char* type_name = (n.type_id < (uint16_t)g_graph.type_count)
? g_graph.types[n.type_id].name : "";
auto specs = ge::enrichers_for_type(type_name);
const auto& all = ge::enrichers_all();
auto specs = ge::enrichers_for_type(type_name);
if (!sql_id) {
ImGui::TextDisabled("(node has no entity id)");
} else if (all.empty()) {
ImGui::TextDisabled("(no enrichers cargados)");
ImGui::TextDisabled("revisa FN_REGISTRY_ROOT");
} else if (specs.empty()) {
ImGui::TextDisabled("(no enrichers para tipo '%s')", type_name);
ImGui::TextDisabled("(0/%d enrichers para tipo '%s')",
(int)all.size(), type_name);
} else {
for (const auto& s : specs) {
if (ImGui::MenuItem(s.name.c_str())) {
char job_id[64];
bool ok = ge::jobs_submit(s.id.c_str(), sql_id, lbl,
"{}", job_id, sizeof(job_id));
if (ok) g_app.panel_jobs = true; // abrir panel auto
if (ok) g_app.panel_jobs = true;
}
if (!s.description.empty() && ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", s.description.c_str());