Skip to content

Commit 310987b

Browse files
committed
fix: git URLs working with bootstrap-parallel
The bootstrap-parallel command failed when top-level requirements were specified as git URLs. During the bootstrap phase, git URLs were correctly stored in the dependency graph, but the build-parallel phase reconstructed requirements as name==version, losing the URL information. This caused the system to treat local directory paths as HTTP URLs, resulting in invalid URL errors. Changes: - Add get_top_level_requirement() method to DependencyGraph to retrieve original requirement specifications from ROOT node edges - Modify build_parallel() to use original top-level requirements when available, preserving git URLs during parallel builds - Add URL parsing logic to download_git_source() to extract @ref from git URLs like repo.git@5.2.0 This fix enables nightly build pipelines that rely on git URLs with the bootstrap-parallel command for faster builds. Now #762 can be revisited. Fixes: #761 Co-authored-by: Claude <claude@anthropic.com> Signed-off-by: Ioannis Angelakopoulos <iangelak@redhat.com>
1 parent 74b0af4 commit 310987b

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

src/fromager/commands/build.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,19 @@ def update_progressbar_cb(future: concurrent.futures.Future) -> None:
696696
"starting to build: %s", sorted(n.key for n in buildable_nodes)
697697
)
698698
for node in buildable_nodes:
699-
req = Requirement(f"{node.canonicalized_name}=={node.version}")
699+
# Try to get the original top-level requirement if it includes a URL.
700+
# We only use the top-level requirement if:
701+
# 1. The node is a direct child of ROOT (it's actually top-level)
702+
# 2. The requirement includes a URL (git, etc.)
703+
# Otherwise, we use the already-resolved version from the node to avoid:
704+
# - Building wrong versions when same package appears multiple times
705+
# - Re-resolving unpinned version specifiers
706+
top_level_req = graph.get_top_level_requirement(node)
707+
if top_level_req and top_level_req.url:
708+
req = top_level_req
709+
logger.debug("using top-level requirement with URL: %s", req)
710+
else:
711+
req = Requirement(f"{node.canonicalized_name}=={node.version}")
700712
reqs.append(req)
701713
future = executor.submit(
702714
_build_parallel,

src/fromager/dependency_graph.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,19 @@ def get_nodes_by_name(self, req_name: str | None) -> list[DependencyNode]:
352352
def get_root_node(self) -> DependencyNode:
353353
return self.nodes[ROOT]
354354

355+
def get_top_level_requirement(self, node: DependencyNode) -> Requirement | None:
356+
"""Get the top-level requirement specification for a node.
357+
358+
For packages that were specified as top-level requirements (e.g., with git URLs),
359+
this returns the original requirement specification. Returns None if the node
360+
is not a direct child of ROOT.
361+
"""
362+
root = self.get_root_node()
363+
for edge in root.children:
364+
if edge.destination_node.key == node.key:
365+
return edge.req
366+
return None
367+
355368
def get_all_nodes(self) -> typing.Iterable[DependencyNode]:
356369
return self.nodes.values()
357370

src/fromager/sources.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,17 @@ def download_git_source(
204204
if url_to_clone.startswith("git+"):
205205
url_to_clone = url_to_clone[len("git+") :]
206206

207+
# Parse ref from URL if it's in the form repo@ref
208+
from urllib.parse import urlparse
209+
210+
if ref is None:
211+
parsed_url = urlparse(url_to_clone)
212+
if "@" in parsed_url.path:
213+
# Extract the ref from the path
214+
new_path, _, git_ref = parsed_url.path.rpartition("@")
215+
url_to_clone = parsed_url._replace(path=new_path).geturl()
216+
ref = git_ref
217+
207218
logger.info(f"cloning source from {url_to_clone}@{ref} to {destination_dir}")
208219
# Get git options from package settings
209220
pbi = ctx.package_build_info(req)

0 commit comments

Comments
 (0)