From 234bba7f8286d467933510e45cd4eb9ac1a0a24c Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Wed, 30 Sep 2009 15:42:50 +0400 Subject: [PATCH] new build number format --- build.txt | 1 + .../intellij/ide/plugins/PluginManager.java | 75 ++++--- .../openapi/application/ApplicationInfo.java | 34 ++- .../intellij/ide/plugins/PluginInstaller.java | 5 +- .../ide/plugins/RepositoryHelper.java | 16 +- .../application/impl/ApplicationInfoImpl.java | 10 +- .../intellij/openapi/util/BuildNumber.java | 205 ++++++++++++++++++ .../openapi/util/BuildNumberTest.java | 17 ++ 8 files changed, 297 insertions(+), 66 deletions(-) create mode 100644 build.txt create mode 100644 platform/util/src/com/intellij/openapi/util/BuildNumber.java create mode 100644 platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java diff --git a/build.txt b/build.txt new file mode 100644 index 000000000000..b478d314c4c5 --- /dev/null +++ b/build.txt @@ -0,0 +1 @@ +90.SNAPSHOT diff --git a/platform/platform-api/src/com/intellij/ide/plugins/PluginManager.java b/platform/platform-api/src/com/intellij/ide/plugins/PluginManager.java index 897b8dafa010..2622bb24fccf 100644 --- a/platform/platform-api/src/com/intellij/ide/plugins/PluginManager.java +++ b/platform/platform-api/src/com/intellij/ide/plugins/PluginManager.java @@ -1,3 +1,19 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.intellij.ide.plugins; import com.intellij.ide.ClassloaderUtil; @@ -13,6 +29,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.LogProvider; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; @@ -56,7 +73,7 @@ public class PluginManager { static final Object lock = new Object(); - private static String ourBuildNumber; + private static BuildNumber ourBuildNumber; @NonNls public static final String PLUGIN_XML = "plugin.xml"; @NonNls public static final String META_INF = "META-INF"; private static final Map ourId2Index = new THashMap(); @@ -381,37 +398,20 @@ public class PluginManager { } public static boolean isIncompatible(final IdeaPluginDescriptor descriptor) { - final String buildNumberString = getBuildNumber(); - if (buildNumberString != null) { - int buildNumber; - try { - buildNumber = Integer.parseInt(buildNumberString); - } - catch (NumberFormatException e) { - return false; - } - final String sinceBuild = descriptor.getSinceBuild(); - try { - int sinceBuildNumber = Integer.parseInt(sinceBuild); - if (sinceBuildNumber > buildNumber) { - return true; - } - } - catch (NumberFormatException e) { - //skip invalid numbers - } + BuildNumber buildNumber = getBuildNumber(); - final String untilBuild = descriptor.getUntilBuild(); - try { - int untilBuildNumber = Integer.parseInt(untilBuild); - if (untilBuildNumber < buildNumber) { - return true; - } - } - catch (NumberFormatException e) { - //skip invalid numbers + if (descriptor.getSinceBuild() != null) { + BuildNumber sinceBuild = BuildNumber.fromString(descriptor.getSinceBuild()); + if (sinceBuild.compareTo(buildNumber) > 0) { + return true; } } + + if (descriptor.getUntilBuild() != null && !buildNumber.isSnapshot()) { + BuildNumber untilBuild = BuildNumber.fromString(descriptor.getUntilBuild()); + if (untilBuild.compareTo(buildNumber) < 0) return true; + } + return false; } @@ -687,16 +687,23 @@ public class PluginManager { return true; } - @Nullable - static String getBuildNumber() { + static BuildNumber getBuildNumber() { if (ourBuildNumber == null) { - ourBuildNumber = System.getProperty("idea.plugins.compatible.build"); + ourBuildNumber = BuildNumber.fromString(System.getProperty("idea.plugins.compatible.build")); if (ourBuildNumber == null) { try { - ourBuildNumber = new String(FileUtil.loadFileText(new File(PathManager.getHomePath() + "/build.txt"))).trim(); + File buildTxtFile = + FileUtil.findFirstThatExist(PathManager.getHomePath() + "/build.txt", PathManager.getHomePath() + "/community/build.txt"); + + if (buildTxtFile != null) { + ourBuildNumber = BuildNumber.fromString(new String(FileUtil.loadFileText(buildTxtFile)).trim()); + } + else { + ourBuildNumber = BuildNumber.fromString("90.SNAPSHOT"); + } } catch (IOException e) { - ourBuildNumber = null; + ourBuildNumber = BuildNumber.fromString("90.SNAPSHOT"); } } } diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java index dcb7f841669f..6ad58e349151 100644 --- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java +++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java @@ -1,25 +1,37 @@ /* - * Copyright 2000-2007 JetBrains s.r.o. + * Copyright 2000-2009 JetBrains s.r.o. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.intellij.openapi.application; +import com.intellij.openapi.util.BuildNumber; + import java.util.Calendar; public abstract class ApplicationInfo { public abstract Calendar getBuildDate(); - public abstract String getBuildNumber(); + + @Deprecated() + /** + * Use {@link #getBuild()} instead + */ + public String getBuildNumber() { + return getBuild().asString(); + } + + public abstract BuildNumber getBuild(); + public abstract String getMajorVersion(); public abstract String getMinorVersion(); public abstract String getVersionName(); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 2c9b8065a449..bbf8c5933104 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -9,6 +9,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.updateSettings.impl.PluginDownloader; +import com.intellij.openapi.util.BuildNumber; import com.intellij.ui.GuiUtils; import org.jetbrains.annotations.NonNls; @@ -138,10 +139,10 @@ public class PluginInstaller { } synchronized (PluginManager.lock) { - final String buildNumber = RepositoryHelper.extractBuildNumber(); + final BuildNumber buildNumber = PluginManager.getBuildNumber(); final @NonNls String url = RepositoryHelper.DOWNLOAD_URL + URLEncoder.encode(pluginNode.getPluginId().getIdString(), "UTF8") + - "&build=" + buildNumber; + "&build=" + buildNumber.asString(); final PluginDownloader downloader = new PluginDownloader(pluginNode.getPluginId().getIdString(), url, null, null, pluginNode.getName()); if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index 59bae100452e..efcff2d5cd9d 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -3,6 +3,7 @@ package com.intellij.ide.plugins; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; +import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.ui.UIUtil; @@ -38,8 +39,8 @@ public class RepositoryHelper { public static ArrayList process(JLabel label) throws IOException, ParserConfigurationException, SAXException { ArrayList plugins = null; try { - String buildNumber = extractBuildNumber(); - @NonNls String url = getListUrl() + "?build=" + buildNumber; + BuildNumber buildNumber = PluginManager.getBuildNumber(); + @NonNls String url = getListUrl() + "?build=" + buildNumber.asString(); setLabelText(label, IdeBundle.message("progress.connecting.to.plugin.manager", getRepositoryHost())); HttpConfigurable.getInstance().prepareURL(getRepositoryHost()); @@ -123,17 +124,6 @@ public class RepositoryHelper { } } - public static String extractBuildNumber() { - String build; - try { - build = Integer.valueOf(PluginManager.getBuildNumber()).toString(); - } - catch (NumberFormatException e) { - build = "3000"; - } - return build; - } - public static String getRepositoryHost() { return ApplicationInfoImpl.getShadowInstance().getPluginManagerUrl(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java index 33ba55c7b100..86e0e772e3cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java @@ -6,10 +6,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMExternalizable; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.*; import org.jdom.Document; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -107,8 +104,9 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern return myBuildDate; } - public String getBuildNumber() { - return myBuildNumber; + @Override + public BuildNumber getBuild() { + return BuildNumber.fromString(myBuildNumber); } public String getMajorVersion() { diff --git a/platform/util/src/com/intellij/openapi/util/BuildNumber.java b/platform/util/src/com/intellij/openapi/util/BuildNumber.java new file mode 100644 index 000000000000..747eec7cb047 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/BuildNumber.java @@ -0,0 +1,205 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @author max + */ +package com.intellij.openapi.util; + +import com.intellij.openapi.util.text.StringUtil; + +public class BuildNumber implements Comparable { + private final String myProductCode; + private final int myBaselineVersion; + private final int myBuildNumber; + + public BuildNumber(String productCode, int baselineVersion, int buildNumber) { + myProductCode = productCode; + myBaselineVersion = baselineVersion; + myBuildNumber = buildNumber; + } + + public String asString() { + StringBuilder builder = new StringBuilder(); + if (!StringUtil.isEmpty(myProductCode)) { + builder.append(myProductCode).append('-'); + } + + builder.append(myBaselineVersion).append('.'); + + if (myBuildNumber != Integer.MAX_VALUE) { + builder.append(myBuildNumber); + } + else { + builder.append("SNAPSHOT"); + } + + return builder.toString(); + } + + @Override + public String toString() { + return asString(); + } + + public static BuildNumber fromString(String version) { + if (version == null) return null; + String code = version; + int productSeparator = code.indexOf('-'); + final String productCode; + if (productSeparator > 0) { + productCode = code.substring(0, productSeparator); + code = code.substring(productSeparator + 1); + } + else { + productCode = ""; + } + + int baselineVersionSeparator = code.indexOf('.'); + int baselineVersion; + int buildNumber; + if (baselineVersionSeparator > 0) { + try { + baselineVersion = Integer.parseInt(code.substring(0, baselineVersionSeparator)); + code = code.substring(baselineVersionSeparator + 1); + } + catch (NumberFormatException e) { + throw new RuntimeException("Unparseable version number: " + version); + } + + if ("SNAPSHOT".equals(code) || "__BUILD_NUMBER__".equals(code)) { + buildNumber = Integer.MAX_VALUE; + } + else { + try { + buildNumber = Integer.parseInt(code); + } + catch (NumberFormatException e) { + throw new RuntimeException("Unparseable version number: " + version); + } + } + } + else { + try { + buildNumber = Integer.parseInt(code); + } + catch (NumberFormatException e) { + throw new RuntimeException("Unparseable version number: " + version); + } + + if (buildNumber <= 2000) { + // it's probably a baseline, not a build number + return new BuildNumber(productCode, buildNumber, 0); + } + + baselineVersion = getBaseLineForHistoricBuilds(buildNumber); + } + + return new BuildNumber(productCode, baselineVersion, buildNumber); + } + + public int compareTo(BuildNumber o) { + if (myBaselineVersion == o.myBaselineVersion) return myBuildNumber - o.myBuildNumber; + return myBaselineVersion - o.myBaselineVersion; + } + + public String getProductCode() { + return myProductCode; + } + + public int getBaselineVersion() { + return myBaselineVersion; + } + + public int getBuildNumber() { + return myBuildNumber; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + BuildNumber that = (BuildNumber)o; + + if (myBaselineVersion != that.myBaselineVersion) return false; + if (myBuildNumber != that.myBuildNumber) return false; + if (!myProductCode.equals(that.myProductCode)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myProductCode.hashCode(); + result = 31 * result + myBaselineVersion; + result = 31 * result + myBuildNumber; + return result; + } + + // See http://www.jetbrains.net/confluence/display/IDEADEV/Build+Number+Ranges for historic build ranges + private static int getBaseLineForHistoricBuilds(int bn) { + if (bn >= 10000) { + return 90; // Maia, 9x builds + } + + if (bn >= 9500) { + return 85; // 8.1 builds + } + + if (bn >= 9100) { + return 81; // 8.0.x builds + } + + if (bn >= 8000) { + return 80; // 8.0, including pre-release builds + } + + if (bn >= 7500) { + return 75; // 7.0.2+ + } + + if (bn >= 7200) { + return 72; // 7.0 final + } + + if (bn >= 6900) { + return 69; // 7.0 pre-M2 + } + + if (bn >= 6500) { + return 65; // 7.0 pre-M1 + } + + if (bn >= 6000) { + return 60; // 6.0.2+ + } + + if (bn >= 5000) { + return 55; // 6.0 branch, including all 6.0 EAP builds + } + + if (bn >= 4000) { + return 50; // 5.1 branch + } + + return 40; + } + + public boolean isSnapshot() { + return myBuildNumber == Integer.MAX_VALUE; + } +} diff --git a/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java new file mode 100644 index 000000000000..77666acc418d --- /dev/null +++ b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java @@ -0,0 +1,17 @@ +/* + * @author max + */ +package com.intellij.openapi.util; + +import junit.framework.TestCase; + +public class BuildNumberTest extends TestCase { + public void testHistoricBuild() { + assertEquals(new BuildNumber("", 75, 7512), BuildNumber.fromString("7512")); + } + + public void testSnapshotDominates() { + assertTrue(BuildNumber.fromString("90.SNAPSHOT").compareTo(BuildNumber.fromString("90.12345")) > 0); + assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-90.12345")) > 0); + } +}