mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
JS: Parse preferred version directly
This commit is contained in:
@@ -14,6 +14,8 @@ import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.semmle.js.dependencies.packument.PackageJson;
|
||||
@@ -55,6 +57,8 @@ public class DependencyResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern semVerToken = Pattern.compile("[~^<>=|&-]+|\\d+(?:\\.[\\dx]+)+(?:-[\\w.-]*)?");
|
||||
|
||||
/**
|
||||
* Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`,
|
||||
* or `null` if no such version number was found.
|
||||
@@ -62,10 +66,25 @@ public class DependencyResolver {
|
||||
* To help ensure deterministic version resolution, we prefer the version mentioned in the constraint, rather than
|
||||
* the latest version satisfying the constraint (as the latter can change in time).
|
||||
*/
|
||||
private SemVer getPreferredVersionFromConstraints(List<VersionConstraint> constraints) {
|
||||
for (VersionConstraint constraint : constraints) {
|
||||
if (!constraint.getOperator().equals("<") && constraint.getVersion() != null) {
|
||||
return constraint.getVersion();
|
||||
public static SemVer getPreferredVersionFromVersionSpec(String versionSpec) {
|
||||
versionSpec = versionSpec.trim();
|
||||
boolean isFirst = true;
|
||||
Matcher m = semVerToken.matcher(versionSpec);
|
||||
while (m.find()) {
|
||||
if (isFirst && m.start() != 0) {
|
||||
return null; // Not a version range
|
||||
}
|
||||
isFirst = false;
|
||||
String text = m.group();
|
||||
if (text.equals("<")) {
|
||||
// Skip next token to ignore upper bound constraints like `< 2.0.0`.
|
||||
if (!m.find()) break;
|
||||
}
|
||||
if (text.charAt(0) >= '0' && text.charAt(0) <= '9') {
|
||||
SemVer semVer = SemVer.tryParse(text.replace("x", "0"));
|
||||
if (semVer != null) {
|
||||
return semVer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -103,8 +122,8 @@ public class DependencyResolver {
|
||||
if (packagesInRepo.contains(targetName)) {
|
||||
return;
|
||||
}
|
||||
List<VersionConstraint> constraints = VersionConstraint.parseVersionConstraints(targetVersions);
|
||||
SemVer preferredVersion = getPreferredVersionFromConstraints(constraints);
|
||||
SemVer preferredVersion = getPreferredVersionFromVersionSpec(targetVersions);
|
||||
System.out.println("Prefer " + preferredVersion + " from " + targetVersions);
|
||||
if (preferredVersion == null) return;
|
||||
futures.add(fetcher.getPackument(targetName).exceptionally(ex -> null).thenCompose(targetPackument -> {
|
||||
if (targetPackument == null) {
|
||||
@@ -198,7 +217,7 @@ public class DependencyResolver {
|
||||
});
|
||||
}
|
||||
|
||||
/** Entry point which installs dependencies from a given `package.json`, used for testing andbenchmarking. */
|
||||
/** Entry point which installs dependencies from a given `package.json`, used for testing and benchmarking. */
|
||||
public static void main(String[] args) throws IOException {
|
||||
ExecutorService executors = Executors.newFixedThreadPool(50);
|
||||
try {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.semmle.js.dependencies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class VersionConstraint {
|
||||
private String operator;
|
||||
private SemVer version;
|
||||
|
||||
public VersionConstraint(String operator, SemVer version) {
|
||||
this.operator = operator;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
public SemVer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("([~^<>=]*)\\s*(\\d.*)");
|
||||
|
||||
public static List<VersionConstraint> parseVersionConstraints(String str) {
|
||||
String[] parts = str.split(",");
|
||||
List<VersionConstraint> constraints = new ArrayList<>();
|
||||
for (String part : parts) {
|
||||
part = part.trim();
|
||||
if (part.equals("*")) {
|
||||
constraints.add(new VersionConstraint("*", null));
|
||||
continue;
|
||||
}
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
if (matcher.matches()) {
|
||||
String operator = matcher.group(1);
|
||||
String versionStr = matcher.group(2);
|
||||
if (operator.isEmpty() && versionStr.contains("x")) {
|
||||
// Treat "1.x" as ">= 1.0"
|
||||
operator = ">=";
|
||||
versionStr = versionStr.replaceAll("x", "0");
|
||||
}
|
||||
SemVer version = SemVer.tryParse(versionStr);
|
||||
if (version != null) {
|
||||
constraints.add(new VersionConstraint(operator, version));
|
||||
}
|
||||
}
|
||||
}
|
||||
return constraints;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user