Skip to content

fix: mcpp self config --mirror X hangs on fresh MCPP_HOME#76

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/self-config-mirror-hang
May 24, 2026
Merged

fix: mcpp self config --mirror X hangs on fresh MCPP_HOME#76
Sunrisepeak merged 1 commit into
mainfrom
fix/self-config-mirror-hang

Conversation

@Sunrisepeak
Copy link
Copy Markdown
Member

@Sunrisepeak Sunrisepeak commented May 24, 2026

Problem

mcpp self config --mirror GLOBAL on a fresh MCPP_HOME hangs because:

  1. cmd_self_configconfig::load_or_init
  2. load_or_init step 5 seeds .xlings.json with the hardcoded default "CN"regardless of --mirror
  3. Step 7 (xlings sandbox bootstrap: xlings self init + ensure_patchelf + ensure_ninja) reads that mirror and downloads via the CN proxy
  4. Only after bootstrap finishes does cmd_self_config call xlings::config_set_mirror to update the file — too late, the user's choice never reached the very network roundtrip they were trying to redirect
  5. For overseas users / GitHub-runner-style networks the CN mirror stalls → command "hangs"

Fix (~15 lines of real logic)

Plumb the user's mirror choice through to the seed step so the first write of .xlings.json already has the right value, and the bootstrap that immediately follows downloads via the chosen mirror.

  • src/config.cppm
    • write_default_xlings_json grows mirror_override parameter (default empty).
    • load_or_init grows initial_mirror parameter (default empty; all 14 existing call sites unchanged).
    • When non-empty, the value is forwarded straight to seed_xlings_json, overriding the "CN" default for that fresh seed.
  • src/cli.cppmcmd_self_config validates --mirror first, then passes it as load_or_init(..., mirror). xlings::config_set_mirror still runs afterwards (no-op on fresh since the seed already has the right value; required for the already-initialized case where the seed is skipped).
  • src/xlings.cppm — TODO comment at seed_xlings_json's "CN" default about the long-term direction (flip default to GLOBAL, or auto-detect on first init).

For an already-initialized MCPP_HOME (.xlings.json already exists), the seed is skipped — no behavior change for that path.

Test

New tests/e2e/46_self_config_mirror_no_bootstrap.sh:

  • Fresh MCPP_HOME
  • mcpp self config --mirror GLOBAL
  • Assert .xlings.json mirror is GLOBAL (proves seed override took effect; the OLD code seeded CN and only switched to GLOBAL post-bootstrap)
  • Round-trip back to CN via a second --mirror call to exercise the already-initialized path

Existing tests/e2e/38_self_config_mirror.sh still passes — it always calls mcpp self env first (no initial_mirror override), so the "default seed is CN" invariant is preserved.

Diff size

 src/cli.cppm                                    | 32 +++++++----
 src/config.cppm                                 | 23 +++++---
 src/xlings.cppm                                 | 14 +++++
 tests/e2e/46_self_config_mirror_no_bootstrap.sh | 52 ++++++++++++++++++
 4 files changed, 107 insertions(+), 14 deletions(-)

Risk

Minimal. Both new parameters default to empty/unchanged behavior. Only cmd_self_config opts in.

Test plan

  • ci-linux (incl. new e2e 46 + existing 38 regression)
  • ci-macos
  • ci-windows

Root cause: on a fresh MCPP_HOME, write_default_xlings_json seeds
.xlings.json with the hardcoded `"CN"` default, regardless of --mirror.
Then load_or_init's xlings sandbox bootstrap (ensure_init / patchelf /
ninja install) reads that mirror and downloads via CN. Only after the
bootstrap finishes does cmd_self_config invoke xlings::config_set_mirror
to update the file — too late: the user's --mirror choice never reached
the very network roundtrip they were trying to redirect.

For an overseas user the CN mirror is slow or unreachable, so the
"download" phase hangs.

Fix (~15 lines): plumb the user's mirror choice through to the seed.

- `config::write_default_xlings_json` grows `mirror_override` param.
- `config::load_or_init` grows `initial_mirror` param (default empty;
  all existing callers unchanged). Passed straight through to
  write_default_xlings_json, so when set it overrides the "CN" default
  for the FRESH seed.
- `cmd_self_config` parses --mirror first, validates, then forwards it
  as load_or_init's initial_mirror. The subsequent
  xlings::config_set_mirror still runs (idempotent on fresh, required
  for the already-initialized case where seed was skipped).
- TODO comment at seed_xlings_json's `"CN"` default about the long-term
  direction (flip default to GLOBAL, or auto-detect).

For an already-initialized MCPP_HOME (`.xlings.json` already exists),
the seed is skipped — no behavior change there. config_set_mirror
handles that case as before.

Test: tests/e2e/46_self_config_mirror_no_bootstrap.sh asserts that
after a fresh `mcpp self config --mirror GLOBAL`, the seeded
.xlings.json has `mirror: GLOBAL` (not the default CN). Then
round-trips back to CN to exercise the post-init path.

Existing 38_self_config_mirror.sh still passes: it always calls
`mcpp self env` first, which doesn't pass an initial_mirror, so the
"default seed is CN" invariant is preserved.
@Sunrisepeak Sunrisepeak force-pushed the fix/self-config-mirror-hang branch from 0d33212 to 6a0f23a Compare May 24, 2026 03:02
@Sunrisepeak Sunrisepeak merged commit 7f8d3e4 into main May 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant