1010package org .elasticsearch .gradle .internal .transport ;
1111
1212import com .google .common .collect .Streams ;
13+ import org .elasticsearch .gradle .Version ;
14+ import org .elasticsearch .gradle .VersionProperties ;
15+ import org .elasticsearch .gradle .internal .transport .TransportVersionUtils .TransportVersionSetData ;
1316import org .gradle .api .DefaultTask ;
1417import org .gradle .api .GradleException ;
1518import org .gradle .api .file .RegularFileProperty ;
1619import org .gradle .api .provider .Property ;
1720import org .gradle .api .tasks .Input ;
1821import org .gradle .api .tasks .InputDirectory ;
1922import org .gradle .api .tasks .TaskAction ;
23+ import org .jetbrains .annotations .NotNull ;
2024
2125import java .io .File ;
2226import java .util .Arrays ;
2529import java .util .regex .Pattern ;
2630import java .util .stream .Stream ;
2731
28- import static org .elasticsearch .gradle .internal .transport .TransportVersionUtils .formatLatestTVSetFilename ;
32+ import static org .elasticsearch .gradle .internal .transport .TransportVersionUtils .LATEST_SUFFIX ;
33+ import static org .elasticsearch .gradle .internal .transport .TransportVersionUtils .getTVSetDataFilePath ;
2934
3035/**
3136 * This task generates TransportVersionSetData data files that contain information about transport versions. These files
@@ -63,116 +68,123 @@ public abstract class GenerateTransportVersionDataTask extends DefaultTask {
6368 * E.g.: "9.2", "8.18", etc.
6469 */
6570 @ Input
66- public abstract Property <String > getReleaseVersionMajorMinor ();
71+ public abstract Property <String > getReleaseVersionForTV ();
6772
6873
6974 @ TaskAction
7075 public void generateTransportVersionData () {
71- var tvDataDir = Objects .requireNonNull (getDataFileDirectory ().getAsFile ().get ());
72- var newTVName = Objects .requireNonNull (getTVSetName ().get ());
73- var majorMinor = Objects .requireNonNull (getReleaseVersionMajorMinor ().get ());
76+ final var tvDataDir = Objects .requireNonNull (getDataFileDirectory ().getAsFile ().get ());
77+ final var tvSetName = Objects .requireNonNull (getTVSetName ().get ());
78+ final var tvReleaseVersion = ReleaseVersion . fromString ( Objects .requireNonNull (getReleaseVersionForTV ().get () ));
7479
75- // Split version into major and minor
76- String [] versionParts = majorMinor .split ("\\ ." );
77- assert versionParts .length == 2 ;
78- var major = Integer .parseInt (versionParts [0 ]);
79- var minor = Integer .parseInt (versionParts [1 ]);
8080
8181 // Get the latest transport version data for the local version.
82- var latestTVSetData = TransportVersionUtils .getLatestTVSetData (tvDataDir , majorMinor );
82+ final var latestTVSetData = TransportVersionUtils .getLatestTVSetData (tvDataDir , tvReleaseVersion . toString () );
8383
8484 // Get the latest transport version data for the prior release version.
85- var priorLatestTVSetDataFileName = getPriorLatestTVSetFilename (tvDataDir , major , minor );
86- var priorLatestTVSetData = TransportVersionUtils .getLatestTVSetData (tvDataDir , priorLatestTVSetDataFileName );
85+ final var priorReleaseVersion = getPriorReleaseVersion (tvDataDir , tvReleaseVersion );
86+ var priorLatestTVSetData = TransportVersionUtils .getLatestTVSetData (tvDataDir , priorReleaseVersion . toString () );
8787 if (priorLatestTVSetData == null ) {
88- // TODO Can this ever be null? No, must populate the data file for the latest branch we can no longer backport to.
88+ throw new GradleException (
89+ "The latest Transport Version ID for the prior release was not found at: "
90+ + tvDataDir .getAbsolutePath () + formatLatestTVSetFilename (priorReleaseVersion )
91+ + " This is required."
92+ );
8993 }
9094
91- // Bump the version number
92- int nextVersion ;
93- if (latestTVSetData == null ) {
94- // TODO do a major or minor version bump here
95- if (minor == 0 ) {
96- // This is major bump
97- nextVersion = major * 1_000_000 ;
98- } else {
99- // This is a minor bump. Just increment as usual but from the prior version.
100- assert priorLatestTVSetData != null ;
101- nextVersion = bumpVersionNumber (priorLatestTVSetData .ids .getFirst ());
102- }
103- } else {
104- nextVersion = bumpVersionNumber (latestTVSetData .ids .getFirst ());
105- }
106- System .out .println ("Latest transport version set: " + latestTVSetData .name + " with IDs: " + latestTVSetData .ids );
107-
108-
109- // Load the tvSetData for the specified name.
110- var tvSetDataFromFile = TransportVersionUtils .getTVSetData (tvDataDir , newTVName );
111-
112- // Create/update the data files
113- if (tvSetDataFromFile == null ) {
114- // Create a new data file for the case where this is a new TV
115- new TransportVersionUtils .TransportVersionSetData (newTVName , List .of (nextVersion )).writeToDataDir (tvDataDir );
116- } else {
117- // This is not a new TV. We are backporting an existing TVSet.
118- // Check to ensure that there isn't already a TV number for this change (e.g. if this task has been run twice).
119- var existingIDsForReleaseVersion = tvSetDataFromFile .ids .stream ().filter (id -> {
120- var priorLatestID = priorLatestTVSetData .ids .getFirst ();
121- var latestID = latestTVSetData .ids .getFirst ();
122- return priorLatestID < id && id < latestID ;
95+ // Determine if it's a (major) version bump
96+ final var isVersionBump = latestTVSetData == null ;
97+ final var isMajorVersionBump = isVersionBump && (tvReleaseVersion .major - priorReleaseVersion .major > 0 );
98+
99+ // Create the new version
100+ final var mainReleaseVersion = ReleaseVersion .of (VersionProperties .getElasticsearchVersion ());
101+ final var isTVReleaseVersionMain = tvReleaseVersion .equals (mainReleaseVersion );
102+ final var tvIDToBump = isVersionBump ? priorLatestTVSetData .ids ().getFirst () : latestTVSetData .ids ().getFirst ();
103+ int newVersion = bumpVersionNumber (tvIDToBump , tvReleaseVersion , isMajorVersionBump , isTVReleaseVersionMain );
104+
105+ // Load the tvSetData for the specified name, if it exists
106+ final var tvSetDataFromFile = TransportVersionUtils .getTVSetData (tvDataDir , tvSetName );
107+ final var tvSetFileExists = tvSetDataFromFile != null ;
108+
109+ // Create/update the data file
110+ if (tvSetFileExists ) {
111+ // This is not a new TVSet. We are creating a backport version for an existing TVSet.
112+ // Check to ensure that there isn't already a TV id for this release version (e.g., if this task has been run twice).
113+ var existingIDsForReleaseVersion = tvSetDataFromFile .ids ().stream ().filter (id -> {
114+ var priorLatestID = priorLatestTVSetData .ids ().getFirst ();
115+ return priorLatestID < id && id <= newVersion ;
123116 }).toList ();
124117 if (existingIDsForReleaseVersion .isEmpty () == false ) {
125- throw new GradleException ("TransportVersion already exists for this release! Release version: " +
126- majorMinor + "TransportVersion Id: " + existingIDsForReleaseVersion .stream ().findFirst ());
118+ throw new GradleException (
119+ "A transport version could not be created because one already exists for this release:"
120+ + " Release version: " + tvReleaseVersion
121+ + " TransportVersion Id: " + existingIDsForReleaseVersion .getFirst ()
122+ + " File: " + getTVSetDataFilePath (tvDataDir , tvSetName )
123+ );
127124 }
128125
129126 // Update the existing data file for the backport.
130- new TransportVersionUtils .TransportVersionSetData (
131- newTVName ,
132- Streams .concat (tvSetDataFromFile .ids .stream (), Stream .of (nextVersion )).sorted ().toList ().reversed ()
127+ new TransportVersionSetData (
128+ tvSetName ,
129+ Streams .concat (tvSetDataFromFile .ids ().stream (), Stream .of (newVersion )).sorted ().toList ().reversed ()
130+ ).writeToDataDir (tvDataDir );
131+ } else {
132+ // Create a new data file for the case where this is a new TV
133+ new TransportVersionSetData (
134+ tvSetName ,
135+ List .of (newVersion )
133136 ).writeToDataDir (tvDataDir );
134137 }
135138
136139 // Update the LATEST file.
137140 TransportVersionUtils .writeTVSetData (
138141 tvDataDir ,
139- formatLatestTVSetFilename (majorMinor ),
140- new TransportVersionUtils . TransportVersionSetData (newTVName , List .of (nextVersion ))
142+ formatLatestTVSetFilename (tvReleaseVersion ),
143+ new TransportVersionSetData (tvSetName , List .of (newVersion ))
141144 );
142145 }
143146
144147
145- // TODO account for bumping majors. Need to make a new data file too.
146- private static int bumpVersionNumber (int versionNumber ) {
147- var main = false ; // TODO how do we know if we are on main?
148+ private static int bumpVersionNumber (
149+ int tvIDToBump ,
150+ ReleaseVersion releaseVersion ,
151+ boolean majorVersionBump ,
152+ boolean isTVReleaseVersionMain
153+ ) {
148154
149- /*
155+ /* The TV format:
156+ *
150157 * M_NNN_S_PP
151158 *
152159 * M - The major version of Elasticsearch
153160 * NNN - The server version part
154161 * S - The subsidiary version part. It should always be 0 here, it is only used in subsidiary repositories.
155162 * PP - The patch version part
156163 */
157- if (main ) {
158- // bump the server versin part
159- return versionNumber + 1000 ; // TODO add check that this doesn't cause overflow out of server versions
164+ if (isTVReleaseVersionMain ) {
165+ if (majorVersionBump ) {
166+ // Bump the major version part, set all other parts to zero.
167+ return releaseVersion .major * 1_000_000 ; // TODO add check that this doesn't cause overflow out of server versions
168+ } else {
169+ // Bump the server version part if not a major bump.
170+ return tvIDToBump + 1000 ; // TODO add check that this doesn't cause overflow out of server versions
171+ }
160172 } else {
161173 // bump the patch version part
162- return versionNumber + 1 ; // TODO add check that this doesn't cause overflow out of patch versions
174+ return tvIDToBump + 1 ; // TODO add check that this doesn't cause overflow out of patch versions
163175 }
164176 }
165177
166178 /**
167179 * Accepts a major.minor version string (e.g. "9.0") and returns the LATEST.json file of the
168180 * previous release string (e.g. "8.19-LATEST.json").
169181 */
170- private static String getPriorLatestTVSetFilename (File tvDataDir , int major , int minor ) {
182+ private static ReleaseVersion getPriorReleaseVersion (File tvDataDir , ReleaseVersion releaseVersion ) {
171183 assert tvDataDir != null ;
172184 assert tvDataDir .isDirectory ();
173185
174- if (minor > 0 ) {
175- return formatLatestTVSetFilename ( major , minor - 1 );
186+ if (releaseVersion . minor > 0 ) {
187+ return new ReleaseVersion ( releaseVersion . major , releaseVersion . minor - 1 );
176188 }
177189
178190 // If the minor is 0, we need to find the largest minor on the previous major
@@ -181,11 +193,55 @@ private static String getPriorLatestTVSetFilename(File tvDataDir, int major, int
181193 .filter (tvDataFile -> tvDataFile .getName ().endsWith ("-LATEST.json" ))
182194 .flatMap (tvDataFile -> {
183195 var matcher = pattern .matcher (tvDataFile .getName ());
184- var localMajor = Integer .parseInt (matcher .group (1 ));
185- var localMinor = Integer .parseInt (matcher .group (2 ));
186- return localMajor == major - 1 ? Stream .of (localMinor ) : Stream .empty ();
196+ var fileMajor = Integer .parseInt (matcher .group (1 ));
197+ var fileMinor = Integer .parseInt (matcher .group (2 ));
198+ return fileMajor == releaseVersion . major - 1 ? Stream .of (fileMinor ) : Stream .empty ();
187199 }).sorted ().toList ().getLast ();
200+ return new ReleaseVersion (releaseVersion .major - 1 , highestMinorOfPrevMajor );
201+ }
188202
189- return formatLatestTVSetFilename (major - 1 , highestMinorOfPrevMajor );
203+
204+ private static String formatLatestTVSetFilename (ReleaseVersion releaseVersion ) {
205+ return releaseVersion .toString () + LATEST_SUFFIX ;
206+ }
207+
208+ private record ReleaseVersion (int major , int minor ) {
209+ public static ReleaseVersion fromString (String string ) {
210+ String [] versionParts = string .split ("\\ ." );
211+ assert versionParts .length == 2 ;
212+ return new ReleaseVersion (
213+ Integer .parseInt (versionParts [0 ]),
214+ Integer .parseInt (versionParts [1 ])
215+ );
216+ }
217+
218+ public static ReleaseVersion of (Version version ) {
219+ return new ReleaseVersion (
220+ version .getMajor (),
221+ version .getMinor ()
222+ );
223+ }
224+
225+ @ Override
226+ public @ NotNull String toString () {
227+ return major + "." + minor ;
228+ }
229+
230+
231+ @ Override
232+ public boolean equals (Object obj ) {
233+ if (this == obj ) return true ;
234+ if (obj instanceof ReleaseVersion ) {
235+ ReleaseVersion that = (ReleaseVersion ) obj ;
236+ return major == that .major && minor == that .minor ;
237+ } else {
238+ return false ;
239+ }
240+ }
241+
242+ @ Override
243+ public int hashCode () {
244+ return Objects .hash (major , minor );
245+ }
190246 }
191247}
0 commit comments