From dc01366f97a94046176447c2b7be076d72e1d3b0 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Tue, 13 Mar 2012 13:25:14 -0400 Subject: [PATCH] bug 364733: Internal Builder does not work with Cygwin toolchain --- .../internal/buildmodel/CommandBuilder.java | 113 +++------------ .../tests/ErrorParserFileMatchingTest.java | 77 +++++----- .../cdt/core/testplugin/ResourceHelper.java | 39 +---- .../eclipse/cdt/core/ErrorParserManager.java | 11 +- .../cdt/core/errorparsers/ErrorPattern.java | 43 +++--- .../core/errorparsers/RegexErrorPattern.java | 10 +- .../org/eclipse/cdt/internal/core/Cygwin.java | 136 ++++++++++++++++++ .../utils/org/eclipse/cdt/utils/CygPath.java | 11 +- .../utils/org/eclipse/cdt/utils/PathUtil.java | 34 ++--- 9 files changed, 244 insertions(+), 230 deletions(-) create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java index 356f69259a5..b0a23fdb090 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/CommandBuilder.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.buildmodel; -import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -21,12 +20,14 @@ import java.util.Set; import org.eclipse.cdt.core.CommandLauncher; import org.eclipse.cdt.core.ICommandLauncher; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; import org.eclipse.cdt.utils.PathUtil; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; /** @@ -41,56 +42,28 @@ import org.eclipse.core.runtime.SubProgressMonitor; */ public class CommandBuilder implements IBuildModelBuilder { private static final String PATH_ENV = "PATH"; //$NON-NLS-1$ - private static final String PROPERTY_DELIMITER = "path.separator"; //$NON-NLS-1$ - private static final String PROPERTY_OS_NAME = "os.name"; //$NON-NLS-1$ - private static final String PROPERTY_OS_VALUE = "windows";//$NON-NLS-1$ - static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$ - static final String DELIMITER_WINDOWS = ";"; //$NON-NLS-1$ + private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ private IBuildCommand fCmd; private Process fProcess; private String fErrMsg; - private static final String BUILDER_MSG_HEADER = "InternalBuilder.msg.header"; //$NON-NLS-1$ - private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - -/* - * no need in this for now, Spawner is always used - * - protected class SpawnerfreeLauncher extends CommandLauncher{ - - public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) { - try { - // add platform specific arguments (shell invocation) - fCommandArgs = constructCommandArray(commandPath.toOSString(), args); - fProcess = Runtime.getRuntime().exec(fCommandArgs, env, changeToDirectory.toFile()); -// ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile()); - fErrorMessage = ""; //$NON-NLS-1$ - } catch (IOException e) { - setErrorMessage(e.getMessage()); - fProcess = null; - } - return fProcess; - } - } -*/ - /* - * a temporary work-around to resolve the bug#145099 - * (https://bugs.eclipse.org/bugs/show_bug.cgi?id=145099) - * - * this will be removed after fixing the bug#145737 - * (https://bugs.eclipse.org/bugs/show_bug.cgi?id=145737) - */ - private class CommandSearchLauncher extends CommandLauncher{ - + private class CommandSearchLauncher extends CommandLauncher { @Override protected String[] constructCommandArray(String command, String[] commandArgs) { String[] args = new String[1 + commandArgs.length]; - if(!isWindows()){ - //find a full path to an executable - String cmd = getExecutable(command, fCmd.getEnvironment()); - if(cmd != null) - command = cmd; + if (Platform.getOS().equals(Platform.OS_WIN32)) { + // find a location of the executable + String envPathValue = fCmd.getEnvironment().get(PATH_ENV); + IPath location = PathUtil.findProgramLocation(command, envPathValue); + if(location != null) { + try { + // Handle cygwin link + command = Cygwin.cygwinToWindowsPath(location.toString(), envPathValue); + } catch (Exception e) { + command = location.toString(); + } + } //if not found, continue with the command passed as an argument } @@ -99,7 +72,6 @@ public class CommandBuilder implements IBuildModelBuilder { return args; } - @Override protected void printCommandLine(OutputStream os) { if (os != null) { @@ -274,7 +246,7 @@ public class CommandBuilder implements IBuildModelBuilder { protected void printMessage(String msg, OutputStream os){ if (os != null) { - msg = ManagedMakeMessages.getFormattedString(BUILDER_MSG_HEADER, msg); + msg = ManagedMakeMessages.getFormattedString("InternalBuilder.msg.header", msg); //$NON-NLS-1$ printMessage(null, msg, os); } @@ -305,53 +277,4 @@ public class CommandBuilder implements IBuildModelBuilder { } return buf.toString(); } - - private String getExecutable(String command, Map environment){ - if(new Path(command).isAbsolute()) - return command; - return searchExecutable(command, getPaths(environment)); - } - - private String[] getPaths(Map env){ - String pathsStr = env.get(PATH_ENV); - if(pathsStr == null){ - Set> entrySet = env.entrySet(); - for (Entry entry : entrySet) { - if(PATH_ENV.equalsIgnoreCase(entry.getKey())){ - pathsStr = entry.getValue(); - break; - } - } - } - if(pathsStr != null){ - String delimiter = getDelimiter(); - - return pathsStr.split(delimiter); - } - return null; - } - - private String getDelimiter(){ - String delimiter = System.getProperty(PROPERTY_DELIMITER); - if(delimiter == null) - delimiter = isWindows() ? DELIMITER_WINDOWS : DELIMITER_UNIX; - return delimiter; - } - - private String searchExecutable(String command, String paths[]){ - if(paths == null) - return null; - - for(int i = 0; i < paths.length; i++){ - File file = new File(paths[i], command.toString()); - if(file.isFile()) - return file.toString(); - } - return null; - } - - private boolean isWindows() { - String prop = System.getProperty(PROPERTY_OS_NAME); - return prop != null ? prop.toLowerCase().startsWith(PROPERTY_OS_VALUE) : false; - } } diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserFileMatchingTest.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserFileMatchingTest.java index 617eea5d12e..0f7b4c86998 100644 --- a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserFileMatchingTest.java +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserFileMatchingTest.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.errorparsers.AbstractErrorParser; import org.eclipse.cdt.core.errorparsers.ErrorPattern; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.ResourceHelper; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.core.internal.registry.ExtensionRegistry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -903,7 +904,7 @@ public class ErrorParserFileMatchingTest extends TestCase { String windowsFileName = fProject.getLocation().append(fileName).toOSString(); String cygwinFileName; try { - cygwinFileName = ResourceHelper.windowsToCygwinPath(windowsFileName); + cygwinFileName = Cygwin.windowsToCygwinPath(windowsFileName); } catch (UnsupportedOperationException e) { // Skip the test if Cygwin is not available. return; @@ -931,7 +932,7 @@ public class ErrorParserFileMatchingTest extends TestCase { String usrIncludeWindowsPath; try { - usrIncludeWindowsPath = ResourceHelper.cygwinToWindowsPath(cygwinFolder); + usrIncludeWindowsPath = Cygwin.cygwinToWindowsPath(cygwinFolder); } catch (UnsupportedOperationException e) { // Skip the test if Cygwin is not available. return; @@ -961,7 +962,7 @@ public class ErrorParserFileMatchingTest extends TestCase { String windowsFileName = anotherProject.getLocation().append(fileName).toOSString(); String cygwinFileName; try { - cygwinFileName = ResourceHelper.windowsToCygwinPath(windowsFileName); + cygwinFileName = Cygwin.windowsToCygwinPath(windowsFileName); } catch (UnsupportedOperationException e) { // Skip the test if Cygwin is not available. return; @@ -1010,7 +1011,7 @@ public class ErrorParserFileMatchingTest extends TestCase { String windowsFileName = fProject.getLocation().append(fileName).toOSString(); String cygwinFileName; try { - cygwinFileName = ResourceHelper.windowsToCygwinPath(windowsFileName); + cygwinFileName = Cygwin.windowsToCygwinPath(windowsFileName); } catch (UnsupportedOperationException e) { // Skip the test if Cygwin is not available. return; @@ -1021,7 +1022,7 @@ public class ErrorParserFileMatchingTest extends TestCase { String lines = "make[0]: Entering directory `dir'\n" + cygwinFileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); @@ -1273,21 +1274,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make -j2\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1298,21 +1299,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make -j 2\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1323,21 +1324,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make -j1\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/Folder/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1348,21 +1349,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make -j 1\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/Folder/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1373,21 +1374,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make --jobs=2\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1398,21 +1399,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "make --jobs=1\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/Folder/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1423,21 +1424,21 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFile(fProject, fileName); ResourceHelper.createFile(fProject, "Folder/"+fileName); - + String lines = "gmake384 -k -j all\n" + "make[0]: Entering directory `Folder'\n" + fileName+":1:error\n"; - + String[] errorParsers = {CWD_LOCATOR_ID, mockErrorParserId }; parseOutput(fProject, fProject.getLocation(), errorParsers, lines); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/"+fileName,problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * @@ -1447,10 +1448,10 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(fProject, "Folder"); ResourceHelper.createFolder(fProject, "Folder/AbsoluteRemoteFolder"); IFile file = ResourceHelper.createFile(fProject, "Folder/AbsoluteRemoteFolder/testMappedRemoteAbsolutePath.h"); - + parseOutput("/AbsoluteRemoteFolder/testMappedRemoteAbsolutePath.h:1:error"); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/FindMatchingFilesTest/Folder/AbsoluteRemoteFolder/testMappedRemoteAbsolutePath.h",problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); @@ -1469,16 +1470,16 @@ public class ErrorParserFileMatchingTest extends TestCase { ResourceHelper.createFolder(anotherProject, "Folder"); ResourceHelper.createFolder(anotherProject, "Folder/AbsoluteRemoteFolder"); IFile file = ResourceHelper.createFile(anotherProject, "Folder/AbsoluteRemoteFolder/testMappedRemoteAbsolutePathAnotherProject.h"); - + parseOutput("/AbsoluteRemoteFolder/testMappedRemoteAbsolutePathAnotherProject.h:1:error"); assertEquals(1, errorList.size()); - + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); assertEquals("L/ProjectMappedRemoteAbsolutePathAnotherProject/Folder/AbsoluteRemoteFolder/testMappedRemoteAbsolutePathAnotherProject.h",problemMarkerInfo.file.toString()); assertEquals(1,problemMarkerInfo.lineNumber); assertEquals("error",problemMarkerInfo.description); } - + /** * Checks if a file from error output can be found. * diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/ResourceHelper.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/ResourceHelper.java index 4b4e7361183..696dae3fbf2 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/ResourceHelper.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/ResourceHelper.java @@ -35,6 +35,7 @@ import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager; import org.eclipse.cdt.core.settings.model.TestCfgDataProvider; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -629,24 +630,7 @@ public class ResourceHelper { * @throws IOException on IO problem. */ public static String windowsToCygwinPath(String windowsPath) throws IOException, UnsupportedOperationException { - if (!Platform.getOS().equals(Platform.OS_WIN32)) { - // Don't run this on non-windows platforms - throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); - } - String[] args = {"cygpath", "-u", windowsPath}; - Process cygpath; - try { - cygpath = Runtime.getRuntime().exec(args); - } catch (IOException ioe) { - throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); - } - BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream())); - - String cygwinPath = stdout.readLine(); - if (cygwinPath == null) { - throw new UnsupportedOperationException("Cygwin utility cygpath is not available."); - } - return cygwinPath.trim(); + return Cygwin.windowsToCygwinPath(windowsPath); } /** @@ -658,24 +642,7 @@ public class ResourceHelper { * @throws IOException on IO problem. */ public static String cygwinToWindowsPath(String cygwinPath) throws IOException, UnsupportedOperationException { - if (!Platform.getOS().equals(Platform.OS_WIN32)) { - // Don't run this on non-windows platforms - throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); - } - String[] args = {"cygpath", "-w", cygwinPath}; - Process cygpath; - try { - cygpath = Runtime.getRuntime().exec(args); - } catch (IOException ioe) { - throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); - } - BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream())); - - String windowsPath = stdout.readLine(); - if (windowsPath == null) { - throw new UnsupportedOperationException("Cygwin utility cygpath is not available."); - } - return windowsPath.trim(); + return Cygwin.cygwinToWindowsPath(cygwinPath); } /** diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java index 65ea2af5837..8b9c0b320b8 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java @@ -25,10 +25,10 @@ import java.util.Vector; import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper; import org.eclipse.cdt.core.resources.ACBuilder; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.cdt.internal.core.IErrorMarkeredOutputStream; import org.eclipse.cdt.internal.core.resources.ResourceLookup; import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager; -import org.eclipse.cdt.utils.CygPath; import org.eclipse.cdt.utils.EFSExtensionManager; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -524,20 +524,13 @@ outer: private IFile findCygwinFile(String filePath) { IFile file=null; - IPath path; - CygPath cygpath = null; try { - cygpath = new CygPath(); - path = new Path(cygpath.getFileName(filePath)); + IPath path = new Path(Cygwin.cygwinToWindowsPath(filePath)); file = findFileInWorkspace(path); } catch (UnsupportedOperationException e) { isCygwin = false; } catch (Exception e) { } - finally { - if (cygpath != null) - cygpath.dispose(); - } return file; } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorPattern.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorPattern.java index e3cadd916d4..d9a81e6b387 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorPattern.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorPattern.java @@ -18,7 +18,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.IMarkerGenerator; -import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -26,7 +26,7 @@ import org.eclipse.core.runtime.Path; /** * Error Pattern - used by Error Parser to convert build output to problem markers * @since 5.1 - * + * * Clients may extend this class. */ public class ErrorPattern { @@ -67,7 +67,7 @@ public class ErrorPattern { this.groupVarName = groupVarName; this.severity = severity; } - + /** * Pattern for errors not associated file a file * (e.g. make and linker errors). @@ -86,7 +86,7 @@ public class ErrorPattern { /** * Pattern for errors that should be skipped. - * + * * @param pattern - error pattern. */ public ErrorPattern(String pattern) { @@ -100,7 +100,7 @@ public class ErrorPattern { public Matcher getMatcher(CharSequence input) { return pattern.matcher(input); } - + /** * @param matcher - matcher to parse the input line. * @return parsed file name or {@code null}. @@ -108,7 +108,7 @@ public class ErrorPattern { public String getFileName(Matcher matcher) { return groupFileName != 0 ? matcher.group(groupFileName) : null; } - + /** * @param matcher - matcher to parse the input line. * @return parsed line number or {@code 0}. @@ -122,7 +122,7 @@ public class ErrorPattern { return 0; } } - + /** * @param matcher - matcher to parse the input line. * @return parsed description or {@code null}. @@ -130,7 +130,7 @@ public class ErrorPattern { public String getDesc(Matcher matcher) { return groupDesc != 0 ? matcher.group(groupDesc) : null; } - + /** * @param matcher - matcher to parse the input line. * @return parsed variable name or {@code null}. @@ -138,7 +138,7 @@ public class ErrorPattern { public String getVarName(Matcher matcher) { return groupVarName != 0 ? matcher.group(groupVarName) : null; } - + /** * @param matcher - matcher to parse the input line. * @return severity of the problem. @@ -146,11 +146,11 @@ public class ErrorPattern { public int getSeverity(Matcher matcher) { return severity; } - + /** * Parse a line of build output and register error/warning for * Problems view. - * + * * @param line - one line of output. * @param eoParser - {@link ErrorParserManager}. * @return {@code true} if error/warning/info problem was found. @@ -162,10 +162,10 @@ public class ErrorPattern { return recordError(matcher, eoParser); } - + /** * Register the error in {@link ErrorParserManager}. - * + * * @param matcher - matcher to parse the input line. * @param eoParser - {@link ErrorParserManager}. * @return {@code true} indicating that error was found. @@ -181,7 +181,7 @@ public class ErrorPattern { String desc = getDesc(matcher); String varName = getVarName(matcher); IPath externalPath = null ; - + IResource file = null; if (fileName != null) { file = eoParser.findFileName(fileName); @@ -193,15 +193,15 @@ public class ErrorPattern { externalPath = getLocation(fileName); } } - + eoParser.generateExternalMarker(file, lineNum, desc, severity, varName, externalPath); return true; } - + /** * If the file designated by filename exists, return the IPath representation of the filename * If it does not exist, try cygpath translation - * + * * @param filename - file name * @return location (outside of the workspace). */ @@ -209,10 +209,8 @@ public class ErrorPattern { IPath path = new Path(filename); File file = path.toFile() ; if (!file.exists() && isCygwin && path.isAbsolute()) { - CygPath cygpath = null ; try { - cygpath = new CygPath("cygpath"); //$NON-NLS-1$ - String cygfilename = cygpath.getFileName(filename); + String cygfilename = Cygwin.cygwinToWindowsPath(filename); IPath convertedPath = new Path(cygfilename); file = convertedPath.toFile() ; if (file.exists()) { @@ -222,11 +220,6 @@ public class ErrorPattern { isCygwin = false; } catch (IOException e) { } - finally { - if (null!=cygpath) { - cygpath.dispose(); - } - } } return path ; } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java index a211cbe2166..5683e49411f 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java @@ -18,7 +18,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.IMarkerGenerator; -import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -330,10 +330,8 @@ public class RegexErrorPattern implements Cloneable { IPath path = new Path(filename); File file = path.toFile() ; if (!file.exists() && isCygwin && path.isAbsolute()) { - CygPath cygpath = null ; try { - cygpath = new CygPath("cygpath"); //$NON-NLS-1$ - String cygfilename = cygpath.getFileName(filename); + String cygfilename = Cygwin.cygwinToWindowsPath(filename); IPath convertedPath = new Path(cygfilename); file = convertedPath.toFile() ; if (file.exists()) { @@ -342,10 +340,6 @@ public class RegexErrorPattern implements Cloneable { } catch (UnsupportedOperationException e) { isCygwin = false; } catch (IOException e) { - } finally { - if (null!=cygpath) { - cygpath.dispose(); - } } } return path ; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java new file mode 100644 index 00000000000..00c9abe7650 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2012, 2012 Andrew Gvozdev and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.eclipse.cdt.utils.PathUtil; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; + +/** + * A collection of cygwin-related utilities. + */ +public class Cygwin { + + private static IPath findCygpathLocation(String envPath) { + return PathUtil.findProgramLocation("cygpath", envPath); //$NON-NLS-1$ + } + + /** + * Check if cygwin path conversion utilities are available in the path. + * + * @param envPath - list of directories to search for cygwin utilities separated + * by path separator (format of environment variable $PATH). + * @return {@code true} if cygwin is available, {@code false} otherwise. + */ + public static boolean isAvailable(String envPath) { + return Platform.getOS().equals(Platform.OS_WIN32) && findCygpathLocation(envPath) != null; + } + + /** + * Conversion from Cygwin path to Windows path. + * + * @param cygwinPath - Cygwin path. + * @param envPath - list of directories to search for cygwin utilities separated + * by path separator (format of environment variable $PATH). + * @return Windows style converted path. Note that that also converts cygwin links to their targets. + * + * @throws UnsupportedOperationException if Cygwin is unavailable. + * @throws IOException on IO problem. + */ + public static String cygwinToWindowsPath(String cygwinPath, String envPath) throws IOException, UnsupportedOperationException { + if (cygwinPath == null || cygwinPath.trim().length() == 0) + return cygwinPath; + + if (!Platform.getOS().equals(Platform.OS_WIN32)) { + // Don't run this on non-windows platforms + throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); //$NON-NLS-1$ + } + + IPath cygpathLocation = findCygpathLocation(envPath); + if (cygpathLocation == null) { + throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); //$NON-NLS-1$ + } + + String[] args = {cygpathLocation.toOSString(), "-w", cygwinPath}; //$NON-NLS-1$ + Process cygpathProcess = Runtime.getRuntime().exec(args); + BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpathProcess.getInputStream())); + + String windowsPath = stdout.readLine(); + if (windowsPath == null) { + throw new IOException("Unexpected output from Cygwin utility cygpath."); //$NON-NLS-1$ + } + return windowsPath.trim(); + } + + /** + * Conversion from Cygwin path to Windows path. + * + * @param cygwinPath - Cygwin path. + * @return Windows style converted path. Note that that also converts cygwin links to their targets. + * + * @throws UnsupportedOperationException if Cygwin is unavailable. + * @throws IOException on IO problem. + */ + public static String cygwinToWindowsPath(String cygwinPath) throws IOException, UnsupportedOperationException { + return cygwinToWindowsPath(cygwinPath, null); + } + + /** + * Conversion from Windows path to Cygwin path. + * + * @param windowsPath - Windows path. + * @param envPath - list of directories to search for cygwin utilities (value of environment variable $PATH). + * @return Cygwin style converted path. + * + * @throws UnsupportedOperationException if Cygwin is unavailable. + * @throws IOException on IO problem. + */ + public static String windowsToCygwinPath(String windowsPath, String envPath) throws IOException, UnsupportedOperationException { + if (windowsPath == null || windowsPath.trim().length() == 0) + return windowsPath; + + if (!Platform.getOS().equals(Platform.OS_WIN32)) { + // Don't run this on non-windows platforms + throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); //$NON-NLS-1$ + } + IPath cygpathLocation = findCygpathLocation(envPath); + if (cygpathLocation == null) { + throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); //$NON-NLS-1$ + } + + String[] args = {cygpathLocation.toOSString(), "-u", windowsPath}; //$NON-NLS-1$ + Process cygpath = Runtime.getRuntime().exec(args); + BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream())); + + String cygwinPath = stdout.readLine(); + if (cygwinPath == null) { + throw new IOException("Unexpected output from Cygwin utility cygpath."); //$NON-NLS-1$ + } + return cygwinPath.trim(); + } + + /** + * Conversion from Windows path to Cygwin path. + * + * @param windowsPath - Windows path. + * @return Cygwin style converted path. + * + * @throws UnsupportedOperationException if Cygwin is unavailable. + * @throws IOException on IO problem. + */ + public static String windowsToCygwinPath(String windowsPath) throws IOException, UnsupportedOperationException { + return windowsToCygwinPath(windowsPath, null); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CygPath.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CygPath.java index bb7d3a5d09e..1ab1456b241 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CygPath.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/CygPath.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import org.eclipse.cdt.internal.core.Cygwin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; @@ -41,7 +42,7 @@ public class CygPath { stdin = new BufferedWriter(new OutputStreamWriter(cygpath.getOutputStream())); stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream())); try { - String test= getFileName("a b"); //$NON-NLS-1$ + String test= getFileName("a b"); //$NON-NLS-1$ if ("a".equals(test)) { //$NON-NLS-1$ // Bug 298615: This version seems to treat space as a separator fSpaceIsSeparator= true; @@ -59,11 +60,15 @@ public class CygPath { this("cygpath"); //$NON-NLS-1$ } + /** + * Use this method for series of translations of paths. + * If a single path needs to be translated consider {@link Cygwin#cygwinToWindowsPath(String)}. + */ public String getFileName(String name) throws IOException { // bug 214603, empty names don't create a response - if (name == null || name.length() == 0) + if (name == null || name.length() == 0) return name; - + if (useOldCygPath) { return internalgetFileName(name); } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/PathUtil.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/PathUtil.java index ad25e1106c6..4d7def4d165 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/PathUtil.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/PathUtil.java @@ -58,7 +58,7 @@ public class PathUtil { public static IPath getCanonicalPath(IPath fullPath) { if (!fullPath.isAbsolute()) return fullPath; - + File file = fullPath.toFile(); try { String canonPath = file.getCanonicalPath(); @@ -97,7 +97,7 @@ public class PathUtil { } return fullPath; } - + public static IPath getProjectRelativePath(IPath fullPath, IProject project) { IPath projectPath = project.getFullPath(); if (isPrefix(projectPath, fullPath)) { @@ -149,7 +149,7 @@ public class PathUtil { } return null; } - + public static IPath makeRelativePathToIncludes(IPath fullPath, String[] includePaths) { IPath relativePath = null; int mostSegments = 0; @@ -180,7 +180,7 @@ public class PathUtil { } return null; } - + public static IPath getValidEnclosingFolder(IPath fullPath) { IWorkspaceRoot root = getWorkspaceRoot(); if (root != null) { @@ -199,7 +199,7 @@ public class PathUtil { /** * Checks whether path1 is the same as path2. * @return true if path1 is the same as path2, and false otherwise - * + * * Similar to IPath.equals(Object obj), but takes case sensitivity of the file system * into account. * @since 5.1 @@ -231,7 +231,7 @@ public class PathUtil { /** * Checks whether path1 is the same as path2. * @return true if path1 is the same as path2, and false otherwise - * + * * Similar to IPath.equals(Object obj), but takes case sensitivity of the file system * into account. * @since 5.3 @@ -266,13 +266,13 @@ public class PathUtil { * Checks whether path1 is a prefix of path2. To be a prefix, path1's segments * must appear in path1 in the same order, and their device ids must match. *

- * An empty path is a prefix of all paths with the same device; a root path is a prefix of + * An empty path is a prefix of all paths with the same device; a root path is a prefix of * all absolute paths with the same device. *

* @return true if path1 is a prefix of path2, and false otherwise - * + * * Similar to IPath.isPrefixOf(IPath anotherPath), but takes case sensitivity of the file system - * into account. + * into account. * @since 5.1 */ public static boolean isPrefix(IPath path1, IPath path2) { @@ -334,22 +334,23 @@ public class PathUtil { /** * Find location of the program inspecting each path in the path list. - * + * * @param prog - program to find. For Windows, extensions "com" and "exe" * can be omitted. * @param pathsStr - the list of paths to inspect separated by path separator * defined in the platform (i.e. ":" in Unix and ";" in Windows). * In case pathStr is {@code null} environment variable ${PATH} is inspected. - * @return - absolute location of the file on the file system. + * @return - absolute location of the file on the file system + * or {@code null} if not found. * @since 5.3 */ public static IPath findProgramLocation(String prog, String pathsStr) { if (prog==null || prog.trim().length()==0) return null; - + if (pathsStr==null) pathsStr = System.getenv("PATH"); //$NON-NLS-1$ - + if (pathsStr.trim().length()==0) return null; @@ -381,7 +382,7 @@ public class PathUtil { for (String dir : dirs) { IPath dirLocation = new Path(dir); File file = null; - + file = dirLocation.append(prog).toFile(); if (file.isFile() && file.canRead()) { locationStr = file.getAbsolutePath(); @@ -399,10 +400,11 @@ public class PathUtil { /** * Find location of the program inspecting each path in the path list * defined by environment variable ${PATH}. - * + * * @param prog - program to find. For Windows, extensions "com" and "exe" * can be omitted. - * @return - absolute location of the file on the file system. + * @return - absolute location of the file on the file system + * or {@code null} if not found. * @since 5.3 */ public static IPath findProgramLocation(String prog) {