| 203 | /* ── Setup / Teardown ─────────────────────────────────────────────── */ |
| 204 | |
| 205 | static int incremental_setup(void) { |
| 206 | snprintf(g_tmpdir, sizeof(g_tmpdir), "/tmp/cbm_incr_XXXXXX"); |
| 207 | if (!cbm_mkdtemp(g_tmpdir)) |
| 208 | return -1; |
| 209 | |
| 210 | snprintf(g_repodir, sizeof(g_repodir), "%s/fastapi", g_tmpdir); |
| 211 | |
| 212 | /* The fixture is cloned from the network at most once per machine, into a |
| 213 | * persistent cache; every run local-clones from there (seconds, offline). |
| 214 | * The one-time clone is staged and committed with an atomic rename so a |
| 215 | * torn download can never masquerade as a valid cache. */ |
| 216 | const char *cache_home = getenv("CBM_TEST_FIXTURE_CACHE"); |
| 217 | char cache_root[512]; |
| 218 | if (cache_home && cache_home[0]) { |
| 219 | snprintf(cache_root, sizeof(cache_root), "%s", cache_home); |
| 220 | } else { |
| 221 | const char *home = getenv("HOME"); |
| 222 | if (!home || !home[0]) |
| 223 | home = "."; |
| 224 | snprintf(cache_root, sizeof(cache_root), "%s/.cache/cbm-test-fixtures", home); |
| 225 | } |
| 226 | char cache_repo[640]; |
| 227 | snprintf(cache_repo, sizeof(cache_repo), "%s/fastapi-0.99.1", cache_root); |
| 228 | char cmd[1600]; |
| 229 | if (!cbm_is_dir(cache_repo)) { |
| 230 | (void)cbm_mkdir_p(cache_root, 0700); |
| 231 | char cache_stage[700]; |
| 232 | snprintf(cache_stage, sizeof(cache_stage), "%s.stage", cache_repo); |
| 233 | th_rmtree(cache_stage); |
| 234 | snprintf(cmd, sizeof(cmd), |
| 235 | "git clone --depth=1 --branch 0.99.1 --quiet " |
| 236 | "https://github.com/fastapi/fastapi.git '%s' 2>&1", |
| 237 | cache_stage); |
| 238 | int fetch_rc = system(cmd); |
| 239 | if (fetch_rc != 0 || rename(cache_stage, cache_repo) != 0) { |
| 240 | th_rmtree(cache_stage); |
| 241 | if (!cbm_is_dir(cache_repo)) { |
| 242 | printf(" fixture clone failed (rc=%d) — network offline?\n", fetch_rc); |
| 243 | return -1; |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | snprintf(cmd, sizeof(cmd), "git clone --quiet '%s' '%s' 2>&1", cache_repo, g_repodir); |
| 248 | int rc = system(cmd); |
| 249 | if (rc != 0) { |
| 250 | printf(" fixture local clone failed (rc=%d)\n", rc); |
| 251 | return -1; |
| 252 | } |
| 253 | /* Index the same corpus everywhere: CI historically indexed a sparse |
| 254 | * checkout without docs/ and tests/ (the assertion thresholds are sized |
| 255 | * for it) while local runs indexed the full tree — twice the files for |
| 256 | * the identical assertions, and a local/CI divergence. Trimming the two |
| 257 | * directories is the portable equivalent of that sparse profile. */ |
| 258 | char trim[600]; |
| 259 | snprintf(trim, sizeof(trim), "%s/docs", g_repodir); |
| 260 | th_rmtree(trim); |
| 261 | snprintf(trim, sizeof(trim), "%s/tests", g_repodir); |
| 262 | th_rmtree(trim); |
no test coverage detected