Skip to content

Commit cb6420f

Browse files
committed
Update generate task
1 parent 832b595 commit cb6420f

File tree

3 files changed

+101
-98
lines changed

3 files changed

+101
-98
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/transport/GenerateTransportVersionDataTask.java

Lines changed: 52 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,22 @@
1010
package org.elasticsearch.gradle.internal.transport;
1111

1212
import com.google.common.collect.Streams;
13-
import org.elasticsearch.gradle.Version;
1413
import org.elasticsearch.gradle.VersionProperties;
15-
import org.elasticsearch.gradle.internal.transport.TransportVersionUtils.TransportVersionSetData;
1614
import org.gradle.api.DefaultTask;
17-
import org.gradle.api.GradleException;
1815
import org.gradle.api.file.RegularFileProperty;
1916
import org.gradle.api.provider.Property;
2017
import org.gradle.api.tasks.Input;
2118
import org.gradle.api.tasks.InputDirectory;
2219
import org.gradle.api.tasks.TaskAction;
23-
import org.jetbrains.annotations.NotNull;
2420

2521
import java.io.IOException;
22+
import java.nio.file.Path;
2623
import java.util.List;
2724
import java.util.Objects;
2825
import java.util.stream.Stream;
2926

30-
import static org.elasticsearch.gradle.internal.transport.TransportVersionUtils.LATEST_SUFFIX;
31-
import static org.elasticsearch.gradle.internal.transport.TransportVersionUtils.getTVSetDataFilePath;
27+
import static org.elasticsearch.gradle.internal.transport.TransportVersionUtils.updateLatestFile;
28+
import static org.elasticsearch.gradle.internal.transport.TransportVersionUtils.writeDefinitionFile;
3229

