mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-21 21:52:10 +02:00
Bug 573712: Reduce work done at Eclipse startup time on main thread
In Bug 466650, the git bash detector was removed from startup to reduce overhead on startup. Later during a rewrite it was added back in under a different code path for Bug 473107. In the context of Bug 573712 which is going to add more detectors that may do much more work on a full load, reduce the amount of work needed to do the presence check. Change-Id: If1ae3f12ec51b1edc2d419f0efd89fed81a7b56e
This commit is contained in:
parent
a7fab87648
commit
a4963b35ad
4 changed files with 83 additions and 29 deletions
|
@ -12,7 +12,6 @@
|
|||
package org.eclipse.tm.terminal.view.ui.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.tm.terminal.view.ui.local.showin.ExternalExecutablesManager;
|
||||
|
@ -27,8 +26,7 @@ public class ExternalExecutablesState extends AbstractSourceProvider {
|
|||
private boolean enabled;
|
||||
|
||||
public ExternalExecutablesState() {
|
||||
List<Map<String, String>> externals = ExternalExecutablesManager.load();
|
||||
this.enabled = (externals != null && !externals.isEmpty());
|
||||
this.enabled = ExternalExecutablesManager.hasEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -41,6 +41,37 @@ public class ExternalExecutablesManager {
|
|||
// XXX: This may make a useful extension point?
|
||||
private static List<IDetectExternalExecutable> detectors = List.of(new DetectGitBash());
|
||||
|
||||
public static boolean hasEntries() {
|
||||
IPath stateLocation = UIPlugin.getDefault().getStateLocation();
|
||||
if (stateLocation != null) {
|
||||
File f = stateLocation.append(".executables/data.properties").toFile(); //$NON-NLS-1$
|
||||
if (f.canRead()) {
|
||||
|
||||
try (FileReader r = new FileReader(f)) {
|
||||
Properties data = new Properties();
|
||||
data.load(r);
|
||||
if (!data.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (Platform.inDebugMode()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There are not any saved entries - run the detectors and if any of them
|
||||
// have entries, then we can stop.
|
||||
for (IDetectExternalExecutable iDetectExternalExecutable : detectors) {
|
||||
if (iDetectExternalExecutable.hasEntries()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the list of all saved external executables.
|
||||
*
|
||||
|
@ -111,7 +142,7 @@ public class ExternalExecutablesManager {
|
|||
}
|
||||
|
||||
var readOnly = Collections.unmodifiableList(externalExecutables);
|
||||
var detected = detectors.stream().flatMap(detector -> detector.run(readOnly).stream())
|
||||
var detected = detectors.stream().flatMap(detector -> detector.getEntries(readOnly).stream())
|
||||
.collect(Collectors.toList());
|
||||
if (!detected.isEmpty()) {
|
||||
externalExecutables.addAll(detected);
|
||||
|
|
|
@ -15,8 +15,13 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.tm.terminal.view.ui.interfaces.IExternalExecutablesProperties;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IDetectExternalExecutable {
|
||||
/**
|
||||
* Detect if {@link #getEntries(List)} will return a non-empty list of entries, assuming externalEntries is an empty
|
||||
* list. This method is used during critical UI times (such as startup) and should be very fast.
|
||||
*/
|
||||
boolean hasEntries();
|
||||
|
||||
/**
|
||||
* Detect any additional external executables that can be added to the Show In list.
|
||||
*
|
||||
|
@ -31,5 +36,6 @@ public interface IDetectExternalExecutable {
|
|||
* that match {@link IExternalExecutablesProperties}. Must not return <code>null</code>, return
|
||||
* an empty list instead.
|
||||
*/
|
||||
List<Map<String, String>> run(List<Map<String, String>> externalExecutables);
|
||||
List<Map<String, String>> getEntries(List<Map<String, String>> externalExecutables);
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,20 @@ public class DetectGitBash implements IDetectExternalExecutable {
|
|||
private static boolean gitBashSearchDone = false;
|
||||
|
||||
@Override
|
||||
public List<Map<String, String>> run(List<Map<String, String>> externalExecutables) {
|
||||
public boolean hasEntries() {
|
||||
if (Platform.OS_WIN32.equals(Platform.getOS())) {
|
||||
// the order of operations here is different than getEntries because we just
|
||||
// want to know if anything can match. We avoid iterating over the whole PATH
|
||||
// if the user has git installed in the default location. This gets us the
|
||||
// correct answer to hasEntries quickly without having to iterate over the whole
|
||||
// PATH (especially if PATH is long!).
|
||||
return getGitInstallDirectory().or(this::getGitInstallDirectoryFromPATH).isPresent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, String>> getEntries(List<Map<String, String>> externalExecutables) {
|
||||
// Lookup git bash (Windows Hosts only)
|
||||
if (!gitBashSearchDone && Platform.OS_WIN32.equals(Platform.getOS())) {
|
||||
// Do not search again for git bash while the session is running
|
||||
|
@ -42,29 +55,9 @@ public class DetectGitBash implements IDetectExternalExecutable {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// If not found in the existing entries, check the path
|
||||
Optional<File> result = ExternalExecutablesUtils.visitPATH(entry -> {
|
||||
File f = new File(entry, "git.exe"); //$NON-NLS-1$
|
||||
if (f.canRead()) {
|
||||
File check = f.getParentFile().getParentFile();
|
||||
if (new File(check, "bin/sh.exe").canExecute()) { //$NON-NLS-1$
|
||||
return Optional.of(check);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
});
|
||||
// If not found in the existing entries, check the path, then
|
||||
// if it is not found in the PATH, check the default install locations
|
||||
result = result.or(() -> {
|
||||
File f = new File("C:/Program Files (x86)/Git/bin/sh.exe"); //$NON-NLS-1$
|
||||
if (!f.exists()) {
|
||||
f = new File("C:/Program Files/Git/bin/sh.exe"); //$NON-NLS-1$
|
||||
}
|
||||
if (f.exists() && f.canExecute()) {
|
||||
return Optional.of(f.getParentFile().getParentFile());
|
||||
}
|
||||
return Optional.empty();
|
||||
});
|
||||
|
||||
Optional<File> result = getGitInstallDirectoryFromPATH().or(this::getGitInstallDirectory);
|
||||
Optional<String> gitPath = result.map(f -> new File(f, "bin/sh.exe").getAbsolutePath()); //$NON-NLS-1$
|
||||
Optional<String> iconPath = result.flatMap(f -> getGitIconPath(f));
|
||||
|
||||
|
@ -81,7 +74,33 @@ public class DetectGitBash implements IDetectExternalExecutable {
|
|||
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Optional<File> getGitInstallDirectoryFromPATH() {
|
||||
return ExternalExecutablesUtils.visitPATH(entry -> {
|
||||
File f = new File(entry, "git.exe"); //$NON-NLS-1$
|
||||
if (f.canRead()) {
|
||||
File check = f.getParentFile().getParentFile();
|
||||
if (new File(check, "bin/sh.exe").canExecute()) { //$NON-NLS-1$
|
||||
return Optional.of(check);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<File> getGitInstallDirectory() {
|
||||
// If 32-bit and 64-bit are both present, prefer the 64-bit one
|
||||
// as it is probably newer and more likely to be present
|
||||
// for the fast check required by hasEntries
|
||||
File f = new File("C:/Program Files/Git/bin/sh.exe"); //$NON-NLS-1$
|
||||
if (!f.exists()) {
|
||||
f = new File("C:/Program Files (x86)/Git/bin/sh.exe"); //$NON-NLS-1$
|
||||
}
|
||||
if (f.exists() && f.canExecute()) {
|
||||
return Optional.of(f.getParentFile().getParentFile());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<String> getGitIconPath(File parent) {
|
||||
|
|
Loading…
Add table
Reference in a new issue