Compare commits
2 Commits
47b3eb439d
...
e1b01abf9b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1b01abf9b | ||
|
|
d07936b666 |
@@ -10,11 +10,20 @@ Handles:
|
|||||||
- Conflict detection
|
- Conflict detection
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
import yaml
|
import yaml
|
||||||
from typing import List, Dict, Any, Optional, Set, Tuple
|
from typing import List, Dict, Any, Optional, Set, Tuple
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
|
|
||||||
|
# Import packaging for PEP 440 version matching
|
||||||
|
try:
|
||||||
|
from packaging.specifiers import SpecifierSet, InvalidSpecifier
|
||||||
|
from packaging.version import Version, InvalidVersion
|
||||||
|
HAS_PACKAGING = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_PACKAGING = False
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Project,
|
Project,
|
||||||
Package,
|
Package,
|
||||||
@@ -304,6 +313,87 @@ def get_reverse_dependencies(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_version_constraint(version_str: str) -> bool:
|
||||||
|
"""Check if a version string contains constraint operators."""
|
||||||
|
if not version_str:
|
||||||
|
return False
|
||||||
|
# Check for common constraint operators
|
||||||
|
return any(op in version_str for op in ['>=', '<=', '!=', '~=', '>', '<', '==', '*'])
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_version_constraint(
|
||||||
|
db: Session,
|
||||||
|
package: Package,
|
||||||
|
constraint: str,
|
||||||
|
) -> Optional[Tuple[str, str, int]]:
|
||||||
|
"""
|
||||||
|
Resolve a version constraint (e.g., '>=1.9') to a specific version.
|
||||||
|
|
||||||
|
Uses PEP 440 version matching to find the best matching version.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db: Database session
|
||||||
|
package: Package to search versions in
|
||||||
|
constraint: Version constraint string (e.g., '>=1.9', '<2.0,>=1.5')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple of (artifact_id, resolved_version, size) or None if not found
|
||||||
|
"""
|
||||||
|
if not HAS_PACKAGING:
|
||||||
|
# Fallback: if packaging not available, can't do constraint matching
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Handle wildcard - return latest version
|
||||||
|
if constraint == '*':
|
||||||
|
# Get the latest version by created_at
|
||||||
|
latest = db.query(PackageVersion).filter(
|
||||||
|
PackageVersion.package_id == package.id,
|
||||||
|
).order_by(PackageVersion.created_at.desc()).first()
|
||||||
|
if latest:
|
||||||
|
artifact = db.query(Artifact).filter(Artifact.id == latest.artifact_id).first()
|
||||||
|
if artifact:
|
||||||
|
return (artifact.id, latest.version, artifact.size)
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
specifier = SpecifierSet(constraint)
|
||||||
|
except InvalidSpecifier:
|
||||||
|
# Invalid constraint, try as exact version
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Get all versions for this package
|
||||||
|
all_versions = db.query(PackageVersion).filter(
|
||||||
|
PackageVersion.package_id == package.id,
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if not all_versions:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Find matching versions
|
||||||
|
matching = []
|
||||||
|
for pv in all_versions:
|
||||||
|
try:
|
||||||
|
v = Version(pv.version)
|
||||||
|
if v in specifier:
|
||||||
|
matching.append((pv, v))
|
||||||
|
except InvalidVersion:
|
||||||
|
# Skip invalid versions
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not matching:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Sort by version (descending) and return the latest matching
|
||||||
|
matching.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
best_match = matching[0][0]
|
||||||
|
|
||||||
|
artifact = db.query(Artifact).filter(Artifact.id == best_match.artifact_id).first()
|
||||||
|
if artifact:
|
||||||
|
return (artifact.id, best_match.version, artifact.size)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _resolve_dependency_to_artifact(
|
def _resolve_dependency_to_artifact(
|
||||||
db: Session,
|
db: Session,
|
||||||
project_name: str,
|
project_name: str,
|
||||||
@@ -314,11 +404,17 @@ def _resolve_dependency_to_artifact(
|
|||||||
"""
|
"""
|
||||||
Resolve a dependency constraint to an artifact ID.
|
Resolve a dependency constraint to an artifact ID.
|
||||||
|
|
||||||
|
Supports:
|
||||||
|
- Exact version matching (e.g., '1.2.3')
|
||||||
|
- Version constraints (e.g., '>=1.9', '<2.0,>=1.5')
|
||||||
|
- Tag matching
|
||||||
|
- Wildcard ('*' for any version)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
db: Database session
|
db: Database session
|
||||||
project_name: Project name
|
project_name: Project name
|
||||||
package_name: Package name
|
package_name: Package name
|
||||||
version: Version constraint (exact)
|
version: Version or version constraint
|
||||||
tag: Tag constraint
|
tag: Tag constraint
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -337,7 +433,13 @@ def _resolve_dependency_to_artifact(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if version:
|
if version:
|
||||||
# Look up by version
|
# Check if this is a version constraint (>=, <, etc.) or exact version
|
||||||
|
if _is_version_constraint(version):
|
||||||
|
result = _resolve_version_constraint(db, package, version)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
# Look up by exact version
|
||||||
pkg_version = db.query(PackageVersion).filter(
|
pkg_version = db.query(PackageVersion).filter(
|
||||||
PackageVersion.package_id == package.id,
|
PackageVersion.package_id == package.id,
|
||||||
PackageVersion.version == version,
|
PackageVersion.version == version,
|
||||||
|
|||||||
@@ -642,6 +642,11 @@ tr:hover .copy-btn {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure file modal needs higher z-index when opened from deps modal */
|
||||||
|
.modal-overlay:has(.ensure-file-modal) {
|
||||||
|
z-index: 1100;
|
||||||
|
}
|
||||||
|
|
||||||
.ensure-file-modal {
|
.ensure-file-modal {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
|
|||||||
Reference in New Issue
Block a user