--- /dev/null
+90.SNAPSHOT
+/*
+ * 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;
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;
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<PluginId,Integer> ourId2Index = new THashMap<PluginId, Integer>();
}
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;
}
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");
}
}
}
/*
- * 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();
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;
}
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())) {
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;
public static ArrayList<IdeaPluginDescriptor> process(JLabel label) throws IOException, ParserConfigurationException, SAXException {
ArrayList<IdeaPluginDescriptor> 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());
}
}
- 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();
}
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;
return myBuildDate;
}
- public String getBuildNumber() {
- return myBuildNumber;
+ @Override
+ public BuildNumber getBuild() {
+ return BuildNumber.fromString(myBuildNumber);
}
public String getMajorVersion() {
--- /dev/null
+/*
+ * 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<BuildNumber> {
+ 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;
+ }
+}
--- /dev/null
+/*
+ * @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);
+ }
+}