diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java index 94d6e373a..d4bcb3a62 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020 Pivotal, Inc. + * Copyright (c) 2020, 2022 Pivotal, Inc. * 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 @@ -59,6 +59,7 @@ import org.springframework.ide.eclipse.boot.dash.model.RunState; import org.springframework.ide.eclipse.boot.dash.model.remote.ChildBearing; import org.springframework.ide.eclipse.boot.dash.model.remote.RefreshStateTracker; import org.springframework.ide.eclipse.boot.dash.util.LineBasedStreamGobler; +import org.springframework.ide.eclipse.boot.launch.util.BootDebugUITools; import org.springframework.ide.eclipse.boot.launch.util.PortFinder; import org.springframework.ide.eclipse.boot.util.JavaProjectUtil; import org.springsource.ide.eclipse.commons.core.pstore.PropertyStoreApi; @@ -190,6 +191,18 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, } public CompletableFuture synchronizeWithDeployment() { + // GH-803: Prompt to save dirty editors prior to + // building the project. + try { + DockerDeployment deployment = deployment(); + RunState desiredRunState = deployment.getRunState(); + if (desiredRunState.isActive() + && !BootDebugUITools.promptForProjectSave(project)) { + return new CompletableFuture(); + } + } catch (Exception e) { + Log.log(e); + } return this.refreshTracker.thenComposeAsync(refreshTracker -> { DockerDeployment deployment = deployment(); return refreshTracker.runAsync("Synchronizing deployment "+deployment.getName(), () -> { diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java index 7671732c0..6026481b7 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2018, 2019, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,12 +14,14 @@ * Martin Oberhuber (Wind River) - [327446] Avoid unnecessary wait-for-build dialog. * Mohamed Hussein - bug 381175 * Pivotal Inc - allow synchronizing with backgroundLaunch + * VMware - Prompt to save editors *******************************************************************************/ package org.springframework.ide.eclipse.boot.launch.util; import java.text.MessageFormat; import java.util.concurrent.CompletableFuture; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -182,4 +184,57 @@ public class BootDebugUITools { job.schedule(); } + /* + * + * The following constants are copied from LaunchConfigurationDelegate + * + * + */ + + /** + * Constant to define debug.core for the status codes + * + * @since 3.2 + */ + private static final String DEBUG_CORE = "org.eclipse.debug.core"; + + /** + * Constant to define debug.ui for the status codes + * + * @since 3.2 + */ + private static final String DEBUG_UI = "org.eclipse.debug.ui"; + + /** + * Status code for which a UI prompter is registered. + */ + protected static final IStatus promptStatus = new Status(IStatus.INFO, DEBUG_UI, 200, "", null); + + /** + * Status code for which a prompter will ask the user to save any/all of the dirty editors which have only to do + * with this launch (scoping them to the current launch/build) + * + * @since 3.2 + */ + protected static final IStatus saveScopedDirtyEditors = new Status(IStatus.INFO, DEBUG_CORE, 222, "", null); + + /** + * Derived from {@link LaunchConfigurationDelegate} + * @param project + * @return true if project was saved. False if canceled + * @throws Exception + */ + public static boolean promptForProjectSave(IProject project) throws Exception { + IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus); + + if(prompter != null) { + IProject[] projects = new IProject[] {project}; + ILaunchConfiguration configuration = null; + if(!((Boolean)prompter.handleStatus(saveScopedDirtyEditors, new Object[]{configuration, projects})).booleanValue()) { + return false; + } + } + return true; + } + }