Skip to content

Commit 83f862a

Browse files
committed
Fix issue #65: Check source directories exist before writing to requirements
When using mxdev -n (no-fetch) or in offline mode, source directories may not exist yet. Previously, mxdev would write references like '-e ./sources/package' to requirements-mxdev.txt regardless, causing pip install to fail later. This fix checks if source directories exist before writing them: - If directory exists: Write normally (existing behavior) - If directory doesn't exist: Write as comment with contextual warning The warning message adapts based on context: - In offline mode: Mentions offline mode and suggests removing -n and --offline flags - Normal mode: Suggests removing -n flag to fetch sources This fixes the mxmake two-stage installation workflow where mxdev -n runs before sources are checked out. Changes: - Update write_dev_sources() to accept State parameter and check path existence - Add contextual warning messages for missing directories - Add tests for missing directories and offline mode warnings - Update existing tests to pass State parameter Fixes #65
1 parent 3154e36 commit 83f862a

File tree

4 files changed

+393
-194
lines changed

4 files changed

+393
-194
lines changed

.claude/settings.local.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
"Bash(git push:*)",
1010
"Bash(uvx:*)",
1111
"Bash(gh run view:*)",
12-
"Bash(gh pr ready:*)"
12+
"Bash(gh pr ready:*)",
13+
"Bash(pip index:*)",
14+
"Bash(python -m venv:*)",
15+
"Bash(/tmp/test-mxdev-pypi/bin/pip install:*)",
16+
"Read(//tmp/test-mxdev-50/sources/**)",
17+
"Read(//tmp/test-mxdev-failing/sources/**)",
18+
"Read(//tmp/test-mxdev-failing/**)"
1319
],
1420
"deny": [],
1521
"ask": []

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
[jensens]
2121
- Feature: #54: Add `fixed` install mode for non-editable installations to support production and Docker deployments. The new `editable` mode replaces `direct` as the default (same behavior, clearer naming). The `direct` mode is now deprecated but still works with a warning. Install modes: `editable` (with `-e`, for development), `fixed` (without `-e`, for production/Docker), `skip` (clone only).
2222
[jensens]
23+
- Fix #65: When generating requirements-mxdev.txt, check if source directories actually exist before writing package references. If a source directory doesn't exist (e.g., when using `mxdev -n` without prior fetch, or in offline mode), write it as a comment with a contextual warning instead of causing pip install to fail later. This fixes the mxmake two-stage installation workflow where `mxdev -n` runs before sources are checked out. Warning messages include context about offline mode when applicable.
24+
[jensens]
2325
- Fix #35: Add `smart-threading` configuration option to prevent overlapping credential prompts when using HTTPS URLs. When enabled (default), HTTPS packages are processed serially first to ensure clean credential prompts, then other packages are processed in parallel for speed. Can be disabled with `smart-threading = false` if you have credential helpers configured.
2426
[jensens]
2527
- Fix #34: The `offline` configuration setting and `--offline` CLI flag are now properly respected to prevent VCS fetch/update operations. Previously, setting `offline = true` in mx.ini or using the `--offline` CLI flag was ignored, and VCS operations still occurred.

src/mxdev/processing.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,24 +210,53 @@ def fetch(state: State) -> None:
210210
)
211211

212212

213-
def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]]):
213+
def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]], state: State):
214214
"""Create requirements configuration for fetched source packages."""
215215
if not packages:
216216
return
217+
218+
# Check if we're in offline mode or no-fetch mode
219+
from .config import to_bool
220+
221+
offline_mode = to_bool(state.configuration.settings.get("offline", False))
222+
217223
fio.write("#" * 79 + "\n")
218224
fio.write("# mxdev development sources\n")
225+
219226
for name, package in packages.items():
220227
if package["install-mode"] == "skip":
221228
continue
229+
230+
# Check if source directory exists
231+
source_path = Path(package["path"])
232+
222233
extras = f"[{package['extras']}]" if package["extras"] else ""
223234
subdir = f"/{package['subdirectory']}" if package["subdirectory"] else ""
224235

225236
# Add -e prefix only for 'editable' mode (not for 'fixed')
226237
prefix = "-e " if package["install-mode"] == "editable" else ""
227-
install_line = f"""{prefix}./{package['target']}/{name}{subdir}{extras}\n"""
238+
install_line = f"""{prefix}./{package['target']}/{name}{subdir}{extras}"""
239+
240+
if not source_path.exists():
241+
# Source not checked out yet - write as comment with warning
242+
if offline_mode:
243+
reason = (
244+
f"Source directory does not exist: {source_path} (package: {name}). "
245+
f"This is expected in offline mode. Run mxdev without -n and --offline flags to fetch sources."
246+
)
247+
else:
248+
reason = (
249+
f"Source directory does not exist: {source_path} (package: {name}). "
250+
f"This could be because -n (no-fetch) flag was used or sources haven't been checked out yet. "
251+
f"Run mxdev without -n flag to fetch sources."
252+
)
253+
logger.warning(reason)
254+
fio.write(f"# {install_line} # mxdev: source not checked out\n")
255+
else:
256+
# Source exists - write normally
257+
logger.debug(f"-> {install_line}")
258+
fio.write(f"{install_line}\n")
228259

229-
logger.debug(f"-> {install_line.strip()}")
230-
fio.write(install_line)
231260
fio.write("\n\n")
232261

233262

@@ -292,6 +321,6 @@ def write(state: State) -> None:
292321
fio.write("#" * 79 + "\n")
293322
fio.write("# mxdev combined constraints\n")
294323
fio.write(f"-c {constraints_ref}\n\n")
295-
write_dev_sources(fio, cfg.packages)
324+
write_dev_sources(fio, cfg.packages, state)
296325
fio.writelines(requirements)
297326
write_main_package(fio, cfg.settings)

0 commit comments

Comments
 (0)