import java.io.File; import java.io.PrintWriter; import java.lang.Process; import java.lang.ProcessBuilder; import java.io.BufferedReader; import java.io.FileReader; import java.io.InputStreamReader; import java.lang.RuntimeException; import java.util.Date; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; public class H2OBuildVersion { // Marker for development build private static final String DEVEL_BUILD_NUMBER = "99999"; // Passed in by caller. File _rootDir; String _versionFromGradle; // Calculated. String _branch; String _buildMajorVersion; String _buildMinorVersion; String _buildIncrementalVersion; String _buildNumber; @Override public String toString() { return "versionFromGradle='" + _versionFromGradle + '\'' + ",projectVersion='" + getProjectVersion() + '\'' + ",branch='" + getBranch() + '\'' + ",lastCommitHash='" + calcLastCommitHash() + '\'' + ",gitDescribe='" + calcDescribe() + '\'' + ",compiledOn='" + calcCompiledOn() + '\'' + ",compiledBy='" + calcCompiledBy() + '\''; } H2OBuildVersion(File rootDir, String versionFromGradle) { _rootDir = rootDir; _versionFromGradle = versionFromGradle; calc(); } public boolean isDevelBuild() { return DEVEL_BUILD_NUMBER.equals(_buildNumber); } private String calcBuildNumber(File rootDir, String versionFromGradle) { try { String buildNumberFileName = rootDir.toString() + File.separator + "gradle" + File.separator + "buildnumber.properties"; File f = new File(buildNumberFileName); if (!f.exists()) { return "99999"; } BufferedReader br = new BufferedReader(new FileReader(buildNumberFileName)); String line = br.readLine(); while (line != null) { Pattern p = Pattern.compile("BUILD_NUMBER\\s*=\\s*(\\S+)"); Matcher m = p.matcher(line); boolean b = m.matches(); if (b) { br.close(); String buildNumber = m.group(1); return buildNumber; } line = br.readLine(); } throw new RuntimeException("BUILD_NUMBER property not found in " + buildNumberFileName); } catch (Exception e) { throw new RuntimeException(e); } } private void calc() { String majorMinorIncremental; if (_versionFromGradle.endsWith("-SNAPSHOT")) { majorMinorIncremental = _versionFromGradle.substring(0, _versionFromGradle.length() - "-SNAPSHOT".length()); } else { majorMinorIncremental = _versionFromGradle; } if (! Pattern.matches("\\d+\\.\\d+\\.\\d+", majorMinorIncremental)) { throw new RuntimeException("majorMinorIncremental is malformed (" + majorMinorIncremental + ")"); } String[] parts = majorMinorIncremental.split("\\."); _buildMajorVersion = parts[0]; _buildMinorVersion = parts[1]; _buildIncrementalVersion = parts[2]; _buildNumber = calcBuildNumber(_rootDir, _versionFromGradle); } private String calcBranch() { try { Process p = new ProcessBuilder("git", "branch").start(); p.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = br.readLine(); while (line != null) { if (!line.startsWith("*")) { line = br.readLine(); continue; } String branch = line.substring(2); return branch; } return "(unknown)"; } catch (Exception e) { return "(unknown)"; } } private String calcLastCommitHash() { try { Process p = new ProcessBuilder("git", "log", "-1", "--format=%H").start(); p.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = br.readLine(); return line; } catch (Exception e) { return "(unknown)"; } } private String calcDescribe() { try { Process p = new ProcessBuilder("git", "describe", "--always", "--dirty").start(); p.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = br.readLine(); return line; } catch (Exception e) { return "(unknown)"; } } private String calcCompiledOn() { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String s = dateFormat.format(date); return s; } private String calcCompiledBy() { return System.getProperty("user.name"); } private String getProjectVersion() { String projectVersion = _buildMajorVersion + "." + _buildMinorVersion + "." + _buildIncrementalVersion + "." + _buildNumber; return projectVersion; } //------------------------------------------------------------ // PUBLIC API BELOW THIS LINE. //------------------------------------------------------------ public String getLastCommitHash() { String s = calcLastCommitHash(); return s; } public String getBranch() { if (_branch == null) { _branch = calcBranch(); } return _branch; } public String getBuildMajorVersion() { return _buildMajorVersion; } public String getBuildMinorVersion() { return _buildMinorVersion; } public String getBuildIncrementalVersion() { return _buildIncrementalVersion; } public String getBuildNumber() { return _buildNumber; } public void emitBuildVersionJavaFileIfNecessary(File fileName) { try { String projectVersion = getProjectVersion(); String branchName = getBranch(); String lastCommitHash = calcLastCommitHash(); String describe = calcDescribe(); String compiledOn = calcCompiledOn(); String compiledBy = calcCompiledBy(); boolean needToEmit = false; if (! fileName.exists()) { System.out.print("NOTE: emitBuildVersionJava found no file, emitting new file"); needToEmit = true; } int found = 0; if (! needToEmit) { final String[][] stuffToCheck = { {"branchName", branchName}, {"lastCommitHash", lastCommitHash}, {"projectVersion", projectVersion} }; BufferedReader br = new BufferedReader(new FileReader(fileName)); String line = br.readLine(); while ((! needToEmit) && (line != null)) { for (String[] feature : stuffToCheck) { String name = feature[0]; String value = feature[1]; Pattern p = Pattern.compile(".*" + name + ".*\"(.*)\";.*"); Matcher m = p.matcher(line); boolean b = m.matches(); if (b) { found++; String v = m.group(1); if (!value.equals(v)) { System.out.print("NOTE: emitBuildVersionJava found a mismatch, emitting new file (" + value + " not equal " + v + ")"); needToEmit = true; break; } } } line = br.readLine(); } br.close(); } if ((! needToEmit) && (found != 3)) { System.out.print("NOTE: emitBuildVersionJava found too few things to check, emitting new file"); needToEmit = true; } if (! needToEmit) { System.out.print("NOTE: emitBuildVersionJava found a match, nothing to do"); return; } PrintWriter writer = new PrintWriter(fileName); writer.println("package water.init;"); writer.println(""); writer.println("public class BuildVersion extends AbstractBuildVersion {"); writer.println(" public String branchName() { return \"" + branchName + "\"; }"); writer.println(" public String lastCommitHash() { return \"" + lastCommitHash + "\"; }"); writer.println(" public String describe() { return \"" + describe + "\"; }"); writer.println(" public String projectVersion() { return \"" + projectVersion + "\"; }"); writer.println(" public String compiledOn() { return \"" + compiledOn + "\"; }"); writer.println(" public String compiledBy() { return \"" + compiledBy + "\"; }"); writer.println("}"); writer.close(); } catch (Exception e) { System.out.println(""); System.out.println("ERROR: H2OBuildVersion emitBuildVersionJavaFileIfNecessary failed"); System.out.println(""); System.out.println(e); System.out.println(""); System.exit(1); } } }