Skip to content

Commit

Permalink
fix(semver): replace semver library with translation from node-semver
Browse files Browse the repository at this point in the history
Translated from
npm/node-semver@cb1ca1d.

Translated SemVer, Range, Comparator, and their associated tests.
  • Loading branch information
MikeDombo committed Mar 21, 2022
1 parent b5712cd commit 5a817cc
Show file tree
Hide file tree
Showing 26 changed files with 2,384 additions and 46 deletions.
8 changes: 2 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.aws.greengrass</groupId>
<artifactId>component-common</artifactId>
<version>2.1.1-SNAPSHOT</version>
<version>2.2.0-SNAPSHOT</version>
<packaging>jar</packaging>

<licenses>
Expand All @@ -31,11 +31,6 @@
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>semver4j</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
Expand Down Expand Up @@ -99,6 +94,7 @@
<excludes>
<exclude>*</exclude>
<exclude>src/*/resources/**</exclude>
<exclude>src/**/semver/**</exclude>
</excludes>
</licenseSet>
</licenseSets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

package com.amazon.aws.iot.greengrass.component.common;

import com.amazon.aws.iot.greengrass.semver.SemVer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.vdurmont.semver4j.Semver;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@JsonDeserialize(builder = ComponentRecipe.ComponentRecipeBuilder.class)
@Value
Expand All @@ -37,7 +37,7 @@ public class ComponentRecipe {

@NonNull
@JsonSerialize(using = SemverSerializer.class)
Semver componentVersion;
SemVer componentVersion;

@Builder.Default
ComponentType componentType = ComponentType.GENERIC;
Expand Down Expand Up @@ -100,17 +100,17 @@ public ComponentRecipeBuilder componentName(String name) {
}
}

public ComponentRecipeBuilder componentVersion(Semver version) {
public ComponentRecipeBuilder componentVersion(SemVer version) {
if (version == null) {
throw new NullPointerException("Component version is null");
} else {
if (version.getValue().length() > COMPONENT_VERSION_LENGTH) {
throw new IllegalArgumentException(String.format("Component version length exceeds %d characters",
COMPONENT_VERSION_LENGTH));
}
if (version.getMajor() > COMPONENT_MAX_VERSION_NUMBER
|| version.getMinor() > COMPONENT_MAX_VERSION_NUMBER
|| version.getPatch() > COMPONENT_MAX_VERSION_NUMBER) {
if (version.major > COMPONENT_MAX_VERSION_NUMBER
|| version.minor > COMPONENT_MAX_VERSION_NUMBER
|| version.patch > COMPONENT_MAX_VERSION_NUMBER) {
throw new IllegalArgumentException("Component version major, minor, patch can't exceed 6 digits");
}
this.componentVersion = version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
package com.amazon.aws.iot.greengrass.component.common;


import com.amazon.aws.iot.greengrass.semver.Range;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.vdurmont.semver4j.Requirement;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
Expand All @@ -19,13 +19,13 @@
public class DependencyProperties {
@JsonSerialize(using = RequirementSerializer.class)
@NonNull
Requirement versionRequirement;
Range versionRequirement;

DependencyType dependencyType;

@Builder
public DependencyProperties(@NonNull String versionRequirement, DependencyType dependencyType) {
this.versionRequirement = Requirement.buildNPM(versionRequirement);
this.versionRequirement = new Range(versionRequirement);
this.dependencyType = dependencyType == null ? DependencyType.HARD : dependencyType;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

package com.amazon.aws.iot.greengrass.component.common;

import com.amazon.aws.iot.greengrass.semver.Range;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.vdurmont.semver4j.Requirement;

import java.io.IOException;

public class RequirementSerializer extends StdSerializer<Requirement> {
public class RequirementSerializer extends StdSerializer<Range> {
public RequirementSerializer() {
super(Requirement.class);
super(Range.class);
}

@Override
public void serialize(final Requirement value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
public void serialize(final Range value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
final String version = value.toString();
gen.writeString(version);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

package com.amazon.aws.iot.greengrass.component.common;

import com.amazon.aws.iot.greengrass.semver.SemVer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.vdurmont.semver4j.Semver;

import java.io.IOException;

public class SemverSerializer extends StdSerializer<Semver> {
public class SemverSerializer extends StdSerializer<SemVer> {
public SemverSerializer() {
super(Semver.class);
super(SemVer.class);
}

@Override
public void serialize(final Semver value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
public void serialize(final SemVer value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {
final String version = value.getValue();
gen.writeString(version);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
package com.amazon.aws.iot.greengrass.configuration.common;

import com.amazon.aws.iot.greengrass.component.common.SemverSerializer;
import com.amazon.aws.iot.greengrass.semver.SemVer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.vdurmont.semver4j.Semver;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -24,7 +24,7 @@
public class ComponentUpdate {

@JsonSerialize(using = SemverSerializer.class)
private Semver version;
private SemVer version;

private ConfigurationUpdate configurationUpdate;

Expand Down
177 changes: 177 additions & 0 deletions src/main/java/com/amazon/aws/iot/greengrass/semver/Comparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Translated from node-semver:
*
* The ISC License
* Copyright (c) Isaac Z. Schlueter and Contributors
*
* See com.amazon.aws.iot.greengrass.semver.THIRD-PARTY-LICENSE
*/