3330
/**
3431
* This task generates TransportVersionSetData data files that contain information about transport versions. These files
@@ -70,69 +67,45 @@ public abstract class GenerateTransportVersionDataTask extends DefaultTask {
7067

7168
@TaskAction
7269
public void generateTransportVersionData() throws IOException {
73-
final var tvDataDir = Objects.requireNonNull(getDataFileDirectory().getAsFile().get());
74-
final var tvSetName = Objects.requireNonNull(getTVName().get());
75-
final var minorVersion = MinorVersion.fromString(Objects.requireNonNull(getMinorVersionForTV().get()));
70+
final Path tvDataDir = Objects.requireNonNull(getDataFileDirectory().getAsFile().get()).toPath();
71+
final var tvName = Objects.requireNonNull(getTVName().get());
72+
final var forMinorVersion = Objects.requireNonNull(getMinorVersionForTV().get());
7673

7774
// Get the latest transport version data for the specified minor version.
78-
final var latestTV = TransportVersionUtils.getLatestFile(tvDataDir.toPath(), minorVersion.toString());
75+
final var latestTV = TransportVersionUtils.getLatestFile(tvDataDir, forMinorVersion);
7976

8077
// Create the new version
81-
final var mainReleaseVersion = MinorVersion.of(VersionProperties.getElasticsearchVersion());
82-
final var isReleaseVersionMain = minorVersion.equals(mainReleaseVersion);
83-
int newVersion = bumpVersionNumber(latestTV.ids().getFirst(), minorVersion, isReleaseVersionMain);
78+
final var mainReleaseVersion = VersionProperties.getElasticsearchVersion();
79+
final var areWeOnMain = forMinorVersion.equals(mainReleaseVersion);
80+
int newVersion = bumpVersionNumber(
81+
latestTV.ids().getFirst(),
82+
areWeOnMain ? PartToBump.SERVER : PartToBump.PATCH
83+
);
8484

8585
// Load the tvSetData for the specified name, if it exists
86-
final var tvSetDataFromFile = TransportVersionUtils.readDefinitionFile(tvDataDir.toPath(), tvSetName);
86+
final var tvSetDataFromFile = TransportVersionUtils.getDefinedFile(tvDataDir, tvName);
8787
final var tvSetFileExists = tvSetDataFromFile != null;
8888

89-
// Create/update the data file
90-
if (tvSetFileExists) {
91-
// This is not a new TVSet. We are creating a backport version for an existing TVSet.
92-
// Check to ensure that there isn't already a TV id for this release version (e.g., if this task has been run twice).
93-
var existingIDsForReleaseVersion = tvSetDataFromFile.ids().stream().filter(id -> {
94-
var priorLatestID = priorLatestTVSetData.ids().getFirst();
95-
return priorLatestID < id && id <= newVersion;
96-
}).toList();
97-
if (existingIDsForReleaseVersion.isEmpty() == false) {
98-
throw new GradleException(
99-
"A transport version could not be created because a preexisting one was found for this name & release."
100-
+ " This could be due to another pre-existing TV with the same name, or a result of running this"
101-
+ " task twice:"
102-
+ " Release version: "
103-
+ minorVersion
104-
+ " TransportVersion Id: "
105-
+ existingIDsForReleaseVersion.getFirst()
106-
+ " File: "
107-
+ getTVSetDataFilePath(tvDataDir, tvSetName)
108-
);
109-
}
110-
// 9.2:123 | 9.1:456 | 9.0:789 |
111-
112-
// Update the existing data file for the backport.
113-
new TransportVersionSetData(
114-
tvSetName,
115-
Streams.concat(tvSetDataFromFile.ids().stream(), Stream.of(newVersion)).sorted().toList().reversed()
116-
).writeToDataDir(tvDataDir);
117-
} else {
118-
// Create a new data file for the case where this is a new TV
119-
new TransportVersionSetData(tvSetName, List.of(newVersion)).writeToDataDir(tvDataDir);
120-
}
89+
// Write the definition file.
90+
final var ids = tvSetFileExists
91+
? Streams.concat(tvSetDataFromFile.ids().stream(), Stream.of(newVersion)).sorted().toList().reversed()
92+
: List.of(newVersion);
93+
writeDefinitionFile(tvDataDir, tvName, ids);
12194

12295
// Update the LATEST file.
123-
TransportVersionUtils.writeTVSetData(
124-
tvDataDir,
125-
formatLatestTVSetFilename(minorVersion),
126-
new TransportVersionSetData(tvSetName, List.of(newVersion))
127-
);
96+
updateLatestFile(tvDataDir, forMinorVersion, tvName, newVersion);
97+
}
98+
99+
public enum PartToBump {
100+
SERVER,
101+
SUBSIDIARY,
102+
PATCH
128103
}
129104

130105
// TODO Do I need to remove the patch when updating the server portion? NO, but probably need some additional checks
131106
private static int bumpVersionNumber(
132107
int tvIDToBump,
133-
MinorVersion minorVersion,
134-
boolean majorVersionBump,
135-
boolean isTVReleaseVersionMain
108+
PartToBump partToBump
136109
) {
137110

138111
/* The TV format:
@@ -144,41 +117,31 @@ private static int bumpVersionNumber(
144117
* S - The subsidiary version part. It should always be 0 here, it is only used in subsidiary repositories.
145118
* PP - The patch version part
146119
*/
147-
if (isTVReleaseVersionMain) {
148-
if (majorVersionBump) {
149-
// Bump the major version part, set all other parts to zero.
150-
return minorVersion.major * 1_000_000; // TODO add check that this doesn't cause overflow out of server versions
151-
} else {
152-
// Bump the server version part if not a major bump.
153-
// TODO add check that this doesn't cause overflow out of server versions
154-
// TODO Do we need to assert on the shape of the number? e.g. no patch version.
155-
return tvIDToBump + 1000;
120+
return switch (partToBump) {
121+
case SERVER -> {
122+
var newId = tvIDToBump + 1000;
123+
if ((newId / 1000) % 100 == 0) {
124+
throw new IllegalStateException("Insufficient server version section in TransportVersion: " + tvIDToBump
125+
+ ", Cannot bump.");
126+
}
127+
yield tvIDToBump + 1000;
156128
}
157-
} else {
158-
// bump the patch version part
159-
return tvIDToBump + 1; // TODO add check that this doesn't cause overflow out of patch versions
160-
}
161-
}
162-
163-
164-
private static String formatLatestTVSetFilename(MinorVersion minorVersion) {
165-
return minorVersion.toString() + LATEST_SUFFIX;
166-
}
167-
168-
private record MinorVersion(int major, int minor) {
169-
public static MinorVersion fromString(String string) {
170-
String[] versionParts = string.split("\\.");
171-
assert versionParts.length == 2;
172-
return new MinorVersion(Integer.parseInt(versionParts[0]), Integer.parseInt(versionParts[1]));
173-
}
174-
175-
public static MinorVersion of(Version version) {
176-
return new MinorVersion(version.getMajor(), version.getMinor());
177-
}
178-
179-
@Override
180-
public @NotNull String toString() {
181-
return major + "." + minor;
182-
}
129+
case SUBSIDIARY -> {
130+
var newId = tvIDToBump + 100;
131+
if ((newId / 100) == 0) {
132+
throw new IllegalStateException("Insufficient subsidiary version section in TransportVersion: " + tvIDToBump
133+
+ ", Cannot bump.");
134+
}
135+
yield newId;
136+
}
137+
case PATCH -> {
138+
var newId = tvIDToBump + 1;
139+
if (newId % 10 == 0) {
140+
throw new IllegalStateException("Insufficient patch version section in TransportVersion: " + tvIDToBump
141+
+ ", Cannot bump.");
142+
}
143+
yield newId;
144+
}
145+
};
183146
}
184147
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/transport/TransportVersionUtils.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.elasticsearch.gradle.internal.transport;
1111

1212
import com.google.common.collect.Comparators;
13+
import org.gradle.api.GradleException;
1314
import org.gradle.api.Project;
1415
import org.gradle.api.attributes.Attribute;
1516
import org.gradle.api.attributes.AttributeContainer;
@@ -22,12 +23,17 @@
2223
import java.util.ArrayList;
2324
import java.util.Comparator;
2425
import java.util.List;
26+
import java.util.regex.Pattern;
27+
import java.util.stream.Collectors;
2528

