5454import java .util .Arrays ;
5555import java .util .List ;
5656import java .util .Locale ;
57+ import java .util .Objects ;
5758import java .util .UUID ;
5859import java .util .logging .Level ;
5960import java .util .logging .Logger ;
61+ import java .util .regex .Matcher ;
6062import java .util .regex .Pattern ;
6163import java .util .zip .ZipEntry ;
6264import java .util .zip .ZipInputStream ;
6668 */
6769public class LocalDatastoreHelper {
6870 private static final Logger log = Logger .getLogger (LocalDatastoreHelper .class .getName ());
69- private static final String GCD_VERSION = "1.2.0" ;
71+ private static final Version GCD_VERSION = Version . fromString ( "1.2.0" ) ;
7072 private static final double DEFAULT_CONSISTENCY = 0.9 ;
7173 private static final String GCD_BASENAME = "cloud-datastore-emulator-" + GCD_VERSION ;
7274 private static final String GCD_FILENAME = GCD_BASENAME + ".zip" ;
@@ -119,8 +121,8 @@ private static Path installedGcdPath() {
119121 Path installedGcdPath = gcloudPath .resolve ("platform" ).resolve ("cloud-datastore-emulator" );
120122 if (Files .exists (installedGcdPath )) {
121123 try {
122- String installedVersion = installedGcdVersion ();
123- if (installedVersion != null && installedVersion .startsWith (GCD_VERSION )) {
124+ Version installedVersion = installedGcdVersion ();
125+ if (installedVersion != null && installedVersion .compareTo (GCD_VERSION ) >= 0 ) {
124126 if (log .isLoggable (Level .FINE )) {
125127 log .fine ("SDK datastore emulator found" );
126128 }
@@ -130,14 +132,14 @@ private static Path installedGcdPath() {
130132 log .fine ("SDK datastore emulator found but version mismatch" );
131133 }
132134 }
133- } catch (IOException | InterruptedException ignore ) {
135+ } catch (IOException | InterruptedException | IllegalArgumentException ignore ) {
134136 // ignore
135137 }
136138 }
137139 return null ;
138140 }
139141
140- private static String installedGcdVersion () throws IOException , InterruptedException {
142+ private static Version installedGcdVersion () throws IOException , InterruptedException {
141143 Process process =
142144 CommandWrapper .create ().command ("gcloud" , "version" ).redirectErrorStream ().start ();
143145 process .waitFor ();
@@ -147,7 +149,7 @@ private static String installedGcdVersion() throws IOException, InterruptedExcep
147149 if (line .startsWith (GCD_VERSION_PREFIX )) {
148150 String [] lineComponents = line .split (" " );
149151 if (lineComponents .length > 1 ) {
150- return lineComponents [1 ];
152+ return Version . fromString ( lineComponents [1 ]) ;
151153 }
152154 }
153155 }
@@ -170,6 +172,59 @@ private static Path executablePath(String cmd) {
170172 return null ;
171173 }
172174
175+ private static class Version implements Comparable <Version > {
176+
177+ private static final Pattern VERSION_PATTERN = Pattern .compile ("(\\ d+).(\\ d+).(\\ d+)" );
178+
179+ final int major ;
180+ final int minor ;
181+ final int patch ;
182+
183+ Version (int major , int minor , int patch ) {
184+ this .major = major ;
185+ this .minor = minor ;
186+ this .patch = patch ;
187+ }
188+
189+ @ Override
190+ public int compareTo (Version version ) {
191+ int result = major - version .major ;
192+ if (result == 0 ) {
193+ result = minor - version .minor ;
194+ if (result == 0 ) {
195+ result = patch - version .patch ;
196+ }
197+ }
198+ return result ;
199+ }
200+
201+ @ Override
202+ public String toString () {
203+ return String .format ("%d.%d.%d" , major , minor , patch );
204+ }
205+
206+ @ Override
207+ public boolean equals (Object other ) {
208+ return this == other || other instanceof Version && compareTo ((Version ) other ) == 0 ;
209+ }
210+
211+ @ Override
212+ public int hashCode () {
213+ return Objects .hash (major , minor , patch );
214+ }
215+
216+ static Version fromString (String version ) {
217+ Matcher matcher = VERSION_PATTERN .matcher (version );
218+ if (matcher .matches ()) {
219+ return new Version (
220+ Integer .valueOf (matcher .group (1 )),
221+ Integer .valueOf (matcher .group (2 )),
222+ Integer .valueOf (matcher .group (3 )));
223+ }
224+ throw new IllegalArgumentException ("Invalid version format" );
225+ }
226+ }
227+
173228 private static class ProcessStreamReader extends Thread {
174229 private final BufferedReader reader ;
175230 private volatile boolean terminated ;
0 commit comments