package com.amazon.aws.iot.greengrass.semver;

import lombok.EqualsAndHashCode;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@EqualsAndHashCode
public class Comparator {
public final String value;
private String operator;
public SemVer semver;
public static final AnySemVer ANY = Comparator.AnySemVer.ANY;

public Comparator(String comp) {
this.parse(comp);

if (this.semver == ANY) {
this.value = "";
} else {
this.value = this.operator + this.semver.getVersion();
}
}

private void parse (String comp) {
Pattern r = SemVerRegexes.re.get(SemVerRegexes.t.get("COMPARATOR"));
Matcher m = r.matcher(comp);

if (!m.find()) {
throw new IllegalArgumentException("Invalid comparator " + comp);
}

this.operator = m.group(1) != null ? m.group(1) : "";
if (this.operator.equals("=")) {
this.operator = "";
}

// if it literally is just '>' or '' then allow anything.
if (m.group(2) == null) {
this.semver = ANY;
} else {
this.semver = new SemVer(m.group(2));
}
}

public boolean test (Object version) {
if (this.semver == ANY || version == ANY) {
return true;
}

if (version instanceof String) {
try {
version = new SemVer((String) version);
} catch (RuntimeException e) {
return false;
}
}

return cmp((SemVer) version, this.operator, this.semver);
}

public static boolean cmp(SemVer a, String op, SemVer b) {
switch (op) {
case "===":
return a.getVersion().equals(b.getVersion());
case "!==":
return !a.getVersion().equals(b.getVersion());
case "":
case "=":
case "==":
return eq(a, b);
case "!=":
return neq(a, b);
case ">":
return gt(a, b);
case ">=":
return gte(a, b);
case "<":
return lt(a, b);
case "<=":
return lte(a, b);
default:
throw new IllegalArgumentException("Invalid operator " + op);
}
}

public static boolean eq(SemVer a, SemVer b){
return a.compareTo(b) == 0;
}

public static boolean neq(SemVer a, SemVer b){
return a.compareTo(b) != 0;
}

public static boolean gt(SemVer a, SemVer b){
return a.compareTo(b) > 0;
}

public static boolean gte(SemVer a, SemVer b){
return a.compareTo(b) >= 0;
}

public static boolean lt(SemVer a, SemVer b){
return a.compareTo(b) < 0;
}

public static boolean lte(SemVer a, SemVer b){
return a.compareTo(b) <= 0;
}

public boolean intersects (Comparator comp) {
if (this.operator.equals("")) {
if (this.value.equals("")) {
return true;
}
return new Range(comp.value).test(this.semver);
} else if (comp.operator.equals("")) {
if (comp.value.equals("")) {
return true;
}
return new Range(this.value).test(comp.semver);
}

boolean sameDirectionIncreasing =
(this.operator.equals(">=") || this.operator.equals(">")) &&
(comp.operator.equals(">=") || comp.operator.equals(">"));
boolean sameDirectionDecreasing =
(this.operator.equals("<=") || this.operator.equals("<")) &&
(comp.operator.equals("<=") || comp.operator.equals("<"));
boolean sameSemVer = Objects.equals(this.semver.getVersion(), comp.semver.getVersion());
boolean differentDirectionsInclusive =
(this.operator.equals(">=") || this.operator.equals("<=")) &&
(comp.operator.equals(">=") || comp.operator.equals("<="));
boolean oppositeDirectionsLessThan =
cmp(this.semver, "<", comp.semver) &&
(Objects.equals(this.operator, ">=") || Objects.equals(this.operator, ">")) &&
(Objects.equals(comp.operator, "<=") || Objects.equals(comp.operator, "<"));
boolean oppositeDirectionsGreaterThan =
cmp(this.semver, ">", comp.semver) &&
(Objects.equals(this.operator, "<=") || Objects.equals(this.operator, "<")) &&
(Objects.equals(comp.operator, ">=") || Objects.equals(comp.operator, ">"));

return (
sameDirectionIncreasing ||
sameDirectionDecreasing ||
(sameSemVer && differentDirectionsInclusive) ||
oppositeDirectionsLessThan ||
oppositeDirectionsGreaterThan
);
}

@Override
public String toString() {
return this.value;
}

public static class AnySemVer extends SemVer {
final static AnySemVer ANY = new AnySemVer();
private AnySemVer() {
super("0.0.0");
}
}
}

Loading

0 comments on commit 5a817cc

Please sign in to comment.