diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index 444a31a8b67c..c40eeae6772c 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -24,6 +24,8 @@ + + diff --git a/bin/linux/fsnotifier b/bin/linux/fsnotifier index df7985a5bfc2..a34b7855db4f 100755 Binary files a/bin/linux/fsnotifier and b/bin/linux/fsnotifier differ diff --git a/bin/linux/fsnotifier64 b/bin/linux/fsnotifier64 index 9f0b3a46d2f2..812e326cd6a1 100755 Binary files a/bin/linux/fsnotifier64 and b/bin/linux/fsnotifier64 differ diff --git a/java/execution/impl/src/com/intellij/execution/RunConfigurationExtension.java b/java/execution/impl/src/com/intellij/execution/RunConfigurationExtension.java index 2353f470ff43..77d2b2db429d 100644 --- a/java/execution/impl/src/com/intellij/execution/RunConfigurationExtension.java +++ b/java/execution/impl/src/com/intellij/execution/RunConfigurationExtension.java @@ -37,7 +37,7 @@ import org.jetbrains.annotations.Nullable; public abstract class RunConfigurationExtension extends RunConfigurationExtensionBase{ public static final ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.runConfigurationExtension"); - public abstract void updateJavaParameters(final T configuration, final JavaParameters params, RunnerSettings runnerSettings); + public abstract void updateJavaParameters(final T configuration, final JavaParameters params, RunnerSettings runnerSettings) throws ExecutionException; @Override diff --git a/lib/jsr305.jar b/lib/jsr305.jar new file mode 100644 index 000000000000..a9afc6619b4b Binary files /dev/null and b/lib/jsr305.jar differ diff --git a/native/fsNotifier/linux/fsnotifier.h b/native/fsNotifier/linux/fsnotifier.h index 0b3e52705513..0140d6be8102 100644 --- a/native/fsNotifier/linux/fsnotifier.h +++ b/native/fsNotifier/linux/fsnotifier.h @@ -21,6 +21,14 @@ #include +// messaging +typedef enum { + MSG_INSTANCE_LIMIT, MSG_WATCH_LIMIT +} MSG; + +void message(MSG id); + + // logging void userlog(int priority, const char* format, ...); @@ -59,8 +67,6 @@ enum { bool init_inotify(); void set_inotify_callback(void (* callback)(char*, int)); int get_inotify_fd(); -int get_watch_count(); -bool watch_limit_reached(); int watch(const char* root, array* mounts); void unwatch(int id); bool process_inotify_input(); diff --git a/native/fsNotifier/linux/inotify.c b/native/fsNotifier/linux/inotify.c index 75a97abc1339..8570d032e782 100644 --- a/native/fsNotifier/linux/inotify.c +++ b/native/fsNotifier/linux/inotify.c @@ -49,30 +49,18 @@ static void (* callback)(char*, int) = NULL; #define EVENT_BUF_LEN (2048 * (EVENT_SIZE + 16)) static char event_buf[EVENT_BUF_LEN]; - -static void read_watch_descriptors_count() { - FILE* f = fopen(WATCH_COUNT_NAME, "r"); - if (f == NULL) { - userlog(LOG_ERR, "can't open %s: %s", WATCH_COUNT_NAME, strerror(errno)); - return; - } - - char* str = read_line(f); - if (str == NULL) { - userlog(LOG_ERR, "can't read from %s", WATCH_COUNT_NAME); - } - else { - watch_count = atoi(str); - } - - fclose(f); -} +static void read_watch_descriptors_count(); +static void watch_limit_reached(); bool init_inotify() { inotify_fd = inotify_init(); if (inotify_fd < 0) { - userlog(LOG_ERR, "inotify_init: %s", strerror(errno)); + int e = errno; + userlog(LOG_ERR, "inotify_init: %s", strerror(e)); + if (e == EMFILE) { + message(MSG_INSTANCE_LIMIT); + } return false; } userlog(LOG_DEBUG, "inotify fd: %d", get_inotify_fd()); @@ -96,6 +84,24 @@ bool init_inotify() { return true; } +static void read_watch_descriptors_count() { + FILE* f = fopen(WATCH_COUNT_NAME, "r"); + if (f == NULL) { + userlog(LOG_ERR, "can't open %s: %s", WATCH_COUNT_NAME, strerror(errno)); + return; + } + + char* str = read_line(f); + if (str == NULL) { + userlog(LOG_ERR, "can't read from %s", WATCH_COUNT_NAME); + } + else { + watch_count = atoi(str); + } + + fclose(f); +} + inline void set_inotify_callback(void (* _callback)(char*, int)) { callback = _callback; @@ -107,16 +113,6 @@ inline int get_inotify_fd() { } -inline int get_watch_count() { - return watch_count; -} - - -inline bool watch_limit_reached() { - return limit_reached; -} - - #define EVENT_MASK IN_MODIFY | IN_ATTRIB | IN_CREATE | IN_DELETE | IN_MOVE | IN_DELETE_SELF static int add_watch(const char* path, watch_node* parent) { @@ -128,7 +124,7 @@ static int add_watch(const char* path, watch_node* parent) { } else if (errno == ENOSPC) { userlog(LOG_WARNING, "inotify_add_watch(%s): %s", path, strerror(errno)); - limit_reached = true; + watch_limit_reached(); return ERR_CONTINUE; } else { @@ -188,6 +184,12 @@ static int add_watch(const char* path, watch_node* parent) { return wd; } +static void watch_limit_reached() { + if (!limit_reached) { + limit_reached = true; + message(MSG_WATCH_LIMIT); + } +} static void rm_watch(int wd, bool update_parent) { watch_node* node = table_get(watches, wd); diff --git a/native/fsNotifier/linux/main.c b/native/fsNotifier/linux/main.c index 87fcf26139b9..27372e35acc1 100644 --- a/native/fsNotifier/linux/main.c +++ b/native/fsNotifier/linux/main.c @@ -48,8 +48,12 @@ #define HELP_MSG \ "Try 'fsnotifier --help' for more information.\n" -#define INOTIFY_LIMIT_MSG \ - "The current inotify(7) watch limit of %d is too low. " \ +#define INSTANCE_LIMIT_TEXT \ + "The inotify(7) instances limit reached. " \ + "More details.\n" + +#define WATCH_LIMIT_TEXT \ + "The current inotify(7) watch limit is too low. " \ "More details.\n" typedef struct { @@ -59,7 +63,6 @@ typedef struct { static array* roots = NULL; -static bool show_warning = true; static bool self_test = false; static void init_log(); @@ -152,6 +155,19 @@ static void init_log() { } +void message(MSG id) { + if (id == MSG_INSTANCE_LIMIT) { + output("MESSAGE\n" INSTANCE_LIMIT_TEXT); + } + else if (id == MSG_WATCH_LIMIT) { + output("MESSAGE\n" WATCH_LIMIT_TEXT); + } + else { + userlog(LOG_ERR, "unknown message: %d", id); + } +} + + void userlog(int priority, const char* format, ...) { va_list ap; @@ -353,12 +369,6 @@ static bool register_roots(array* new_roots, array* unwatchable, array* mounts) return false; } else if (id != ERR_IGNORE) { - if (show_warning && watch_limit_reached()) { - int limit = get_watch_count(); - userlog(LOG_WARNING, "watch limit (%d) reached", limit); - output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit); - show_warning = false; // warn only once - } CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false); } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java index 4d156792a1ec..323f3b955020 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -28,6 +28,8 @@ import com.intellij.notification.Notifications; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.ex.ApplicationInfoEx; +import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; @@ -831,7 +833,11 @@ public class PluginManager { if (ourBuildNumber == null) { ourBuildNumber = BuildNumber.fromString(System.getProperty("idea.plugins.compatible.build")); if (ourBuildNumber == null) { - ourBuildNumber = BuildNumber.fromFile(); + ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance(); + ourBuildNumber = appInfo != null ? appInfo.getBuild() : null; + if (ourBuildNumber == null) { + ourBuildNumber = BuildNumber.fallback(); + } } } return ourBuildNumber; diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index 9a475c352139..e2b4ded22112 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -21,6 +21,7 @@ import com.intellij.openapi.options.BaseConfigurable; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.ui.components.JBCheckBox; import com.intellij.util.ui.UIUtil; @@ -66,6 +67,20 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myLafComboBox.setModel(new DefaultComboBoxModel(LafManager.getInstance().getInstalledLookAndFeels())); myComponent.myLafComboBox.setRenderer(new LafComboBoxRenderer()); + Dictionary delayDictionary = new Hashtable(); + delayDictionary.put(new Integer(0), new JLabel("0")); + delayDictionary.put(new Integer(1200), new JLabel("1200")); + //delayDictionary.put(new Integer(2400), new JLabel("2400")); + myComponent.myInitialTooltipDelaySlider.setLabelTable(delayDictionary); + UIUtil.setSliderIsFilled(myComponent.myInitialTooltipDelaySlider, Boolean.TRUE); + myComponent.myInitialTooltipDelaySlider.setMinimum(0); + myComponent.myInitialTooltipDelaySlider.setMaximum(1200); + myComponent.myInitialTooltipDelaySlider.setPaintLabels(true); + myComponent.myInitialTooltipDelaySlider.setPaintTicks(true); + myComponent.myInitialTooltipDelaySlider.setPaintTrack(true); + myComponent.myInitialTooltipDelaySlider.setMajorTickSpacing(1200); + myComponent.myInitialTooltipDelaySlider.setMinorTickSpacing(100); + myComponent.myEnableAlphaModeCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { boolean state = myComponent.myEnableAlphaModeCheckBox.isSelected(); @@ -196,6 +211,11 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab settings.ALPHA_MODE_RATIO = ratio; } } + int tooltipDelay = Math.min(myComponent.myInitialTooltipDelaySlider.getValue(), 5000); + if (tooltipDelay != Registry.intValue("ide.tooltip.initialDelay")) { + update = true; + Registry.get("ide.tooltip.initialDelay").setValue(tooltipDelay); + } if (update) { settings.fireUISettingsChanged(); @@ -240,6 +260,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myAlphaModeRatioSlider.setValue(ratio); myComponent.myAlphaModeRatioSlider.setToolTipText(ratio + "%"); myComponent.myAlphaModeRatioSlider.setEnabled(alphaModeEnabled && settings.ENABLE_ALPHA_MODE); + myComponent.myInitialTooltipDelaySlider.setValue(Registry.intValue("ide.tooltip.initialDelay")); myComponent.updateCombo(); } @@ -284,6 +305,9 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab float ratio = myComponent.myAlphaModeRatioSlider.getValue() / 100f; isModified |= ratio != settings.ALPHA_MODE_RATIO; } + int tooltipDelay = -1; + tooltipDelay = myComponent.myInitialTooltipDelaySlider.getValue(); + isModified |= tooltipDelay != Registry.intValue("ide.tooltip.initialDelay"); return isModified; } @@ -320,9 +344,10 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab private JCheckBox myCbDisplayIconsInMenu; private JCheckBox myDisableMnemonics; private JCheckBox myDisableMnemonicInControlsCheckBox; - private JBCheckBox myHideNavigationPopupsCheckBox; + private JCheckBox myHideNavigationPopupsCheckBox; private JCheckBox myAllowMergeButtons; private JBCheckBox myUseSmallLabelsOnTabs; + private JSlider myInitialTooltipDelaySlider; public MyComponent() { myOverrideLAFFonts.addActionListener( new ActionListener() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form index 5153fa2eaa2c..01a66b46b136 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form @@ -16,7 +16,7 @@ - + @@ -147,6 +147,7 @@ + @@ -161,14 +162,42 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java index a3f859887f8c..c06dbee44c1a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -67,8 +67,12 @@ public class ConfigurableExtensionPointUtil { final String parentId = wrapper.getParentId(); if (parentId != null) { final ConfigurableWrapper parent = idToConfigurable.get(parentId); - LOG.assertTrue(parent != null, "Can't find parent for " + parentId + " (" + wrapper + ")"); - idToConfigurable.put(parentId, parent.addChild(wrapper)); + if (parent != null) { + idToConfigurable.put(parentId, parent.addChild(wrapper)); + } + else { + LOG.error("Can't find parent for " + parentId + " (" + wrapper + ")"); + } } } //leave only roots (i.e. configurables without parents) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index 9e8750d079cc..20ee724be726 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -41,7 +41,6 @@ import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static com.intellij.util.containers.ContainerUtil.*; @@ -81,44 +80,30 @@ public class FileWatcher { private final ManagingFS myManagingFS; private final File myExecutable; - private final AtomicBoolean myInitialized = new AtomicBoolean(false); private volatile MyProcessHandler myProcessHandler; private volatile int myStartAttemptCount = 0; private volatile boolean myIsShuttingDown = false; private volatile boolean myFailureShownToTheUser = false; private final AtomicInteger mySettingRoots = new AtomicInteger(0); - private final ModalityState myDefaultModalityState; /** @deprecated use {@linkplain com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl#getFileWatcher()} (to remove in IDEA 13) */ public static FileWatcher getInstance() { return ((LocalFileSystemImpl)LocalFileSystem.getInstance()).getFileWatcher(); } - FileWatcher(@NotNull final ManagingFS managingFS) { + FileWatcher(@NotNull ManagingFS managingFS) { myManagingFS = managingFS; - // eager initialization to avoid deadlock during component initialization (PY-8724) - myDefaultModalityState = ModalityState.defaultModalityState(); - boolean disabled = Boolean.parseBoolean(System.getProperty(PROPERTY_WATCHER_DISABLED)); myExecutable = getExecutable(); if (disabled) { - myInitialized.set(true); LOG.info("Native file watcher is disabled"); } else if (myExecutable == null) { - myInitialized.set(true); LOG.info("Native file watcher is not supported on this platform"); } - } - - private void init() { - if (!myInitialized.compareAndSet(false, true)) { - return; - } - - if (!myExecutable.exists()) { + else if (!myExecutable.exists()) { notifyOnFailure(ApplicationBundle.message("watcher.exe.not.found"), null); } else if (!myExecutable.canExecute()) { @@ -188,7 +173,7 @@ public class FileWatcher { private static boolean isUpToDate(File executable) { long length = SystemInfo.isWindows ? 70216 : SystemInfo.isMac ? 13924 : - SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29308 : 22809 : + SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29227 : 22734 : -1; return length < 0 || length == executable.length(); } @@ -203,7 +188,7 @@ public class FileWatcher { String title = ApplicationBundle.message("watcher.slow.sync"); Notifications.Bus.notify(NOTIFICATION_GROUP.getValue().createNotification(title, cause, NotificationType.WARNING, listener)); } - }, myDefaultModalityState); + }, ModalityState.NON_MODAL); } } @@ -256,7 +241,7 @@ public class FileWatcher { } public boolean isOperational() { - return !myInitialized.get() || myProcessHandler != null; + return myProcessHandler != null; } public boolean isSettingRoots() { @@ -292,7 +277,6 @@ public class FileWatcher { } public void setWatchRoots(final List recursive, final List flat) { - init(); setWatchRoots(recursive, flat, false); } diff --git a/platform/platform-tests/testSrc/com/intellij/util/StringBuilderSpinAllocatorTest.java b/platform/platform-tests/testSrc/com/intellij/util/StringBuilderSpinAllocatorTest.java index 499c55578e48..ac61b53a5717 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/StringBuilderSpinAllocatorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/StringBuilderSpinAllocatorTest.java @@ -1,12 +1,26 @@ +/* + * Copyright 2000-2013 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.util; -import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; public class StringBuilderSpinAllocatorTest { - private final String[] myStrings = new String[]{ "First String is the smallest", "Second String is definitely larger than the first one", @@ -14,17 +28,20 @@ public class StringBuilderSpinAllocatorTest { "Fourth String is the largest amongst all the myStrings. Congrats! It must be even larger than it is." }; - @Before - public void setUp() throws Exception { - // warm-up - new StringBuilder(); - StringBuilderSpinAllocator.dispose(StringBuilderSpinAllocator.alloc()); + @Test + public void testPerformance() { + assumeTrue(!com.intellij.testFramework.PlatformTestUtil.COVERAGE_ENABLED_BUILD); + doTest(true); + doTest(false); } - @Test - public void testPerformance() throws InterruptedException { + private void doTest(boolean warmUp) { StringBuilder builder; - final int count = 1000000; + int count = warmUp ? 1000 : 1000000; + + System.gc(); + System.runFinalization(); + TimeoutUtil.sleep(1000); long start = System.nanoTime(); for (int i = 0; i < count; ++i) { @@ -32,12 +49,11 @@ public class StringBuilderSpinAllocatorTest { builder.append(myStrings[i & 3]); builder.append(builder.toString()); } - final long regularTime = (System.nanoTime() - start)/1000; - System.out.println("StringBuilder regular allocations took: " + regularTime); + long regularTime = (System.nanoTime() - start) / 1000; System.gc(); System.runFinalization(); - Thread.sleep(2000); + TimeoutUtil.sleep(1000); start = System.nanoTime(); for (int i = 0; i < count; ++i) { @@ -46,10 +62,11 @@ public class StringBuilderSpinAllocatorTest { builder.append(builder.toString()); StringBuilderSpinAllocator.dispose(builder); } - final long spinTime = (System.nanoTime() - start)/1000; - System.out.println("StringBuilder spin allocations took: " + spinTime); + long spinTime = (System.nanoTime() - start) / 1000; - if (!com.intellij.testFramework.PlatformTestUtil.COVERAGE_ENABLED_BUILD) { + if (!warmUp) { + System.out.println("StringBuilder regular allocations took: " + regularTime); + System.out.println("StringBuilder spin allocations took: " + spinTime); assertTrue("regular:" + regularTime + "mks, spin:" + spinTime + "mks", spinTime < regularTime); } } diff --git a/platform/util/src/com/intellij/openapi/util/BuildNumber.java b/platform/util/src/com/intellij/openapi/util/BuildNumber.java index 4212c34484be..363771bb644a 100644 --- a/platform/util/src/com/intellij/openapi/util/BuildNumber.java +++ b/platform/util/src/com/intellij/openapi/util/BuildNumber.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -13,10 +13,6 @@ * 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.application.PathManager; @@ -27,8 +23,14 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +/** + * @author max + */ public class BuildNumber implements Comparable { private static final String BUILD_NUMBER = "__BUILD_NUMBER__"; + private static final String SNAPSHOT = "SNAPSHOT"; + private static final String FALLBACK_VERSION = "999.SNAPSHOT"; + private static final int TOP_BASELINE_VERSION = fromFile().getBaselineVersion(); private final String myProductCode; @@ -42,7 +44,7 @@ public class BuildNumber implements Comparable { } public String asString() { - return asString(true); + return asString(true); } public String asStringWithoutProductCode() { @@ -51,10 +53,9 @@ public class BuildNumber implements Comparable { private String asString(boolean includeProductCode) { StringBuilder builder = new StringBuilder(); - if (includeProductCode) { - if (!StringUtil.isEmpty(myProductCode)) { - builder.append(myProductCode).append('-'); - } + + if (includeProductCode && !StringUtil.isEmpty(myProductCode)) { + builder.append(myProductCode).append('-'); } builder.append(myBaselineVersion).append('.'); @@ -63,7 +64,7 @@ public class BuildNumber implements Comparable { builder.append(myBuildNumber); } else { - builder.append("SNAPSHOT"); + builder.append(SNAPSHOT); } return builder.toString(); @@ -103,7 +104,7 @@ public class BuildNumber implements Comparable { code = code.substring(baselineVersionSeparator + 1); } catch (NumberFormatException e) { - throw new RuntimeException("Unparseable version number: " + version + "; plugin name: " + name); + throw new RuntimeException("Invalid version number: " + version + "; plugin name: " + name); } buildNumber = parseBuildNumber(version, code, name); @@ -123,29 +124,34 @@ public class BuildNumber implements Comparable { } private static int parseBuildNumber(String version, String code, String name) { - if ("SNAPSHOT".equals(code) || BUILD_NUMBER.equals(code)) { + if (SNAPSHOT.equals(code) || BUILD_NUMBER.equals(code)) { return Integer.MAX_VALUE; } try { return Integer.parseInt(code); } catch (NumberFormatException e) { - throw new RuntimeException("Unparseable version number: " + version +"; plugin name: " + name); + throw new RuntimeException("Invalid version number: " + version + "; plugin name: " + name); } } - public static BuildNumber fromFile() { - String text = "999.SNAPSHOT"; + private static BuildNumber fromFile() { try { final String homePath = PathManager.getHomePath(); final File buildTxtFile = FileUtil.findFirstThatExist(homePath + "/build.txt", homePath + "/community/build.txt"); if (buildTxtFile != null) { - text = FileUtil.loadFile(buildTxtFile).trim(); + String text = FileUtil.loadFile(buildTxtFile).trim(); + return fromString(text); } } - catch (IOException ignored) { } + catch (IOException ignored) { + } - return fromString(text); + return fallback(); + } + + public static BuildNumber fallback() { + return fromString(FALLBACK_VERSION); } @Override @@ -197,6 +203,7 @@ public class BuildNumber implements Comparable { if (bn == Integer.MAX_VALUE) { return TOP_BASELINE_VERSION; // SNAPSHOTS } + if (bn >= 10000) { return 88; // Maia, 9x builds } diff --git a/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java index ed5a3a0b16bd..445bb4180d04 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/BuildNumberTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -13,20 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.openapi.util; -import junit.framework.TestCase; +import org.junit.Test; -public class BuildNumberTest extends TestCase { - public void testHistoricBuild() { +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author max + */ +public class BuildNumberTest { + @Test + public void historicBuild() { assertEquals(new BuildNumber("", 75, 7512), BuildNumber.fromString("7512")); } - - public void testSnapshotDominates() { + + @Test + public void snapshotDomination() { assertTrue(BuildNumber.fromString("90.SNAPSHOT").compareTo(BuildNumber.fromString("90.12345")) > 0); assertTrue(BuildNumber.fromString("IU-90.SNAPSHOT").compareTo(BuildNumber.fromString("RM-90.12345")) > 0); }