Skip to content

Commit b554a7f

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 52e7d66 commit b554a7f

File tree

4 files changed

+390
-206
lines changed

4 files changed

+390
-206
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
@@ -11,6 +11,8 @@
1111
[jensens]
1212
- 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).
1313
[jensens]
14+
- 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.
15+
[jensens]
1416
- 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.
1517
[jensens]
1618
- 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
@@ -207,24 +207,53 @@ def fetch(state: State) -> None:
207207
)
208208

209209

210-
def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]]):
210+
def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]], state: State):
211211
"""Create requirements configuration for fetched source packages."""
212212
if not packages:
213213
return
214+
215+
# Check if we're in offline mode or no-fetch mode
216+
from .config import to_bool
217+
218+
offline_mode = to_bool(state.configuration.settings.get("offline", False))
219+
214220
fio.write("#" * 79 + "\n")
215221
fio.write("# mxdev development sources\n")
222+
216223
for name, package in packages.items():
217224
if package["install-mode"] == "skip":
218225
continue
226+
227+
# Check if source directory exists
228+
source_path = Path(package["path"])
229+
219230
extras = f"[{package['extras']}]" if package["extras"] else ""
220231
subdir = f"/{package['subdirectory']}" if package["subdirectory"] else ""
221232

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

226-
logger.debug(f"-> {install_line.strip()}")
227-
fio.write(install_line)
228257
fio.write("\n\n")
229258

230259

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

0 commit comments

Comments
 (0)