fix: prevent false circular dependency detection on self-dependencies
When packages like pytest have extras (e.g., pytest[testing]) that depend on the base package, the resolution was incorrectly detecting this as a circular dependency. Added additional check to skip dependencies that resolve to an artifact already in the visiting set, preventing the false cycle detection while still catching real circular dependencies.
This commit is contained in:
@@ -806,6 +806,10 @@ def resolve_dependencies(
|
|||||||
if dep_artifact_id == artifact_id:
|
if dep_artifact_id == artifact_id:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Skip if this artifact is already being visited (would cause cycle)
|
||||||
|
if dep_artifact_id in visiting:
|
||||||
|
continue
|
||||||
|
|
||||||
_resolve_recursive(
|
_resolve_recursive(
|
||||||
dep_artifact_id,
|
dep_artifact_id,
|
||||||
dep.dependency_project,
|
dep.dependency_project,
|
||||||
@@ -1142,14 +1146,19 @@ async def resolve_dependencies_with_fetch(
|
|||||||
).all()
|
).all()
|
||||||
|
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
# Skip self-dependencies
|
# Skip self-dependencies (common with PyPI extras like pytest[testing] -> pytest)
|
||||||
dep_proj_normalized = dep.dependency_project.lower()
|
dep_proj_normalized = dep.dependency_project.lower()
|
||||||
dep_pkg_normalized = _normalize_pypi_package_name(dep.dependency_package)
|
dep_pkg_normalized = _normalize_pypi_package_name(dep.dependency_package)
|
||||||
curr_proj_normalized = proj_name.lower()
|
curr_proj_normalized = proj_name.lower()
|
||||||
curr_pkg_normalized = _normalize_pypi_package_name(pkg_name)
|
curr_pkg_normalized = _normalize_pypi_package_name(pkg_name)
|
||||||
if dep_proj_normalized == curr_proj_normalized and dep_pkg_normalized == curr_pkg_normalized:
|
if dep_proj_normalized == curr_proj_normalized and dep_pkg_normalized == curr_pkg_normalized:
|
||||||
|
logger.debug(
|
||||||
|
f"Skipping self-dependency: {pkg_key} -> {dep.dependency_project}/{dep.dependency_package}"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Also check if this dependency would resolve to the current artifact
|
||||||
|
# (handles cases where package names differ but resolve to same artifact)
|
||||||
resolved_dep = _resolve_dependency_to_artifact(
|
resolved_dep = _resolve_dependency_to_artifact(
|
||||||
db,
|
db,
|
||||||
dep.dependency_project,
|
dep.dependency_project,
|
||||||
@@ -1185,7 +1194,20 @@ async def resolve_dependencies_with_fetch(
|
|||||||
|
|
||||||
dep_artifact_id, dep_version, dep_size = resolved_dep
|
dep_artifact_id, dep_version, dep_size = resolved_dep
|
||||||
|
|
||||||
|
# Skip if resolved to same artifact (self-dependency at artifact level)
|
||||||
if dep_artifact_id == artifact_id:
|
if dep_artifact_id == artifact_id:
|
||||||
|
logger.debug(
|
||||||
|
f"Skipping self-dependency (same artifact): {pkg_key} -> "
|
||||||
|
f"{dep.dependency_project}/{dep.dependency_package} (artifact {dep_artifact_id[:12]})"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Skip if this artifact is already being visited (would cause cycle)
|
||||||
|
if dep_artifact_id in visiting:
|
||||||
|
logger.debug(
|
||||||
|
f"Skipping dependency already in resolution stack: {pkg_key} -> "
|
||||||
|
f"{dep.dependency_project}/{dep.dependency_package} (artifact {dep_artifact_id[:12]})"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
await _resolve_recursive_async(
|
await _resolve_recursive_async(
|
||||||
|
|||||||
Reference in New Issue
Block a user