Write each fixture file into a fresh temp project, index it via the MCP * production flow (discover -> extract -> registry -> resolve -> dump), and open * the resulting graph DB. Returns the store (NULL on any failure). */
| 106 | * production flow (discover -> extract -> registry -> resolve -> dump), and open |
| 107 | * the resulting graph DB. Returns the store (NULL on any failure). */ |
| 108 | static cbm_store_t *lang_index_files(LangProj *lp, const LangFile *files, int nfiles) { |
| 109 | memset(lp, 0, sizeof(*lp)); |
| 110 | snprintf(lp->tmpdir, sizeof(lp->tmpdir), "/tmp/cbm_lc_XXXXXX"); |
| 111 | if (!cbm_mkdtemp(lp->tmpdir)) { |
| 112 | return NULL; |
| 113 | } |
| 114 | lc_to_fwd_slashes(lp->tmpdir); |
| 115 | for (int i = 0; i < nfiles; i++) { |
| 116 | char path[700]; |
| 117 | snprintf(path, sizeof(path), "%s/%s", lp->tmpdir, files[i].name); |
| 118 | /* Create parent directories if the fixture name embeds subdirs. |
| 119 | * Use mkdir_p (not mkdir) so multi-level paths like |
| 120 | * "pkg/validation/x.go" create every intermediate directory. */ |
| 121 | char *slash = strrchr(path, '/'); |
| 122 | if (slash && slash > path + strlen(lp->tmpdir)) { |
| 123 | *slash = '\0'; |
| 124 | cbm_mkdir_p(path, 0755); |
| 125 | *slash = '/'; |
| 126 | } |
| 127 | /* Binary mode: keep fixture line endings exactly as written ("\n"). |
| 128 | * Windows text mode rewrites "\n"→"\r\n", which makes line-ending- |
| 129 | * sensitive grammars under-extract (below_min / calls_breadth). */ |
| 130 | FILE *f = fopen(path, "wb"); |
| 131 | if (!f) { |
| 132 | return NULL; |
| 133 | } |
| 134 | fputs(files[i].content, f); |
| 135 | fclose(f); |
| 136 | } |
| 137 | |
| 138 | return lang_open_indexed(lp); |
| 139 | } |
| 140 | |
| 141 | /* Convenience: index a single fixture file. */ |
| 142 | static cbm_store_t *lang_index(LangProj *lp, const char *filename, const char *content) { |
no test coverage detected