diff options
Diffstat (limited to 'src/path.c')
| -rw-r--r-- | src/path.c | 86 |
1 files changed, 86 insertions, 0 deletions
@@ -114,6 +114,92 @@ char *ecex_path_normalize(const char *path) { return joined; } +static int ecex_project_root_has_marker(const char *dir) { + static const char *const markers[] = { + ".git", + "compile_commands.json", + "compile_flags.txt", + ".ecex-project", + }; + + for (size_t i = 0; i < sizeof(markers) / sizeof(markers[0]); i++) { + char *path = ecex_path_join(dir, markers[i]); + if (!path) continue; + int found = ecex_path_exists(path); + free(path); + if (found) return 1; + } + + return 0; +} + +static char *ecex_path_parent_dup(const char *path) { + if (!path || !path[0]) return NULL; + + char *parent = ecex_strdup(path); + if (!parent) return NULL; + + size_t len = strlen(parent); + while (len > 1 && parent[len - 1] == '/') parent[--len] = '\0'; + if (strcmp(parent, "/") == 0) return parent; + + char *slash = strrchr(parent, '/'); + if (!slash) { + free(parent); + return NULL; + } + + if (slash == parent) parent[1] = '\0'; + else *slash = '\0'; + return parent; +} + +char *ecex_project_root_for_file(const char *path) { + char *start = NULL; + + if (path && path[0]) { + if (ecex_path_is_dir(path)) { + start = ecex_path_normalize(path); + } else { + char *dir = ecex_path_dirname(path); + if (dir) { + start = ecex_path_normalize(dir); + free(dir); + } + } + } else { + char cwd[4096]; + if (ecex_path_cwd(cwd, sizeof(cwd)) == 0) start = ecex_path_normalize(cwd); + } + + if (!start) return NULL; + char *fallback = ecex_strdup(start); + if (!fallback) { + free(start); + return NULL; + } + + char *dir = start; + while (dir && dir[0]) { + if (ecex_project_root_has_marker(dir)) { + free(fallback); + return dir; + } + + char *parent = ecex_path_parent_dup(dir); + if (!parent || strcmp(parent, dir) == 0) { + free(parent); + break; + } + + free(dir); + dir = parent; + } + + free(dir); + return fallback; +} + int ecex_path_exists(const char *path) { if (!path) return 0; char *expanded = ecex_path_expand_user(path); |