2629
import static org.gradle.api.artifacts.type.ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE;
2730

2831
class TransportVersionUtils {
2932
static final Attribute<Boolean> TRANSPORT_VERSION_REFERENCES_ATTRIBUTE = Attribute.of("transport-version-references", Boolean.class);
3033

34+
private static final String LATEST_DIR = "latest";
35+
private static final String DEFINED_DIR = "defined";
36+
3137
record TransportVersionDefinition(String name, List<Integer> ids) {
3238
}
3339

@@ -38,8 +44,44 @@ public String toString() {
3844
}
3945
}
4046

41-
static TransportVersionDefinition getLatestFile(Path latestDataDir, String majorMinor) throws IOException {
42-
return readDefinitionFile(latestDataDir.resolve(majorMinor + ".csv"), true);
47+
static TransportVersionDefinition getLatestFile(Path dataDir, String majorMinor) throws IOException {
48+
return readDefinitionFile(dataDir.resolve(LATEST_DIR).resolve(majorMinor + ".csv"), true);
49+
}
50+
51+
static TransportVersionDefinition getDefinedFile(Path dataDir, String name) throws IOException {
52+
validateNameFormat(name);
53+
var filePath = dataDir.resolve(DEFINED_DIR).resolve(name);
54+
if (Files.isRegularFile(filePath) == false) {
55+
return null;
56+
}
57+
return readDefinitionFile(filePath, false);
58+
}
59+
60+
static void writeDefinitionFile(Path dataDir, String name, List<Integer> ids) throws IOException {
61+
validateNameFormat(name);
62+
assert ids != null && ids.isEmpty() == false : "Ids must be non-empty";
63+
Files.writeString(
64+
dataDir.resolve(DEFINED_DIR).resolve(name + ".csv"),
65+
ids.stream().map(String::valueOf).collect(Collectors.joining(",")) + "\n",
66+
StandardCharsets.UTF_8
67+
);
68+
}
69+
70+
static void updateLatestFile(Path dataDir, String majorMinor, String name, int id) throws IOException {
71+
validateNameFormat(name);
72+
var path = dataDir.resolve(LATEST_DIR).resolve(majorMinor + ".csv");
73+
assert Files.isRegularFile(path) : "\"Latest\" file was not found at" + path + ", but is required: ";
74+
Files.writeString(
75+
path,
76+
name + "," + id + "\n",
77+
StandardCharsets.UTF_8
78+
);
79+
}
80+
81+
static void validateNameFormat(String name) {
82+
if (Pattern.compile("^\\w+$").matcher(name).matches() == false) {
83+
throw new GradleException("The TransportVersion name must only contain underscores and alphanumeric characters.");
84+
}
4385
}
4486

4587
static TransportVersionDefinition readDefinitionFile(Path file, boolean nameInFile) throws IOException {
@@ -53,12 +95,12 @@ static TransportVersionDefinition readDefinitionFile(Path file, boolean nameInFi
5395
try {
5496
ids.add(Integer.parseInt(parts[i]));
5597
} catch (NumberFormatException nfe) {
56-
throw new IllegalStateException("invalid transport version file format [" + file + "]", nfe);
98+
throw new IllegalStateException("Invalid transport version file format [" + file + "], id could not be parsed", nfe);
5799
}
58100
}
59101

60102
if (Comparators.isInOrder(ids, Comparator.reverseOrder()) == false) {
61-
throw new IOException("invalid transport version data file [" + file + "], ids are not in sorted");
103+
throw new IOException("Invalid transport version data file [" + file + "], ids are not in sorted");
62104
}
63105
return new TransportVersionDefinition(name, ids);
64106
}
@@ -85,6 +127,4 @@ static void addTransportVersionReferencesAttribute(AttributeContainer attributes
85127
attributes.attribute(ARTIFACT_TYPE_ATTRIBUTE, "txt");
86128
attributes.attribute(TransportVersionUtils.TRANSPORT_VERSION_REFERENCES_ATTRIBUTE, true);
87129
}
88-
89-
90130
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/transport/ValidateTransportVersionDefinitionsTask.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import static org.elasticsearch.gradle.internal.transport.TransportVersionUtils.readReferencesFile;
2828

2929
/**
30-
* Validates that each defined transport version constant is referenced by at least one project.
30+
* Validates that each defined transport version definition file is referenced by at least one project.
3131
*/
3232
public abstract class ValidateTransportVersionDefinitionsTask extends DefaultTask {
3333

@@ -47,8 +47,8 @@ public void validateTransportVersions() throws IOException {
4747
}
4848

4949
try (var definitionsStream = Files.list(definitionsDir)) {
50-
for (var constantsFile : definitionsStream.toList()) {
51-
var tv = readDefinitionFile(constantsFile, false);
50+
for (var definitionFile : definitionsStream.toList()) {
51+
var tv = readDefinitionFile(definitionFile, false);
5252
if (allTvNames.contains(tv.name()) == false) {
5353
throw new IllegalStateException("Transport version constant " + tv.name() + " is not referenced");
5454
}

0 commit comments

Comments
 (0)