mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 579944: Clean up Docker include path code
This patch refactors multiple aspects of the code related to copying include paths from docker images: * document code * extract common code to methods * reduce indentation by returning early * support using \\WSL$\... paths Change-Id: I983d1e9bdfa84aa48928f5ba88df191d56ac0f17 Signed-off-by: Moritz 'Morty' Strübe <moritz.struebe@mathema.de>
This commit is contained in:
parent
9a2558bd66
commit
02d2c81ec9
6 changed files with 344 additions and 309 deletions
|
@ -1,3 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2022 Red Hat Inc. and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
* Mathema - Refactor
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.docker.launcher;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -9,6 +23,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.cdt.core.ICommandLauncher;
|
||||
import org.eclipse.cdt.core.build.ICBuildCommandLauncher;
|
||||
|
@ -17,6 +32,7 @@ import org.eclipse.cdt.core.build.IToolChain;
|
|||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
||||
import org.eclipse.cdt.internal.core.ProcessClosure;
|
||||
import org.eclipse.cdt.internal.docker.launcher.ContainerLaunchUtils;
|
||||
import org.eclipse.cdt.internal.docker.launcher.Messages;
|
||||
import org.eclipse.cdt.internal.docker.launcher.PreferenceConstants;
|
||||
import org.eclipse.cdt.managedbuilder.buildproperties.IOptionalBuildProperties;
|
||||
|
@ -158,23 +174,16 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
|
|||
labels.put("org.eclipse.cdt.project-name", projectName); //$NON-NLS-1$
|
||||
|
||||
List<String> additionalDirs = new ArrayList<>();
|
||||
List<IPath> additionalPaths = new ArrayList<>();
|
||||
|
||||
//
|
||||
IPath projectLocation = fProject.getLocation();
|
||||
String projectPath = projectLocation.toPortableString();
|
||||
if (projectLocation.getDevice() != null) {
|
||||
projectPath = "/" + projectPath.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
additionalDirs.add(projectPath);
|
||||
additionalPaths.add(fProject.getLocation());
|
||||
|
||||
ArrayList<String> commandSegments = new ArrayList<>();
|
||||
|
||||
List<String> cmdList = new ArrayList<>();
|
||||
|
||||
String commandString = commandPath.toPortableString();
|
||||
if (commandPath.getDevice() != null) {
|
||||
commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
String commandString = ContainerLaunchUtils.toDockerPath(commandPath);
|
||||
|
||||
cmdList.add(commandString);
|
||||
commandSegments.add(commandString);
|
||||
for (String arg : args) {
|
||||
|
@ -189,12 +198,11 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
|
|||
// and modify the argument to be unix-style
|
||||
if (f.isFile() || f.isDirectory()) {
|
||||
f = f.getParentFile();
|
||||
modifiedArg = "/" //$NON-NLS-1$
|
||||
+ p.toPortableString().replace(':', '/');
|
||||
modifiedArg = ContainerLaunchUtils.toDockerPath(p);
|
||||
p = p.removeLastSegments(1);
|
||||
}
|
||||
if (f != null && f.exists()) {
|
||||
additionalDirs.add("/" + p.toPortableString().replace(':', '/')); //$NON-NLS-1$
|
||||
additionalPaths.add(p);
|
||||
realArg = modifiedArg;
|
||||
}
|
||||
}
|
||||
|
@ -206,9 +214,10 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
|
|||
File f = p.toFile();
|
||||
if (f.isFile()) {
|
||||
f = f.getParentFile();
|
||||
p.removeLastSegments(1);
|
||||
}
|
||||
if (f != null && f.exists()) {
|
||||
additionalDirs.add(f.getAbsolutePath());
|
||||
additionalPaths.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,19 +229,15 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
|
|||
|
||||
IProject[] referencedProjects = fProject.getReferencedProjects();
|
||||
for (IProject referencedProject : referencedProjects) {
|
||||
String referencedProjectPath = referencedProject.getLocation().toPortableString();
|
||||
if (referencedProject.getLocation().getDevice() != null) {
|
||||
referencedProjectPath = "/" //$NON-NLS-1$
|
||||
+ referencedProjectPath.replace(':', '/');
|
||||
}
|
||||
additionalDirs.add(referencedProjectPath);
|
||||
IPath referencedProjectPath = referencedProject.getLocation();
|
||||
additionalPaths.add(referencedProjectPath);
|
||||
}
|
||||
|
||||
String workingDir = workingDirectory.makeAbsolute().toPortableString();
|
||||
String workingDir;
|
||||
if (workingDirectory.toPortableString().equals(".")) { //$NON-NLS-1$
|
||||
workingDir = "/tmp"; //$NON-NLS-1$
|
||||
} else if (workingDirectory.getDevice() != null) {
|
||||
workingDir = "/" + workingDir.replace(':', '/'); //$NON-NLS-1$
|
||||
} else {
|
||||
workingDir = ContainerLaunchUtils.toDockerPath(workingDirectory.makeAbsolute());
|
||||
}
|
||||
parseEnvironment(env);
|
||||
Map<String, String> origEnv = null;
|
||||
|
@ -283,6 +288,9 @@ public class ContainerCommandLauncher implements ICommandLauncher, ICBuildComman
|
|||
}
|
||||
setImageName(imageName);
|
||||
|
||||
additionalDirs.addAll(
|
||||
additionalPaths.stream().map(p -> ContainerLaunchUtils.toDockerVolume(p)).collect(Collectors.toList()));
|
||||
|
||||
fProcess = launcher.runCommand(connectionName, imageName, fProject, this, cmdList, workingDir, additionalDirs,
|
||||
origEnv, fEnvironment, supportStdin, privilegedMode, labels, keepContainer);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Red Hat Inc. and others.
|
||||
* Copyright (c) 2017, 2022 Red Hat Inc. and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
|
@ -10,16 +10,14 @@
|
|||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
* Mathema - Refactor
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.docker.launcher;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.cdt.core.ICommandLauncher;
|
||||
import org.eclipse.cdt.core.ICommandLauncherFactory;
|
||||
|
@ -50,15 +48,121 @@ import org.eclipse.linuxtools.docker.ui.launch.ContainerLauncher;
|
|||
@SuppressWarnings("restriction")
|
||||
public class ContainerCommandLauncherFactory implements ICommandLauncherFactory, ICommandLauncherFactory2 {
|
||||
|
||||
private IProject project;
|
||||
private IProject m_project;
|
||||
|
||||
/**
|
||||
* Helper-Struct
|
||||
*/
|
||||
private class ImageConnection {
|
||||
final String connectionName;
|
||||
final String imageName;
|
||||
|
||||
public ImageConnection(String connectionName, String imageName) {
|
||||
this.connectionName = connectionName;
|
||||
this.imageName = imageName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out paths that should not be copied from the container
|
||||
* @param dirs A List of paths that should be filtered
|
||||
* @return The filtered list
|
||||
*/
|
||||
private List<String> filterOutLocalPaths(List<String> dirs) {
|
||||
String prj = m_project.getLocation().toString();
|
||||
return dirs.stream().filter(x -> !(x.startsWith(prj) || x.startsWith("/${ProjName}")) //$NON-NLS-1$
|
||||
).collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a string into something that can be used as path name
|
||||
* @param name The name that should be used as part of a path
|
||||
* @return A string that should be usable as path name
|
||||
*/
|
||||
private String normalizeToPathName(String name) {
|
||||
String cleanName = name.replace("unix:///", "unix_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
cleanName = cleanName.replace("tcp://", "tcp_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
cleanName = cleanName.replaceAll("[:/.]", "_"); //$NON-NLS-1$ //$NON-NLS-2$#
|
||||
assert Path.ROOT.isValidSegment(cleanName) : "Invalid Path - please file a bug"; //$NON-NLS-1$
|
||||
return cleanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the ImageConnection to the local path where the data is mirrored to
|
||||
* @param imgCon The connection
|
||||
* @return A host path
|
||||
*/
|
||||
private IPath getHostMirrorPath(ImageConnection imgCon) {
|
||||
IPath pluginPath = Platform.getStateLocation(Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
|
||||
.append("HEADERS"); //$NON-NLS-1$
|
||||
pluginPath = pluginPath.append(normalizeToPathName(imgCon.connectionName));
|
||||
pluginPath = pluginPath.append(normalizeToPathName(imgCon.imageName));
|
||||
return pluginPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror a list of paths from the imgCon to the host
|
||||
* @param imgCon The image and connection to copy from
|
||||
* @param paths The paths to copy
|
||||
* @return Whether the operation was successful
|
||||
*/
|
||||
private boolean getPaths(ImageConnection imgCon, List<String> paths) {
|
||||
IPath targetPath = getHostMirrorPath(imgCon);
|
||||
|
||||
ContainerLauncher launcher = new ContainerLauncher();
|
||||
int rv = launcher.fetchContainerDirs(imgCon.connectionName, imgCon.imageName, paths, null, targetPath);
|
||||
return (rv == 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Image and Connection from the current project configuration
|
||||
* @return An ImageConnection or null if connection and image are configured
|
||||
*/
|
||||
private ImageConnection getImgCnn() {
|
||||
ICConfigurationDescription cfgd = CoreModel.getDefault().getProjectDescription(m_project)
|
||||
.getActiveConfiguration();
|
||||
IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(cfgd);
|
||||
IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
|
||||
if (props == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
if (enablementProperty == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Boolean.parseBoolean(enablementProperty)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String connectionName = props.getProperty(ContainerCommandLauncher.CONNECTION_ID);
|
||||
String imageName = props.getProperty(ContainerCommandLauncher.IMAGE_ID);
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null || imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ImageConnection(connectionName, imageName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICommandLauncher getCommandLauncher(IProject project) {
|
||||
this.project = project;
|
||||
m_project = project;
|
||||
// check if container build enablement has been checked
|
||||
ICConfigurationDescription cfgd = CoreModel.getDefault().getProjectDescription(project, false)
|
||||
.getActiveConfiguration();
|
||||
|
||||
return getCommandLauncher(cfgd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICommandLauncher getCommandLauncher(ICConfigurationDescription cfgd) {
|
||||
// check if container build enablement has been checked
|
||||
IConfiguration cfg = null;
|
||||
|
||||
try {
|
||||
|
@ -79,31 +183,8 @@ public class ContainerCommandLauncherFactory implements ICommandLauncherFactory,
|
|||
if (cfg == null) {
|
||||
return null;
|
||||
}
|
||||
IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
|
||||
|
||||
if (props != null) {
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
if (enablementProperty != null) {
|
||||
boolean enableContainer = Boolean.parseBoolean(enablementProperty);
|
||||
// enablement has occurred, we can return a
|
||||
// ContainerCommandLauncher
|
||||
if (enableContainer) {
|
||||
return new ContainerCommandLauncher();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICommandLauncher getCommandLauncher(ICConfigurationDescription cfgd) {
|
||||
// check if container build enablement has been checked
|
||||
IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(cfgd);
|
||||
// TODO: figure out why this occurs
|
||||
if (cfg == null) {
|
||||
return null;
|
||||
}
|
||||
this.project = (IProject) cfg.getManagedProject().getOwner();
|
||||
m_project = (IProject) cfg.getManagedProject().getOwner();
|
||||
IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
|
||||
if (props != null) {
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
|
@ -122,7 +203,7 @@ public class ContainerCommandLauncherFactory implements ICommandLauncherFactory,
|
|||
@Override
|
||||
public ICommandLauncher getCommandLauncher(ICBuildConfiguration cfgd) {
|
||||
try {
|
||||
this.project = cfgd.getBuildConfiguration().getProject();
|
||||
m_project = cfgd.getBuildConfiguration().getProject();
|
||||
} catch (CoreException e1) {
|
||||
return null;
|
||||
}
|
||||
|
@ -143,97 +224,32 @@ public class ContainerCommandLauncherFactory implements ICommandLauncherFactory,
|
|||
|
||||
@Override
|
||||
public void registerLanguageSettingEntries(IProject project, List<? extends ICLanguageSettingEntry> langEntries) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ICLanguageSettingEntry> entries = (List<ICLanguageSettingEntry>) langEntries;
|
||||
if (langEntries == null) {
|
||||
// langEntries can be null when the last item is removed from a list,
|
||||
// see org.eclipse.cdt.internal.ui.language.settings.providers.LanguageSettingsEntriesTab.saveEntries(ILanguageSettingsProvider, List<ICLanguageSettingEntry>)
|
||||
// for an example that passes null to mean "use parent entries instead".
|
||||
return;
|
||||
}
|
||||
ICConfigurationDescription cfgd = CoreModel.getDefault().getProjectDescription(project)
|
||||
.getActiveConfiguration();
|
||||
IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(cfgd);
|
||||
IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
|
||||
if (props != null) {
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
if (enablementProperty != null) {
|
||||
boolean enableContainer = Boolean.parseBoolean(enablementProperty);
|
||||
if (enableContainer) {
|
||||
String connectionName = props.getProperty(ContainerCommandLauncher.CONNECTION_ID);
|
||||
String imageName = props.getProperty(ContainerCommandLauncher.IMAGE_ID);
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null
|
||||
|| imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return;
|
||||
}
|
||||
ContainerLauncher launcher = new ContainerLauncher();
|
||||
List<String> paths = new ArrayList<>();
|
||||
for (ICLanguageSettingEntry entry : entries) {
|
||||
if (entry instanceof ICIncludePathEntry) {
|
||||
paths.add(entry.getValue());
|
||||
} else if (entry instanceof ICIncludeFileEntry) {
|
||||
paths.add(new org.eclipse.core.runtime.Path(entry.getValue()).removeLastSegments(1)
|
||||
.toString());
|
||||
}
|
||||
}
|
||||
if (paths.size() > 0) {
|
||||
// Create a directory to put the header files for
|
||||
// the image. Use the connection name to form
|
||||
// the directory name as the connection may be
|
||||
// connected to a different repo using the same
|
||||
// image name.
|
||||
IPath pluginPath = Platform.getStateLocation(Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
|
||||
.append("HEADERS"); //$NON-NLS-1$
|
||||
pluginPath.toFile().mkdir();
|
||||
pluginPath = pluginPath.append(getCleanName(connectionName));
|
||||
pluginPath.toFile().mkdir();
|
||||
// To allow the user to later manage the headers, store
|
||||
// the
|
||||
// real connection name in a file.
|
||||
IPath connectionNamePath = pluginPath.append(".name"); //$NON-NLS-1$
|
||||
File f = connectionNamePath.toFile();
|
||||
try {
|
||||
f.createNewFile();
|
||||
try (FileWriter writer = new FileWriter(f);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(writer);) {
|
||||
bufferedWriter.write(connectionName);
|
||||
bufferedWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return;
|
||||
}
|
||||
pluginPath = pluginPath.append(getCleanName(imageName));
|
||||
pluginPath.toFile().mkdir();
|
||||
// To allow the user to later manage the headers,
|
||||
// store the
|
||||
// real image name in a file.
|
||||
IPath imageNamePath = pluginPath.append(".name"); //$NON-NLS-1$
|
||||
f = imageNamePath.toFile();
|
||||
f.createNewFile();
|
||||
try (FileWriter writer = new FileWriter(f);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(writer);) {
|
||||
bufferedWriter.write(imageName);
|
||||
bufferedWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return;
|
||||
}
|
||||
IPath hostDir = pluginPath;
|
||||
List<String> excludeList = new ArrayList<>();
|
||||
excludeList.add(project.getLocation().toString());
|
||||
@SuppressWarnings("unused")
|
||||
int status = launcher.fetchContainerDirs(connectionName, imageName, paths, excludeList,
|
||||
hostDir);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ICLanguageSettingEntry> entries = (List<ICLanguageSettingEntry>) langEntries;
|
||||
|
||||
List<String> paths = new ArrayList<>();
|
||||
for (ICLanguageSettingEntry entry : entries) {
|
||||
if (entry instanceof ICIncludePathEntry) {
|
||||
paths.add(entry.getValue());
|
||||
} else if (entry instanceof ICIncludeFileEntry) {
|
||||
paths.add(new org.eclipse.core.runtime.Path(entry.getValue()).removeLastSegments(1).toString());
|
||||
}
|
||||
}
|
||||
|
||||
paths = filterOutLocalPaths(paths);
|
||||
if (paths.size() == 0) {
|
||||
return;
|
||||
}
|
||||
ImageConnection imgCnn = getImgCnn();
|
||||
getPaths(imgCnn, paths);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,109 +258,72 @@ public class ContainerCommandLauncherFactory implements ICommandLauncherFactory,
|
|||
@Override
|
||||
public List<String> verifyIncludePaths(ICBuildConfiguration cfgd, List<String> includePaths) {
|
||||
IToolChain toolchain = null;
|
||||
boolean isContainerEnabled = false;
|
||||
|
||||
try {
|
||||
toolchain = cfgd.getToolChain();
|
||||
if (toolchain != null) {
|
||||
if (ContainerTargetTypeProvider.CONTAINER_LINUX.equals(toolchain.getProperty(IToolChain.ATTR_OS))) {
|
||||
isContainerEnabled = true;
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
}
|
||||
|
||||
if (isContainerEnabled) {
|
||||
String connectionName = toolchain.getProperty(IContainerLaunchTarget.ATTR_CONNECTION_URI);
|
||||
String imageName = toolchain.getProperty(IContainerLaunchTarget.ATTR_IMAGE_ID);
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null || imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return includePaths;
|
||||
}
|
||||
if (includePaths.size() > 0) {
|
||||
ContainerLauncher launcher = new ContainerLauncher();
|
||||
// Create a directory to put the header files for
|
||||
// the image. Use the connection name to form
|
||||
// the directory name as the connection may be
|
||||
// connected to a different repo using the same
|
||||
// image name.
|
||||
IPath pluginPath = Platform.getStateLocation(Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
|
||||
.append("HEADERS"); //$NON-NLS-1$
|
||||
pluginPath.toFile().mkdir();
|
||||
pluginPath = pluginPath.append(getCleanName(connectionName));
|
||||
pluginPath.toFile().mkdir();
|
||||
// To allow the user to later manage the headers, store
|
||||
// the
|
||||
// real connection name in a file.
|
||||
IPath connectionNamePath = pluginPath.append(".name"); //$NON-NLS-1$
|
||||
File f = connectionNamePath.toFile();
|
||||
try {
|
||||
f.createNewFile();
|
||||
try (FileWriter writer = new FileWriter(f);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(writer);) {
|
||||
bufferedWriter.write(connectionName);
|
||||
bufferedWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return includePaths;
|
||||
}
|
||||
pluginPath = pluginPath.append(getCleanName(imageName));
|
||||
pluginPath.toFile().mkdir();
|
||||
// To allow the user to later manage the headers,
|
||||
// store the
|
||||
// real image name in a file.
|
||||
IPath imageNamePath = pluginPath.append(".name"); //$NON-NLS-1$
|
||||
f = imageNamePath.toFile();
|
||||
f.createNewFile();
|
||||
try (FileWriter writer = new FileWriter(f);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(writer);) {
|
||||
bufferedWriter.write(imageName);
|
||||
bufferedWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return includePaths;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
DockerLaunchUIPlugin.log(e);
|
||||
return includePaths;
|
||||
}
|
||||
IPath hostDir = pluginPath;
|
||||
// exclude project directories from any copying operation
|
||||
List<String> excludeList = new ArrayList<>();
|
||||
excludeList.add(project.getLocation().toString());
|
||||
int status = launcher.fetchContainerDirsSync(connectionName, imageName, includePaths, excludeList,
|
||||
hostDir);
|
||||
if (status == 0) {
|
||||
Set<String> copiedVolumes = launcher.getCopiedVolumes(connectionName, imageName);
|
||||
List<String> newEntries = new ArrayList<>();
|
||||
if (toolchain == null) {
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
for (String path : includePaths) {
|
||||
if (copiedVolumes.contains(path)) {
|
||||
IPath newPath = hostDir.append(path);
|
||||
String newEntry = newPath.toOSString();
|
||||
newEntries.add(newEntry);
|
||||
} else {
|
||||
newEntries.add(path);
|
||||
}
|
||||
}
|
||||
return newEntries;
|
||||
}
|
||||
if (!ContainerTargetTypeProvider.CONTAINER_LINUX.equals(toolchain.getProperty(IToolChain.ATTR_OS))) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_container_type);
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
String connectionName = toolchain.getProperty(IContainerLaunchTarget.ATTR_CONNECTION_URI);
|
||||
String imageName = toolchain.getProperty(IContainerLaunchTarget.ATTR_IMAGE_ID);
|
||||
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null || imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
ImageConnection imgCnn = new ImageConnection(connectionName, imageName);
|
||||
|
||||
if (includePaths.isEmpty()) {
|
||||
// Bug 536884 - if no include entries, check if the copied
|
||||
// header files have been erased by the end-user in which
|
||||
// case mark that scanner info needs refreshing (only way
|
||||
// the headers will be recopied)
|
||||
// TODO: fix this in a minor release to be an additional method
|
||||
// that can be registered by the removal of the header files
|
||||
IPath pluginPath = getHostMirrorPath(imgCnn);
|
||||
toolchain.setProperty("cdt.needScannerRefresh", //$NON-NLS-1$
|
||||
pluginPath.toFile().exists() ? "false" : "true"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
List<String> fetchPaths = filterOutLocalPaths(includePaths);
|
||||
if (fetchPaths.size() == 0) {
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
if (!getPaths(imgCnn, includePaths)) {
|
||||
// There should be sufficient log messages by the root cause
|
||||
return includePaths;
|
||||
}
|
||||
|
||||
// Do the actual work
|
||||
|
||||
IPath tpath = getHostMirrorPath(imgCnn);
|
||||
Set<IPath> copiedVolumes = ContainerLauncher.getCopiedVolumes(tpath);
|
||||
List<String> newEntries = new ArrayList<>();
|
||||
|
||||
for (String path : includePaths) {
|
||||
if (copiedVolumes.contains(new Path(path))) {
|
||||
IPath newPath = tpath.append(path);
|
||||
String newEntry = newPath.toOSString();
|
||||
newEntries.add(newEntry);
|
||||
} else {
|
||||
// Bug 536884 - if no include entries, check if the copied
|
||||
// header files have been erased by the end-user in which
|
||||
// case mark that scanner info needs refreshing (only way
|
||||
// the headers will be recopied)
|
||||
// TODO: fix this in a minor release to be an additional method
|
||||
// that can be registered by the removal of the header files
|
||||
IPath pluginPath = Platform.getStateLocation(Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID))
|
||||
.append("HEADERS").append(getCleanName(connectionName)) //$NON-NLS-1$
|
||||
.append(getCleanName(imageName));
|
||||
toolchain.setProperty("cdt.needScannerRefresh", //$NON-NLS-1$
|
||||
pluginPath.toFile().exists() ? "false" : "true"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
newEntries.add(path);
|
||||
}
|
||||
}
|
||||
return includePaths;
|
||||
return newEntries;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -353,64 +332,56 @@ public class ContainerCommandLauncherFactory implements ICommandLauncherFactory,
|
|||
if (entries == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ICConfigurationDescription cfgd = CoreModel.getDefault().getProjectDescription(project)
|
||||
.getActiveConfiguration();
|
||||
IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(cfgd);
|
||||
IOptionalBuildProperties props = cfg.getOptionalBuildProperties();
|
||||
if (props != null) {
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
if (enablementProperty != null) {
|
||||
boolean enableContainer = Boolean.parseBoolean(enablementProperty);
|
||||
if (enableContainer) {
|
||||
String connectionName = props.getProperty(ContainerCommandLauncher.CONNECTION_ID);
|
||||
String imageName = props.getProperty(ContainerCommandLauncher.IMAGE_ID);
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null
|
||||
|| imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return entries;
|
||||
}
|
||||
|
||||
ContainerLauncher launcher = new ContainerLauncher();
|
||||
Set<String> copiedVolumes = launcher.getCopiedVolumes(connectionName, imageName);
|
||||
List<ICLanguageSettingEntry> newEntries = new ArrayList<>();
|
||||
IPath pluginPath = Platform.getStateLocation(Platform.getBundle(DockerLaunchUIPlugin.PLUGIN_ID));
|
||||
IPath hostDir = pluginPath.append("HEADERS") //$NON-NLS-1$
|
||||
.append(getCleanName(connectionName)).append(getCleanName(imageName));
|
||||
if (props == null)
|
||||
return entries;
|
||||
|
||||
for (ICLanguageSettingEntry entry : entries) {
|
||||
if (entry instanceof ICIncludePathEntry) {
|
||||
if (copiedVolumes.contains(((ICIncludePathEntry) entry).getName().toString())) {
|
||||
// //$NON-NLS-2$
|
||||
IPath newPath = hostDir.append(entry.getName());
|
||||
CIncludePathEntry newEntry = new CIncludePathEntry(newPath.toString(),
|
||||
entry.getFlags());
|
||||
newEntries.add(newEntry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (entry instanceof ICIncludeFileEntry) {
|
||||
IPath p = new Path(((ICIncludeFileEntry) entry).getName());
|
||||
if (copiedVolumes.contains(p.removeLastSegments(1).toString())) {
|
||||
IPath newPath = hostDir.append(entry.getName());
|
||||
CIncludeFileEntry newEntry = new CIncludeFileEntry(newPath.toString(),
|
||||
entry.getFlags());
|
||||
newEntries.add(newEntry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
newEntries.add(entry);
|
||||
}
|
||||
return newEntries;
|
||||
String enablementProperty = props.getProperty(ContainerCommandLauncher.CONTAINER_BUILD_ENABLED);
|
||||
if (enablementProperty == null)
|
||||
return entries;
|
||||
|
||||
boolean enableContainer = Boolean.parseBoolean(enablementProperty);
|
||||
if (!enableContainer)
|
||||
return entries;
|
||||
|
||||
String connectionName = props.getProperty(ContainerCommandLauncher.CONNECTION_ID);
|
||||
String imageName = props.getProperty(ContainerCommandLauncher.IMAGE_ID);
|
||||
if (connectionName == null || connectionName.isEmpty() || imageName == null || imageName.isEmpty()) {
|
||||
DockerLaunchUIPlugin.logErrorMessage(Messages.ContainerCommandLauncher_invalid_values);
|
||||
return entries;
|
||||
}
|
||||
|
||||
IPath tpath = getHostMirrorPath(new ImageConnection(connectionName, imageName));
|
||||
Set<IPath> copiedVolumes = ContainerLauncher.getCopiedVolumes(tpath);
|
||||
List<ICLanguageSettingEntry> newEntries = new ArrayList<>();
|
||||
|
||||
for (ICLanguageSettingEntry entry : entries) {
|
||||
if (entry instanceof ICIncludePathEntry) {
|
||||
Path tp = new Path(((ICIncludePathEntry) entry).getName().toString());
|
||||
if (copiedVolumes.stream().anyMatch(p -> p.isPrefixOf(tp))) {
|
||||
IPath newPath = tpath.append(entry.getName());
|
||||
CIncludePathEntry newEntry = new CIncludePathEntry(newPath.toString(), entry.getFlags());
|
||||
newEntries.add(newEntry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (entry instanceof ICIncludeFileEntry) {
|
||||
IPath tp = new Path(((ICIncludeFileEntry) entry).getName()).removeLastSegments(1);
|
||||
if (copiedVolumes.stream().anyMatch(p -> p.isPrefixOf(tp))) {
|
||||
IPath newPath = tpath.append(entry.getName());
|
||||
CIncludeFileEntry newEntry = new CIncludeFileEntry(newPath.toString(), entry.getFlags());
|
||||
newEntries.add(newEntry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
newEntries.add(entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
private String getCleanName(String name) {
|
||||
String cleanName = name.replace("unix:///", "unix_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
cleanName = cleanName.replace("tcp://", "tcp_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return cleanName.replaceAll("[:/.]", "_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return newEntries;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2020 Red Hat and others.
|
||||
* Copyright (c) 2015, 2022 Red Hat and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
|
@ -160,13 +160,8 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
String projectName = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
|
||||
labels.put("org.eclipse.cdt.project-name", projectName); //$NON-NLS-1$
|
||||
if (mode.equals(ILaunchManager.RUN_MODE)) {
|
||||
String commandDir = commandPath.removeLastSegments(1).toPortableString();
|
||||
String commandString = commandPath.toPortableString();
|
||||
|
||||
if (commandPath.getDevice() != null) {
|
||||
commandDir = "/" + commandDir.replace(':', '/'); //$NON-NLS-1$
|
||||
commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
String commandDir = ContainerLaunchUtils.toDockerPath(commandPath.removeLastSegments(1));
|
||||
String commandString = ContainerLaunchUtils.toDockerPath(commandPath);
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(commandString);
|
||||
|
@ -191,8 +186,7 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
if (workingDir != null) {
|
||||
IPath workingPath = new Path(workingDir);
|
||||
if (workingPath.getDevice() != null) {
|
||||
workingDir = "/" + workingPath.toPortableString() //$NON-NLS-1$
|
||||
.replace(':', '/');
|
||||
workingDir = ContainerLaunchUtils.toDockerPath(workingPath);
|
||||
}
|
||||
}
|
||||
Map<String, String> envMap = configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES,
|
||||
|
@ -208,10 +202,8 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
List<String> dirs = new ArrayList<>();
|
||||
for (String additionalDir : additionalDirs) {
|
||||
IPath path = new Path(additionalDir);
|
||||
String dir = path.toPortableString();
|
||||
if (path.getDevice() != null) {
|
||||
dir = "/" + dir.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
String dir = ContainerLaunchUtils.toDockerPath(path);
|
||||
|
||||
dirs.add(dir);
|
||||
}
|
||||
additionalDirs = dirs;
|
||||
|
@ -298,13 +290,8 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
String gdbserverCommand = configuration.getAttribute(ILaunchConstants.ATTR_GDBSERVER_COMMAND,
|
||||
ILaunchConstants.ATTR_GDBSERVER_COMMAND_DEFAULT);
|
||||
|
||||
String commandString = commandPath.toPortableString();
|
||||
String commandDir = commandPath.removeLastSegments(1).toPortableString();
|
||||
|
||||
if (commandPath.getDevice() != null) {
|
||||
commandDir = "/" + commandDir.replace(':', '/'); //$NON-NLS-1$
|
||||
commandString = "/" + commandString.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
String commandString = ContainerLaunchUtils.toDockerPath(commandPath);
|
||||
String commandDir = ContainerLaunchUtils.toDockerPath(commandPath.removeLastSegments(1));
|
||||
|
||||
String commandArguments = ":" + gdbserverPortNumber + " " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ spaceEscapify(commandString);
|
||||
|
@ -331,8 +318,7 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
if (workingDir != null) {
|
||||
IPath workingPath = new Path(workingDir);
|
||||
if (workingPath.getDevice() != null) {
|
||||
workingDir = "/" + workingPath.toPortableString() //$NON-NLS-1$
|
||||
.replace(':', '/');
|
||||
workingDir = ContainerLaunchUtils.toDockerPath(workingPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,10 +335,7 @@ public class ContainerLaunchConfigurationDelegate extends GdbLaunchDelegate {
|
|||
List<String> dirs = new ArrayList<>();
|
||||
for (String additionalDir : additionalDirs) {
|
||||
IPath path = new Path(additionalDir);
|
||||
String dir = path.toPortableString();
|
||||
if (path.getDevice() != null) {
|
||||
dir = "/" + dir.replace(':', '/'); //$NON-NLS-1$
|
||||
}
|
||||
String dir = ContainerLaunchUtils.toDockerPath(path);
|
||||
dirs.add(dir);
|
||||
}
|
||||
additionalDirs = dirs;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2022 Red Hat Inc. and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.docker.launcher;
|
||||
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
|
||||
public class ContainerLaunchUtils {
|
||||
|
||||
/**
|
||||
* Maps the local path, to a path that is used within a docker container.
|
||||
* @param path The host path
|
||||
* @return the path within the docker container
|
||||
* @see toDockerPath(String)
|
||||
*/
|
||||
public static final String toDockerPath(IPath path) {
|
||||
String pathstring = path.toPortableString();
|
||||
if (path.getDevice() != null) {
|
||||
if (pathstring.charAt(0) != '/') {
|
||||
pathstring = '/' + pathstring;
|
||||
}
|
||||
}
|
||||
return ContainerLaunchUtils.toDockerPath(pathstring);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the local path, to a path that is used within a docker container.
|
||||
* C: is mapped to /c, etc.
|
||||
* //$WSL/<NAME>/ is a bit more tricky. For now it will be mapped to /WSL/<NAME>/
|
||||
* @param path The host path
|
||||
* @return the path within the docker container
|
||||
*/
|
||||
public static final String toDockerPath(String path) {
|
||||
if (Platform.getOS().equals(Platform.OS_WIN32)) {
|
||||
path = path.replace(':', '/');
|
||||
//Fix WSL which starts with //$WSL - TODO: Make more robust
|
||||
path = path.replace("//WSL$/", "/WSL/"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
//Ensure the path is global.
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Path to a string that can be passed as docker volume to be mapped into the Docker container
|
||||
* toDockerPath() is used to get the path within the Docker container.
|
||||
* @param path The path on the hose
|
||||
* @return The string to be passed to the docker daemon
|
||||
*/
|
||||
public static final String toDockerVolume(IPath path) {
|
||||
IPath p = path.makeAbsolute();
|
||||
String rv = toDockerPath(p);
|
||||
rv += ":HOST_FILE_SYSTEM:"; //$NON-NLS-1$
|
||||
rv += p.toOSString();
|
||||
rv += ":false:true"; //$NON-NLS-1$ RO=false, selected = true
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2020 Red Hat, Inc.
|
||||
* Copyright (c) 2012, 2022 Red Hat, Inc.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
|
@ -32,12 +32,12 @@ public class Messages extends NLS {
|
|||
public static String LaunchShortcut_Launcher;
|
||||
public static String Default_Image;
|
||||
public static String Keep_Container_After_Launch;
|
||||
|
||||
public static String ContainerTab_Name;
|
||||
public static String ContainerTab_Group_Name;
|
||||
public static String ContainerTab_Option_Group_Name;
|
||||
public static String ContainerTab_Ports_Group_Name;
|
||||
public static String ContainerTab_Specify_Ports_Label;
|
||||
|
||||
public static String ContainerTab_Add_Button;
|
||||
public static String ContainerTab_Edit_Button;
|
||||
public static String ContainerTab_New_Button;
|
||||
|
@ -123,6 +123,7 @@ public class Messages extends NLS {
|
|||
public static String ContainerTarget_name;
|
||||
|
||||
public static String ContainerCommandLauncher_invalid_values;
|
||||
public static String ContainerCommandLauncher_invalid_container_type;
|
||||
|
||||
public static String Gdbserver_Settings_Remotetimeout_label;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#*******************************************************************************
|
||||
# Copyright (c) 2015, 2020 Red Hat.
|
||||
# Copyright (c) 2015, 2022 Red Hat.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License 2.0
|
||||
|
@ -77,6 +77,7 @@ HeaderPreferencePage_Confirm_Removal_Msg=Confirm removal of specified cached hea
|
|||
|
||||
ContainerCommandLauncher_image_msg=[Running in image <{0}>]
|
||||
ContainerCommandLauncher_invalid_values=Invalid values for Connection and/or Image name
|
||||
ContainerCommandLauncher_invalid_container_type=Toolchain is not a Linux Container toolchain
|
||||
|
||||
CommandLauncher_CommandCancelled=Command cancelled
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue