Merge branch 'master' into spi
commit
a1dfdfb04e
|
|
@ -210,9 +210,14 @@ che.docker.ip.external=NULL
|
|||
# - 'docker-local': internal address is address of container within docker network, and exposed ports
|
||||
# are used.
|
||||
# - 'custom': The evaluation strategy may be customized through a template property.
|
||||
# - 'docker-local-custom': internal address is set as in docker-local strategy, external address is composed
|
||||
# as in the custom strategy with the 'template' and the 'external.protocol' properties.
|
||||
|
||||
# The 'docker-local' strategy may be useful if a firewall prevents communication between che-server and
|
||||
# workspace containers, but will prevent communication when che-server and workspace containers are not
|
||||
# on the same Docker network.
|
||||
# The 'docker-local-custom' strategy may be useful when Che and the workspace servers need to be exposed on the
|
||||
# same single TCP port.
|
||||
che.docker.server_evaluation_strategy=default
|
||||
|
||||
|
||||
|
|
@ -317,12 +322,52 @@ che.openshift.project=eclipse-che
|
|||
che.openshift.serviceaccountname=cheserviceaccount
|
||||
che.openshift.liveness.probe.delay=300
|
||||
che.openshift.liveness.probe.timeout=1
|
||||
che.openshift.workspaces.pvc.name=claim-che-workspace
|
||||
che.openshift.workspaces.pvc.quantity=10Gi
|
||||
# Create secure route against HTTPS
|
||||
# NOTE: In order to create routes against HTTPS
|
||||
# Property 'strategy.che.docker.server_evaluation_strategy.secure.external.urls' should be also set to true
|
||||
che.openshift.secure.routes=false
|
||||
# Pod that is launched when performing persistent volume claim maintenance jobs on OpenShift
|
||||
che.openshift.jobs.image=centos:centos7
|
||||
che.openshift.jobs.memorylimit=250Mi
|
||||
|
||||
# Run job to create workspace subpath directories in persistent volume before launching workspace.
|
||||
# Necessary in some versions of OpenShift/Kubernetes as workspace subpath volumemounts are created
|
||||
# with root permissions, and thus cannot be modified by workspaces running as user (presents as error
|
||||
# importing projects into workspace in Che). Default is "true", but should be set to false if version
|
||||
# of Openshift/Kubernetes creates subdirectories with user permissions.
|
||||
# Relevant issue: https://github.com/kubernetes/kubernetes/issues/41638
|
||||
che.openshift.precreate.workspace.dirs=true
|
||||
|
||||
# Specifications of compute resources that can be consumed
|
||||
# by the workspace container:
|
||||
#
|
||||
# - Amount of memory required for a workspace container to run e.g. 512Mi
|
||||
che.openshift.workspace.memory.request=NULL
|
||||
#
|
||||
# - Maximum amount of memory a workspace container can use e.g. 1.3Gi
|
||||
che.openshift.workspace.memory.override=NULL
|
||||
|
||||
# The Openshift will idle the server if no workspace is run for
|
||||
# this length of time.
|
||||
che.openshift.server.inactive.stop.timeout.ms=1800000
|
||||
|
||||
#
|
||||
#
|
||||
# Be aware that setting che.openshift.workspace.memory.override
|
||||
# will override Che memory limits
|
||||
#
|
||||
# More information about setting Compute Resources in OpenShift can be
|
||||
# found here: https://docs.openshift.org/latest/dev_guide/compute_resources.html#dev-compute-resources
|
||||
|
||||
# Which implementation of DockerConnector to use in managing containers. In general,
|
||||
# the base implementation of DockerConnector is appropriate, but OpenShiftConnector
|
||||
# is necessary for deploying Che on OpenShift. Options:
|
||||
# - 'default' : Use DockerConnector
|
||||
# - 'openshift' : use OpenShiftConnector
|
||||
# Note that if 'openshift' connector is used, the property che.docker.ip.external
|
||||
# MUST be set.
|
||||
che.docker.connector=default
|
||||
|
||||
# Defines whether stacks loaded once or each time server starts.
|
||||
|
|
|
|||
|
|
@ -255,6 +255,17 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mycila</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<!-- Exclude files until #3281 is resolved -->
|
||||
<exclude>**/ServerIdleEvent.java</exclude>
|
||||
<!-- End excluded files -->
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.core.event;
|
||||
/**
|
||||
* Event informing about idling the che server.
|
||||
*/
|
||||
public class ServerIdleEvent {
|
||||
private long timeout;
|
||||
|
||||
/**
|
||||
* Implements the handler to handle idling.
|
||||
*/
|
||||
public ServerIdleEvent(long timeout) {
|
||||
super();
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
public long getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(long timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
|
@ -48,3 +48,6 @@ EXPOSE 8000 8080
|
|||
COPY entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
ADD eclipse-che.tar.gz /home/user/
|
||||
RUN mkdir /logs && chmod 0777 /logs
|
||||
RUN chmod -R 0777 /home/user/
|
||||
RUN mkdir /data && chmod 0777 /data
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ Variables:
|
|||
export CHE_REGISTRY_HOST=${CHE_REGISTRY_HOST:-${DEFAULT_CHE_REGISTRY_HOST}}
|
||||
|
||||
DEFAULT_CHE_PORT=8080
|
||||
CHE_PORT=${CHE_PORT:-${DEFAULT_CHE_PORT}}
|
||||
export CHE_PORT=${CHE_PORT:-${DEFAULT_CHE_PORT}}
|
||||
|
||||
DEFAULT_CHE_IP=
|
||||
CHE_IP=${CHE_IP:-${DEFAULT_CHE_IP}}
|
||||
|
|
@ -246,18 +246,40 @@ init() {
|
|||
fi
|
||||
### Are we going to use the embedded che.properties or one provided by user?`
|
||||
### CHE_LOCAL_CONF_DIR is internal Che variable that sets where to load
|
||||
export CHE_LOCAL_CONF_DIR="/conf"
|
||||
if [ -f "/conf/che.properties" ]; then
|
||||
echo "Found custom che.properties..."
|
||||
if [ "$CHE_USER" != "root" ]; then
|
||||
sudo chown -R ${CHE_USER} ${CHE_LOCAL_CONF_DIR}
|
||||
# check if we have permissions to create /conf folder.
|
||||
if [ -w / ]; then
|
||||
export CHE_LOCAL_CONF_DIR="/conf"
|
||||
if [ -f "/conf/che.properties" ]; then
|
||||
echo "Found custom che.properties..."
|
||||
if [ "$CHE_USER" != "root" ]; then
|
||||
sudo chown -R ${CHE_USER} ${CHE_LOCAL_CONF_DIR}
|
||||
fi
|
||||
else
|
||||
if [ ! -d ${CHE_LOCAL_CONF_DIR} ]; then
|
||||
mkdir -p ${CHE_LOCAL_CONF_DIR}
|
||||
fi
|
||||
if [ -w ${CHE_LOCAL_CONF_DIR} ];then
|
||||
echo "ERROR: user ${CHE_USER} does OK have write permissions to ${CHE_LOCAL_CONF_DIR}"
|
||||
echo "Using embedded che.properties... Copying template to ${CHE_LOCAL_CONF_DIR}/che.properties"
|
||||
cp -rf "${CHE_HOME}/conf/che.properties" ${CHE_LOCAL_CONF_DIR}/che.properties
|
||||
else
|
||||
echo "ERROR: user ${CHE_USER} does not have write permissions to ${CHE_LOCAL_CONF_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ ! -d /conf ]; then
|
||||
mkdir -p /conf
|
||||
echo "WARN: parent dir is not writeable, CHE_LOCAL_CONF_DIR will be set to ${CHE_DATA}/conf"
|
||||
export CHE_LOCAL_CONF_DIR="${CHE_DATA}/conf"
|
||||
if [ ! -d ${CHE_LOCAL_CONF_DIR} ]; then
|
||||
mkdir -p ${CHE_LOCAL_CONF_DIR}
|
||||
fi
|
||||
if [ -w ${CHE_LOCAL_CONF_DIR} ];then
|
||||
echo "Using embedded che.properties... Copying template to ${CHE_LOCAL_CONF_DIR}/che.properties"
|
||||
cp -rf "${CHE_HOME}/conf/che.properties" ${CHE_LOCAL_CONF_DIR}/che.properties
|
||||
else
|
||||
echo "ERROR: user ${CHE_USER} does not have write permissions to ${CHE_LOCAL_CONF_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Using embedded che.properties... Copying template to ${CHE_LOCAL_CONF_DIR}/che.properties"
|
||||
cp -rf "${CHE_HOME}/conf/che.properties" ${CHE_LOCAL_CONF_DIR}/che.properties
|
||||
fi
|
||||
|
||||
# Update the provided che.properties with the location of the /data mounts
|
||||
|
|
|
|||
|
|
@ -30,4 +30,12 @@ public interface ModificationTracker {
|
|||
* @return modification tracker value
|
||||
*/
|
||||
String getModificationStamp();
|
||||
|
||||
/**
|
||||
* Update modification tracker value by content. Modification tracker is a value is changed by any modification of the content
|
||||
* of the file.
|
||||
*
|
||||
* @param content actual file content
|
||||
*/
|
||||
void updateModificationStamp(String content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,9 +87,9 @@ public class CommandManagerImpl implements CommandManager {
|
|||
this.commandNameGenerator = commandNameGenerator;
|
||||
|
||||
commands = new HashMap<>();
|
||||
registerNative();
|
||||
|
||||
// FIXME: spi
|
||||
// Temporary solution while a better mechanism of obtaining appContext.getProjects() with Promises is being considered...
|
||||
// TODO (spi ide): Temporary solution while a better mechanism of obtaining appContext.getProjects() with Promises is being considered...
|
||||
eventBus.addHandler(WorkspaceReadyEvent.getType(), e -> fetchCommands());
|
||||
eventBus.addHandler(WorkspaceStoppedEvent.TYPE, e -> {
|
||||
commands.clear();
|
||||
|
|
@ -380,4 +380,17 @@ public class CommandManagerImpl implements CommandManager {
|
|||
private void notifyCommandUpdated(CommandImpl prevCommand, CommandImpl command) {
|
||||
eventBus.fireEvent(new CommandUpdatedEvent(prevCommand, command));
|
||||
}
|
||||
|
||||
/* Expose Command Manager's internal API to the world, to allow selenium tests or clients that use IDE to refresh commands. */
|
||||
private native void registerNative() /*-{
|
||||
var that = this;
|
||||
|
||||
var CommandManager = {};
|
||||
|
||||
CommandManager.refresh = $entry(function () {
|
||||
that.@org.eclipse.che.ide.command.manager.CommandManagerImpl::fetchCommands()();
|
||||
});
|
||||
|
||||
$wnd.IDE.CommandManager = CommandManager;
|
||||
}-*/;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ public class EditorGroupSynchronizationImpl implements EditorGroupSynchronizatio
|
|||
});
|
||||
}
|
||||
|
||||
private void updateContent(String newContent, String oldStamp, VirtualFile virtualFile) {
|
||||
private void updateContent(String newContent, String eventModificationStamp, VirtualFile virtualFile) {
|
||||
final DocumentHandle documentHandle = getDocumentHandleFor(groupLeaderEditor);
|
||||
if (documentHandle == null) {
|
||||
return;
|
||||
|
|
@ -184,14 +184,14 @@ public class EditorGroupSynchronizationImpl implements EditorGroupSynchronizatio
|
|||
}
|
||||
|
||||
final File file = (File)virtualFile;
|
||||
final String newStamp = file.getModificationStamp();
|
||||
final String currentStamp = file.getModificationStamp();
|
||||
|
||||
if (oldStamp == null && !Objects.equals(newContent, oldContent)) {
|
||||
if (eventModificationStamp == null && !Objects.equals(newContent, oldContent)) {
|
||||
replaceContent(document, newContent, oldContent, cursorPosition);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Objects.equals(oldStamp, newStamp)) {
|
||||
if (!Objects.equals(eventModificationStamp, currentStamp)) {
|
||||
replaceContent(document, newContent, oldContent, cursorPosition);
|
||||
|
||||
notificationManager.notify("External operation", "File '" + file.getName() + "' is updated", SUCCESS, EMERGE_MODE);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ package org.eclipse.che.ide.factory.utils;
|
|||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
|
||||
import org.eclipse.che.api.core.model.workspace.config.SourceStorage;
|
||||
import org.eclipse.che.api.git.shared.GitCheckoutEvent;
|
||||
import org.eclipse.che.api.promises.client.Function;
|
||||
|
|
@ -37,19 +39,17 @@ import org.eclipse.che.ide.api.resources.Project;
|
|||
import org.eclipse.che.ide.api.user.AskCredentialsDialog;
|
||||
import org.eclipse.che.ide.api.user.Credentials;
|
||||
import org.eclipse.che.ide.api.workspace.model.ProjectConfigImpl;
|
||||
import org.eclipse.che.ide.projectimport.wizard.ProjectImportOutputJsonRpcNotifier;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
|
||||
import org.eclipse.che.ide.util.ExceptionUtils;
|
||||
import org.eclipse.che.ide.util.StringUtils;
|
||||
import org.eclipse.che.ide.websocket.MessageBus;
|
||||
import org.eclipse.che.ide.websocket.MessageBusProvider;
|
||||
import org.eclipse.che.ide.websocket.WebSocketException;
|
||||
import org.eclipse.che.ide.websocket.rest.SubscriptionHandler;
|
||||
import org.eclipse.che.security.oauth.OAuthStatus;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -73,17 +73,18 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.SUC
|
|||
* @author Valeriy Svydenko
|
||||
* @author Anton Korneta
|
||||
*/
|
||||
@Singleton
|
||||
public class FactoryProjectImporter extends AbstractImporter {
|
||||
private static final String CHANNEL = "git:checkout:";
|
||||
private final AskCredentialsDialog askCredentialsDialog;
|
||||
private final CoreLocalizationConstant locale;
|
||||
private final NotificationManager notificationManager;
|
||||
private final String restContext;
|
||||
private final DialogFactory dialogFactory;
|
||||
private final OAuth2AuthenticatorRegistry oAuth2AuthenticatorRegistry;
|
||||
private final RequestTransmitter requestTransmitter;
|
||||
private final ProjectImportOutputJsonRpcNotifier subscriber;
|
||||
|
||||
private final MessageBusProvider messageBusProvider;
|
||||
private final AskCredentialsDialog askCredentialsDialog;
|
||||
private final CoreLocalizationConstant locale;
|
||||
private final NotificationManager notificationManager;
|
||||
private final String restContext;
|
||||
private final DialogFactory dialogFactory;
|
||||
private final OAuth2AuthenticatorRegistry oAuth2AuthenticatorRegistry;
|
||||
private final DtoUnmarshallerFactory dtoUnmarshallerFactory;
|
||||
private final Map<String, CheckoutContext> checkoutContextRegistry = new HashMap<>();
|
||||
|
||||
private FactoryImpl factory;
|
||||
private AsyncCallback<Void> callback;
|
||||
|
|
@ -96,8 +97,8 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
ImportProjectNotificationSubscriberFactory subscriberFactory,
|
||||
DialogFactory dialogFactory,
|
||||
OAuth2AuthenticatorRegistry oAuth2AuthenticatorRegistry,
|
||||
MessageBusProvider messageBusProvider,
|
||||
DtoUnmarshallerFactory dtoUnmarshallerFactory) {
|
||||
RequestTransmitter requestTransmitter,
|
||||
ProjectImportOutputJsonRpcNotifier subscriber) {
|
||||
super(appContext, subscriberFactory);
|
||||
this.notificationManager = notificationManager;
|
||||
this.askCredentialsDialog = askCredentialsDialog;
|
||||
|
|
@ -105,8 +106,34 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
this.restContext = appContext.getMasterEndpoint();
|
||||
this.dialogFactory = dialogFactory;
|
||||
this.oAuth2AuthenticatorRegistry = oAuth2AuthenticatorRegistry;
|
||||
this.messageBusProvider = messageBusProvider;
|
||||
this.dtoUnmarshallerFactory = dtoUnmarshallerFactory;
|
||||
this.requestTransmitter = requestTransmitter;
|
||||
this.subscriber = subscriber;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void configure(RequestHandlerConfigurator requestHandlerConfigurator) {
|
||||
requestHandlerConfigurator.newConfiguration()
|
||||
.methodName("git/checkoutOutput")
|
||||
.paramsAsDto(GitCheckoutEvent.class)
|
||||
.noResult()
|
||||
.withConsumer(this::consumeGitCheckoutEvent);
|
||||
}
|
||||
|
||||
private void consumeGitCheckoutEvent(GitCheckoutEvent event) {
|
||||
CheckoutContext context = checkoutContextRegistry.get(event.getWorkspaceId() + event.getProjectName());
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String projectName = context.projectName;
|
||||
String reference = event.isCheckoutOnly() ? event.getBranchRef() : context.startPoint;
|
||||
String repository = context.repository;
|
||||
String branch = context.branch;
|
||||
|
||||
String title = locale.clonedSource(projectName);
|
||||
String content = locale.clonedSourceWithCheckout(projectName, repository, reference, branch);
|
||||
|
||||
notificationManager.notify(title, content, SUCCESS, FLOAT_MODE);
|
||||
}
|
||||
|
||||
public void startImporting(FactoryImpl factory, AsyncCallback<Void> callback) {
|
||||
|
|
@ -183,7 +210,6 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
@NotNull final SourceStorage sourceStorage) {
|
||||
final String projectName = pathToProject.lastSegment();
|
||||
final StatusNotification notification = notificationManager.notify(locale.cloningSource(projectName), null, PROGRESS, FLOAT_MODE);
|
||||
final ProjectNotificationSubscriber subscriber = subscriberFactory.createSubscriber();
|
||||
subscriber.subscribe(projectName, notification);
|
||||
String location = sourceStorage.getLocation();
|
||||
// it's needed for extract repository name from repository url e.g https://github.com/codenvy/che-core.git
|
||||
|
|
@ -192,37 +218,8 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
final Map<String, String> parameters = firstNonNull(sourceStorage.getParameters(), Collections.<String, String>emptyMap());
|
||||
final String branch = parameters.get("branch");
|
||||
final String startPoint = parameters.get("startPoint");
|
||||
final MessageBus messageBus = messageBusProvider.getMachineMessageBus();
|
||||
final String channel = CHANNEL + appContext.getWorkspaceId() + ':' + projectName;
|
||||
final SubscriptionHandler<GitCheckoutEvent> successImportHandler = new SubscriptionHandler<GitCheckoutEvent>(
|
||||
dtoUnmarshallerFactory.newWSUnmarshaller(GitCheckoutEvent.class)) {
|
||||
@Override
|
||||
protected void onMessageReceived(GitCheckoutEvent result) {
|
||||
if (result.isCheckoutOnly()) {
|
||||
notificationManager.notify(locale.clonedSource(projectName),
|
||||
locale.clonedSourceWithCheckout(projectName, repository, result.getBranchRef(), branch),
|
||||
SUCCESS,
|
||||
FLOAT_MODE);
|
||||
} else {
|
||||
notificationManager.notify(locale.clonedSource(projectName),
|
||||
locale.clonedWithCheckoutOnStartPoint(projectName, repository, startPoint, branch),
|
||||
SUCCESS,
|
||||
FLOAT_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onErrorReceived(Throwable e) {
|
||||
try {
|
||||
messageBus.unsubscribe(channel, this);
|
||||
} catch (WebSocketException ignore) {
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
messageBus.subscribe(channel, successImportHandler);
|
||||
} catch (WebSocketException ignore) {
|
||||
}
|
||||
subscribe(projectName, repository, branch, startPoint);
|
||||
|
||||
MutableProjectConfig importConfig = new MutableProjectConfig();
|
||||
importConfig.setPath(pathToProject.toString());
|
||||
|
|
@ -236,6 +233,8 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
@Override
|
||||
public Project apply(Project project) throws FunctionException {
|
||||
subscriber.onSuccess();
|
||||
unsubscribe(projectName);
|
||||
|
||||
notification.setContent(locale.clonedSource(projectName));
|
||||
notification.setStatus(SUCCESS);
|
||||
|
||||
|
|
@ -246,9 +245,11 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
@Override
|
||||
public Promise<Project> apply(PromiseError err) throws FunctionException {
|
||||
final int errorCode = ExceptionUtils.getErrorCode(err.getCause());
|
||||
unsubscribe(projectName);
|
||||
switch (errorCode) {
|
||||
case UNAUTHORIZED_GIT_OPERATION:
|
||||
subscriber.onFailure(err.getMessage());
|
||||
|
||||
final Map<String, String> attributes = ExceptionUtils.getAttributes(err.getCause());
|
||||
final String providerName = attributes.get(PROVIDER_NAME);
|
||||
final String authenticateUrl = attributes.get(AUTHENTICATE_URL);
|
||||
|
|
@ -296,6 +297,28 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
});
|
||||
}
|
||||
|
||||
private void subscribe(String projectName, String repository, String branch, String startPoint) {
|
||||
String key = appContext.getWorkspaceId() + projectName;
|
||||
|
||||
checkoutContextRegistry.put(key, new CheckoutContext(projectName, repository, branch, startPoint));
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId("ws-agent")
|
||||
.methodName("git/checkoutOutput/subscribe")
|
||||
.paramsAsString(key)
|
||||
.sendAndSkipResult();
|
||||
}
|
||||
|
||||
private void unsubscribe(String projectName) {
|
||||
String key = appContext.getWorkspaceId() + projectName;
|
||||
|
||||
checkoutContextRegistry.remove(key);
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId("ws-agent")
|
||||
.methodName("git/checkoutOutput/unsubscribe")
|
||||
.paramsAsString(key)
|
||||
.sendAndSkipResult();
|
||||
}
|
||||
|
||||
private Promise<Project> tryAuthenticateAndRepeatImport(@NotNull final String providerName,
|
||||
@NotNull final String authenticateUrl,
|
||||
@NotNull final Path pathToProject,
|
||||
|
|
@ -337,4 +360,18 @@ public class FactoryProjectImporter extends AbstractImporter {
|
|||
callback.onFailure(error.getCause());
|
||||
});
|
||||
}
|
||||
|
||||
private class CheckoutContext {
|
||||
private final String projectName;
|
||||
private final String repository;
|
||||
private final String branch;
|
||||
private final String startPoint;
|
||||
|
||||
private CheckoutContext(String projectName, String repository, String branch, String startPoint) {
|
||||
this.projectName = projectName;
|
||||
this.repository = repository;
|
||||
this.branch = branch;
|
||||
this.startPoint = startPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import org.eclipse.che.ide.api.data.tree.TreeExpander;
|
|||
import org.eclipse.che.ide.api.data.tree.settings.NodeSettings;
|
||||
import org.eclipse.che.ide.api.data.tree.settings.SettingsProvider;
|
||||
import org.eclipse.che.ide.api.extension.ExtensionsInitializedEvent;
|
||||
import org.eclipse.che.ide.api.extension.ExtensionsInitializedEvent.ExtensionsInitializedHandler;
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
import org.eclipse.che.ide.api.parts.base.BasePresenter;
|
||||
import org.eclipse.che.ide.api.resources.Container;
|
||||
|
|
@ -49,12 +48,6 @@ import org.eclipse.che.ide.resources.reveal.RevealResourceEvent;
|
|||
import org.eclipse.che.ide.resources.tree.ResourceNode;
|
||||
import org.eclipse.che.ide.ui.smartTree.NodeDescriptor;
|
||||
import org.eclipse.che.ide.ui.smartTree.Tree;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.BeforeExpandNodeEvent;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.CollapseNodeEvent;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.ExpandNodeEvent;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.PostLoadEvent;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.SelectionChangedEvent;
|
||||
import org.eclipse.che.ide.ui.smartTree.event.SelectionChangedEvent.SelectionChangedHandler;
|
||||
import org.eclipse.che.providers.DynaObject;
|
||||
import org.vectomatic.dom.svg.ui.SVGResource;
|
||||
|
||||
|
|
@ -90,6 +83,7 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
private final CoreLocalizationConstant locale;
|
||||
private final Resources resources;
|
||||
private final TreeExpander treeExpander;
|
||||
private final AppContext appContext;
|
||||
private final RequestTransmitter requestTransmitter;
|
||||
private final DtoFactory dtoFactory;
|
||||
private UpdateTask updateTask = new UpdateTask();
|
||||
|
|
@ -112,6 +106,7 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
this.settingsProvider = settingsProvider;
|
||||
this.locale = locale;
|
||||
this.resources = resources;
|
||||
this.appContext = appContext;
|
||||
this.requestTransmitter = requestTransmitter;
|
||||
this.dtoFactory = dtoFactory;
|
||||
this.view.setDelegate(this);
|
||||
|
|
@ -119,40 +114,22 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
eventBus.addHandler(ResourceChangedEvent.getType(), this);
|
||||
eventBus.addHandler(MarkerChangedEvent.getType(), this);
|
||||
eventBus.addHandler(SyntheticNodeUpdateEvent.getType(), this);
|
||||
eventBus.addHandler(WorkspaceStoppedEvent.TYPE, new WorkspaceStoppedEvent.Handler() {
|
||||
@Override
|
||||
public void onWorkspaceStopped(WorkspaceStoppedEvent event) {
|
||||
getTree().getNodeStorage().clear();
|
||||
eventBus.addHandler(WorkspaceStoppedEvent.TYPE, event -> getTree().getNodeStorage().clear());
|
||||
|
||||
view.getTree().getSelectionModel().addSelectionChangedHandler(event -> setSelection(new Selection<>(event.getSelection())));
|
||||
|
||||
view.getTree().addBeforeExpandHandler(event -> {
|
||||
NodeDescriptor nodeDescriptor = view.getTree().getNodeDescriptor(event.getNode());
|
||||
|
||||
if (event.getNode() instanceof SyntheticNode && nodeDescriptor != null && nodeDescriptor.isExpandDeep()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
});
|
||||
|
||||
view.getTree().getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler() {
|
||||
@Override
|
||||
public void onSelectionChanged(SelectionChangedEvent event) {
|
||||
setSelection(new Selection<>(event.getSelection()));
|
||||
}
|
||||
});
|
||||
|
||||
view.getTree().addBeforeExpandHandler(new BeforeExpandNodeEvent.BeforeExpandNodeHandler() {
|
||||
@Override
|
||||
public void onBeforeExpand(BeforeExpandNodeEvent event) {
|
||||
final NodeDescriptor nodeDescriptor = view.getTree().getNodeDescriptor(event.getNode());
|
||||
|
||||
if (event.getNode() instanceof SyntheticNode && nodeDescriptor != null && nodeDescriptor.isExpandDeep()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
view.getTree().getNodeLoader().addPostLoadHandler(new PostLoadEvent.PostLoadHandler() {
|
||||
@Override
|
||||
public void onPostLoad(PostLoadEvent event) {
|
||||
for (Node node : event.getReceivedNodes()) {
|
||||
|
||||
if (node instanceof ResourceNode && expandQueue.remove(((ResourceNode)node).getData().getLocation())) {
|
||||
view.getTree().setExpanded(node, true);
|
||||
}
|
||||
|
||||
view.getTree().getNodeLoader().addPostLoadHandler(event -> {
|
||||
for (Node node : event.getReceivedNodes()) {
|
||||
if (node instanceof ResourceNode && expandQueue.remove(((ResourceNode)node).getData().getLocation())) {
|
||||
view.getTree().setExpanded(node, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -162,12 +139,9 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
registerNative();
|
||||
|
||||
// when ide has already initialized, then we force set focus to the current part
|
||||
eventBus.addHandler(ExtensionsInitializedEvent.getType(), new ExtensionsInitializedHandler() {
|
||||
@Override
|
||||
public void onExtensionsInitialized(ExtensionsInitializedEvent event) {
|
||||
if (partStack != null) {
|
||||
partStack.setActivePart(ProjectExplorerPresenter.this);
|
||||
}
|
||||
eventBus.addHandler(ExtensionsInitializedEvent.getType(), event -> {
|
||||
if (partStack != null) {
|
||||
partStack.setActivePart(ProjectExplorerPresenter.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -177,41 +151,35 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
final String endpointId = "ws-agent";
|
||||
final String method = "track:project-tree";
|
||||
|
||||
getTree().addExpandHandler(new ExpandNodeEvent.ExpandNodeHandler() {
|
||||
@Override
|
||||
public void onExpand(ExpandNodeEvent event) {
|
||||
Node node = event.getNode();
|
||||
getTree().addExpandHandler(event -> {
|
||||
Node node = event.getNode();
|
||||
|
||||
if (node instanceof ResourceNode) {
|
||||
Resource data = ((ResourceNode)node).getData();
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(endpointId)
|
||||
.methodName(method)
|
||||
.paramsAsDto(dtoFactory.createDto(ProjectTreeTrackingOperationDto.class)
|
||||
.withPath(data.getLocation().toString())
|
||||
.withType(START))
|
||||
.sendAndSkipResult();
|
||||
if (node instanceof ResourceNode) {
|
||||
Resource data = ((ResourceNode)node).getData();
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(endpointId)
|
||||
.methodName(method)
|
||||
.paramsAsDto(dtoFactory.createDto(ProjectTreeTrackingOperationDto.class)
|
||||
.withPath(data.getLocation().toString())
|
||||
.withType(START))
|
||||
.sendAndSkipResult();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getTree().addCollapseHandler(new CollapseNodeEvent.CollapseNodeHandler() {
|
||||
@Override
|
||||
public void onCollapse(CollapseNodeEvent event) {
|
||||
Node node = event.getNode();
|
||||
getTree().addCollapseHandler(event -> {
|
||||
Node node = event.getNode();
|
||||
|
||||
if (node instanceof ResourceNode) {
|
||||
Resource data = ((ResourceNode)node).getData();
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(endpointId)
|
||||
.methodName(method)
|
||||
.paramsAsDto(dtoFactory.createDto(ProjectTreeTrackingOperationDto.class)
|
||||
.withPath(data.getLocation().toString())
|
||||
.withType(STOP))
|
||||
.sendAndSkipResult();
|
||||
if (node instanceof ResourceNode) {
|
||||
Resource data = ((ResourceNode)node).getData();
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(endpointId)
|
||||
.methodName(method)
|
||||
.paramsAsDto(dtoFactory.createDto(ProjectTreeTrackingOperationDto.class)
|
||||
.withPath(data.getLocation().toString())
|
||||
.withType(STOP))
|
||||
.sendAndSkipResult();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -232,7 +200,11 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
|
||||
ProjectExplorer.reveal = $entry(function (path) {
|
||||
that.@org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter::doReveal(*)(path);
|
||||
})
|
||||
});
|
||||
|
||||
ProjectExplorer.refresh = $entry(function () {
|
||||
that.@org.eclipse.che.ide.part.explorer.project.ProjectExplorerPresenter::doRefresh()();
|
||||
});
|
||||
|
||||
$wnd.IDE.ProjectExplorer = ProjectExplorer;
|
||||
}-*/;
|
||||
|
|
@ -253,6 +225,10 @@ public class ProjectExplorerPresenter extends BasePresenter implements ActionDel
|
|||
eventBus.fireEvent(new RevealResourceEvent(Path.valueOf(path)));
|
||||
}
|
||||
|
||||
private void doRefresh() {
|
||||
appContext.getWorkspaceRoot().synchronize();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onResourceChanged(ResourceChangedEvent event) {
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class FileImpl extends ResourceImpl implements File {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Promise<Void> updateContent(String content) {
|
||||
setModificationStamp(TextUtils.md5(content));
|
||||
updateModificationStamp(content);
|
||||
|
||||
return resourceManager.write(this, content);
|
||||
}
|
||||
|
|
@ -140,4 +140,9 @@ class FileImpl extends ResourceImpl implements File {
|
|||
public String getModificationStamp() {
|
||||
return modificationStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateModificationStamp(String content) {
|
||||
this.modificationStamp = TextUtils.md5(content);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2618,5 +2618,69 @@
|
|||
}
|
||||
],
|
||||
"creator": "Dharmit Shah"
|
||||
},
|
||||
{
|
||||
"id": "centos-go",
|
||||
"creator": "Dharmit Shah",
|
||||
"name": "CentOS Go",
|
||||
"description": "CentOS based Go Stack",
|
||||
"scope": "advanced",
|
||||
"tags": [
|
||||
"CentOS",
|
||||
"Go"
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "CentOS",
|
||||
"version": "7.3"
|
||||
},
|
||||
{
|
||||
"name": "Go",
|
||||
"version": "1.6.2"
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "image",
|
||||
"origin": "registry.centos.org/che-stacks/centos-go"
|
||||
},
|
||||
"workspaceConfig": {
|
||||
"environments": {
|
||||
"default": {
|
||||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"org.eclipse.che.exec", "org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
"memoryLimitBytes": "2147483648"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recipe": {
|
||||
"location": "registry.centos.org/che-stacks/centos-go",
|
||||
"type": "dockerimage"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "default",
|
||||
"defaultEnv": "default",
|
||||
"description": null,
|
||||
"commands": [
|
||||
{
|
||||
"name": "run",
|
||||
"type": "custom",
|
||||
"commandLine": "cd ${current.project.path} && go get -d && go run main.go",
|
||||
"attributes": {
|
||||
"previewUrl": "http://${server.port.8080}",
|
||||
"goal": "Run"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"stackIcon": {
|
||||
"name": "type-go.svg",
|
||||
"mediaType": "image/svg+xml"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ package org.eclipse.che.ide.editor.orion.client;
|
|||
|
||||
import com.google.web.bindery.event.shared.HandlerRegistration;
|
||||
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.eclipse.che.ide.editor.orion.client.jso.ModelChangedEventOverlay;
|
||||
import org.eclipse.che.ide.editor.orion.client.jso.OrionEditorOverlay;
|
||||
import org.eclipse.che.ide.editor.orion.client.jso.OrionPixelPositionOverlay;
|
||||
|
|
@ -197,6 +199,7 @@ public class OrionDocument extends AbstractDocument {
|
|||
|
||||
public void replace(int offset, int length, String text) {
|
||||
this.editorOverlay.getModel().setText(text, offset, offset + length);
|
||||
updateModificationTimeStamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -205,6 +208,14 @@ public class OrionDocument extends AbstractDocument {
|
|||
int lineStart = model.getLineStart(startLine);
|
||||
int lineEnd = model.getLineStart(endLine);
|
||||
editorOverlay.setText(text, lineStart + startChar, lineEnd + endChar);
|
||||
updateModificationTimeStamp();
|
||||
}
|
||||
|
||||
private void updateModificationTimeStamp() {
|
||||
VirtualFile file = this.getFile();
|
||||
if (file instanceof File) {
|
||||
((File)file).updateModificationStamp(editorOverlay.getText());
|
||||
}
|
||||
}
|
||||
|
||||
public int getContentsCharCount() {
|
||||
|
|
|
|||
|
|
@ -1015,7 +1015,13 @@ public class OrionEditorPresenter extends AbstractEditorPresenter implements Tex
|
|||
editorView.setEditorWidget(editorWidget);
|
||||
|
||||
document = editorWidget.getDocument();
|
||||
document.setFile(input.getFile());
|
||||
final VirtualFile file = input.getFile();
|
||||
document.setFile(file);
|
||||
|
||||
if (file instanceof File) {
|
||||
((File)file).updateModificationStamp(content);
|
||||
}
|
||||
|
||||
cursorModel = new OrionCursorModel(document);
|
||||
|
||||
editorWidget.setTabSize(configuration.getTabWidth());
|
||||
|
|
@ -1032,7 +1038,7 @@ public class OrionEditorPresenter extends AbstractEditorPresenter implements Tex
|
|||
if (delayedFocus) {
|
||||
editorWidget.refresh();
|
||||
editorWidget.setFocus();
|
||||
setSelection(new Selection<>(input.getFile()));
|
||||
setSelection(new Selection<>(file));
|
||||
delayedFocus = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@
|
|||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>ST4</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
|
|
@ -198,8 +202,11 @@
|
|||
<exclude>**/DefaultServerEvaluationStrategyTest.java</exclude>
|
||||
<exclude>**/LocalDockerServerEvaluationStrategy.java</exclude>
|
||||
<exclude>**/LocalDockerServerEvaluationStrategyTest.java</exclude>
|
||||
<exclude>**/LocalDockerCustomServerEvaluationStrategy.java</exclude>
|
||||
<exclude>**/LocalDockerCustomServerEvaluationStrategyTest.java</exclude>
|
||||
<exclude>**/DockerInstanceRuntimeInfo.java</exclude>
|
||||
<exclude>**/DockerInstanceRuntimeInfoTest.java</exclude>
|
||||
<exclude>**/ServerIdleDetector.java</exclude>
|
||||
<!-- End excluded files -->
|
||||
</excludes>
|
||||
</configuration>
|
||||
|
|
|
|||
|
|
@ -614,6 +614,12 @@ public class DockerMachineStarter {
|
|||
env = commonMachineEnvVariables;
|
||||
volumes = commonMachineSystemVolumes;
|
||||
}
|
||||
// register workspace ID and Machine Name
|
||||
env.put(CHE_WORKSPACE_ID, workspaceId);
|
||||
// FIXME: spi
|
||||
// env.put(DockerInstanceRuntimeInfo.CHE_MACHINE_NAME, machineName);
|
||||
// env.put(DockerInstanceRuntimeInfo.CHE_IS_DEV_MACHINE, Boolean.toString(isDev));
|
||||
|
||||
containerConfig.getExpose().addAll(portsToExpose);
|
||||
containerConfig.getEnvironment().putAll(env);
|
||||
containerConfig.getVolumes().addAll(volumes);
|
||||
|
|
|
|||
|
|
@ -16,15 +16,11 @@ import com.google.inject.name.Named;
|
|||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.strategy.BaseServerEvaluationStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.strategy.ServerEvaluationStrategy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* Represents a server evaluation strategy for the configuration where the workspace server and
|
||||
* workspace containers are running on the same Docker network. Calling
|
||||
|
|
@ -37,63 +33,11 @@ import static com.google.common.base.Strings.isNullOrEmpty;
|
|||
* @author Angel Misevski <amisevsk@redhat.com>
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public class LocalDockerServerEvaluationStrategy extends ServerEvaluationStrategy {
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip}, if applicable.
|
||||
*/
|
||||
protected String internalAddressProperty;
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip.external}. if applicable.
|
||||
*/
|
||||
protected String externalAddressProperty;
|
||||
public class LocalDockerServerEvaluationStrategy extends BaseServerEvaluationStrategy {
|
||||
|
||||
@Inject
|
||||
public LocalDockerServerEvaluationStrategy(@Nullable @Named("che.docker.ip") String internalAddress,
|
||||
@Nullable @Named("che.docker.ip.external") String externalAddress) {
|
||||
this.internalAddressProperty = internalAddress;
|
||||
this.externalAddressProperty = externalAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getInternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
String internalAddressContainer = containerInfo.getNetworkSettings().getIpAddress();
|
||||
|
||||
String internalAddress;
|
||||
boolean useExposedPorts = true;
|
||||
if (!isNullOrEmpty(internalAddressContainer)) {
|
||||
internalAddress = internalAddressContainer;
|
||||
} else {
|
||||
internalAddress = internalHost;
|
||||
useExposedPorts = false;
|
||||
}
|
||||
|
||||
Map<String, List<PortBinding>> portBindings = containerInfo.getNetworkSettings().getPorts();
|
||||
|
||||
Map<String, String> addressesAndPorts = new HashMap<>();
|
||||
for (Map.Entry<String, List<PortBinding>> portEntry : portBindings.entrySet()) {
|
||||
String exposedPort = portEntry.getKey().split("/")[0];
|
||||
String ephemeralPort = portEntry.getValue().get(0).getHostPort();
|
||||
if (useExposedPorts) {
|
||||
addressesAndPorts.put(portEntry.getKey(), internalAddress + ":" + exposedPort);
|
||||
} else {
|
||||
addressesAndPorts.put(portEntry.getKey(), internalAddress + ":" + ephemeralPort);
|
||||
}
|
||||
}
|
||||
return addressesAndPorts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getExternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
String externalAddressContainer = containerInfo.getNetworkSettings().getGateway();
|
||||
|
||||
String externalAddress = externalAddressProperty != null ?
|
||||
externalAddressProperty :
|
||||
!isNullOrEmpty(externalAddressContainer) ?
|
||||
externalAddressContainer :
|
||||
internalHost;
|
||||
|
||||
return getExposedPortsToAddressPorts(externalAddress, containerInfo.getNetworkSettings().getPorts());
|
||||
super(internalAddress, externalAddress, null, null, null, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,514 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.strategy;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* Represents a server evaluation strategy for the configuration where the strategy can be customized through template properties.
|
||||
*
|
||||
* @author Florent Benoit
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public abstract class BaseServerEvaluationStrategy extends ServerEvaluationStrategy {
|
||||
|
||||
/**
|
||||
* Regexp to extract port (under the form 22/tcp or 4401/tcp, etc.) from label references
|
||||
*/
|
||||
public static final String LABEL_CHE_SERVER_REF_KEY = "^che:server:(.*):ref$";
|
||||
|
||||
/**
|
||||
* Name of the property for getting the workspace ID.
|
||||
*/
|
||||
public static final String CHE_WORKSPACE_ID_PROPERTY = "CHE_WORKSPACE_ID=";
|
||||
|
||||
/**
|
||||
* Name of the property to get the machine name property
|
||||
*/
|
||||
public static final String CHE_MACHINE_NAME_PROPERTY = "CHE_MACHINE_NAME=";
|
||||
|
||||
/**
|
||||
* Name of the property to get the property that indicates if the machine is the dev machine
|
||||
*/
|
||||
public static final String CHE_IS_DEV_MACHINE_PROPERTY = "CHE_IS_DEV_MACHINE=";
|
||||
|
||||
/**
|
||||
* Prefix added in front of the generated name to build the workspaceId
|
||||
*/
|
||||
public static final String CHE_WORKSPACE_ID_PREFIX = "workspace";
|
||||
|
||||
|
||||
/**
|
||||
* name of the macro that indicates if the machine is the dev machine
|
||||
*/
|
||||
public static final String IS_DEV_MACHINE_MACRO = "isDevMachine";
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip}, if applicable.
|
||||
*/
|
||||
protected String cheDockerIp;
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip.external}. if applicable.
|
||||
*/
|
||||
protected String cheDockerIpExternal;
|
||||
|
||||
/**
|
||||
* The current port of che.
|
||||
*/
|
||||
private final String chePort;
|
||||
|
||||
/**
|
||||
* Secured or not ? (for example https vs http)
|
||||
*/
|
||||
private final String cheDockerCustomExternalProtocol;
|
||||
|
||||
/**
|
||||
* Template for external addresses.
|
||||
*/
|
||||
private String cheDockerCustomExternalTemplate;
|
||||
|
||||
/**
|
||||
* Option to enable the use of the container address, when searching for addresses.
|
||||
*/
|
||||
private boolean localDockerMode;
|
||||
|
||||
|
||||
/**
|
||||
* Option to tell if an exception should be thrown when the host defined in the `externalAddress` isn't known
|
||||
* and cannot be converted into a valid IP.
|
||||
*/
|
||||
private boolean throwOnUnknownHost = true;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public BaseServerEvaluationStrategy(String cheDockerIp,
|
||||
String cheDockerIpExternal,
|
||||
String cheDockerCustomExternalTemplate,
|
||||
String cheDockerCustomExternalProtocol,
|
||||
String chePort) {
|
||||
this(cheDockerIp, cheDockerIpExternal, cheDockerCustomExternalTemplate, cheDockerCustomExternalProtocol, chePort, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to be called by derived strategies
|
||||
*/
|
||||
public BaseServerEvaluationStrategy(String cheDockerIp,
|
||||
String cheDockerIpExternal,
|
||||
String cheDockerCustomExternalTemplate,
|
||||
String cheDockerCustomExternalProtocol,
|
||||
String chePort,
|
||||
boolean localDockerMode) {
|
||||
this.cheDockerIp = cheDockerIp;
|
||||
this.cheDockerIpExternal = cheDockerIpExternal;
|
||||
this.chePort = chePort;
|
||||
this.cheDockerCustomExternalTemplate = cheDockerCustomExternalTemplate;
|
||||
this.cheDockerCustomExternalProtocol = cheDockerCustomExternalProtocol;
|
||||
this.localDockerMode = localDockerMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getInternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
final String internalAddressContainer = containerInfo.getNetworkSettings().getIpAddress();
|
||||
|
||||
final String internalAddress;
|
||||
|
||||
if (localDockerMode) {
|
||||
internalAddress = !isNullOrEmpty(internalAddressContainer) ?
|
||||
internalAddressContainer :
|
||||
internalHost;
|
||||
} else {
|
||||
internalAddress =
|
||||
cheDockerIp != null ?
|
||||
cheDockerIp :
|
||||
internalHost;
|
||||
}
|
||||
|
||||
boolean useExposedPorts = localDockerMode && internalAddress != internalHost;
|
||||
|
||||
return getExposedPortsToAddressPorts(internalAddress, containerInfo.getNetworkSettings().getPorts(), useExposedPorts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override the host for all ports by using the external template.
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, String> getExternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
|
||||
// create Rendering evaluation
|
||||
RenderingEvaluation renderingEvaluation = getOnlineRenderingEvaluation(containerInfo, internalHost);
|
||||
|
||||
// get current ports
|
||||
Map<String, List<PortBinding>> ports = containerInfo.getNetworkSettings().getPorts();
|
||||
|
||||
if (isNullOrEmpty(cheDockerCustomExternalTemplate)) {
|
||||
return getExposedPortsToAddressPorts(renderingEvaluation.getExternalAddress(), ports, false);
|
||||
}
|
||||
|
||||
return ports.keySet().stream()
|
||||
.collect(Collectors.toMap(portKey -> portKey,
|
||||
portKey -> renderingEvaluation.render(cheDockerCustomExternalTemplate, portKey)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a map of {@link ServerImpl} from provided parameters, using selected strategy
|
||||
* for evaluating addresses and ports.
|
||||
*
|
||||
* <p>Keys consist of port number and transport protocol (tcp or udp) separated by
|
||||
* a forward slash (e.g. 8080/tcp)
|
||||
*
|
||||
* @param containerInfo
|
||||
* the {@link ContainerInfo} describing the container.
|
||||
* @param internalHost
|
||||
* alternative hostname to use, if address cannot be obtained from containerInfo
|
||||
* @param serverConfMap
|
||||
* additional Map of {@link OldServerConfImpl}. Configurations here override those found
|
||||
* in containerInfo.
|
||||
* @return a Map of the servers exposed by the container.
|
||||
*/
|
||||
public Map<String, ServerImpl> getServers(ContainerInfo containerInfo,
|
||||
String internalHost,
|
||||
Map<String, OldServerConfImpl> serverConfMap) {
|
||||
Map<String, ServerImpl> servers = super.getServers(containerInfo, internalHost, serverConfMap);
|
||||
return servers.entrySet().stream().collect(Collectors.toMap(map -> map.getKey(), map -> updateServer(map.getValue())));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the protocol for the given server by using given protocol (like https) for http URLs.
|
||||
* @param server the server to update
|
||||
* @return updated server object
|
||||
*/
|
||||
protected ServerImpl updateServer(ServerImpl server) {
|
||||
if (!Strings.isNullOrEmpty(cheDockerCustomExternalProtocol)) {
|
||||
// FIXME: spi
|
||||
// if ("http".equals(server.getProtocol())) {
|
||||
// server.setProtocol(cheDockerCustomExternalProtocol);
|
||||
// String url = server.getUrl();
|
||||
// int length = "http".length();
|
||||
// server.setUrl(cheDockerCustomExternalProtocol.concat(url.substring(length)));
|
||||
// }
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called online as in this case we have access to container info
|
||||
*/
|
||||
public RenderingEvaluation getOnlineRenderingEvaluation(ContainerInfo containerInfo, String internalHost) {
|
||||
return new OnlineRenderingEvaluation(containerInfo).withInternalHost(internalHost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called offline as without container info, user need to provide merge of container and images data
|
||||
*/
|
||||
public RenderingEvaluation getOfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
return new OfflineRenderingEvaluation(labels, exposedPorts, env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface for performing the rendering for a given portby using the given template
|
||||
*
|
||||
* @author Florent Benoit
|
||||
*/
|
||||
public interface RenderingEvaluation {
|
||||
/**
|
||||
* Gets the template rendering for the given port and using the given template
|
||||
*
|
||||
* @param template
|
||||
* which can include <propertyName></propertyName>
|
||||
* @param port
|
||||
* the port for the mapping
|
||||
* @return the rendering of the template
|
||||
*/
|
||||
String render(String template, String port);
|
||||
|
||||
/**
|
||||
* Gets default external address.
|
||||
*/
|
||||
String getExternalAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Online implementation (using the container info)
|
||||
*/
|
||||
protected class OnlineRenderingEvaluation extends OfflineRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
private String gatewayAddressContainer;
|
||||
private String internalHost;
|
||||
|
||||
protected OnlineRenderingEvaluation(ContainerInfo containerInfo) {
|
||||
super(containerInfo.getConfig().getLabels(), containerInfo.getConfig().getExposedPorts().keySet(),
|
||||
containerInfo.getConfig().getEnv());
|
||||
this.gatewayAddressContainer = containerInfo.getNetworkSettings().getGateway();
|
||||
}
|
||||
|
||||
protected OnlineRenderingEvaluation withInternalHost(String internalHost) {
|
||||
this.internalHost = internalHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExternalAddress() {
|
||||
if (localDockerMode) {
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal :
|
||||
!isNullOrEmpty(gatewayAddressContainer) ?
|
||||
gatewayAddressContainer :
|
||||
this.internalHost;
|
||||
}
|
||||
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal :
|
||||
cheDockerIp != null ?
|
||||
cheDockerIp :
|
||||
!isNullOrEmpty(gatewayAddressContainer) ?
|
||||
gatewayAddressContainer :
|
||||
this.internalHost;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offline implementation (container not yet created)
|
||||
*/
|
||||
protected class OfflineRenderingEvaluation extends DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
public OfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
super(labels, exposedPorts, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class used to perform the rendering
|
||||
*/
|
||||
protected abstract class DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
/**
|
||||
* Labels
|
||||
*/
|
||||
private Map<String, String> labels;
|
||||
|
||||
/**
|
||||
* Ports
|
||||
*/
|
||||
private Set<String> exposedPorts;
|
||||
|
||||
/**
|
||||
* Environment variables
|
||||
*/
|
||||
private final String[] env;
|
||||
|
||||
/**
|
||||
* Map with properties for all ports
|
||||
*/
|
||||
private Map<String, String> globalPropertiesMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Mapping between a port and the server ref name
|
||||
*/
|
||||
private Map<String, String> portsToRefName;
|
||||
|
||||
/**
|
||||
* Data initialized ?
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected DefaultRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
this.labels = labels;
|
||||
this.exposedPorts = exposedPorts;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize data
|
||||
*/
|
||||
protected void init() {
|
||||
this.initPortMapping();
|
||||
this.populateGlobalProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute port mapping with server ref name
|
||||
*/
|
||||
protected void initPortMapping() {
|
||||
// ok, so now we have a map of labels and a map of exposed ports
|
||||
// need to extract the name of the ref (if defined in a label) or then pickup default name "Server-<port>-<protocol>"
|
||||
Pattern pattern = Pattern.compile(LABEL_CHE_SERVER_REF_KEY);
|
||||
Map<String, String> portsToKnownRefName = labels.entrySet().stream()
|
||||
.filter(map -> pattern.matcher(map.getKey()).matches())
|
||||
.collect(Collectors.toMap(p -> {
|
||||
Matcher matcher = pattern.matcher(p.getKey());
|
||||
matcher.matches();
|
||||
String val = matcher.group(1);
|
||||
return val.contains("/") ? val : val.concat("/tcp");
|
||||
}, p -> p.getValue()));
|
||||
|
||||
// add to this map only port without a known ref name
|
||||
Map<String, String> portsToUnkownRefName =
|
||||
exposedPorts.stream().filter((port) -> !portsToKnownRefName.containsKey(port))
|
||||
.collect(Collectors.toMap(p -> p, p -> "server-" + p.replace('/', '-')));
|
||||
|
||||
// list of all ports with refName (known/unknown)
|
||||
this.portsToRefName = new HashMap(portsToKnownRefName);
|
||||
portsToRefName.putAll(portsToUnkownRefName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default external address.
|
||||
*/
|
||||
public String getExternalAddress() {
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal : cheDockerIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the template properties
|
||||
*/
|
||||
protected void populateGlobalProperties() {
|
||||
String externalAddress = getExternalAddress();
|
||||
String externalIP = getExternalIp(externalAddress);
|
||||
globalPropertiesMap.put("internalIp", cheDockerIp);
|
||||
globalPropertiesMap.put("externalAddress", externalAddress);
|
||||
globalPropertiesMap.put("externalIP", externalIP);
|
||||
globalPropertiesMap.put("workspaceId", getWorkspaceId());
|
||||
globalPropertiesMap.put("workspaceIdWithoutPrefix", getWorkspaceId().replaceFirst(CHE_WORKSPACE_ID_PREFIX,""));
|
||||
globalPropertiesMap.put("machineName", getMachineName());
|
||||
globalPropertiesMap.put("wildcardNipDomain", getWildcardNipDomain(externalAddress));
|
||||
globalPropertiesMap.put("wildcardXipDomain", getWildcardXipDomain(externalAddress));
|
||||
globalPropertiesMap.put("chePort", chePort);
|
||||
globalPropertiesMap.put(IS_DEV_MACHINE_MACRO, getIsDevMachine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering
|
||||
*/
|
||||
@Override
|
||||
public String render(String template, String port) {
|
||||
if (!this.initialized) {
|
||||
init();
|
||||
this.initialized = true;
|
||||
}
|
||||
ST stringTemplate = new ST(template);
|
||||
globalPropertiesMap.forEach((key, value) -> stringTemplate.add(key,
|
||||
IS_DEV_MACHINE_MACRO.equals(key) ?
|
||||
Boolean.parseBoolean(value)
|
||||
: value));
|
||||
stringTemplate.add("serverName", portsToRefName.get(port));
|
||||
return stringTemplate.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if the current machine is the dev machine
|
||||
*
|
||||
* @return true if the curent machine is the dev machine
|
||||
*/
|
||||
protected String getIsDevMachine() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_IS_DEV_MACHINE_PROPERTY))
|
||||
.map(s -> s.substring(CHE_IS_DEV_MACHINE_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace ID from the config of the given container
|
||||
*
|
||||
* @return workspace ID
|
||||
*/
|
||||
protected String getWorkspaceId() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_WORKSPACE_ID_PROPERTY))
|
||||
.map(s -> s.substring(CHE_WORKSPACE_ID_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace Machine Name from the config of the given container
|
||||
*
|
||||
* @return machine name of the workspace
|
||||
*/
|
||||
protected String getMachineName() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_MACHINE_NAME_PROPERTY))
|
||||
.map(s -> s.substring(CHE_MACHINE_NAME_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP address of the external address
|
||||
*
|
||||
* @return IP Address
|
||||
*/
|
||||
protected String getExternalIp(String externalAddress) {
|
||||
try {
|
||||
return InetAddress.getByName(externalAddress).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
if (throwOnUnknownHost) {
|
||||
throw new UnsupportedOperationException("Unable to find the IP for the address '" + externalAddress + "'", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider nip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardNipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "nip.io");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider xip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardXipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "xip.io");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useHttpsForExternalUrls() {
|
||||
return "https".equals(cheDockerCustomExternalProtocol);
|
||||
}
|
||||
|
||||
public BaseServerEvaluationStrategy withThrowOnUnknownHost(boolean throwOnUnknownHost) {
|
||||
this.throwOnUnknownHost = throwOnUnknownHost;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -31,42 +31,11 @@ import java.util.Map;
|
|||
* @author Alexander Garagatyi
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public class DefaultServerEvaluationStrategy extends ServerEvaluationStrategy {
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip}, if applicable.
|
||||
*/
|
||||
protected String internalAddressProperty;
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip.external}. if applicable.
|
||||
*/
|
||||
protected String externalAddressProperty;
|
||||
public class DefaultServerEvaluationStrategy extends BaseServerEvaluationStrategy {
|
||||
|
||||
@Inject
|
||||
public DefaultServerEvaluationStrategy(@Nullable @Named("che.docker.ip") String internalAddress,
|
||||
@Nullable @Named("che.docker.ip.external") String externalAddress) {
|
||||
this.internalAddressProperty = internalAddress;
|
||||
this.externalAddressProperty = externalAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getInternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
String internalAddress = internalAddressProperty != null ?
|
||||
internalAddressProperty :
|
||||
internalHost;
|
||||
|
||||
return getExposedPortsToAddressPorts(internalAddress, containerInfo.getNetworkSettings().getPorts());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getExternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
String externalAddress = externalAddressProperty != null ?
|
||||
externalAddressProperty :
|
||||
internalAddressProperty != null ?
|
||||
internalAddressProperty :
|
||||
internalHost;
|
||||
|
||||
return super.getExposedPortsToAddressPorts(externalAddress, containerInfo.getNetworkSettings().getPorts());
|
||||
super(internalAddress, externalAddress, null, null, null, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.strategy;
|
||||
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
|
||||
/**
|
||||
* Represents a strategy for resolving Servers associated with workspace containers.
|
||||
* Used to extract relevant information from e.g. {@link ContainerInfo} into a map of
|
||||
|
|
@ -27,14 +27,26 @@ import java.util.Map;
|
|||
*
|
||||
* @author Angel Misevski <amisevsk@redhat.com>
|
||||
* @author Alexander Garagatyi
|
||||
* @author Ilya Buziuk
|
||||
* @see ServerEvaluationStrategyProvider
|
||||
*/
|
||||
public abstract class ServerEvaluationStrategy {
|
||||
private static final String HTTP = "http";
|
||||
private static final String HTTPS = "https";
|
||||
|
||||
protected static final String SERVER_CONF_LABEL_REF_KEY = "che:server:%s:ref";
|
||||
protected static final String SERVER_CONF_LABEL_PROTOCOL_KEY = "che:server:%s:protocol";
|
||||
protected static final String SERVER_CONF_LABEL_PATH_KEY = "che:server:%s:path";
|
||||
|
||||
|
||||
/**
|
||||
* @return true if <strong>external</strong> addresses need to be exposed against https, false otherwise
|
||||
*/
|
||||
protected boolean useHttpsForExternalUrls() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a map of all <strong>internal</strong> addresses exposed by the container in the form of
|
||||
* {@code "<address>:<port>"}
|
||||
|
|
@ -109,7 +121,11 @@ public abstract class ServerEvaluationStrategy {
|
|||
// Add protocol and path to internal/external address, if applicable
|
||||
String internalUrl = null;
|
||||
String externalUrl = null;
|
||||
if (serverConf.getProtocol() != null) {
|
||||
|
||||
String internalProtocol = serverConf.getProtocol();
|
||||
String externalProtocol = getProtocolForExternalUrl(internalProtocol);
|
||||
|
||||
if (internalProtocol != null) {
|
||||
String pathSuffix = serverConf.getPath();
|
||||
if (pathSuffix != null && !pathSuffix.isEmpty()) {
|
||||
if (pathSuffix.charAt(0) != '/') {
|
||||
|
|
@ -118,8 +134,9 @@ public abstract class ServerEvaluationStrategy {
|
|||
} else {
|
||||
pathSuffix = "";
|
||||
}
|
||||
internalUrl = serverConf.getProtocol() + "://" + internalAddressAndPort + pathSuffix;
|
||||
externalUrl = serverConf.getProtocol() + "://" + externalAddressAndPort + pathSuffix;
|
||||
|
||||
internalUrl = internalProtocol + "://" + internalAddressAndPort + pathSuffix;
|
||||
externalUrl = externalProtocol + "://" + externalAddressAndPort + pathSuffix;
|
||||
}
|
||||
|
||||
servers.put(serverConf.getRef(), new ServerImpl(externalUrl));
|
||||
|
|
@ -215,14 +232,37 @@ public abstract class ServerEvaluationStrategy {
|
|||
* "9090/udp" : "my-host.com:32722"
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
*/
|
||||
protected Map<String, String> getExposedPortsToAddressPorts(String address, Map<String, List<PortBinding>> ports) {
|
||||
protected Map<String, String> getExposedPortsToAddressPorts(String address, Map<String, List<PortBinding>> ports, boolean useExposedPorts) {
|
||||
Map<String, String> addressesAndPorts = new HashMap<>();
|
||||
for (Map.Entry<String, List<PortBinding>> portEntry : ports.entrySet()) {
|
||||
String exposedPort = portEntry.getKey().split("/")[0];
|
||||
// there is one value always
|
||||
String port = portEntry.getValue().get(0).getHostPort();
|
||||
addressesAndPorts.put(portEntry.getKey(), address + ":" + port);
|
||||
String ephemeralPort = portEntry.getValue().get(0).getHostPort();
|
||||
if (useExposedPorts) {
|
||||
addressesAndPorts.put(portEntry.getKey(), address + ":" + exposedPort);
|
||||
} else {
|
||||
addressesAndPorts.put(portEntry.getKey(), address + ":" + ephemeralPort);
|
||||
}
|
||||
}
|
||||
return addressesAndPorts;
|
||||
}
|
||||
|
||||
protected Map<String, String> getExposedPortsToAddressPorts(String address, Map<String, List<PortBinding>> ports) {
|
||||
return getExposedPortsToAddressPorts(address, ports, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param protocolForInternalUrl
|
||||
* @return https, if {@link #useHttpsForExternalUrls()} method in sub-class returns true and protocol for internal Url is http
|
||||
*/
|
||||
private String getProtocolForExternalUrl(final String protocolForInternalUrl) {
|
||||
if (useHttpsForExternalUrls() && HTTP.equals(protocolForInternalUrl)) {
|
||||
return HTTPS;
|
||||
}
|
||||
return protocolForInternalUrl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class ServerEvaluationStrategyTest {
|
|||
expected.put("9090/udp", DEFAULT_HOSTNAME + ":" + "32101");
|
||||
|
||||
// when
|
||||
Map<String, String> actual = strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports);
|
||||
Map<String, String> actual = strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports, false);
|
||||
|
||||
// then
|
||||
assertEquals(actual, expected);
|
||||
|
|
@ -85,7 +85,7 @@ public class ServerEvaluationStrategyTest {
|
|||
expected.put("9090/udp", DEFAULT_HOSTNAME + ":" + "32101");
|
||||
|
||||
// when
|
||||
Map<String, String> actual = strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports);
|
||||
Map<String, String> actual = strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports, false);
|
||||
|
||||
// then
|
||||
assertEquals(actual, expected);
|
||||
|
|
@ -352,7 +352,7 @@ public class ServerEvaluationStrategyTest {
|
|||
.withHostPort("32101")));
|
||||
when(networkSettings.getPorts()).thenReturn(ports);
|
||||
Map<String, String> exposedPortsToAddressPorts =
|
||||
strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports);
|
||||
strategy.getExposedPortsToAddressPorts(DEFAULT_HOSTNAME, ports, false);
|
||||
when(strategy.getExternalAddressesAndPorts(containerInfo, DEFAULT_HOSTNAME))
|
||||
.thenReturn(exposedPortsToAddressPorts);
|
||||
when(strategy.getInternalAddressesAndPorts(containerInfo, DEFAULT_HOSTNAME))
|
||||
|
|
@ -373,6 +373,11 @@ public class ServerEvaluationStrategyTest {
|
|||
String internalAddress) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useHttpsForExternalUrls() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class ComposerValueProviderFactory implements ValueProviderFactory {
|
|||
JsonObject model = readModel(projectFolder);
|
||||
String value = "";
|
||||
|
||||
if (attributeName.equals(PACKAGE)) {
|
||||
if (attributeName.equals(PACKAGE) && model.has("name")) {
|
||||
value = model.get("name").getAsString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public class Exec {
|
|||
private final String[] command;
|
||||
private final String id;
|
||||
|
||||
Exec(String[] command, String id) {
|
||||
public Exec(String[] command, String id) {
|
||||
this.command = command;
|
||||
this.id = id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,517 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* Represents a server evaluation strategy for the configuration where the strategy can be customized through template properties.
|
||||
*
|
||||
* @author Florent Benoit
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public abstract class BaseServerEvaluationStrategy extends ServerEvaluationStrategy {
|
||||
|
||||
/**
|
||||
* Regexp to extract port (under the form 22/tcp or 4401/tcp, etc.) from label references
|
||||
*/
|
||||
public static final String LABEL_CHE_SERVER_REF_KEY = "^che:server:(.*):ref$";
|
||||
|
||||
/**
|
||||
* Name of the property for getting the workspace ID.
|
||||
*/
|
||||
public static final String CHE_WORKSPACE_ID_PROPERTY = "CHE_WORKSPACE_ID=";
|
||||
|
||||
/**
|
||||
* Name of the property to get the machine name property
|
||||
*/
|
||||
public static final String CHE_MACHINE_NAME_PROPERTY = "CHE_MACHINE_NAME=";
|
||||
|
||||
/**
|
||||
* Name of the property to get the property that indicates if the machine is the dev machine
|
||||
*/
|
||||
public static final String CHE_IS_DEV_MACHINE_PROPERTY = "CHE_IS_DEV_MACHINE=";
|
||||
|
||||
/**
|
||||
* Prefix added in front of the generated name to build the workspaceId
|
||||
*/
|
||||
public static final String CHE_WORKSPACE_ID_PREFIX = "workspace";
|
||||
|
||||
|
||||
/**
|
||||
* name of the macro that indicates if the machine is the dev machine
|
||||
*/
|
||||
public static final String IS_DEV_MACHINE_MACRO = "isDevMachine";
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip}, if applicable.
|
||||
*/
|
||||
protected String cheDockerIp;
|
||||
|
||||
/**
|
||||
* Used to store the address set by property {@code che.docker.ip.external}. if applicable.
|
||||
*/
|
||||
protected String cheDockerIpExternal;
|
||||
|
||||
/**
|
||||
* The current port of che.
|
||||
*/
|
||||
private final String chePort;
|
||||
|
||||
/**
|
||||
* Secured or not ? (for example https vs http)
|
||||
*/
|
||||
private final String cheDockerCustomExternalProtocol;
|
||||
|
||||
/**
|
||||
* Template for external addresses.
|
||||
*/
|
||||
private String cheDockerCustomExternalTemplate;
|
||||
|
||||
/**
|
||||
* Option to enable the use of the container address, when searching for addresses.
|
||||
*/
|
||||
private boolean localDockerMode;
|
||||
|
||||
|
||||
/**
|
||||
* Option to tell if an exception should be thrown when the host defined in the `externalAddress` isn't known
|
||||
* and cannot be converted into a valid IP.
|
||||
*/
|
||||
private boolean throwOnUnknownHost = true;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public BaseServerEvaluationStrategy(String cheDockerIp,
|
||||
String cheDockerIpExternal,
|
||||
String cheDockerCustomExternalTemplate,
|
||||
String cheDockerCustomExternalProtocol,
|
||||
String chePort) {
|
||||
this(cheDockerIp, cheDockerIpExternal, cheDockerCustomExternalTemplate, cheDockerCustomExternalProtocol, chePort, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to be called by derived strategies
|
||||
*/
|
||||
public BaseServerEvaluationStrategy(String cheDockerIp,
|
||||
String cheDockerIpExternal,
|
||||
String cheDockerCustomExternalTemplate,
|
||||
String cheDockerCustomExternalProtocol,
|
||||
String chePort,
|
||||
boolean localDockerMode) {
|
||||
this.cheDockerIp = cheDockerIp;
|
||||
this.cheDockerIpExternal = cheDockerIpExternal;
|
||||
this.chePort = chePort;
|
||||
this.cheDockerCustomExternalTemplate = cheDockerCustomExternalTemplate;
|
||||
this.cheDockerCustomExternalProtocol = cheDockerCustomExternalProtocol;
|
||||
this.localDockerMode = localDockerMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getInternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
final String internalAddressContainer = containerInfo.getNetworkSettings().getIpAddress();
|
||||
|
||||
final String internalAddress;
|
||||
|
||||
if (localDockerMode) {
|
||||
internalAddress = !isNullOrEmpty(internalAddressContainer) ?
|
||||
internalAddressContainer :
|
||||
internalHost;
|
||||
} else {
|
||||
internalAddress =
|
||||
cheDockerIp != null ?
|
||||
cheDockerIp :
|
||||
internalHost;
|
||||
}
|
||||
|
||||
boolean useExposedPorts = localDockerMode && internalAddress != internalHost;
|
||||
|
||||
return getExposedPortsToAddressPorts(internalAddress, containerInfo.getNetworkSettings().getPorts(), useExposedPorts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override the host for all ports by using the external template.
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, String> getExternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
|
||||
// create Rendering evaluation
|
||||
RenderingEvaluation renderingEvaluation = getOnlineRenderingEvaluation(containerInfo, internalHost);
|
||||
|
||||
// get current ports
|
||||
Map<String, List<PortBinding>> ports = containerInfo.getNetworkSettings().getPorts();
|
||||
|
||||
if (isNullOrEmpty(cheDockerCustomExternalTemplate)) {
|
||||
return getExposedPortsToAddressPorts(renderingEvaluation.getExternalAddress(), ports, false);
|
||||
}
|
||||
|
||||
return ports.keySet().stream()
|
||||
.collect(Collectors.toMap(portKey -> portKey,
|
||||
portKey -> renderingEvaluation.render(cheDockerCustomExternalTemplate, portKey)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a map of {@link ServerImpl} from provided parameters, using selected strategy
|
||||
* for evaluating addresses and ports.
|
||||
*
|
||||
* <p>Keys consist of port number and transport protocol (tcp or udp) separated by
|
||||
* a forward slash (e.g. 8080/tcp)
|
||||
*
|
||||
* @param containerInfo
|
||||
* the {@link ContainerInfo} describing the container.
|
||||
* @param internalHost
|
||||
* alternative hostname to use, if address cannot be obtained from containerInfo
|
||||
* @param serverConfMap
|
||||
* additional Map of {@link ServerConfImpl}. Configurations here override those found
|
||||
* in containerInfo.
|
||||
* @return a Map of the servers exposed by the container.
|
||||
*/
|
||||
public Map<String, ServerImpl> getServers(ContainerInfo containerInfo,
|
||||
String internalHost,
|
||||
Map<String, ServerConfImpl> serverConfMap) {
|
||||
Map<String, ServerImpl> servers = super.getServers(containerInfo, internalHost, serverConfMap);
|
||||
return servers.entrySet().stream().collect(Collectors.toMap(map -> map.getKey(), map -> updateServer(map.getValue())));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the protocol for the given server by using given protocol (like https) for http URLs.
|
||||
* @param server the server to update
|
||||
* @return updated server object
|
||||
*/
|
||||
protected ServerImpl updateServer(ServerImpl server) {
|
||||
if (!Strings.isNullOrEmpty(cheDockerCustomExternalProtocol)) {
|
||||
if ("http".equals(server.getProtocol())) {
|
||||
server.setProtocol(cheDockerCustomExternalProtocol);
|
||||
String url = server.getUrl();
|
||||
int length = "http".length();
|
||||
server.setUrl(cheDockerCustomExternalProtocol.concat(url.substring(length)));
|
||||
}
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called online as in this case we have access to container info
|
||||
*/
|
||||
public RenderingEvaluation getOnlineRenderingEvaluation(ContainerInfo containerInfo, String internalHost) {
|
||||
return new OnlineRenderingEvaluation(containerInfo).withInternalHost(internalHost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called offline as without container info, user need to provide merge of container and images data
|
||||
*/
|
||||
public RenderingEvaluation getOfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
return new OfflineRenderingEvaluation(labels, exposedPorts, env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface for performing the rendering for a given portby using the given template
|
||||
*
|
||||
* @author Florent Benoit
|
||||
*/
|
||||
public interface RenderingEvaluation {
|
||||
/**
|
||||
* Gets the template rendering for the given port and using the given template
|
||||
*
|
||||
* @param template
|
||||
* which can include <propertyName></propertyName>
|
||||
* @param port
|
||||
* the port for the mapping
|
||||
* @return the rendering of the template
|
||||
*/
|
||||
String render(String template, String port);
|
||||
|
||||
/**
|
||||
* Gets default external address.
|
||||
*/
|
||||
String getExternalAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Online implementation (using the container info)
|
||||
*/
|
||||
protected class OnlineRenderingEvaluation extends OfflineRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
private String gatewayAddressContainer;
|
||||
private String internalHost;
|
||||
|
||||
protected OnlineRenderingEvaluation(ContainerInfo containerInfo) {
|
||||
super(containerInfo.getConfig().getLabels(), containerInfo.getConfig().getExposedPorts().keySet(),
|
||||
containerInfo.getConfig().getEnv());
|
||||
this.gatewayAddressContainer = containerInfo.getNetworkSettings().getGateway();
|
||||
}
|
||||
|
||||
protected OnlineRenderingEvaluation withInternalHost(String internalHost) {
|
||||
this.internalHost = internalHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExternalAddress() {
|
||||
if (localDockerMode) {
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal :
|
||||
!isNullOrEmpty(gatewayAddressContainer) ?
|
||||
gatewayAddressContainer :
|
||||
this.internalHost;
|
||||
}
|
||||
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal :
|
||||
cheDockerIp != null ?
|
||||
cheDockerIp :
|
||||
!isNullOrEmpty(gatewayAddressContainer) ?
|
||||
gatewayAddressContainer :
|
||||
this.internalHost;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offline implementation (container not yet created)
|
||||
*/
|
||||
protected class OfflineRenderingEvaluation extends DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
public OfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
super(labels, exposedPorts, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class used to perform the rendering
|
||||
*/
|
||||
protected abstract class DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
/**
|
||||
* Labels
|
||||
*/
|
||||
private Map<String, String> labels;
|
||||
|
||||
/**
|
||||
* Ports
|
||||
*/
|
||||
private Set<String> exposedPorts;
|
||||
|
||||
/**
|
||||
* Environment variables
|
||||
*/
|
||||
private final String[] env;
|
||||
|
||||
/**
|
||||
* Map with properties for all ports
|
||||
*/
|
||||
private Map<String, String> globalPropertiesMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Mapping between a port and the server ref name
|
||||
*/
|
||||
private Map<String, String> portsToRefName;
|
||||
|
||||
/**
|
||||
* Data initialized ?
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected DefaultRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
this.labels = labels;
|
||||
this.exposedPorts = exposedPorts;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize data
|
||||
*/
|
||||
protected void init() {
|
||||
this.initPortMapping();
|
||||
this.populateGlobalProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute port mapping with server ref name
|
||||
*/
|
||||
protected void initPortMapping() {
|
||||
// ok, so now we have a map of labels and a map of exposed ports
|
||||
// need to extract the name of the ref (if defined in a label) or then pickup default name "Server-<port>-<protocol>"
|
||||
Pattern pattern = Pattern.compile(LABEL_CHE_SERVER_REF_KEY);
|
||||
Map<String, String> portsToKnownRefName = labels.entrySet().stream()
|
||||
.filter(map -> pattern.matcher(map.getKey()).matches())
|
||||
.collect(Collectors.toMap(p -> {
|
||||
Matcher matcher = pattern.matcher(p.getKey());
|
||||
matcher.matches();
|
||||
String val = matcher.group(1);
|
||||
return val.contains("/") ? val : val.concat("/tcp");
|
||||
}, p -> p.getValue()));
|
||||
|
||||
// add to this map only port without a known ref name
|
||||
Map<String, String> portsToUnkownRefName =
|
||||
exposedPorts.stream().filter((port) -> !portsToKnownRefName.containsKey(port))
|
||||
.collect(Collectors.toMap(p -> p, p -> "server-" + p.replace('/', '-')));
|
||||
|
||||
// list of all ports with refName (known/unknown)
|
||||
this.portsToRefName = new HashMap(portsToKnownRefName);
|
||||
portsToRefName.putAll(portsToUnkownRefName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default external address.
|
||||
*/
|
||||
public String getExternalAddress() {
|
||||
return cheDockerIpExternal != null ?
|
||||
cheDockerIpExternal : cheDockerIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the template properties
|
||||
*/
|
||||
protected void populateGlobalProperties() {
|
||||
String externalAddress = getExternalAddress();
|
||||
String externalIP = getExternalIp(externalAddress);
|
||||
globalPropertiesMap.put("internalIp", cheDockerIp);
|
||||
globalPropertiesMap.put("externalAddress", externalAddress);
|
||||
globalPropertiesMap.put("externalIP", externalIP);
|
||||
globalPropertiesMap.put("workspaceId", getWorkspaceId());
|
||||
globalPropertiesMap.put("workspaceIdWithoutPrefix", getWorkspaceId().replaceFirst(CHE_WORKSPACE_ID_PREFIX,""));
|
||||
globalPropertiesMap.put("machineName", getMachineName());
|
||||
globalPropertiesMap.put("wildcardNipDomain", getWildcardNipDomain(externalAddress));
|
||||
globalPropertiesMap.put("wildcardXipDomain", getWildcardXipDomain(externalAddress));
|
||||
globalPropertiesMap.put("chePort", chePort);
|
||||
globalPropertiesMap.put(IS_DEV_MACHINE_MACRO, getIsDevMachine());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering
|
||||
*/
|
||||
@Override
|
||||
public String render(String template, String port) {
|
||||
if (!this.initialized) {
|
||||
init();
|
||||
this.initialized = true;
|
||||
}
|
||||
ST stringTemplate = new ST(template);
|
||||
globalPropertiesMap.forEach((key, value) -> stringTemplate.add(key,
|
||||
IS_DEV_MACHINE_MACRO.equals(key) ?
|
||||
Boolean.parseBoolean(value)
|
||||
: value));
|
||||
stringTemplate.add("serverName", portsToRefName.get(port));
|
||||
return stringTemplate.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if the current machine is the dev machine
|
||||
*
|
||||
* @return true if the curent machine is the dev machine
|
||||
*/
|
||||
protected String getIsDevMachine() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_IS_DEV_MACHINE_PROPERTY))
|
||||
.map(s -> s.substring(CHE_IS_DEV_MACHINE_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace ID from the config of the given container
|
||||
*
|
||||
* @return workspace ID
|
||||
*/
|
||||
protected String getWorkspaceId() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_WORKSPACE_ID_PROPERTY))
|
||||
.map(s -> s.substring(CHE_WORKSPACE_ID_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace Machine Name from the config of the given container
|
||||
*
|
||||
* @return machine name of the workspace
|
||||
*/
|
||||
protected String getMachineName() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_MACHINE_NAME_PROPERTY))
|
||||
.map(s -> s.substring(CHE_MACHINE_NAME_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP address of the external address
|
||||
*
|
||||
* @return IP Address
|
||||
*/
|
||||
protected String getExternalIp(String externalAddress) {
|
||||
try {
|
||||
return InetAddress.getByName(externalAddress).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
if (throwOnUnknownHost) {
|
||||
throw new UnsupportedOperationException("Unable to find the IP for the address '" + externalAddress + "'", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider nip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardNipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "nip.io");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider xip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardXipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "xip.io");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useHttpsForExternalUrls() {
|
||||
return "https".equals(cheDockerCustomExternalProtocol);
|
||||
}
|
||||
|
||||
public BaseServerEvaluationStrategy withThrowOnUnknownHost(boolean throwOnUnknownHost) {
|
||||
this.throwOnUnknownHost = throwOnUnknownHost;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,29 +10,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* Represents a server evaluation strategy for the configuration where the strategy can be customized through template properties.
|
||||
|
|
@ -40,39 +21,7 @@ import static com.google.common.base.Strings.isNullOrEmpty;
|
|||
* @author Florent Benoit
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public class CustomServerEvaluationStrategy extends DefaultServerEvaluationStrategy {
|
||||
|
||||
/**
|
||||
* Regexp to extract port (under the form 22/tcp or 4401/tcp, etc.) from label references
|
||||
*/
|
||||
public static final String LABEL_CHE_SERVER_REF_KEY = "^che:server:(.*):ref$";
|
||||
|
||||
/**
|
||||
* Name of the property for getting the workspace ID.
|
||||
*/
|
||||
public static final String CHE_WORKSPACE_ID_PROPERTY = "CHE_WORKSPACE_ID=";
|
||||
|
||||
/**
|
||||
* Name of the property to get the machine name property
|
||||
*/
|
||||
public static final String CHE_MACHINE_NAME_PROPERTY = "CHE_MACHINE_NAME=";
|
||||
|
||||
/**
|
||||
* The current port of che.
|
||||
*/
|
||||
private final String chePort;
|
||||
|
||||
/**
|
||||
* Secured or not ? (for example https vs http)
|
||||
*/
|
||||
private final String cheDockerCustomExternalProtocol;
|
||||
|
||||
/**
|
||||
* Template for external addresses.
|
||||
*/
|
||||
private String cheDockerCustomExternalTemplate;
|
||||
|
||||
|
||||
public class CustomServerEvaluationStrategy extends BaseServerEvaluationStrategy {
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
|
|
@ -82,317 +31,6 @@ public class CustomServerEvaluationStrategy extends DefaultServerEvaluationStrat
|
|||
@Nullable @Named("che.docker.server_evaluation_strategy.custom.template") String cheDockerCustomExternalTemplate,
|
||||
@Nullable @Named("che.docker.server_evaluation_strategy.custom.external.protocol") String cheDockerCustomExternalProtocol,
|
||||
@Named("che.port") String chePort) {
|
||||
super(cheDockerIp, cheDockerIpExternal);
|
||||
this.chePort = chePort;
|
||||
this.cheDockerCustomExternalTemplate = cheDockerCustomExternalTemplate;
|
||||
this.cheDockerCustomExternalProtocol = cheDockerCustomExternalProtocol;
|
||||
super(cheDockerIp, cheDockerIpExternal, cheDockerCustomExternalTemplate, cheDockerCustomExternalProtocol, chePort, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the host for all ports by using the external template.
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, String> getExternalAddressesAndPorts(ContainerInfo containerInfo, String internalHost) {
|
||||
|
||||
// create Rendering evaluation
|
||||
RenderingEvaluation renderingEvaluation = getOnlineRenderingEvaluation(containerInfo, internalHost);
|
||||
|
||||
// get current ports
|
||||
Map<String, List<PortBinding>> ports = containerInfo.getNetworkSettings().getPorts();
|
||||
|
||||
return ports.keySet().stream()
|
||||
.collect(Collectors.toMap(portKey -> portKey,
|
||||
portKey -> renderingEvaluation.render(cheDockerCustomExternalTemplate, portKey)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a map of {@link ServerImpl} from provided parameters, using selected strategy
|
||||
* for evaluating addresses and ports.
|
||||
*
|
||||
* <p>Keys consist of port number and transport protocol (tcp or udp) separated by
|
||||
* a forward slash (e.g. 8080/tcp)
|
||||
*
|
||||
* @param containerInfo
|
||||
* the {@link ContainerInfo} describing the container.
|
||||
* @param internalHost
|
||||
* alternative hostname to use, if address cannot be obtained from containerInfo
|
||||
* @param serverConfMap
|
||||
* additional Map of {@link ServerConfImpl}. Configurations here override those found
|
||||
* in containerInfo.
|
||||
* @return a Map of the servers exposed by the container.
|
||||
*/
|
||||
public Map<String, ServerImpl> getServers(ContainerInfo containerInfo,
|
||||
String internalHost,
|
||||
Map<String, ServerConfImpl> serverConfMap) {
|
||||
Map<String, ServerImpl> servers = super.getServers(containerInfo, internalHost, serverConfMap);
|
||||
return servers.entrySet().stream().collect(Collectors.toMap(map -> map.getKey(), map -> updateServer(map.getValue())));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the protocol for the given server by using given protocol (like https) for http URLs.
|
||||
* @param server the server to update
|
||||
* @return updated server object
|
||||
*/
|
||||
protected ServerImpl updateServer(ServerImpl server) {
|
||||
if (!Strings.isNullOrEmpty(cheDockerCustomExternalProtocol)) {
|
||||
if ("http".equals(server.getProtocol())) {
|
||||
server.setProtocol(cheDockerCustomExternalProtocol);
|
||||
String url = server.getUrl();
|
||||
int length = "http".length();
|
||||
server.setUrl(cheDockerCustomExternalProtocol.concat(url.substring(length)));
|
||||
}
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called online as in this case we have access to container info
|
||||
*/
|
||||
public RenderingEvaluation getOnlineRenderingEvaluation(ContainerInfo containerInfo, String internalHost) {
|
||||
return new OnlineRenderingEvaluation(containerInfo).withInternalHost(internalHost);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to get the rendering outside of the evaluation strategies.
|
||||
* It is called offline as without container info, user need to provide merge of container and images data
|
||||
*/
|
||||
public RenderingEvaluation getOfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
return new OfflineRenderingEvaluation(labels, exposedPorts, env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface for performing the rendering for a given portby using the given template
|
||||
*
|
||||
* @author Florent Benoit
|
||||
*/
|
||||
public interface RenderingEvaluation {
|
||||
/**
|
||||
* Gets the template rendering for the given port and using the given template
|
||||
*
|
||||
* @param template
|
||||
* which can include <propertyName></propertyName>
|
||||
* @param port
|
||||
* the port for the mapping
|
||||
* @return the rendering of the template
|
||||
*/
|
||||
String render(String template, String port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Online implementation (using the container info)
|
||||
*/
|
||||
protected class OnlineRenderingEvaluation extends OfflineRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
private String gatewayAddressContainer;
|
||||
private String internalHost;
|
||||
|
||||
protected OnlineRenderingEvaluation(ContainerInfo containerInfo) {
|
||||
super(containerInfo.getConfig().getLabels(), containerInfo.getConfig().getExposedPorts().keySet(),
|
||||
containerInfo.getConfig().getEnv());
|
||||
this.gatewayAddressContainer = containerInfo.getNetworkSettings().getGateway();
|
||||
}
|
||||
|
||||
protected OnlineRenderingEvaluation withInternalHost(String internalHost) {
|
||||
this.internalHost = internalHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExternalAddress() {
|
||||
return externalAddressProperty != null ?
|
||||
externalAddressProperty :
|
||||
internalAddressProperty != null ?
|
||||
internalAddressProperty :
|
||||
!isNullOrEmpty(gatewayAddressContainer) ?
|
||||
gatewayAddressContainer :
|
||||
this.internalHost;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offline implementation (container not yet created)
|
||||
*/
|
||||
protected class OfflineRenderingEvaluation extends DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
public OfflineRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
super(labels, exposedPorts, env);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class used to perform the rendering
|
||||
*/
|
||||
protected abstract class DefaultRenderingEvaluation implements RenderingEvaluation {
|
||||
|
||||
/**
|
||||
* Labels
|
||||
*/
|
||||
private Map<String, String> labels;
|
||||
|
||||
/**
|
||||
* Ports
|
||||
*/
|
||||
private Set<String> exposedPorts;
|
||||
|
||||
/**
|
||||
* Environment variables
|
||||
*/
|
||||
private final String[] env;
|
||||
|
||||
/**
|
||||
* Map with properties for all ports
|
||||
*/
|
||||
private Map<String, String> globalPropertiesMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Mapping between a port and the server ref name
|
||||
*/
|
||||
private Map<String, String> portsToRefName;
|
||||
|
||||
/**
|
||||
* Data initialized ?
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected DefaultRenderingEvaluation(Map<String, String> labels, Set<String> exposedPorts, String[] env) {
|
||||
this.labels = labels;
|
||||
this.exposedPorts = exposedPorts;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize data
|
||||
*/
|
||||
protected void init() {
|
||||
this.initPortMapping();
|
||||
this.populateGlobalProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute port mapping with server ref name
|
||||
*/
|
||||
protected void initPortMapping() {
|
||||
// ok, so now we have a map of labels and a map of exposed ports
|
||||
// need to extract the name of the ref (if defined in a label) or then pickup default name "Server-<port>-<protocol>"
|
||||
Pattern pattern = Pattern.compile(LABEL_CHE_SERVER_REF_KEY);
|
||||
Map<String, String> portsToKnownRefName = labels.entrySet().stream()
|
||||
.filter(map -> pattern.matcher(map.getKey()).matches())
|
||||
.collect(Collectors.toMap(p -> {
|
||||
Matcher matcher = pattern.matcher(p.getKey());
|
||||
matcher.matches();
|
||||
String val = matcher.group(1);
|
||||
return val.contains("/") ? val : val.concat("/tcp");
|
||||
}, p -> p.getValue()));
|
||||
|
||||
// add to this map only port without a known ref name
|
||||
Map<String, String> portsToUnkownRefName =
|
||||
exposedPorts.stream().filter((port) -> !portsToKnownRefName.containsKey(port))
|
||||
.collect(Collectors.toMap(p -> p, p -> "Server-" + p.replace('/', '-')));
|
||||
|
||||
// list of all ports with refName (known/unknown)
|
||||
this.portsToRefName = new HashMap(portsToKnownRefName);
|
||||
portsToRefName.putAll(portsToUnkownRefName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default external address.
|
||||
*/
|
||||
protected String getExternalAddress() {
|
||||
return externalAddressProperty != null ?
|
||||
externalAddressProperty : internalAddressProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the template properties
|
||||
*/
|
||||
protected void populateGlobalProperties() {
|
||||
String externalAddress = getExternalAddress();
|
||||
String externalIP = getExternalIp(externalAddress);
|
||||
globalPropertiesMap.put("internalIp", internalAddressProperty);
|
||||
globalPropertiesMap.put("externalAddress", externalAddress);
|
||||
globalPropertiesMap.put("externalIP", externalIP);
|
||||
globalPropertiesMap.put("workspaceId", getWorkspaceId());
|
||||
globalPropertiesMap.put("machineName", getMachineName());
|
||||
globalPropertiesMap.put("wildcardNipDomain", getWildcardNipDomain(externalAddress));
|
||||
globalPropertiesMap.put("wildcardXipDomain", getWildcardXipDomain(externalAddress));
|
||||
globalPropertiesMap.put("chePort", chePort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering
|
||||
*/
|
||||
@Override
|
||||
public String render(String template, String port) {
|
||||
if (!this.initialized) {
|
||||
init();
|
||||
this.initialized = true;
|
||||
}
|
||||
ST stringTemplate = new ST(template);
|
||||
globalPropertiesMap.forEach((key, value) -> stringTemplate.add(key, value));
|
||||
stringTemplate.add("serverName", portsToRefName.get(port));
|
||||
return stringTemplate.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace ID from the config of the given container
|
||||
*
|
||||
* @return workspace ID
|
||||
*/
|
||||
protected String getWorkspaceId() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_WORKSPACE_ID_PROPERTY))
|
||||
.map(s -> s.substring(CHE_WORKSPACE_ID_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workspace Machine Name from the config of the given container
|
||||
*
|
||||
* @return machine name of the workspace
|
||||
*/
|
||||
protected String getMachineName() {
|
||||
return Arrays.stream(env).filter(env -> env.startsWith(CHE_MACHINE_NAME_PROPERTY))
|
||||
.map(s -> s.substring(CHE_MACHINE_NAME_PROPERTY.length()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP address of the external address
|
||||
*
|
||||
* @return IP Address
|
||||
*/
|
||||
protected String getExternalIp(String externalAddress) {
|
||||
try {
|
||||
return InetAddress.getByName(externalAddress).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new UnsupportedOperationException("Unable to find the IP for the address '" + externalAddress + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider nip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardNipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "nip.io");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Wildcard domain based on the ip using an external provider xip.io
|
||||
*
|
||||
* @return wildcard domain
|
||||
*/
|
||||
protected String getWildcardXipDomain(String externalAddress) {
|
||||
return String.format("%s.%s", getExternalIp(externalAddress), "xip.io");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016-2017 Red Hat 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a server evaluation strategy for the configuration where the workspace server and workspace
|
||||
* containers are running on the same Docker network and are exposed through the same single port.
|
||||
*
|
||||
* This server evaluation strategy will return a completed {@link ServerImpl} with internal addresses set
|
||||
* as {@link LocalDockerServerEvaluationStrategy} does. Contrary external addresses will be managed by the
|
||||
* `custom` evaluation strategy,and its template property `che.docker.server_evaluation_strategy.custom.template`
|
||||
*
|
||||
* <p>cheExternalAddress can be set using property {@code che.docker.ip.external}.
|
||||
* This strategy is useful when Che and the workspace servers need to be exposed on the same single TCP port
|
||||
*
|
||||
* @author Mario Loriedo <mloriedo@redhat.com>
|
||||
* @see ServerEvaluationStrategy
|
||||
*/
|
||||
public class LocalDockerCustomServerEvaluationStrategy extends BaseServerEvaluationStrategy {
|
||||
|
||||
@Inject
|
||||
public LocalDockerCustomServerEvaluationStrategy(@Nullable @Named("che.docker.ip") String internalAddress,
|
||||
@Nullable @Named("che.docker.ip.external") String externalAddress,
|
||||
@Nullable @Named("che.docker.server_evaluation_strategy.custom.template") String cheDockerCustomExternalTemplate,
|
||||
@Nullable @Named("che.docker.server_evaluation_strategy.custom.external.protocol") String cheDockerCustomExternalProtocol,
|
||||
@Named("che.port") String chePort) {
|
||||
super(internalAddress, externalAddress, cheDockerCustomExternalTemplate, cheDockerCustomExternalProtocol, chePort, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine.idle;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.event.ServerIdleEvent;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.notification.EventSubscriber;
|
||||
import org.eclipse.che.api.workspace.server.WorkspaceManager;
|
||||
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
/**
|
||||
* Notifies about idling the che server
|
||||
* Fires {@link org.eclipse.che.api.core.event.ServerIdleEvent} if no workspace
|
||||
* is run for <b>che.openshift.server.inactive.stop.timeout.ms</b> milliseconds
|
||||
*/
|
||||
@Singleton
|
||||
public class ServerIdleDetector implements EventSubscriber<WorkspaceStatusEvent> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ServerIdleDetector.class);
|
||||
private static final String IDLING_CHE_SERVER_SCHEDULED = "Idling che server scheduled [timeout=%s] seconds]";
|
||||
|
||||
private final long timeout;
|
||||
private ScheduledFuture<?> future;
|
||||
private ScheduledExecutorService executor;
|
||||
private WorkspaceManager workspaceManager;
|
||||
private final EventService eventService;
|
||||
|
||||
@Inject
|
||||
public ServerIdleDetector(WorkspaceManager workspaceManager,
|
||||
EventService eventService,
|
||||
@Named("che.openshift.server.inactive.stop.timeout.ms") long timeout) {
|
||||
this.timeout = timeout;
|
||||
this.eventService = eventService;
|
||||
this.workspaceManager = workspaceManager;
|
||||
if (timeout > 0) {
|
||||
this.executor = Executors.newSingleThreadScheduledExecutor();
|
||||
this.future = executor.schedule(this::run, timeout, TimeUnit.MILLISECONDS);
|
||||
LOG.info(String.format(IDLING_CHE_SERVER_SCHEDULED, timeout/1000));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(WorkspaceStatusEvent event) {
|
||||
if (future != null) {
|
||||
String workspaceId = event.getWorkspaceId();
|
||||
switch (event.getEventType()) {
|
||||
case RUNNING:
|
||||
if (!future.isCancelled()) {
|
||||
future.cancel(true);
|
||||
LOG.info("Idling che server canceled");
|
||||
}
|
||||
break;
|
||||
case STOPPED:
|
||||
Set<String> ids = workspaceManager.getRunningWorkspacesIds();
|
||||
ids.remove(workspaceId);
|
||||
if (ids.size() <= 0) {
|
||||
if (!future.isCancelled()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
future = executor.schedule(this::run, timeout, TimeUnit.MILLISECONDS);
|
||||
LOG.info(String.format(IDLING_CHE_SERVER_SCHEDULED, timeout/1000));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void run() {
|
||||
Set<String> ids = workspaceManager.getRunningWorkspacesIds();
|
||||
if (ids.size() <= 0) {
|
||||
eventService.publish(new ServerIdleEvent(timeout));
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void subscribe() {
|
||||
eventService.subscribe(this);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void unsubscribe() {
|
||||
eventService.unsubscribe(this);
|
||||
if (future != null && !future.isCancelled()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
if (executor != null && !executor.isShutdown()) {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.eclipse.che.plugin.docker.machine.CustomServerEvaluationStrategy.CHE_WORKSPACE_ID_PREFIX;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
|
|
@ -43,11 +44,19 @@ public class CustomServerEvaluationStrategyTest {
|
|||
|
||||
private static final String ALL_IP_ADDRESS = "0.0.0.0";
|
||||
|
||||
private static final String WORKSPACE_ID_VALUE = "work123";
|
||||
private static final String WORKSPACE_ID_PROPERTY = "CHE_WORKSPACE_ID=" + WORKSPACE_ID_VALUE;
|
||||
private static final String WORKSPACE_ID_WITHOUT_PREFIX_VALUE = "ABCDEFG";
|
||||
|
||||
private static final String WORKSPACE_ID_VALUE = CHE_WORKSPACE_ID_PREFIX + WORKSPACE_ID_WITHOUT_PREFIX_VALUE;
|
||||
private static final String WORKSPACE_ID_PROPERTY_PREFIX = "CHE_WORKSPACE_ID=";
|
||||
private static final String WORKSPACE_ID_PROPERTY = WORKSPACE_ID_PROPERTY_PREFIX + WORKSPACE_ID_VALUE;
|
||||
|
||||
private static final String MACHINE_NAME_VALUE = "myMachine";
|
||||
private static final String MACHINE_NAME_PROPERTY = "CHE_MACHINE_NAME=" + MACHINE_NAME_VALUE;
|
||||
private static final String MACHINE_NAME_PROPERTY_PREFIX = "CHE_MACHINE_NAME=";
|
||||
private static final String MACHINE_NAME_PROPERTY = MACHINE_NAME_PROPERTY_PREFIX + MACHINE_NAME_VALUE;
|
||||
|
||||
private static final String IS_DEV_MACHINE_PROPERTY_PREFIX = "CHE_IS_DEV_MACHINE=";
|
||||
private static final String IS_DEV_MACHINE_PROPERTY_TRUE = IS_DEV_MACHINE_PROPERTY_PREFIX + "true";
|
||||
private static final String IS_DEV_MACHINE_PROPERTY_FALSE = IS_DEV_MACHINE_PROPERTY_PREFIX + "false";
|
||||
|
||||
@Mock
|
||||
private ContainerConfig containerConfig;
|
||||
|
|
@ -76,7 +85,7 @@ public class CustomServerEvaluationStrategyTest {
|
|||
when(containerConfig.getLabels()).thenReturn(containerLabels);
|
||||
when(containerConfig.getExposedPorts()).thenReturn(containerExposedPorts);
|
||||
|
||||
envContainerConfig = new String[]{WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY};
|
||||
envContainerConfig = new String[]{WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY_TRUE};
|
||||
when(containerConfig.getEnv()).thenReturn(envContainerConfig);
|
||||
|
||||
when(containerInfo.getNetworkSettings()).thenReturn(networkSettings);
|
||||
|
|
@ -126,6 +135,52 @@ public class CustomServerEvaluationStrategyTest {
|
|||
Assert.assertEquals(portMapping.get("4401/tcp"), WORKSPACE_ID_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check workspace Id without prefix template
|
||||
*/
|
||||
@Test
|
||||
public void testWorkspaceIdWithoutPrefixRule() throws Throwable {
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("10.0.0.1", "192.168.1.1", "<workspaceIdWithoutPrefix>", "http", "8080");
|
||||
|
||||
Map<String, String> portMapping = this.customServerEvaluationStrategy.getExternalAddressesAndPorts(containerInfo, "localhost");
|
||||
|
||||
Assert.assertTrue(portMapping.containsKey("4401/tcp"));
|
||||
Assert.assertEquals(portMapping.get("4401/tcp"), WORKSPACE_ID_WITHOUT_PREFIX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the isDevMachine macro in template
|
||||
*/
|
||||
@Test
|
||||
public void testIsDevMachineWhenTrue() throws Throwable {
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("10.0.0.1", "192.168.1.1",
|
||||
"<if(isDevMachine)><workspaceId><else><machineName><endif>", "http", "8080");
|
||||
|
||||
Map<String, String> portMapping = this.customServerEvaluationStrategy.getExternalAddressesAndPorts(containerInfo, "localhost");
|
||||
|
||||
Assert.assertTrue(portMapping.containsKey("4401/tcp"));
|
||||
Assert.assertEquals(portMapping.get("4401/tcp"), WORKSPACE_ID_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the isDevMachine macro in template
|
||||
*/
|
||||
@Test
|
||||
public void testIsDevMachineWhenFalse() throws Throwable {
|
||||
this.envContainerConfig = new String[]{WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY_FALSE};
|
||||
when(containerConfig.getEnv()).thenReturn(envContainerConfig);
|
||||
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("10.0.0.1", "192.168.1.1",
|
||||
"<if(isDevMachine)><workspaceId><else><machineName><endif>", "http", "8080");
|
||||
|
||||
Map<String, String> portMapping = this.customServerEvaluationStrategy.getExternalAddressesAndPorts(containerInfo, "localhost");
|
||||
|
||||
Assert.assertTrue(portMapping.containsKey("4401/tcp"));
|
||||
Assert.assertEquals(portMapping.get("4401/tcp"), MACHINE_NAME_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check workspace Id template
|
||||
|
|
@ -213,7 +268,7 @@ public class CustomServerEvaluationStrategyTest {
|
|||
exposedPorts.add("4401/tcp");
|
||||
exposedPorts.add("4411/tcp");
|
||||
exposedPorts.add("8080/tcp");
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY);
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY_TRUE);
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("127.0.0.1", null, "<externalAddress>-<workspaceId>", "https", "8080");
|
||||
CustomServerEvaluationStrategy.RenderingEvaluation renderingEvaluation = this.customServerEvaluationStrategy
|
||||
|
|
@ -233,7 +288,7 @@ public class CustomServerEvaluationStrategyTest {
|
|||
exposedPorts.add("4401/tcp");
|
||||
exposedPorts.add("4411/tcp");
|
||||
exposedPorts.add("8080/tcp");
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY);
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY_TRUE);
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("127.0.0.1", "127.0.0.1", "<externalAddress>-<workspaceId>", "https", "8080");
|
||||
CustomServerEvaluationStrategy.RenderingEvaluation renderingEvaluation = this.customServerEvaluationStrategy
|
||||
|
|
@ -253,7 +308,7 @@ public class CustomServerEvaluationStrategyTest {
|
|||
exposedPorts.add("4401/tcp");
|
||||
exposedPorts.add("4411/tcp");
|
||||
exposedPorts.add("8080/tcp");
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY);
|
||||
List<String> env = Arrays.asList(WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY_TRUE);
|
||||
this.customServerEvaluationStrategy =
|
||||
new CustomServerEvaluationStrategy("127.0.0.1", "300.300.300.300", "<externalAddress>-<workspaceId>", "https", "8080");
|
||||
CustomServerEvaluationStrategy.RenderingEvaluation renderingEvaluation = this.customServerEvaluationStrategy
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016-2017 Red Hat 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerConfImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerPropertiesImpl;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerConfig;
|
||||
import org.eclipse.che.plugin.docker.client.json.ContainerInfo;
|
||||
import org.eclipse.che.plugin.docker.client.json.NetworkSettings;
|
||||
import org.eclipse.che.plugin.docker.client.json.PortBinding;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class LocalDockerCustomServerEvaluationStrategyTest {
|
||||
|
||||
private static final String CHE_DOCKER_IP_EXTERNAL = "container-host-ext.com";
|
||||
private static final String ALL_IP_ADDRESS = "0.0.0.0";
|
||||
private static final String CONTAINERCONFIG_HOSTNAME = "che-ws-y6jwknht0efzczit-4086112300-fm0aj";
|
||||
private static final String WORKSPACE_ID = "79rfwhqaztq2ru2k";
|
||||
|
||||
private static final String WORKSPACE_ID_VALUE = WORKSPACE_ID;
|
||||
private static final String WORKSPACE_ID_PROPERTY = "CHE_WORKSPACE_ID=" + WORKSPACE_ID_VALUE;
|
||||
|
||||
private static final String MACHINE_NAME_VALUE = "myMachine";
|
||||
private static final String MACHINE_NAME_PROPERTY = "CHE_MACHINE_NAME=" + MACHINE_NAME_VALUE;
|
||||
|
||||
private static final String IS_DEV_MACHINE_VALUE = "true";
|
||||
private static final String IS_DEV_MACHINE_PROPERTY = "CHE_IS_DEV_MACHINE=" + IS_DEV_MACHINE_VALUE;
|
||||
|
||||
private static final String CHE_DOCKER_SERVER_EVALUATION_STRATEGY_CUSTOM_TEMPLATE = "<serverName>-<if(isDevMachine)><workspaceIdWithoutPrefix><else><machineName><endif>-<externalAddress>";
|
||||
|
||||
@Mock
|
||||
private ContainerInfo containerInfo;
|
||||
@Mock
|
||||
private ContainerConfig containerConfig;
|
||||
@Mock
|
||||
private NetworkSettings networkSettings;
|
||||
|
||||
private ServerEvaluationStrategy strategy;
|
||||
|
||||
private Map<String, ServerConfImpl> serverConfs;
|
||||
|
||||
private Map<String, List<PortBinding>> ports;
|
||||
|
||||
private Map<String, String> labels;
|
||||
|
||||
private String[] env;
|
||||
|
||||
private String[] envContainerConfig;
|
||||
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
|
||||
serverConfs = new HashMap<>();
|
||||
serverConfs.put("4301/tcp", new ServerConfImpl("sysServer1-tcp", "4301/tcp", "http", "/some/path1"));
|
||||
serverConfs.put("4305/udp", new ServerConfImpl("devSysServer1-udp", "4305/udp", null, "some/path4"));
|
||||
|
||||
ports = new HashMap<>();
|
||||
ports.put("4301/tcp", Collections.singletonList(new PortBinding().withHostIp(ALL_IP_ADDRESS )
|
||||
.withHostPort("32100")));
|
||||
ports.put("4305/udp", Collections.singletonList(new PortBinding().withHostIp(ALL_IP_ADDRESS )
|
||||
.withHostPort("32103")));
|
||||
|
||||
labels = new HashMap<>();
|
||||
labels.put("che:server:4301/tcp:ref", "sysServer1-tcp");
|
||||
labels.put("che:server:4305/udp:ref", "devSysServer1-udp");
|
||||
|
||||
env = new String[]{"CHE_WORKSPACE_ID="+ WORKSPACE_ID};
|
||||
|
||||
when(containerInfo.getNetworkSettings()).thenReturn(networkSettings);
|
||||
when(networkSettings.getIpAddress()).thenReturn(CONTAINERCONFIG_HOSTNAME);
|
||||
when(networkSettings.getPorts()).thenReturn(ports);
|
||||
when(containerInfo.getConfig()).thenReturn(containerConfig);
|
||||
when(containerConfig.getHostname()).thenReturn(CONTAINERCONFIG_HOSTNAME);
|
||||
when(containerConfig.getEnv()).thenReturn(env);
|
||||
when(containerConfig.getLabels()).thenReturn(labels);
|
||||
|
||||
envContainerConfig = new String[]{WORKSPACE_ID_PROPERTY, MACHINE_NAME_PROPERTY, IS_DEV_MACHINE_PROPERTY};
|
||||
when(containerConfig.getEnv()).thenReturn(envContainerConfig);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: single port strategy should use .
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseServerRefToBuildAddressWhenAvailable() throws Exception {
|
||||
// given
|
||||
strategy = new LocalDockerCustomServerEvaluationStrategy(null, null, CHE_DOCKER_SERVER_EVALUATION_STRATEGY_CUSTOM_TEMPLATE, "http", null).withThrowOnUnknownHost(false);
|
||||
|
||||
final Map<String, ServerImpl> expectedServers = getExpectedServers(CHE_DOCKER_IP_EXTERNAL,
|
||||
CONTAINERCONFIG_HOSTNAME,
|
||||
true);
|
||||
|
||||
// when
|
||||
final Map<String, ServerImpl> servers = strategy.getServers(containerInfo,
|
||||
CHE_DOCKER_IP_EXTERNAL,
|
||||
serverConfs);
|
||||
|
||||
// then
|
||||
assertEquals(servers, expectedServers);
|
||||
}
|
||||
|
||||
private Map<String, ServerImpl> getExpectedServers(String externalAddress,
|
||||
String internalAddress,
|
||||
boolean useExposedPorts) {
|
||||
String port1;
|
||||
String port2;
|
||||
if (useExposedPorts) {
|
||||
port1 = ":4301";
|
||||
port2 = ":4305";
|
||||
} else {
|
||||
port1 = ":32100";
|
||||
port2 = ":32103";
|
||||
}
|
||||
Map<String, ServerImpl> expectedServers = new HashMap<>();
|
||||
expectedServers.put("4301/tcp", new ServerImpl("sysServer1-tcp",
|
||||
"http",
|
||||
"sysServer1-tcp-" + WORKSPACE_ID + "-" + externalAddress,
|
||||
"http://" + "sysServer1-tcp-" + WORKSPACE_ID + "-" + externalAddress + "/some/path1",
|
||||
new ServerPropertiesImpl("/some/path1",
|
||||
internalAddress + port1,
|
||||
"http://" + internalAddress + port1 + "/some/path1")));
|
||||
expectedServers.put("4305/udp", new ServerImpl("devSysServer1-udp",
|
||||
null,
|
||||
"devSysServer1-udp-" + WORKSPACE_ID + "-" + externalAddress,
|
||||
null,
|
||||
new ServerPropertiesImpl("some/path4",
|
||||
internalAddress + port2,
|
||||
null)));
|
||||
return expectedServers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -55,6 +55,22 @@
|
|||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.plugin</groupId>
|
||||
<artifactId>che-plugin-docker-client</artifactId>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,232 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ContainerBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSourceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Quantity;
|
||||
import io.fabric8.kubernetes.api.model.Volume;
|
||||
import io.fabric8.kubernetes.api.model.VolumeBuilder;
|
||||
import io.fabric8.kubernetes.api.model.VolumeMount;
|
||||
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
|
||||
import io.fabric8.openshift.client.DefaultOpenShiftClient;
|
||||
import io.fabric8.openshift.client.OpenShiftClient;
|
||||
|
||||
/**
|
||||
* Helper class for executing simple commands in a Persistent Volume on Openshift.
|
||||
* <p>
|
||||
* Creates a short-lived Pod using a CentOS image which mounts a specified PVC and
|
||||
* executes a command (either {@code mkdir -p <path>} or {@code rm -rf <path}). Reports
|
||||
* back whether the pod succeeded or failed. Supports multiple paths for one command.
|
||||
* <p>
|
||||
* For mkdir commands, an in-memory list of created workspaces is stored and used to avoid
|
||||
* calling mkdir unnecessarily. However, this list is not persisted, so dir creation is
|
||||
* not tracked between restarts.
|
||||
*
|
||||
* @author amisevsk
|
||||
*/
|
||||
public class OpenShiftPvcHelper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenShiftPvcHelper.class);
|
||||
|
||||
private static final String POD_PHASE_SUCCEEDED = "Succeeded";
|
||||
private static final String POD_PHASE_FAILED = "Failed";
|
||||
private static final String[] MKDIR_WORKSPACE_COMMAND = new String[] {"mkdir", "-p"};
|
||||
private static final String[] RMDIR_WORKSPACE_COMMAND = new String[] {"rm", "-rf"};
|
||||
|
||||
private static final Set<String> createdWorkspaces = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private final String jobImage;
|
||||
private final String jobMemoryLimit;
|
||||
|
||||
protected enum Command {REMOVE, MAKE}
|
||||
|
||||
@Inject
|
||||
protected OpenShiftPvcHelper(@Named("che.openshift.jobs.image") String jobImage,
|
||||
@Named("che.openshift.jobs.memorylimit") String jobMemoryLimit) {
|
||||
this.jobImage = jobImage;
|
||||
this.jobMemoryLimit = jobMemoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pod with {@code command} and reports whether it succeeded
|
||||
* @param workspacesPvcName
|
||||
* name of the PVC to mount
|
||||
* @param projectNamespace
|
||||
* OpenShift namespace
|
||||
* @param jobNamePrefix
|
||||
* prefix used for pod metadata name. Name structure will normally
|
||||
* be {@code <prefix><workspaceDirs>} if only one path is passed, or
|
||||
* {@code <prefix>batch} if multiple paths are provided
|
||||
* @param command
|
||||
* command to execute in PVC.
|
||||
* @param workspaceDirs
|
||||
* list of arguments attached to command. A list of directories to
|
||||
* create/delete.
|
||||
* @return true if Pod terminates with phase "Succeeded" or mkdir command issued
|
||||
* for already created worksapce, false otherwise.
|
||||
*
|
||||
* @see Command
|
||||
*/
|
||||
protected boolean createJobPod(String workspacesPvcName,
|
||||
String projectNamespace,
|
||||
String jobNamePrefix,
|
||||
Command command,
|
||||
String... workspaceDirs) {
|
||||
|
||||
if (workspaceDirs.length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Command.MAKE.equals(command)) {
|
||||
String[] dirsToCreate = filterDirsToCreate(workspaceDirs);
|
||||
if (dirsToCreate.length == 0) {
|
||||
return true;
|
||||
}
|
||||
workspaceDirs = dirsToCreate;
|
||||
}
|
||||
|
||||
VolumeMount vm = new VolumeMountBuilder()
|
||||
.withMountPath("/projects")
|
||||
.withName(workspacesPvcName)
|
||||
.build();
|
||||
|
||||
PersistentVolumeClaimVolumeSource pvcs = new PersistentVolumeClaimVolumeSourceBuilder()
|
||||
.withClaimName(workspacesPvcName)
|
||||
.build();
|
||||
|
||||
Volume volume = new VolumeBuilder()
|
||||
.withPersistentVolumeClaim(pvcs)
|
||||
.withName(workspacesPvcName)
|
||||
.build();
|
||||
|
||||
String[] jobCommand = getCommand(command, "/projects/", workspaceDirs);
|
||||
LOG.info("Executing command {} in PVC {} for {} dirs", jobCommand[0], workspacesPvcName, workspaceDirs.length);
|
||||
|
||||
Map<String, Quantity> limit = Collections.singletonMap("memory", new Quantity(jobMemoryLimit));
|
||||
|
||||
String podName = workspaceDirs.length > 1 ? jobNamePrefix + "batch"
|
||||
: jobNamePrefix + workspaceDirs[0];
|
||||
|
||||
Container container = new ContainerBuilder().withName(podName)
|
||||
.withImage(jobImage)
|
||||
.withImagePullPolicy("IfNotPresent")
|
||||
.withNewSecurityContext()
|
||||
.withPrivileged(false)
|
||||
.endSecurityContext()
|
||||
.withCommand(jobCommand)
|
||||
.withVolumeMounts(vm)
|
||||
.withNewResources()
|
||||
.withLimits(limit)
|
||||
.endResources()
|
||||
.build();
|
||||
|
||||
Pod podSpec = new PodBuilder().withNewMetadata()
|
||||
.withName(podName)
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withContainers(container)
|
||||
.withVolumes(volume)
|
||||
.withRestartPolicy("Never")
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
|
||||
try (OpenShiftClient openShiftClient = new DefaultOpenShiftClient()){
|
||||
openShiftClient.pods().inNamespace(projectNamespace).create(podSpec);
|
||||
boolean completed = false;
|
||||
while(!completed) {
|
||||
Pod pod = openShiftClient.pods().inNamespace(projectNamespace).withName(podName).get();
|
||||
String phase = pod.getStatus().getPhase();
|
||||
switch (phase) {
|
||||
case POD_PHASE_FAILED:
|
||||
LOG.info("Pod command {} failed", Arrays.toString(jobCommand));
|
||||
case POD_PHASE_SUCCEEDED:
|
||||
openShiftClient.resource(pod).delete();
|
||||
updateCreatedDirs(command, phase, workspaceDirs);
|
||||
return POD_PHASE_SUCCEEDED.equals(phase);
|
||||
default:
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String[] getCommand(Command commandType, String mountPath, String... dirs) {
|
||||
String[] command = new String[0];
|
||||
switch (commandType) {
|
||||
case MAKE :
|
||||
command = MKDIR_WORKSPACE_COMMAND;
|
||||
break;
|
||||
case REMOVE :
|
||||
command = RMDIR_WORKSPACE_COMMAND;
|
||||
break;
|
||||
}
|
||||
|
||||
String[] dirsWithPath = Arrays.asList(dirs).stream()
|
||||
.map(dir -> mountPath + dir)
|
||||
.toArray(String[]::new);
|
||||
|
||||
String[] fullCommand = new String[command.length + dirsWithPath.length];
|
||||
|
||||
System.arraycopy(command, 0, fullCommand, 0, command.length);
|
||||
System.arraycopy(dirsWithPath, 0, fullCommand, command.length, dirsWithPath.length);
|
||||
return fullCommand;
|
||||
}
|
||||
|
||||
private void updateCreatedDirs(Command command, String phase, String... workspaceDirs) {
|
||||
if (!POD_PHASE_SUCCEEDED.equals(phase)) {
|
||||
return;
|
||||
}
|
||||
List<String> dirs = Arrays.asList(workspaceDirs);
|
||||
switch (command) {
|
||||
case MAKE:
|
||||
createdWorkspaces.addAll(dirs);
|
||||
break;
|
||||
case REMOVE:
|
||||
createdWorkspaces.removeAll(dirs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String[] filterDirsToCreate(String[] allDirs) {
|
||||
List<String> dirs = Arrays.asList(allDirs);
|
||||
List<String> dirsToCreate = new ArrayList<>();
|
||||
for(String dir : dirs) {
|
||||
if (!createdWorkspaces.contains(dir)) {
|
||||
dirsToCreate.add(dir);
|
||||
}
|
||||
}
|
||||
return dirsToCreate.toArray(new String[dirsToCreate.size()]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.openshift.client;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.fabric8.openshift.api.model.DoneableRoute;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
import io.fabric8.openshift.api.model.RouteFluent.SpecNested;
|
||||
import io.fabric8.openshift.client.DefaultOpenShiftClient;
|
||||
import io.fabric8.openshift.client.OpenShiftClient;
|
||||
|
||||
public class OpenShiftRouteCreator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenShiftRouteCreator.class);
|
||||
private static final String TLS_TERMINATION_EDGE = "edge";
|
||||
private static final String REDIRECT_INSECURE_EDGE_TERMINATION_POLICY = "Redirect";
|
||||
|
||||
public static void createRoute (final String namespace,
|
||||
final String openShiftNamespaceExternalAddress,
|
||||
final String serverRef,
|
||||
final String serviceName,
|
||||
final String deploymentName,
|
||||
final String routeId,
|
||||
final boolean enableTls) {
|
||||
|
||||
if (openShiftNamespaceExternalAddress == null) {
|
||||
throw new IllegalArgumentException("Property che.docker.ip.external must be set when using openshift.");
|
||||
}
|
||||
|
||||
try (OpenShiftClient openShiftClient = new DefaultOpenShiftClient()) {
|
||||
String routeName = generateRouteName(routeId, serverRef);
|
||||
String serviceHost = generateRouteHost(routeName, openShiftNamespaceExternalAddress);
|
||||
|
||||
SpecNested<DoneableRoute> routeSpec = openShiftClient
|
||||
.routes()
|
||||
.inNamespace(namespace)
|
||||
.createNew()
|
||||
.withNewMetadata()
|
||||
.withName(routeName)
|
||||
.addToLabels(OpenShiftConnector.OPENSHIFT_DEPLOYMENT_LABEL, deploymentName)
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withHost(serviceHost)
|
||||
.withNewTo()
|
||||
.withKind("Service")
|
||||
.withName(serviceName)
|
||||
.endTo()
|
||||
.withNewPort()
|
||||
.withNewTargetPort()
|
||||
.withStrVal(serverRef)
|
||||
.endTargetPort()
|
||||
.endPort();
|
||||
|
||||
if (enableTls) {
|
||||
routeSpec.withNewTls()
|
||||
.withTermination(TLS_TERMINATION_EDGE)
|
||||
.withInsecureEdgeTerminationPolicy(REDIRECT_INSECURE_EDGE_TERMINATION_POLICY)
|
||||
.endTls();
|
||||
}
|
||||
|
||||
Route route = routeSpec.endSpec().done();
|
||||
|
||||
LOG.info("OpenShift route {} created", route.getMetadata().getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static String generateRouteName(final String serviceName, final String serverRef) {
|
||||
return serverRef + "-" + serviceName;
|
||||
}
|
||||
|
||||
private static String generateRouteHost(final String routeName, final String openShiftNamespaceExternalAddress) {
|
||||
return routeName + "-" + openShiftNamespaceExternalAddress;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.event.ServerIdleEvent;
|
||||
import org.eclipse.che.api.core.model.workspace.Workspace;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.notification.EventSubscriber;
|
||||
import org.eclipse.che.api.workspace.server.WorkspaceFilesCleaner;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Class used to remove workspace directories in Persistent Volume when a workspace
|
||||
* is delete while running on OpenShift. Deleted workspace directories are stored
|
||||
* in a list. Upon Che server idling, all of these workspaces are deleted simultaneously
|
||||
* from the PVC using a {@link OpenShiftPvcHelper} job.
|
||||
* <p>
|
||||
* Since deleting a workspace does not immediately remove its files, re-creating a workspace
|
||||
* with a previously used name can result in files from the previous workspace still being
|
||||
* present.
|
||||
*
|
||||
* @see WorkspaceFilesCleaner
|
||||
* @author amisevsk
|
||||
*/
|
||||
@Singleton
|
||||
public class OpenShiftWorkspaceFilesCleaner implements WorkspaceFilesCleaner {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenShiftConnector.class);
|
||||
private static final Set<String> deleteQueue = ConcurrentHashMap.newKeySet();
|
||||
private final String projectNamespace;
|
||||
private final String workspacesPvcName;
|
||||
private final OpenShiftPvcHelper openShiftPvcHelper;
|
||||
|
||||
@Inject
|
||||
public OpenShiftWorkspaceFilesCleaner(EventService eventService,
|
||||
OpenShiftPvcHelper openShiftPvcHelper,
|
||||
@Named("che.openshift.project") String projectNamespace,
|
||||
@Named("che.openshift.workspaces.pvc.name") String workspacesPvcName) {
|
||||
this.projectNamespace = projectNamespace;
|
||||
this.workspacesPvcName = workspacesPvcName;
|
||||
this.openShiftPvcHelper = openShiftPvcHelper;
|
||||
eventService.subscribe(new EventSubscriber<ServerIdleEvent>() {
|
||||
@Override
|
||||
public void onEvent(ServerIdleEvent event) {
|
||||
deleteWorkspacesInQueue(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Workspace workspace) throws IOException, ServerException {
|
||||
String workspaceName = workspace.getConfig().getName();
|
||||
if (isNullOrEmpty(workspaceName)) {
|
||||
LOG.error("Could not get workspace name for files removal.");
|
||||
return;
|
||||
}
|
||||
deleteQueue.add(workspaceName);
|
||||
}
|
||||
|
||||
private void deleteWorkspacesInQueue(ServerIdleEvent event) {
|
||||
List<String> deleteQueueCopy = new ArrayList<>(deleteQueue);
|
||||
String[] dirsToDelete = deleteQueueCopy.toArray(new String[deleteQueueCopy.size()]);
|
||||
|
||||
LOG.info("Deleting {} workspaces on PVC {}", deleteQueueCopy.size(), workspacesPvcName);
|
||||
boolean successful = openShiftPvcHelper.createJobPod(workspacesPvcName,
|
||||
projectNamespace,
|
||||
"delete-",
|
||||
OpenShiftPvcHelper.Command.REMOVE,
|
||||
dirsToDelete);
|
||||
if (successful) {
|
||||
deleteQueue.removeAll(deleteQueueCopy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the list of workspace directories to be deleted. Necessary for testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected static void clearDeleteQueue() {
|
||||
deleteQueue.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ public final class KubernetesContainer {
|
|||
|
||||
int portNumber = Integer.parseInt(port);
|
||||
String portName = CheServicePorts.get().get(portNumber);
|
||||
portName = isNullOrEmpty(portName) ? exposedPort.replace("/", "-") : portName;
|
||||
portName = isNullOrEmpty(portName) ? "server-" + exposedPort.replace("/", "-") : portName;
|
||||
|
||||
ContainerPort containerPort = new ContainerPortBuilder().withName(portName).withProtocol(protocol)
|
||||
.withContainerPort(portNumber).build();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client.kubernetes;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.che.plugin.openshift.client.OpenShiftConnector;
|
||||
|
||||
/**
|
||||
* Holder class for metadata about an exec, to be used with {@link OpenShiftConnector}.
|
||||
*
|
||||
* <p> In OpenShift, {@code createExec()} is not separate from {@code startExec()},
|
||||
* so this class has to be used to pass data between {@code createExec()} and
|
||||
* {@code startExec()} calls.
|
||||
*
|
||||
* @see OpenShiftConnector#createExec(org.eclipse.che.plugin.docker.client.params.CreateExecParams)
|
||||
* @see OpenShiftConnector#startExec(org.eclipse.che.plugin.docker.client.params.StartExecParams, org.eclipse.che.plugin.docker.client.MessageProcessor)
|
||||
*/
|
||||
public class KubernetesExecHolder {
|
||||
|
||||
private String[] command;
|
||||
private String podName;
|
||||
|
||||
public KubernetesExecHolder withCommand(String[] command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public KubernetesExecHolder withPod(String podName) {
|
||||
this.podName = podName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String[] getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String getPod() {
|
||||
return podName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("KubernetesExecHolder {command=%s, podName=%s}",
|
||||
Arrays.asList(command).toString(),
|
||||
podName);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,9 @@ public final class KubernetesLabelConverter {
|
|||
*/
|
||||
public static Map<String, String> labelsToNames(Map<String, String> labels) {
|
||||
Map<String, String> names = new HashMap<>();
|
||||
if (labels == null) {
|
||||
return names;
|
||||
}
|
||||
for (Map.Entry<String, String> label : labels.entrySet()) {
|
||||
|
||||
if (!hasConversionProblems(label)) {
|
||||
|
|
@ -103,6 +106,9 @@ public final class KubernetesLabelConverter {
|
|||
*/
|
||||
public static Map<String, String> namesToLabels(Map<String, String> names) {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
if (names == null) {
|
||||
return labels;
|
||||
}
|
||||
for (Map.Entry<String, String> entry: names.entrySet()){
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client.kubernetes;
|
||||
|
||||
import io.fabric8.kubernetes.client.Callback;
|
||||
import io.fabric8.kubernetes.client.utils.InputStreamPumper;
|
||||
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.plugin.docker.client.LogMessage;
|
||||
import org.eclipse.che.plugin.docker.client.MessageProcessor;
|
||||
|
||||
/**
|
||||
* Adapter class for passing data from a {@code kubernetes-client} output stream (e.g.
|
||||
* for an exec call) to {@link MessageProcessor}. This class should be passed to a
|
||||
* {@link InputStreamPumper} along with the output of the exec call.
|
||||
*
|
||||
* <p> Output passed in via the {@link #call(byte[])} method is parsed into lines,
|
||||
* (respecting {@code '\n'} and {@code CRLF} as line separators), and
|
||||
* passed to the {@link MessageProcessor} as {@link LogMessage}s.
|
||||
*/
|
||||
public class KubernetesOutputAdapter implements Callback<byte[]> {
|
||||
|
||||
private LogMessage.Type type;
|
||||
private MessageProcessor<LogMessage> execOutputProcessor;
|
||||
private StringBuilder lineBuffer;
|
||||
|
||||
/**
|
||||
* Create a new KubernetesOutputAdapter
|
||||
*
|
||||
* @param type
|
||||
* the type of LogMessages being passed to the MessageProcessor
|
||||
* @param processor
|
||||
* the processor receiving LogMessages. If null, calling {@link #call(byte[])}
|
||||
* will return immediately.
|
||||
*/
|
||||
public KubernetesOutputAdapter(LogMessage.Type type,
|
||||
@Nullable MessageProcessor<LogMessage> processor) {
|
||||
this.type = type;
|
||||
this.execOutputProcessor = processor;
|
||||
this.lineBuffer = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(byte[] data) {
|
||||
if (data == null || data.length == 0 || execOutputProcessor == null) {
|
||||
return;
|
||||
}
|
||||
int start = 0;
|
||||
int offset = 0;
|
||||
|
||||
for (int pos = 0; pos < data.length; pos++) {
|
||||
if (data[pos] == '\n' || data[pos] == '\r') {
|
||||
offset = pos - start;
|
||||
String line = new String(data, start, offset);
|
||||
lineBuffer.append(line);
|
||||
execOutputProcessor.process(new LogMessage(type, lineBuffer.toString()));
|
||||
lineBuffer.setLength(0);
|
||||
if (data[pos] == '\r') {
|
||||
pos += 1;
|
||||
}
|
||||
start = pos + 1;
|
||||
}
|
||||
}
|
||||
String trailingChars = new String(data, start, data.length - start);
|
||||
lineBuffer.append(trailingChars);
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ public final class KubernetesService {
|
|||
|
||||
int portNumber = Integer.parseInt(port);
|
||||
String portName = CheServicePorts.get().get(portNumber);
|
||||
portName = isNullOrEmpty(portName) ? exposedPort.replace("/", "-") : portName;
|
||||
portName = isNullOrEmpty(portName) ? "server-" + exposedPort.replace("/", "-") : portName;
|
||||
|
||||
int targetPortNumber = portNumber;
|
||||
ServicePort servicePort = new ServicePort();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.plugin.docker.client.DockerApiVersionPathPrefixProvider;
|
||||
import org.eclipse.che.plugin.docker.client.DockerConnectorConfiguration;
|
||||
import org.eclipse.che.plugin.docker.client.DockerRegistryAuthResolver;
|
||||
|
|
@ -31,9 +32,17 @@ import org.testng.annotations.Test;
|
|||
public class OpenShiftConnectorTest {
|
||||
private static final String[] CONTAINER_ENV_VARIABLES = {"CHE_WORKSPACE_ID=abcd1234"};
|
||||
private static final String CHE_DEFAULT_OPENSHIFT_PROJECT_NAME = "eclipse-che";
|
||||
private static final String CHE_DEFAULT_OPENSHIFT_SERVICEACCOUNT = "cheserviceaccount";
|
||||
private static final int OPENSHIFT_LIVENESS_PROBE_DELAY = 300;
|
||||
private static final int OPENSHIFT_LIVENESS_PROBE_TIMEOUT = 1;
|
||||
private static final String OPENSHIFT_DEFAULT_WORKSPACE_PERSISTENT_VOLUME_CLAIM = "che_claim_data";
|
||||
private static final String OPENSHIFT_DEFAULT_WORKSPACE_QUANTITY = "10Gi";
|
||||
private static final String OPENSHIFT_DEFAULT_WORKSPACE_STORAGE = "/data/workspaces";
|
||||
private static final String OPENSHIFT_DEFAULT_WORKSPACE_PROJECTS_STORAGE = "/projects";
|
||||
private static final String CHE_DEFAULT_SERVER_EXTERNAL_ADDRESS = "che.openshift.mini";
|
||||
private static final String CHE_WORKSPACE_CPU_LIMIT = "1";
|
||||
private static final boolean SECURE_ROUTES = false;
|
||||
private static final boolean CREATE_WORKSPACE_DIRS = true;
|
||||
|
||||
|
||||
@Mock
|
||||
private DockerConnectorConfiguration dockerConnectorConfiguration;
|
||||
|
|
@ -45,6 +54,10 @@ public class OpenShiftConnectorTest {
|
|||
private DockerApiVersionPathPrefixProvider dockerApiVersionPathPrefixProvider;
|
||||
@Mock
|
||||
private CreateContainerParams createContainerParams;
|
||||
@Mock
|
||||
private EventService eventService;
|
||||
@Mock
|
||||
private OpenShiftPvcHelper openShiftPvcHelper;
|
||||
|
||||
private OpenShiftConnector openShiftConnector;
|
||||
|
||||
|
|
@ -62,10 +75,20 @@ public class OpenShiftConnectorTest {
|
|||
dockerConnectionFactory,
|
||||
authManager,
|
||||
dockerApiVersionPathPrefixProvider,
|
||||
openShiftPvcHelper,
|
||||
eventService,
|
||||
CHE_DEFAULT_SERVER_EXTERNAL_ADDRESS,
|
||||
CHE_DEFAULT_OPENSHIFT_PROJECT_NAME,
|
||||
CHE_DEFAULT_OPENSHIFT_SERVICEACCOUNT,
|
||||
OPENSHIFT_LIVENESS_PROBE_DELAY,
|
||||
OPENSHIFT_LIVENESS_PROBE_TIMEOUT);
|
||||
OPENSHIFT_LIVENESS_PROBE_TIMEOUT,
|
||||
OPENSHIFT_DEFAULT_WORKSPACE_PERSISTENT_VOLUME_CLAIM,
|
||||
OPENSHIFT_DEFAULT_WORKSPACE_QUANTITY,
|
||||
OPENSHIFT_DEFAULT_WORKSPACE_STORAGE,
|
||||
OPENSHIFT_DEFAULT_WORKSPACE_PROJECTS_STORAGE,
|
||||
CHE_WORKSPACE_CPU_LIMIT,
|
||||
null,
|
||||
SECURE_ROUTES,
|
||||
CREATE_WORKSPACE_DIRS);
|
||||
String workspaceID = openShiftConnector.getCheWorkspaceId(createContainerParams);
|
||||
|
||||
//Then
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.event.ServerIdleEvent;
|
||||
import org.eclipse.che.api.core.model.workspace.Workspace;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class OpenShiftWorkspaceFilesCleanerTest {
|
||||
|
||||
private static final String CHE_OPENSHIFT_PROJECT = "eclipse-che";
|
||||
private static final String WORKSPACES_PVC_NAME = "che-data-volume";
|
||||
private static final String WORKSPACE_ONE = "testworkspaceone";
|
||||
private static final String WORKSPACE_TWO = "testworkspacetwo";
|
||||
|
||||
@Mock
|
||||
private OpenShiftPvcHelper pvcHelper;
|
||||
@Mock
|
||||
private ServerIdleEvent serverIdleEvent;
|
||||
private EventService eventService;
|
||||
private OpenShiftWorkspaceFilesCleaner cleaner;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() {
|
||||
OpenShiftWorkspaceFilesCleaner.clearDeleteQueue();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
eventService = new EventService();
|
||||
cleaner = new OpenShiftWorkspaceFilesCleaner(eventService,
|
||||
pvcHelper,
|
||||
CHE_OPENSHIFT_PROJECT,
|
||||
WORKSPACES_PVC_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDoNothingWithoutIdleEvent() throws ServerException, IOException {
|
||||
// Given
|
||||
Workspace workspace = generateWorkspace(WORKSPACE_ONE);
|
||||
|
||||
// When
|
||||
cleaner.clear(workspace);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, never()).createJobPod(anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
any(OpenShiftPvcHelper.Command.class),
|
||||
any(String[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteWorkspaceOnIdleEvent() throws ServerException, IOException {
|
||||
// Given
|
||||
Workspace workspace = generateWorkspace(WORKSPACE_ONE);
|
||||
|
||||
// When
|
||||
cleaner.clear(workspace);
|
||||
eventService.publish(serverIdleEvent);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, times(1)).createJobPod(anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
eq(OpenShiftPvcHelper.Command.REMOVE),
|
||||
eq(WORKSPACE_ONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteMultipleQueuedWorkspacesAtOnce() throws ServerException, IOException {
|
||||
// Given
|
||||
Workspace workspaceOne = generateWorkspace(WORKSPACE_ONE);
|
||||
Workspace workspaceTwo = generateWorkspace(WORKSPACE_TWO);
|
||||
String[] expectedDirs = new String[] {WORKSPACE_ONE, WORKSPACE_TWO};
|
||||
ArgumentCaptor<String> dirCaptor = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
// When
|
||||
cleaner.clear(workspaceOne);
|
||||
cleaner.clear(workspaceTwo);
|
||||
eventService.publish(serverIdleEvent);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, times(1)).createJobPod(anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
eq(OpenShiftPvcHelper.Command.REMOVE),
|
||||
dirCaptor.capture(), // Varargs capture doesn't seem to work.
|
||||
dirCaptor.capture());
|
||||
|
||||
List<String> dirs = dirCaptor.getAllValues();
|
||||
String[] actualDirs = dirs.toArray(new String[dirs.size()]);
|
||||
// Sort arrays to ignore order
|
||||
Arrays.sort(actualDirs);
|
||||
Arrays.sort(expectedDirs);
|
||||
assertEquals(actualDirs, expectedDirs, "Expected all dirs to be deleted when server is idled.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRetainQueueIfDeletionFails() throws ServerException, IOException {
|
||||
// Given
|
||||
Workspace workspaceOne = generateWorkspace(WORKSPACE_ONE);
|
||||
when(pvcHelper.createJobPod(any(), any(), any(), any(), any())).thenReturn(false);
|
||||
|
||||
// When
|
||||
cleaner.clear(workspaceOne);
|
||||
eventService.publish(serverIdleEvent);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, times(1)).createJobPod(anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
eq(OpenShiftPvcHelper.Command.REMOVE),
|
||||
eq(WORKSPACE_ONE));
|
||||
|
||||
// When
|
||||
eventService.publish(serverIdleEvent);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, times(2)).createJobPod(anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
eq(OpenShiftPvcHelper.Command.REMOVE),
|
||||
eq(WORKSPACE_ONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseProjectNamespaceAndPvcNameAsParameters() throws ServerException, IOException {
|
||||
// Given
|
||||
Workspace workspaceOne = generateWorkspace(WORKSPACE_ONE);
|
||||
|
||||
// When
|
||||
cleaner.clear(workspaceOne);
|
||||
eventService.publish(serverIdleEvent);
|
||||
|
||||
// Then
|
||||
verify(pvcHelper, times(1)).createJobPod(eq(WORKSPACES_PVC_NAME),
|
||||
eq(CHE_OPENSHIFT_PROJECT),
|
||||
anyString(),
|
||||
eq(OpenShiftPvcHelper.Command.REMOVE),
|
||||
eq(WORKSPACE_ONE));
|
||||
}
|
||||
|
||||
private Workspace generateWorkspace(String id) {
|
||||
WorkspaceConfigImpl config = new WorkspaceConfigImpl();
|
||||
config.setName(id);
|
||||
return new WorkspaceImpl(id, null, config);
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ public class KubernetesContainerTest {
|
|||
map(p -> Integer.toString(p.getContainerPort()) +
|
||||
"/" +
|
||||
p.getProtocol().toLowerCase()).collect(Collectors.toList());
|
||||
assertTrue(exposedPorts.stream().anyMatch(portsAndProtocols::contains));
|
||||
assertTrue(exposedPorts.stream().allMatch(portsAndProtocols::contains));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -61,7 +61,7 @@ public class KubernetesContainerTest {
|
|||
map(p -> Integer.toString(p.getContainerPort()) +
|
||||
"/" +
|
||||
p.getProtocol().toLowerCase()).collect(Collectors.toList());
|
||||
assertTrue(imageExposedPorts.keySet().stream().anyMatch(portsAndProtocols::contains));
|
||||
assertTrue(imageExposedPorts.keySet().stream().allMatch(portsAndProtocols::contains));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class KubernetesEnvVarTest {
|
|||
|
||||
// Then
|
||||
List<String> keysAndValues = env.stream().map(k -> k.getName() + "=" + k.getValue()).collect(Collectors.toList());
|
||||
assertTrue(Arrays.stream(envVariables).anyMatch(keysAndValues::contains));
|
||||
assertTrue(Arrays.stream(envVariables).allMatch(keysAndValues::contains));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ import static org.testng.Assert.assertTrue;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class KubernetesLabelConverterTest {
|
||||
|
||||
private final String prefix = KubernetesLabelConverter.getCheServerLabelPrefix();
|
||||
|
||||
@Test
|
||||
public void shouldConvertLabelsToValidKubernetesLabelNames() {
|
||||
String validLabelRegex = "([A-Za-z0-9][-A-Za-z0-9_\\.]*)?[A-Za-z0-9]";
|
||||
String prefix = KubernetesLabelConverter.getCheServerLabelPrefix();
|
||||
|
||||
// Given
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
|
|
@ -46,7 +46,6 @@ public class KubernetesLabelConverterTest {
|
|||
@Test
|
||||
public void shouldBeAbleToRecoverOriginalLabelsAfterConversion() {
|
||||
// Given
|
||||
String prefix = KubernetesLabelConverter.getCheServerLabelPrefix();
|
||||
Map<String, String> originalLabels = new HashMap<>();
|
||||
originalLabels.put(prefix + "4401/tcp:path:", "/api");
|
||||
originalLabels.put(prefix + "8000/tcp:ref:", "tomcat-debug");
|
||||
|
|
@ -59,4 +58,58 @@ public class KubernetesLabelConverterTest {
|
|||
assertEquals(originalLabels, unconverted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreAndLogProblemLabels() {
|
||||
// Given
|
||||
Map<String, String> originalLabels = new HashMap<>();
|
||||
Map<String, String> validLabels = new HashMap<>();
|
||||
validLabels.put(prefix + "4401/tcp:path:", "/api");
|
||||
validLabels.put(prefix + "8000/tcp:ref:", "tomcat-debug");
|
||||
Map<String, String> invalidLabels = new HashMap<>();
|
||||
invalidLabels.put(prefix + "9999/t.cp:path:", "/api");
|
||||
invalidLabels.put(prefix + "1111/tcp:path:", "/a_pi");
|
||||
|
||||
originalLabels.putAll(validLabels);
|
||||
originalLabels.putAll(invalidLabels);
|
||||
|
||||
// When
|
||||
Map<String, String> converted = KubernetesLabelConverter.labelsToNames(originalLabels);
|
||||
Map<String, String> unconverted = KubernetesLabelConverter.namesToLabels(converted);
|
||||
|
||||
// Then
|
||||
assertTrue(validLabels.entrySet().stream().allMatch(unconverted.entrySet()::contains),
|
||||
"Valid labels should be there when converting + unconverting");
|
||||
assertTrue(invalidLabels.entrySet().stream().noneMatch(unconverted.entrySet()::contains),
|
||||
"Labels with invalid characters should be ignored");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreEmptyValues() {
|
||||
// Given
|
||||
Map<String, String> originalLabels = new HashMap<>();
|
||||
originalLabels.put(prefix + "4401/tcp:path:", null);
|
||||
originalLabels.put(prefix + "4402/tcp:path:", "");
|
||||
originalLabels.put(prefix + "4403/tcp:path:", " ");
|
||||
|
||||
// When
|
||||
Map<String, String> converted = KubernetesLabelConverter.labelsToNames(originalLabels);
|
||||
|
||||
// Then
|
||||
assertTrue(converted.isEmpty(), "Labels with null, empty, or whitespace values should be ignored");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotIgnoreValuesWithoutPrefix() {
|
||||
// Given
|
||||
Map<String, String> originalLabels = new HashMap<>();
|
||||
originalLabels.put("4401/tcp:path:", "/api");
|
||||
originalLabels.put(prefix + "8000/tcp:ref:", "tomcat-debug");
|
||||
|
||||
// When
|
||||
Map<String, String> converted = KubernetesLabelConverter.labelsToNames(originalLabels);
|
||||
|
||||
// Then
|
||||
// Currently we put a warning in the logs but convert these labels anyways.
|
||||
assertTrue(converted.size() == 2, "Should convert labels even without prefix");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Red Hat, 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.che.plugin.openshift.client.kubernetes;
|
||||
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.che.plugin.docker.client.LogMessage;
|
||||
import org.eclipse.che.plugin.docker.client.MessageProcessor;
|
||||
|
||||
|
||||
public class KubernetesOutputAdapterTest {
|
||||
|
||||
private static LogMessage.Type LOG_TYPE = LogMessage.Type.DOCKER;
|
||||
private testMessageProcessor processor;
|
||||
private KubernetesOutputAdapter adapter;
|
||||
|
||||
private class testMessageProcessor implements MessageProcessor<LogMessage> {
|
||||
|
||||
private List<String> messages;
|
||||
private LogMessage.Type type = null;
|
||||
|
||||
public testMessageProcessor() {
|
||||
this.messages = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(LogMessage message) {
|
||||
LogMessage.Type messageType = message.getType();
|
||||
if (type == null) {
|
||||
type = messageType;
|
||||
}
|
||||
messages.add(message.getContent());
|
||||
}
|
||||
|
||||
public List<String> getMessages() {
|
||||
return new ArrayList<>(messages);
|
||||
}
|
||||
|
||||
public LogMessage.Type getType() {
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
processor = new testMessageProcessor();
|
||||
adapter = new KubernetesOutputAdapter(LOG_TYPE, processor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBreakLinesCorrectly() {
|
||||
// Given
|
||||
byte[] input = "line1\nline2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(input);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should break lines on \\n char");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCacheUnfinishedLinesBetweenCalls() {
|
||||
// Given
|
||||
byte[] firstInput = "line1\nlin".getBytes();
|
||||
byte[] secondInput = "e2\nline3\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2", "line3");
|
||||
|
||||
// When
|
||||
adapter.call(firstInput);
|
||||
adapter.call(secondInput);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should store unfinished lines between calls");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseProvidedLogMessageType() {
|
||||
for (LogMessage.Type type : LogMessage.Type.values()) {
|
||||
// Given
|
||||
byte[] input = "line1\n".getBytes();
|
||||
LogMessage.Type expected = type;
|
||||
processor = new testMessageProcessor();
|
||||
adapter = new KubernetesOutputAdapter(type, processor);
|
||||
|
||||
// When
|
||||
adapter.call(input);
|
||||
|
||||
// Then
|
||||
LogMessage.Type actual = processor.getType();
|
||||
assertEquals(actual, expected, "Should call MessageProcessor with provided type");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBreakLinesNormallyWithCarriageReturn() {
|
||||
// Given
|
||||
byte[] input = "line1\r\nline2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(input);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should break lines normally on \\r\\n characters");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotIgnoreEmptyLines() {
|
||||
// Given
|
||||
byte[] input = "line1\n\nline2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(input);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should call processor.process() with empty Strings");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCallWithoutFinalNewline() {
|
||||
// Given
|
||||
byte[] input = "line1\nline2".getBytes(); // No trailing \n
|
||||
List<String> firstExpected = generateExpected("line1");
|
||||
List<String> secondExpected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(input);
|
||||
|
||||
// Then
|
||||
List<String> firstActual = processor.getMessages();
|
||||
assertEquals(firstActual, firstExpected, "Should only process lines when they are terminated by \\n or \\r\\n");
|
||||
|
||||
// When
|
||||
adapter.call("\n".getBytes());
|
||||
|
||||
// Then
|
||||
List<String> secondActual = processor.getMessages();
|
||||
assertEquals(secondActual, secondExpected, "Should buffer lines until newline is encountered.");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreNullCalls() {
|
||||
// Given
|
||||
byte[] firstInput = "line1\n".getBytes();
|
||||
byte[] secondInput = "line2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(firstInput);
|
||||
adapter.call(null);
|
||||
adapter.call(secondInput);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should ignore calls with null arguments");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldKeepBufferPastNullCalls() {
|
||||
// Given
|
||||
byte[] firstInput = "lin".getBytes();
|
||||
byte[] secondInput = "e1\nline2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(firstInput);
|
||||
adapter.call(null);
|
||||
adapter.call(secondInput);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "Should ignore calls with null arguments");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDoNothingWhenExecOutputProcessorIsNull() {
|
||||
// Given
|
||||
byte[] firstInput = "line1\n".getBytes();
|
||||
byte[] secondInput = "line2\n".getBytes();
|
||||
adapter = new KubernetesOutputAdapter(LOG_TYPE, null);
|
||||
|
||||
// When
|
||||
adapter.call(firstInput);
|
||||
adapter.call(secondInput);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertTrue(actual.isEmpty(), "Should do nothing when ExecOutputProcessor is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreCallsWhenDataIsEmpty() {
|
||||
// Given
|
||||
byte[] emptyInput = "".getBytes();
|
||||
byte[] firstInput = "line1\n".getBytes();
|
||||
byte[] secondInput = "line2\n".getBytes();
|
||||
List<String> expected = generateExpected("line1", "line2");
|
||||
|
||||
// When
|
||||
adapter.call(emptyInput);
|
||||
adapter.call(firstInput);
|
||||
adapter.call(emptyInput);
|
||||
adapter.call(secondInput);
|
||||
adapter.call(emptyInput);
|
||||
|
||||
// Then
|
||||
List<String> actual = processor.getMessages();
|
||||
assertEquals(actual, expected, "KubernetesOutputAdapter ignore empty data calls");
|
||||
|
||||
}
|
||||
|
||||
private List<String> generateExpected(String... strings) {
|
||||
List<String> expected = new ArrayList<>();
|
||||
for (String string : strings) {
|
||||
expected.add(string);
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ public class KubernetesServiceTest {
|
|||
map(p -> Integer.toString(p.getPort()) +
|
||||
"/" +
|
||||
p.getProtocol()).collect(Collectors.toList());
|
||||
assertTrue(imageExposedPorts.keySet().stream().anyMatch(portsAndProtocols::contains));
|
||||
assertTrue(imageExposedPorts.keySet().stream().allMatch(portsAndProtocols::contains));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -60,7 +60,7 @@ public class KubernetesServiceTest {
|
|||
map(p -> Integer.toString(p.getPort()) +
|
||||
"/" +
|
||||
p.getProtocol()).collect(Collectors.toList());
|
||||
assertTrue(exposedPorts.keySet().stream().anyMatch(portsAndProtocols::contains));
|
||||
assertTrue(exposedPorts.keySet().stream().allMatch(portsAndProtocols::contains));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -73,13 +73,13 @@ public class KubernetesServiceTest {
|
|||
exposedPorts.put("4411/tcp",null);
|
||||
exposedPorts.put("4412/tcp",null);
|
||||
exposedPorts.put("8080/tcp",null);
|
||||
exposedPorts.put("8888/tcp",null);
|
||||
exposedPorts.put("8000/tcp",null);
|
||||
exposedPorts.put("9876/tcp",null);
|
||||
|
||||
Set<String> expectedPortNames = new HashSet<>();
|
||||
expectedPortNames.add("sshd");
|
||||
expectedPortNames.add("wsagent");
|
||||
expectedPortNames.add("wsagent-pda");
|
||||
expectedPortNames.add("wsagent-jpda");
|
||||
expectedPortNames.add("terminal");
|
||||
expectedPortNames.add("exec-agent");
|
||||
expectedPortNames.add("tomcat");
|
||||
|
|
@ -92,7 +92,7 @@ public class KubernetesServiceTest {
|
|||
map(p -> p.getName()).collect(Collectors.toList());
|
||||
|
||||
// Then
|
||||
assertTrue(actualPortNames.stream().anyMatch(expectedPortNames::contains));
|
||||
assertTrue(actualPortNames.stream().allMatch(expectedPortNames::contains));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -102,7 +102,7 @@ public class KubernetesServiceTest {
|
|||
exposedPorts.put("55/tcp",null);
|
||||
|
||||
Set<String> expectedPortNames = new HashSet<>();
|
||||
expectedPortNames.add("55-tcp");
|
||||
expectedPortNames.add("server-55-tcp");
|
||||
|
||||
// When
|
||||
List<ServicePort> servicePorts = KubernetesService.getServicePortsFrom(exposedPorts.keySet());
|
||||
|
|
@ -110,7 +110,7 @@ public class KubernetesServiceTest {
|
|||
map(p -> p.getName()).collect(Collectors.toList());
|
||||
|
||||
// Then
|
||||
assertTrue(actualPortNames.stream().anyMatch(expectedPortNames::contains));
|
||||
assertTrue(actualPortNames.stream().allMatch(expectedPortNames::contains));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.git.client;
|
||||
|
||||
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.BranchListMode;
|
||||
import org.eclipse.che.api.git.shared.CheckoutRequest;
|
||||
|
|
@ -28,9 +27,6 @@ import org.eclipse.che.api.git.shared.StatusFormat;
|
|||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
import org.eclipse.che.ide.rest.AsyncRequestCallback;
|
||||
import org.eclipse.che.ide.websocket.WebSocketException;
|
||||
import org.eclipse.che.ide.websocket.rest.RequestCallback;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -40,29 +36,10 @@ import java.util.Map;
|
|||
*
|
||||
* @author Ann Zhuleva
|
||||
* @author Vlad Zhukovskyi
|
||||
* @author Igor Vinokur
|
||||
*/
|
||||
public interface GitServiceClient {
|
||||
|
||||
/**
|
||||
* Add changes to Git index (temporary storage). Sends request over WebSocket.
|
||||
*
|
||||
* @param projectConfig
|
||||
* project (root of GIT repository)
|
||||
* @param update
|
||||
* if <code>true</code> then never stage new files, but stage modified new contents of tracked files and remove files from
|
||||
* the index if the corresponding files in the working tree have been removed
|
||||
* @param filePattern
|
||||
* pattern of the files to be added, default is "." (all files are added)
|
||||
* @param callback
|
||||
* callback
|
||||
* @throws WebSocketException
|
||||
* @deprecated use {@link #add(Path, boolean, Path[])}
|
||||
*/
|
||||
void add(ProjectConfig projectConfig,
|
||||
boolean update,
|
||||
List<String> filePattern,
|
||||
RequestCallback<Void> callback) throws WebSocketException;
|
||||
|
||||
/**
|
||||
* Add changes to Git index (temporary storage). Sends request over WebSocket.
|
||||
*
|
||||
|
|
@ -73,7 +50,6 @@ public interface GitServiceClient {
|
|||
* the index if the corresponding files in the working tree have been removed
|
||||
* @param paths
|
||||
* pattern of the files to be added, default is "." (all files are added)
|
||||
* @throws WebSocketException
|
||||
*/
|
||||
Promise<Void> add(Path project, boolean update, Path[] paths);
|
||||
|
||||
|
|
@ -95,7 +71,6 @@ public interface GitServiceClient {
|
|||
* </ul>
|
||||
* @param removeDeletedRefs
|
||||
* if <code>true</code> then delete removed refs from local repository
|
||||
* @throws WebSocketException
|
||||
*/
|
||||
Promise<Void> fetch(Path project, String remote, List<String> refspec, boolean removeDeletedRefs);
|
||||
|
||||
|
|
@ -107,51 +82,42 @@ public interface GitServiceClient {
|
|||
* project (root of GIT repository)
|
||||
* @param mode
|
||||
* get remote branches
|
||||
* @param callback
|
||||
* @deprecated use {@link #branchList(Path, BranchListMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
void branchList(ProjectConfig project,
|
||||
@Nullable BranchListMode mode,
|
||||
AsyncRequestCallback<List<Branch>> callback);
|
||||
|
||||
/**
|
||||
* Get the list of the branches. For now, all branches cannot be returned at once, so the parameter <code>remote</code> tells to get
|
||||
* remote branches if <code>true</code> or local ones (if <code>false</code>).
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param mode
|
||||
*/
|
||||
Promise<List<Branch>> branchList(Path project, BranchListMode mode);
|
||||
|
||||
/**
|
||||
* Delete branch.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param name
|
||||
* name of the branch to delete
|
||||
* @param force
|
||||
* force if <code>true</code> delete branch {@code name} even if it is not fully merged
|
||||
* force if <code>true</code> delete branch {@code name} even if it is not fully merged
|
||||
*/
|
||||
Promise<Void> branchDelete(Path project, String name, boolean force);
|
||||
|
||||
/**
|
||||
* Checkout the branch with pointed name.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param oldName
|
||||
* branch's current name
|
||||
* @param newName
|
||||
* branch's new name
|
||||
*/
|
||||
Promise<Void> branchRename(Path project, String oldName, String newName);
|
||||
|
||||
/**
|
||||
* Create new branch with pointed name.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param name
|
||||
* new branch's name
|
||||
* @param startPoint
|
||||
* name of a commit at which to start the new branch
|
||||
*/
|
||||
Promise<Branch> branchCreate(Path project, String name, String startPoint);
|
||||
|
||||
|
|
@ -160,38 +126,10 @@ public interface GitServiceClient {
|
|||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param checkoutRequest
|
||||
* checkout request
|
||||
* @deprecated {@link #checkout(Path, CheckoutRequest)}
|
||||
*/
|
||||
@Deprecated
|
||||
void checkout(ProjectConfig project,
|
||||
CheckoutRequest checkoutRequest,
|
||||
AsyncRequestCallback<String> callback);
|
||||
|
||||
/**
|
||||
* Checkout the branch with pointed name.
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param request
|
||||
* checkout request
|
||||
*/
|
||||
Promise<Void> checkout(Path project, CheckoutRequest request);
|
||||
|
||||
/**
|
||||
* Get the list of remote repositories for pointed by {@code projectConfig} parameter one.
|
||||
*
|
||||
* @param projectConfig
|
||||
* project (root of GIT repository)
|
||||
* @param remoteName
|
||||
* remote repository's name. Can be null in case when it is need to fetch all {@link Remote}
|
||||
* @param verbose
|
||||
* If <code>true</code> show remote url and name otherwise show remote name
|
||||
* @return a promise that provides list {@link Remote} repositories for the {@code workspaceId}, {@code projectConfig},
|
||||
* {@code remoteName}, {@code verbose} or rejects with an error.
|
||||
* @deprecated use {@link #remoteList(Path, String, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Promise<List<Remote>> remoteList(ProjectConfig projectConfig, @Nullable String remoteName, boolean verbose);
|
||||
Promise<String> checkout(Path project, CheckoutRequest request);
|
||||
|
||||
/**
|
||||
* Get the list of remote repositories for pointed by {@code projectConfig} parameter one.
|
||||
|
|
@ -204,7 +142,6 @@ public interface GitServiceClient {
|
|||
* If <code>true</code> show remote url and name otherwise show remote name
|
||||
* @return a promise that provides list {@link Remote} repositories for the {@code workspaceId}, {@code projectConfig},
|
||||
* {@code remoteName}, {@code verbose} or rejects with an error.
|
||||
* @deprecated use {@link #remoteList(Path, String, boolean)}
|
||||
*/
|
||||
Promise<List<Remote>> remoteList(Path project, String remote, boolean verbose);
|
||||
|
||||
|
|
@ -217,21 +154,6 @@ public interface GitServiceClient {
|
|||
* remote repository's name
|
||||
* @param url
|
||||
* remote repository's URL
|
||||
* @deprecated use {@link #remoteAdd(Path, String, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
void remoteAdd(ProjectConfig project,
|
||||
String name,
|
||||
String url,
|
||||
AsyncRequestCallback<String> callback);
|
||||
|
||||
/**
|
||||
* Adds remote repository to the list of remote repositories.
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param name
|
||||
* remote repository's name
|
||||
* @param url
|
||||
*/
|
||||
Promise<Void> remoteAdd(Path project, String name, String url);
|
||||
|
||||
|
|
@ -242,28 +164,18 @@ public interface GitServiceClient {
|
|||
* project (root of GIT repository)
|
||||
* @param name
|
||||
* remote repository name to delete
|
||||
* @deprecated use {@link #remoteDelete(Path, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
void remoteDelete(ProjectConfig project,
|
||||
String name,
|
||||
AsyncRequestCallback<String> callback);
|
||||
|
||||
/**
|
||||
* Deletes the pointed(by name) remote repository from the list of repositories.
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param name
|
||||
*/
|
||||
Promise<Void> remoteDelete(Path project, String name);
|
||||
|
||||
/**
|
||||
* Remove items from the working tree and the index.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param items
|
||||
* items to remove
|
||||
* @param cached
|
||||
* is for removal only from index
|
||||
*/
|
||||
Promise<Void> remove(Path project, Path[] items, boolean cached);
|
||||
|
||||
|
|
@ -272,28 +184,33 @@ public interface GitServiceClient {
|
|||
* 1. Reset files in index - content of files is untouched. Typically it is useful to remove from index mistakenly added files.<br>
|
||||
* <code>git reset [paths]</code> is the opposite of <code>git add [paths]</code>. 2. Reset the current branch head to [commit] and
|
||||
* possibly updates the index (resetting it to the tree of [commit]) and the working tree depending on [mode].
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param commit
|
||||
* commit to which current head should be reset
|
||||
* @param resetType
|
||||
* type of the reset
|
||||
* type of the reset
|
||||
* @param files
|
||||
* pattern of the files to reset the index. If <code>null</code> then reset the current branch head to [commit],
|
||||
* pattern of the files to reset the index. If <code>null</code> then reset the current branch head to [commit],
|
||||
* else reset received files in index.
|
||||
*/
|
||||
Promise<Void> reset(Path project, String commit, ResetRequest.ResetType resetType, Path[] files);
|
||||
|
||||
/**
|
||||
* Initializes new Git repository (over WebSocket).
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param bare
|
||||
* to create bare repository or not
|
||||
*/
|
||||
Promise<Void> init(Path project, boolean bare);
|
||||
|
||||
/**
|
||||
* Pull (fetch and merge) changes from remote repository to local one (sends request over WebSocket).
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param refSpec
|
||||
* list of refspec to fetch.
|
||||
|
|
@ -305,6 +222,7 @@ public interface GitServiceClient {
|
|||
* <li>featured - remote branch name.</li>
|
||||
* </ul>
|
||||
* @param remote
|
||||
* remote remote repository's name
|
||||
*/
|
||||
Promise<PullResponse> pull(Path project, String refSpec, String remote);
|
||||
|
||||
|
|
@ -320,50 +238,22 @@ public interface GitServiceClient {
|
|||
* @param force
|
||||
* push refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. If <code>true</code>
|
||||
* disables the check. This can cause the remote repository to lose commits
|
||||
* @deprecated use {@link #push(Path, List, String, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Promise<PushResponse> push(ProjectConfig project,
|
||||
List<String> refSpec,
|
||||
String remote,
|
||||
boolean force);
|
||||
|
||||
/**
|
||||
* Push changes from local repository to remote one (sends request over WebSocket).
|
||||
* @param project
|
||||
* project
|
||||
* @param refSpec
|
||||
* list of refspec to push
|
||||
* @param remote
|
||||
* remote repository name or url
|
||||
* @param force
|
||||
* push refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. If <code>true</code>
|
||||
*/
|
||||
Promise<PushResponse> push(Path project, List<String> refSpec, String remote, boolean force);
|
||||
|
||||
/**
|
||||
* Performs commit changes from index to repository. The result of the commit is represented by {@link Revision}, which is returned by
|
||||
* callback in <code>onSuccess(Revision result)</code>. Sends request over WebSocket.
|
||||
* Clones one remote repository to local one (over WebSocket).
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param message
|
||||
* commit log message
|
||||
* @param all
|
||||
* automatically stage files that have been modified and deleted
|
||||
* @param amend
|
||||
* indicates that previous commit must be overwritten
|
||||
* @param callback
|
||||
* callback
|
||||
* @throws WebSocketException
|
||||
* @deprecated use {@link #commit(Path, String, boolean, boolean)}
|
||||
* @param remoteUri
|
||||
* the location of the remote repository
|
||||
* @param remoteName
|
||||
* remote name instead of "origin"
|
||||
*/
|
||||
@Deprecated
|
||||
void commit(ProjectConfig project,
|
||||
String message,
|
||||
boolean all,
|
||||
boolean amend,
|
||||
AsyncRequestCallback<Revision> callback);
|
||||
Promise<Void> clone(Path project,
|
||||
String remoteUri,
|
||||
String remoteName);
|
||||
|
||||
/**
|
||||
* Performs commit changes from index to repository. The result of the commit is represented by {@link Revision}, which is returned by
|
||||
|
|
@ -377,62 +267,50 @@ public interface GitServiceClient {
|
|||
* automatically stage files that have been modified and deleted
|
||||
* @param amend
|
||||
* indicates that previous commit must be overwritten
|
||||
* @throws WebSocketException
|
||||
*/
|
||||
Promise<Revision> commit(Path project, String message, boolean all, boolean amend);
|
||||
|
||||
/**
|
||||
* Performs commit for the given files (ignoring git index).
|
||||
* Performs commit changes from index to repository.
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param message
|
||||
* commit log message
|
||||
* @param files
|
||||
* the list of iles that are commited, ignoring the index
|
||||
* @param amend
|
||||
* indicates that previous commit must be overwritten
|
||||
* @throws WebSocketException
|
||||
*/
|
||||
Promise<Revision> commit(Path project, String message, Path[] files, boolean amend);
|
||||
|
||||
/**
|
||||
* Performs commit changes from index to repository.
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param message
|
||||
* commit log message
|
||||
* @param all
|
||||
* automatically stage files that have been modified and deleted
|
||||
* @param files
|
||||
* the list of files that are committed, ignoring the index
|
||||
* @param amend
|
||||
* the list of files that are committed, ignoring the index
|
||||
*/
|
||||
Promise<Revision> commit(Path project, String message, boolean all, Path[] files, boolean amend);
|
||||
Promise<Revision> commit(Path project, String message, boolean amend, Path[] files);
|
||||
|
||||
/**
|
||||
* Get repository options.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param requestedConfig
|
||||
* list of config keys
|
||||
*/
|
||||
Promise<Map<String, String>> config(Path project, List<String> requestedConfig);
|
||||
|
||||
/**
|
||||
* Compare two commits, get the diff for pointed file(s) or for the whole project in text format.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param fileFilter
|
||||
* files for which to show changes
|
||||
* @param type
|
||||
* type of diff format
|
||||
* type of diff format
|
||||
* @param noRenames
|
||||
* don't show renamed files
|
||||
* don't show renamed files
|
||||
* @param renameLimit
|
||||
* the limit of shown renamed files
|
||||
* the limit of shown renamed files
|
||||
* @param commitA
|
||||
* first commit to compare
|
||||
* first commit to compare
|
||||
* @param commitB
|
||||
* second commit to be compared
|
||||
*/
|
||||
Promise<String> diff(Path project,
|
||||
List<String> fileFilter,
|
||||
|
|
@ -445,19 +323,21 @@ public interface GitServiceClient {
|
|||
/**
|
||||
* Compare commit with index or working tree (depends on {@code cached}), get the diff for pointed file(s) or for the whole project in
|
||||
* text format.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param files
|
||||
* files for which to show changes
|
||||
* @param type
|
||||
* type of diff format
|
||||
* type of diff format
|
||||
* @param noRenames
|
||||
* don't show renamed files
|
||||
* don't show renamed files
|
||||
* @param renameLimit
|
||||
* the limit of shown renamed files
|
||||
* the limit of shown renamed files
|
||||
* @param commitA
|
||||
* commit to compare
|
||||
* commit to compare
|
||||
* @param cached
|
||||
* if <code>true</code> then compare commit with index, if <code>false</code>, then compare with working tree.
|
||||
*/
|
||||
Promise<String> diff(Path project,
|
||||
List<String> files,
|
||||
|
|
@ -469,47 +349,39 @@ public interface GitServiceClient {
|
|||
|
||||
/**
|
||||
* Get the file content from specified revision or branch.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project configuration of root GIT repository
|
||||
* @param file
|
||||
* file name with its full path
|
||||
* @param version
|
||||
* revision or branch where the showed file is present
|
||||
*/
|
||||
Promise<ShowFileContentResponse> showFileContent(Path project, Path file, String version);
|
||||
|
||||
/**
|
||||
* Get log of commits.
|
||||
*
|
||||
* Method is deprecated. Use {@link #log(Path, Path[], int, int, boolean)} to pass
|
||||
* {@code skip} and {@code maxCount} parameters to limit the number of returning entries.
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param fileFilter
|
||||
* range of files to filter revisions list
|
||||
* @param plainText
|
||||
*/
|
||||
@Deprecated
|
||||
Promise<LogResponse> log(Path project, @Nullable Path[] fileFilter, boolean plainText);
|
||||
|
||||
/**
|
||||
* Get log of commits.
|
||||
* @param project
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param fileFilter
|
||||
* range of files to filter revisions list
|
||||
* @param skip
|
||||
* the number of commits that will be skipped
|
||||
* the number of commits that will be skipped
|
||||
* @param maxCount
|
||||
* the number of commits that will be returned
|
||||
* the number of commits that will be returned
|
||||
* @param plainText
|
||||
* if <code>true</code> the loq response will be in text format
|
||||
*/
|
||||
Promise<LogResponse> log(Path project, @Nullable Path[] fileFilter, int skip, int maxCount, boolean plainText);
|
||||
|
||||
/**
|
||||
* Merge the pointed commit with current HEAD.
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param commit
|
||||
* commit's reference to merge with
|
||||
*/
|
||||
Promise<MergeResult> merge(Path project, String commit);
|
||||
|
||||
|
|
@ -535,9 +407,11 @@ public interface GitServiceClient {
|
|||
* D 123.txt
|
||||
* ?? folder/test.css
|
||||
* </pre>
|
||||
* @param project
|
||||
*
|
||||
* @param project
|
||||
* project (root of GIT repository)
|
||||
* @param format
|
||||
* to show in short format or not
|
||||
*/
|
||||
Promise<String> statusText(Path project, StatusFormat format);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.git.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
|
||||
import org.eclipse.che.api.git.shared.AddRequest;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.BranchCreateRequest;
|
||||
import org.eclipse.che.api.git.shared.BranchListMode;
|
||||
import org.eclipse.che.api.git.shared.CheckoutRequest;
|
||||
import org.eclipse.che.api.git.shared.CloneRequest;
|
||||
import org.eclipse.che.api.git.shared.CommitRequest;
|
||||
import org.eclipse.che.api.git.shared.Commiters;
|
||||
import org.eclipse.che.api.git.shared.DiffType;
|
||||
import org.eclipse.che.api.git.shared.FetchRequest;
|
||||
import org.eclipse.che.api.git.shared.LogResponse;
|
||||
|
|
@ -37,39 +37,26 @@ import org.eclipse.che.api.git.shared.Revision;
|
|||
import org.eclipse.che.api.git.shared.ShowFileContentResponse;
|
||||
import org.eclipse.che.api.git.shared.Status;
|
||||
import org.eclipse.che.api.git.shared.StatusFormat;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper.RequestCall;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.MimeType;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.machine.WsAgentStateController;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
import org.eclipse.che.ide.rest.AsyncRequest;
|
||||
import org.eclipse.che.ide.rest.AsyncRequestCallback;
|
||||
import org.eclipse.che.ide.rest.AsyncRequestFactory;
|
||||
import org.eclipse.che.ide.rest.AsyncRequestLoader;
|
||||
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
|
||||
import org.eclipse.che.ide.rest.StringMapUnmarshaller;
|
||||
import org.eclipse.che.ide.rest.StringUnmarshaller;
|
||||
import org.eclipse.che.ide.ui.loaders.request.LoaderFactory;
|
||||
import org.eclipse.che.ide.websocket.Message;
|
||||
import org.eclipse.che.ide.websocket.MessageBuilder;
|
||||
import org.eclipse.che.ide.websocket.MessageBus;
|
||||
import org.eclipse.che.ide.websocket.WebSocketException;
|
||||
import org.eclipse.che.ide.websocket.rest.RequestCallback;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.gwt.http.client.RequestBuilder.DELETE;
|
||||
import static com.google.gwt.http.client.RequestBuilder.POST;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.che.api.git.shared.AddRequest.DEFAULT_PATTERN;
|
||||
import static org.eclipse.che.api.git.shared.StatusFormat.PORCELAIN;
|
||||
import static org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper.createFromAsyncRequest;
|
||||
import static org.eclipse.che.ide.MimeType.APPLICATION_JSON;
|
||||
import static org.eclipse.che.ide.MimeType.TEXT_PLAIN;
|
||||
import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;
|
||||
|
|
@ -83,41 +70,39 @@ import static org.eclipse.che.ide.rest.HTTPHeader.CONTENTTYPE;
|
|||
*/
|
||||
@Singleton
|
||||
public class GitServiceClientImpl implements GitServiceClient {
|
||||
private static final String ADD = "/git/add";
|
||||
private static final String BRANCH = "/git/branch";
|
||||
private static final String CHECKOUT = "/git/checkout";
|
||||
private static final String COMMIT = "/git/commit";
|
||||
private static final String CONFIG = "/git/config";
|
||||
private static final String DIFF = "/git/diff";
|
||||
private static final String FETCH = "/git/fetch";
|
||||
private static final String INIT = "/git/init";
|
||||
private static final String LOG = "/git/log";
|
||||
private static final String SHOW = "/git/show";
|
||||
private static final String MERGE = "/git/merge";
|
||||
private static final String STATUS = "/git/status";
|
||||
private static final String PUSH = "/git/push";
|
||||
private static final String PULL = "/git/pull";
|
||||
private static final String REMOTE = "/git/remote";
|
||||
private static final String REMOVE = "/git/remove";
|
||||
private static final String RESET = "/git/reset";
|
||||
private static final String REPOSITORY = "/git/repository";
|
||||
private static final String ADD = "/git/add";
|
||||
private static final String BRANCH = "/git/branch";
|
||||
private static final String CHECKOUT = "/git/checkout";
|
||||
private static final String CLONE = "/git/clone";
|
||||
private static final String COMMIT = "/git/commit";
|
||||
private static final String CONFIG = "/git/config";
|
||||
private static final String DIFF = "/git/diff";
|
||||
private static final String FETCH = "/git/fetch";
|
||||
private static final String INIT = "/git/init";
|
||||
private static final String LOG = "/git/log";
|
||||
private static final String SHOW = "/git/show";
|
||||
private static final String MERGE = "/git/merge";
|
||||
private static final String STATUS = "/git/status";
|
||||
private static final String PUSH = "/git/push";
|
||||
private static final String PULL = "/git/pull";
|
||||
private static final String REMOTE = "/git/remote";
|
||||
private static final String REMOVE = "/git/remove";
|
||||
private static final String RESET = "/git/reset";
|
||||
private static final String REPOSITORY = "/git/repository";
|
||||
|
||||
/** Loader to be displayed. */
|
||||
private final AsyncRequestLoader loader;
|
||||
private final DtoFactory dtoFactory;
|
||||
private final DtoUnmarshallerFactory dtoUnmarshallerFactory;
|
||||
private final AsyncRequestFactory asyncRequestFactory;
|
||||
private final WsAgentStateController wsAgentStateController;
|
||||
private final AppContext appContext;
|
||||
|
||||
@Inject
|
||||
protected GitServiceClientImpl(LoaderFactory loaderFactory,
|
||||
WsAgentStateController wsAgentStateController,
|
||||
DtoFactory dtoFactory,
|
||||
AsyncRequestFactory asyncRequestFactory,
|
||||
DtoUnmarshallerFactory dtoUnmarshallerFactory,
|
||||
AppContext appContext) {
|
||||
this.wsAgentStateController = wsAgentStateController;
|
||||
this.appContext = appContext;
|
||||
this.loader = loaderFactory.newLoader();
|
||||
this.dtoFactory = dtoFactory;
|
||||
|
|
@ -126,46 +111,30 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> init(final Path project, final boolean bare) {
|
||||
return createFromAsyncRequest(new RequestCall<Void>() {
|
||||
@Override
|
||||
public void makeCall(final AsyncCallback<Void> callback) {
|
||||
String url = INIT + "?projectPath=" + project.toString() + "&bare=" + bare;
|
||||
|
||||
Message message = new MessageBuilder(POST, url).header(ACCEPT, TEXT_PLAIN).build();
|
||||
|
||||
sendMessageToWS(message, new RequestCallback<Void>() {
|
||||
@Override
|
||||
protected void onSuccess(Void result) {
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable exception) {
|
||||
callback.onFailure(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
public Promise<Void> init(Path project, boolean bare) {
|
||||
String url = getWsAgentBaseUrl() + INIT + "?projectPath=" + project + "&bare=" + bare;
|
||||
return asyncRequestFactory.createPostRequest(url, null).loader(loader).send();
|
||||
}
|
||||
|
||||
private void sendMessageToWS(final @NotNull Message message, final @NotNull RequestCallback<?> callback) {
|
||||
wsAgentStateController.getMessageBus().then(new Operation<MessageBus>() {
|
||||
@Override
|
||||
public void apply(MessageBus arg) throws OperationException {
|
||||
try {
|
||||
arg.send(message, callback);
|
||||
} catch (WebSocketException e) {
|
||||
throw new OperationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Promise<Void> clone(Path project,
|
||||
String remoteUri,
|
||||
String remoteName) {
|
||||
CloneRequest cloneRequest = dtoFactory.createDto(CloneRequest.class)
|
||||
.withRemoteName(remoteName)
|
||||
.withRemoteUri(remoteUri)
|
||||
.withWorkingDir(project.toString());
|
||||
|
||||
String params = "?projectPath=" + project;
|
||||
String url = CLONE + params;
|
||||
|
||||
return asyncRequestFactory.createPostRequest(url, cloneRequest).loader(loader).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<String> statusText(Path project, StatusFormat format) {
|
||||
String params = "?projectPath=" + project.toString() + "&format=" + format;
|
||||
String url = appContext.getDevAgentEndpoint() + STATUS + params;
|
||||
String params = "?projectPath=" + project + "&format=" + format;
|
||||
String url = getWsAgentBaseUrl() + STATUS + params;
|
||||
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.loader(loader)
|
||||
|
|
@ -175,78 +144,13 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void add(ProjectConfig project,
|
||||
boolean update,
|
||||
@Nullable List<String> filePattern,
|
||||
RequestCallback<Void> callback) throws WebSocketException {
|
||||
AddRequest addRequest = dtoFactory.createDto(AddRequest.class).withUpdate(update);
|
||||
if (filePattern == null) {
|
||||
addRequest.setFilePattern(AddRequest.DEFAULT_PATTERN);
|
||||
} else {
|
||||
addRequest.setFilePattern(filePattern);
|
||||
}
|
||||
String url = ADD + "?projectPath=" + project.getPath();
|
||||
|
||||
MessageBuilder builder = new MessageBuilder(POST, url);
|
||||
builder.data(dtoFactory.toJson(addRequest))
|
||||
.header(CONTENTTYPE, APPLICATION_JSON);
|
||||
Message message = builder.build();
|
||||
|
||||
sendMessageToWS(message, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> add(final Path project, final boolean update, final Path[] paths) {
|
||||
return createFromAsyncRequest(new RequestCall<Void>() {
|
||||
@Override
|
||||
public void makeCall(final AsyncCallback<Void> callback) {
|
||||
final AddRequest addRequest = dtoFactory.createDto(AddRequest.class).withUpdate(update);
|
||||
|
||||
if (paths == null) {
|
||||
addRequest.setFilePattern(AddRequest.DEFAULT_PATTERN);
|
||||
} else {
|
||||
|
||||
final List<String> patterns = new ArrayList<>(); //need for compatible with server side
|
||||
for (Path path : paths) {
|
||||
patterns.add(path.isEmpty() ? "." : path.toString());
|
||||
}
|
||||
|
||||
addRequest.setFilePattern(patterns);
|
||||
}
|
||||
|
||||
final String url = ADD + "?projectPath=" + project.toString();
|
||||
final Message message = new MessageBuilder(POST, url).data(dtoFactory.toJson(addRequest))
|
||||
.header(CONTENTTYPE, APPLICATION_JSON)
|
||||
.build();
|
||||
|
||||
sendMessageToWS(message, new RequestCallback<Void>() {
|
||||
@Override
|
||||
protected void onSuccess(Void result) {
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable exception) {
|
||||
callback.onFailure(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(ProjectConfig project,
|
||||
String message,
|
||||
boolean all,
|
||||
boolean amend,
|
||||
AsyncRequestCallback<Revision> callback) {
|
||||
CommitRequest commitRequest = dtoFactory.createDto(CommitRequest.class)
|
||||
.withMessage(message)
|
||||
.withAmend(amend)
|
||||
.withAll(all);
|
||||
String url = appContext.getDevAgentEndpoint() + COMMIT + "?projectPath=" + project.getPath();
|
||||
|
||||
asyncRequestFactory.createPostRequest(url, commitRequest).loader(loader).send(callback);
|
||||
public Promise<Void> add(Path project, boolean update, Path[] paths) {
|
||||
AddRequest addRequest = dtoFactory.createDto(AddRequest.class)
|
||||
.withUpdate(update);
|
||||
addRequest.setFilePattern(paths == null ? DEFAULT_PATTERN :
|
||||
stream(paths).map(path -> path.isEmpty() ? "." : path.toString()).collect(toList()));
|
||||
String url = getWsAgentBaseUrl() + ADD + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, addRequest).loader(loader).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -255,34 +159,22 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
.withMessage(message)
|
||||
.withAmend(amend)
|
||||
.withAll(all);
|
||||
String url = appContext.getDevAgentEndpoint() + COMMIT + "?projectPath=" + project;
|
||||
|
||||
String url = getWsAgentBaseUrl() + COMMIT + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, commitRequest)
|
||||
.loader(loader)
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(Revision.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Revision> commit(Path project, String message, Path[] files, boolean amend) {
|
||||
return commit(project, message, false, files, amend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Revision> commit(Path project, String message, boolean all, Path[] files, boolean amend) {
|
||||
List<String> paths = new ArrayList<>(files.length);
|
||||
|
||||
for (Path file : files) {
|
||||
if (!file.isEmpty()) {
|
||||
paths.add(file.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public Promise<Revision> commit(Path project, String message, boolean amend, Path[] files) {
|
||||
CommitRequest commitRequest = dtoFactory.createDto(CommitRequest.class)
|
||||
.withMessage(message)
|
||||
.withAmend(amend)
|
||||
.withAll(all)
|
||||
.withFiles(paths);
|
||||
String url = appContext.getDevAgentEndpoint() + COMMIT + "?projectPath=" + project;
|
||||
.withFiles(stream(files).filter(file -> !file.isEmpty())
|
||||
.map(Path::toString)
|
||||
.collect(toList()));
|
||||
|
||||
String url = getWsAgentBaseUrl() + COMMIT + "?projectPath=" + project;
|
||||
|
||||
return asyncRequestFactory.createPostRequest(url, commitRequest)
|
||||
.loader(loader)
|
||||
|
|
@ -291,80 +183,48 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
|
||||
@Override
|
||||
public Promise<Map<String, String>> config(Path project, List<String> requestedConfig) {
|
||||
String params = "?projectPath=" + project.toString();
|
||||
String params = "?projectPath=" + project;
|
||||
if (requestedConfig != null) {
|
||||
for (String entry : requestedConfig) {
|
||||
params += "&requestedConfig=" + entry;
|
||||
}
|
||||
}
|
||||
String url = appContext.getDevAgentEndpoint() + CONFIG + params;
|
||||
String url = getWsAgentBaseUrl() + CONFIG + params;
|
||||
return asyncRequestFactory.createGetRequest(url).loader(loader).send(new StringMapUnmarshaller());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<PushResponse> push(ProjectConfig project, List<String> refSpec, String remote, boolean force) {
|
||||
PushRequest pushRequest = dtoFactory.createDto(PushRequest.class)
|
||||
.withRemote(remote)
|
||||
.withRefSpec(refSpec)
|
||||
.withForce(force);
|
||||
return asyncRequestFactory.createPostRequest(appContext.getDevAgentEndpoint() + PUSH +
|
||||
"?projectPath=" + project.getPath(), pushRequest)
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(PushResponse.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<PushResponse> push(Path project, List<String> refSpec, String remote, boolean force) {
|
||||
PushRequest pushRequest = dtoFactory.createDto(PushRequest.class)
|
||||
.withRemote(remote)
|
||||
.withRefSpec(refSpec)
|
||||
.withForce(force);
|
||||
return asyncRequestFactory.createPostRequest(appContext.getDevAgentEndpoint() + PUSH + "?projectPath=" + project, pushRequest)
|
||||
String url = getWsAgentBaseUrl() + PUSH + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, pushRequest)
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(PushResponse.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<List<Remote>> remoteList(ProjectConfig project, @Nullable String remoteName, boolean verbose) {
|
||||
String params = "?projectPath=" + project.getPath() + "&verbose=" + String.valueOf(verbose);
|
||||
if (remoteName != null) {
|
||||
params += "&remoteName=" + remoteName;
|
||||
}
|
||||
String url = appContext.getDevAgentEndpoint() + REMOTE + params;
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.loader(loader)
|
||||
.send(dtoUnmarshallerFactory.newListUnmarshaller(Remote.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<List<Remote>> remoteList(Path project, String remoteName, boolean verbose) {
|
||||
String params = "?projectPath=" + project.toString() + (remoteName != null ? "&remoteName=" + remoteName : "") +
|
||||
String params = "?projectPath=" + project +
|
||||
(remoteName != null ? "&remoteName=" + remoteName : "") +
|
||||
"&verbose=" + String.valueOf(verbose);
|
||||
String url = appContext.getDevAgentEndpoint() + REMOTE + params;
|
||||
String url = getWsAgentBaseUrl() + REMOTE + params;
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.loader(loader)
|
||||
.send(dtoUnmarshallerFactory.newListUnmarshaller(Remote.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void branchList(ProjectConfig project,
|
||||
BranchListMode listMode,
|
||||
AsyncRequestCallback<List<Branch>> callback) {
|
||||
String url = appContext.getDevAgentEndpoint() + BRANCH + "?projectPath=" + project.getPath() +
|
||||
(listMode == null ? "" : "&listMode=" + listMode);
|
||||
asyncRequestFactory.createGetRequest(url).send(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<List<Branch>> branchList(Path project, BranchListMode listMode) {
|
||||
String url = appContext.getDevAgentEndpoint() + BRANCH + "?projectPath=" + project.toString() +
|
||||
(listMode == null ? "" : "&listMode=" + listMode);
|
||||
String url = getWsAgentBaseUrl() + BRANCH + "?projectPath=" + project + (listMode == null ? "" : "&listMode=" + listMode);
|
||||
return asyncRequestFactory.createGetRequest(url).send(dtoUnmarshallerFactory.newListUnmarshaller(Branch.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Status> getStatus(Path project) {
|
||||
final String params = "?projectPath=" + project.toString() + "&format=" + PORCELAIN;
|
||||
final String url = appContext.getDevAgentEndpoint() + STATUS + params;
|
||||
String params = "?projectPath=" + project + "&format=" + PORCELAIN;
|
||||
String url = getWsAgentBaseUrl() + STATUS + params;
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.loader(loader)
|
||||
.header(CONTENTTYPE, APPLICATION_JSON)
|
||||
|
|
@ -374,15 +234,14 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
|
||||
@Override
|
||||
public Promise<Void> branchDelete(Path project, String name, boolean force) {
|
||||
String url = appContext.getDevAgentEndpoint() + BRANCH + "?projectPath=" + project.toString()
|
||||
+ "&name=" + name + "&force=" + force;
|
||||
String url = getWsAgentBaseUrl() + BRANCH + "?projectPath=" + project + "&name=" + name + "&force=" + force;
|
||||
return asyncRequestFactory.createDeleteRequest(url).loader(loader).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> branchRename(Path project, String oldName, String newName) {
|
||||
String params = "?projectPath=" + project.toString() + "&oldName=" + oldName + "&newName=" + newName;
|
||||
String url = appContext.getDevAgentEndpoint() + BRANCH + params;
|
||||
String params = "?projectPath=" + project + "&oldName=" + oldName + "&newName=" + newName;
|
||||
String url = getWsAgentBaseUrl() + BRANCH + params;
|
||||
return asyncRequestFactory.createPostRequest(url, null).loader(loader)
|
||||
.header(CONTENTTYPE, MimeType.APPLICATION_FORM_URLENCODED)
|
||||
.send();
|
||||
|
|
@ -391,7 +250,7 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
@Override
|
||||
public Promise<Branch> branchCreate(Path project, String name, String startPoint) {
|
||||
BranchCreateRequest branchCreateRequest = dtoFactory.createDto(BranchCreateRequest.class).withName(name).withStartPoint(startPoint);
|
||||
String url = appContext.getDevAgentEndpoint() + BRANCH + "?projectPath=" + project.toString();
|
||||
String url = getWsAgentBaseUrl() + BRANCH + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, branchCreateRequest)
|
||||
.loader(loader)
|
||||
.header(ACCEPT, APPLICATION_JSON)
|
||||
|
|
@ -399,31 +258,21 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkout(ProjectConfig project,
|
||||
CheckoutRequest checkoutRequest,
|
||||
AsyncRequestCallback<String> callback) {
|
||||
String url = appContext.getDevAgentEndpoint() + CHECKOUT + "?projectPath=" + project.getPath();
|
||||
asyncRequestFactory.createPostRequest(url, checkoutRequest).loader(loader).send(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> checkout(Path project,
|
||||
CheckoutRequest request) {
|
||||
|
||||
final String url = appContext.getDevAgentEndpoint() + CHECKOUT + "?projectPath=" + project.toString();
|
||||
return asyncRequestFactory.createPostRequest(url, request).loader(loader).send();
|
||||
public Promise<String> checkout(Path project, CheckoutRequest request) {
|
||||
String url = getWsAgentBaseUrl() + CHECKOUT + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, request).loader(loader).send(new StringUnmarshaller());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> remove(Path project, Path[] items, boolean cached) {
|
||||
String params = "?projectPath=" + project.toString();
|
||||
String params = "?projectPath=" + project;
|
||||
if (items != null) {
|
||||
for (Path item : items) {
|
||||
params += "&items=" + item.toString();
|
||||
}
|
||||
}
|
||||
params += "&cached=" + String.valueOf(cached);
|
||||
String url = appContext.getDevAgentEndpoint() + REMOVE + params;
|
||||
String url = getWsAgentBaseUrl() + REMOVE + params;
|
||||
return asyncRequestFactory.createDeleteRequest(url).loader(loader).send();
|
||||
}
|
||||
|
||||
|
|
@ -434,32 +283,24 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
resetRequest.setType(resetType);
|
||||
}
|
||||
if (files != null) {
|
||||
List<String> fileList = new ArrayList<>(files.length);
|
||||
for (Path file : files) {
|
||||
fileList.add(file.isEmpty() ? "." : file.toString());
|
||||
}
|
||||
resetRequest.setFilePattern(fileList);
|
||||
resetRequest.setFilePattern(stream(files).map(file -> file.isEmpty() ? "." : file.toString()).collect(toList()));
|
||||
}
|
||||
String url = appContext.getDevAgentEndpoint() + RESET + "?projectPath=" + project;
|
||||
String url = getWsAgentBaseUrl() + RESET + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, resetRequest).loader(loader).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<LogResponse> log(Path project, Path[] fileFilter, boolean plainText) {
|
||||
return log(project, fileFilter, -1, -1, plainText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<LogResponse> log(Path project, Path[] fileFilter, int skip, int maxCount, boolean plainText) {
|
||||
StringBuilder params = new StringBuilder().append("?projectPath=").append(project.toString());
|
||||
StringBuilder params = new StringBuilder().append("?projectPath=")
|
||||
.append(project)
|
||||
.append("&skip=")
|
||||
.append(skip)
|
||||
.append("&maxCount=")
|
||||
.append(maxCount);
|
||||
if (fileFilter != null) {
|
||||
for (Path file : fileFilter) {
|
||||
params.append("&fileFilter=").append(file.toString());
|
||||
}
|
||||
stream(fileFilter).forEach(file -> params.append("&fileFilter=").append(file));
|
||||
}
|
||||
params.append("&skip=").append(skip);
|
||||
params.append("&maxCount=").append(maxCount);
|
||||
String url = appContext.getDevAgentEndpoint() + LOG + params;
|
||||
String url = getWsAgentBaseUrl() + LOG + params;
|
||||
if (plainText) {
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(LogResponse.class));
|
||||
|
|
@ -470,34 +311,16 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteAdd(ProjectConfig project,
|
||||
String name,
|
||||
String repositoryURL,
|
||||
AsyncRequestCallback<String> callback) {
|
||||
RemoteAddRequest remoteAddRequest = dtoFactory.createDto(RemoteAddRequest.class).withName(name).withUrl(repositoryURL);
|
||||
String url = appContext.getDevAgentEndpoint() + REMOTE + "?projectPath=" + project.getPath();
|
||||
asyncRequestFactory.createPutRequest(url, remoteAddRequest).loader(loader).send(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> remoteAdd(Path project, String name, String url) {
|
||||
RemoteAddRequest remoteAddRequest = dtoFactory.createDto(RemoteAddRequest.class).withName(name).withUrl(url);
|
||||
String requestUrl = appContext.getDevAgentEndpoint() + REMOTE + "?projectPath=" + project.toString();
|
||||
String requestUrl = getWsAgentBaseUrl() + REMOTE + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPutRequest(requestUrl, remoteAddRequest).loader(loader).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteDelete(ProjectConfig project,
|
||||
String name,
|
||||
AsyncRequestCallback<String> callback) {
|
||||
String url = appContext.getDevAgentEndpoint() + REMOTE + '/' + name + "?projectPath=" + project.getPath();
|
||||
asyncRequestFactory.createDeleteRequest(url).loader(loader).send(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> remoteDelete(Path project, String name) {
|
||||
String url = appContext.getDevAgentEndpoint() + REMOTE + '/' + name + "?projectPath=" + project.toString();
|
||||
String url = getWsAgentBaseUrl() + REMOTE + '/' + name + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createDeleteRequest(url).loader(loader).send();
|
||||
}
|
||||
|
||||
|
|
@ -507,37 +330,49 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
.withRefSpec(refspec)
|
||||
.withRemote(remote)
|
||||
.withRemoveDeletedRefs(removeDeletedRefs);
|
||||
String url = appContext.getDevAgentEndpoint() + FETCH + "?projectPath=" + project;
|
||||
String url = getWsAgentBaseUrl() + FETCH + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, fetchRequest).send();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<PullResponse> pull(Path project, String refSpec, String remote) {
|
||||
PullRequest pullRequest = dtoFactory.createDto(PullRequest.class).withRemote(remote).withRefSpec(refSpec);
|
||||
String url = appContext.getDevAgentEndpoint() + PULL + "?projectPath=" + project;
|
||||
String url = getWsAgentBaseUrl() + PULL + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, pullRequest).send(dtoUnmarshallerFactory.newUnmarshaller(PullResponse.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<String> diff(Path project,
|
||||
List<String> fileFilter,
|
||||
public Promise<String> diff(Path project, List<String> fileFilter,
|
||||
DiffType type,
|
||||
boolean noRenames,
|
||||
int renameLimit,
|
||||
String commitA,
|
||||
String commitB) {
|
||||
return diff(project, fileFilter, type, noRenames, renameLimit, commitA, commitB, false).send(new StringUnmarshaller());
|
||||
return diff(project,
|
||||
fileFilter,
|
||||
type,
|
||||
noRenames,
|
||||
renameLimit,
|
||||
commitA,
|
||||
commitB,
|
||||
false).send(new StringUnmarshaller());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<String> diff(Path project,
|
||||
List<String> files,
|
||||
public Promise<String> diff(Path project, List<String> files,
|
||||
DiffType type,
|
||||
boolean noRenames,
|
||||
int renameLimit,
|
||||
String commitA,
|
||||
boolean cached) {
|
||||
return diff(project, files, type, noRenames, renameLimit, commitA, null, cached).send(new StringUnmarshaller());
|
||||
return diff(project,
|
||||
files,
|
||||
type,
|
||||
noRenames,
|
||||
renameLimit,
|
||||
commitA,
|
||||
null,
|
||||
cached).send(new StringUnmarshaller());
|
||||
}
|
||||
|
||||
private AsyncRequest diff(Path project,
|
||||
|
|
@ -548,36 +383,31 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
String commitA,
|
||||
String commitB,
|
||||
boolean cached) {
|
||||
StringBuilder params = new StringBuilder().append("?projectPath=").append(project.toString());
|
||||
StringBuilder params = new StringBuilder().append("?projectPath=")
|
||||
.append(project)
|
||||
.append("&noRenames=").append(noRenames)
|
||||
.append("&renameLimit=").append(renameLimit)
|
||||
.append("&cached=").append(cached);
|
||||
if (fileFilter != null) {
|
||||
for (String file : fileFilter) {
|
||||
if (file.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
params.append("&fileFilter=").append(file);
|
||||
}
|
||||
fileFilter.stream().filter(file -> !file.isEmpty()).forEach(file -> params.append("&fileFilter=").append(file));
|
||||
}
|
||||
if (type != null) {
|
||||
params.append("&diffType=").append(type);
|
||||
}
|
||||
params.append("&noRenames=").append(noRenames);
|
||||
params.append("&renameLimit=").append(renameLimit);
|
||||
if (commitA != null) {
|
||||
params.append("&commitA=").append(commitA);
|
||||
}
|
||||
if (commitB != null) {
|
||||
params.append("&commitB=").append(commitB);
|
||||
}
|
||||
params.append("&cached=").append(cached);
|
||||
|
||||
String url = appContext.getDevAgentEndpoint() + DIFF + params;
|
||||
String url = getWsAgentBaseUrl() + DIFF + params;
|
||||
return asyncRequestFactory.createGetRequest(url).loader(loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise<ShowFileContentResponse> showFileContent(Path project, Path file, String version) {
|
||||
String params = "?projectPath=" + project.toString() + "&file=" + file + "&version=" + version ;
|
||||
String url = appContext.getDevAgentEndpoint() + SHOW + params;
|
||||
String params = "?projectPath=" + project + "&file=" + file + "&version=" + version;
|
||||
String url = getWsAgentBaseUrl() + SHOW + params;
|
||||
return asyncRequestFactory.createGetRequest(url)
|
||||
.loader(loader)
|
||||
.send(dtoUnmarshallerFactory.newUnmarshaller(ShowFileContentResponse.class));
|
||||
|
|
@ -586,7 +416,7 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
@Override
|
||||
public Promise<MergeResult> merge(Path project, String commit) {
|
||||
MergeRequest mergeRequest = dtoFactory.createDto(MergeRequest.class).withCommit(commit);
|
||||
String url = appContext.getDevAgentEndpoint() + MERGE + "?projectPath=" + project;
|
||||
String url = getWsAgentBaseUrl() + MERGE + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createPostRequest(url, mergeRequest)
|
||||
.loader(loader)
|
||||
.header(ACCEPT, APPLICATION_JSON)
|
||||
|
|
@ -594,26 +424,12 @@ public class GitServiceClientImpl implements GitServiceClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Promise<Void> deleteRepository(final Path project) {
|
||||
return createFromAsyncRequest(new RequestCall<Void>() {
|
||||
@Override
|
||||
public void makeCall(final AsyncCallback<Void> callback) {
|
||||
String url = REPOSITORY + "?projectPath=" + project.toString();
|
||||
final Message message = new MessageBuilder(DELETE, url).header(ACCEPT, TEXT_PLAIN)
|
||||
.build();
|
||||
public Promise<Void> deleteRepository(Path project) {
|
||||
String url = getWsAgentBaseUrl() + REPOSITORY + "?projectPath=" + project;
|
||||
return asyncRequestFactory.createDeleteRequest(url).loader(loader).send();
|
||||
}
|
||||
|
||||
sendMessageToWS(message, new RequestCallback<Void>() {
|
||||
@Override
|
||||
protected void onSuccess(Void result) {
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable exception) {
|
||||
callback.onFailure(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
private String getWsAgentBaseUrl() {
|
||||
return appContext.getDevMachine().getWsAgentBaseUrl();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,9 +109,8 @@ public class AddToIndexAction extends GitAction {
|
|||
}
|
||||
|
||||
private boolean containsInSelected(List<String> items) {
|
||||
Resource[] appContextResources = appContext.getResources();
|
||||
for (String item : items) {
|
||||
for (Resource selectedItem : appContextResources) {
|
||||
for (Resource selectedItem : appContext.getResources()) {
|
||||
String selectedItemPath = selectedItem.getLocation()
|
||||
.removeFirstSegments(1) // remove project name from path
|
||||
.toString();
|
||||
|
|
|
|||
|
|
@ -10,18 +10,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.git.client.action;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
|
|
@ -89,44 +84,33 @@ public class CompareWithLatestAction extends GitAction {
|
|||
.removeTrailingSeparator()
|
||||
.toString();
|
||||
|
||||
service.diff(
|
||||
project.getLocation(),
|
||||
selectedItemPath.isEmpty() ? null : singletonList(selectedItemPath),
|
||||
NAME_STATUS, false, 0, REVISION, false)
|
||||
.then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(String diff) throws OperationException {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
project.getFile(changedFiles[0].substring(2)).then(new Operation<Optional<File>>() {
|
||||
@Override
|
||||
public void apply(Optional<File> file) throws OperationException {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(),
|
||||
defineStatus(changedFiles[0].substring(0, 1)),
|
||||
REVISION);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Map<String, Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
service.diff(project.getLocation(),
|
||||
selectedItemPath.isEmpty() ? null : singletonList(selectedItemPath), NAME_STATUS, false, 0, REVISION, false)
|
||||
.then(diff -> {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
project.getFile(changedFiles[0].substring(2)).then(file -> {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(),
|
||||
defineStatus(changedFiles[0].substring(0, 1)),
|
||||
REVISION);
|
||||
}
|
||||
changesListPresenter.show(items, REVISION, null, project);
|
||||
});
|
||||
} else {
|
||||
Map<String, Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
}
|
||||
changesListPresenter.show(items, REVISION, null, project);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError arg) throws OperationException {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(arg -> {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import org.eclipse.che.ide.api.resources.Project;
|
|||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.git.client.GitResources;
|
||||
import org.eclipse.che.ide.ext.git.client.delete.DeleteRepositoryPresenter;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
|
@ -52,11 +51,6 @@ public class DeleteRepositoryAction extends GitAction {
|
|||
|
||||
dialogFactory.createConfirmDialog(constant.deleteGitRepositoryTitle(),
|
||||
constant.deleteGitRepositoryQuestion(project.getName()),
|
||||
new ConfirmCallback() {
|
||||
@Override
|
||||
public void accepted() {
|
||||
presenter.deleteRepository(project);
|
||||
}
|
||||
}, null).show();
|
||||
() -> presenter.deleteRepository(project), null).show();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
|||
import org.eclipse.che.ide.ext.git.client.GitResources;
|
||||
import org.eclipse.che.ide.ext.git.client.GitUtil;
|
||||
import org.eclipse.che.ide.ext.git.client.init.InitRepositoryPresenter;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
|
@ -58,12 +57,7 @@ public class InitRepositoryAction extends GitAction {
|
|||
|
||||
dialogFactory.createConfirmDialog(constant.createTitle(),
|
||||
constant.messagesInitRepoQuestion(project.getName()),
|
||||
new ConfirmCallback() {
|
||||
@Override
|
||||
public void accepted() {
|
||||
presenter.initRepository(project);
|
||||
}
|
||||
}, null).show();
|
||||
() -> presenter.initRepository(project), null).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -13,11 +13,9 @@ package org.eclipse.che.ide.ext.git.client.add;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.machine.DevMachine;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.Container;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
|
|
@ -84,7 +82,6 @@ public class AddToIndexPresenter implements AddToIndexView.ActionDelegate {
|
|||
view.showDialog();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onAddClicked() {
|
||||
Resource[] resources = appContext.getResources();
|
||||
|
|
@ -97,25 +94,18 @@ public class AddToIndexPresenter implements AddToIndexView.ActionDelegate {
|
|||
final GitOutputConsole console = gitOutputConsoleFactory.create(constant.addToIndexCommandName());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
service.add(projectLocation, view.isUpdated(), paths)
|
||||
.then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void arg) throws OperationException {
|
||||
console.print(constant.addSuccess());
|
||||
notificationManager.notify(constant.addSuccess());
|
||||
view.close();
|
||||
}
|
||||
.then(arg -> {
|
||||
console.print(constant.addSuccess());
|
||||
notificationManager.notify(constant.addSuccess());
|
||||
view.close();
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError arg) throws OperationException {
|
||||
console.printError(constant.addFailed());
|
||||
notificationManager.notify(constant.addFailed(), FAIL, FLOAT_MODE);
|
||||
view.close();
|
||||
}
|
||||
.catchError(arg -> {
|
||||
console.printError(constant.addFailed());
|
||||
notificationManager.notify(constant.addFailed(), FAIL, FLOAT_MODE);
|
||||
view.close();
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCancelClicked() {
|
||||
view.close();
|
||||
|
|
|
|||
|
|
@ -16,13 +16,8 @@ import com.google.inject.Singleton;
|
|||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.CheckoutRequest;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.api.dialogs.InputCallback;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
|
@ -33,7 +28,6 @@ import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsoleFactory;
|
|||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.che.api.git.shared.BranchListMode.LIST_ALL;
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
|
||||
|
|
@ -48,11 +42,12 @@ import static org.eclipse.che.ide.util.ExceptionUtils.getErrorCode;
|
|||
*/
|
||||
@Singleton
|
||||
public class BranchPresenter implements BranchView.ActionDelegate {
|
||||
public static final String BRANCH_RENAME_COMMAND_NAME = "Git rename branch";
|
||||
public static final String BRANCH_DELETE_COMMAND_NAME = "Git delete branch";
|
||||
public static final String BRANCH_CHECKOUT_COMMAND_NAME = "Git checkout branch";
|
||||
public static final String BRANCH_CREATE_COMMAND_NAME = "Git create branch";
|
||||
public static final String BRANCH_LIST_COMMAND_NAME = "Git list of branches";
|
||||
|
||||
private static final String BRANCH_RENAME_COMMAND_NAME = "Git rename branch";
|
||||
private static final String BRANCH_DELETE_COMMAND_NAME = "Git delete branch";
|
||||
private static final String BRANCH_CHECKOUT_COMMAND_NAME = "Git checkout branch";
|
||||
private static final String BRANCH_CREATE_COMMAND_NAME = "Git create branch";
|
||||
private static final String BRANCH_LIST_COMMAND_NAME = "Git list of branches";
|
||||
|
||||
private final DtoFactory dtoFactory;
|
||||
private final BranchView view;
|
||||
|
|
@ -96,24 +91,17 @@ public class BranchPresenter implements BranchView.ActionDelegate {
|
|||
getBranches();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCloseClicked() {
|
||||
view.close();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onRenameClicked() {
|
||||
if (selectedBranch.isRemote()) {
|
||||
dialogFactory.createConfirmDialog(constant.branchConfirmRenameTitle(),
|
||||
constant.branchConfirmRenameMessage(),
|
||||
new ConfirmCallback() {
|
||||
@Override
|
||||
public void accepted() {
|
||||
renameBranch();
|
||||
}
|
||||
},
|
||||
this::renameBranch,
|
||||
null).show();
|
||||
} else {
|
||||
renameBranch();
|
||||
|
|
@ -127,29 +115,18 @@ public class BranchPresenter implements BranchView.ActionDelegate {
|
|||
selectedBranchName,
|
||||
0,
|
||||
selectedBranchName.length(),
|
||||
new InputCallback() {
|
||||
@Override
|
||||
public void accepted(String newBranchName) {
|
||||
renameBranch(newBranchName);
|
||||
}
|
||||
},
|
||||
this::renameBranch,
|
||||
null).show();
|
||||
}
|
||||
|
||||
private void renameBranch(String newName) {
|
||||
service.branchRename(project.getLocation(), selectedBranch.getDisplayName(), newName)
|
||||
.then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
getBranches();
|
||||
}
|
||||
.then(ignored -> {
|
||||
getBranches();
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_RENAME_COMMAND_NAME);
|
||||
getBranches();//rename of remote branch occurs in three stages, so needs update list of branches on view
|
||||
}
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_RENAME_COMMAND_NAME);
|
||||
getBranches();//rename of remote branch occurs in three stages, so needs update list of branches on view
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -160,24 +137,18 @@ public class BranchPresenter implements BranchView.ActionDelegate {
|
|||
return tokens.length > 0 ? tokens[tokens.length - 1] : selectedBranchName;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onDeleteClicked() {
|
||||
|
||||
service.branchDelete(project.getLocation(), selectedBranch.getName(), true).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
getBranches();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_DELETE_COMMAND_NAME);
|
||||
}
|
||||
});
|
||||
service.branchDelete(project.getLocation(), selectedBranch.getName(), true)
|
||||
.then(ignored -> {
|
||||
getBranches();
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_DELETE_COMMAND_NAME);
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCheckoutClicked() {
|
||||
final CheckoutRequest checkoutRequest = dtoFactory.createDto(CheckoutRequest.class);
|
||||
|
|
@ -187,65 +158,48 @@ public class BranchPresenter implements BranchView.ActionDelegate {
|
|||
checkoutRequest.setName(selectedBranch.getDisplayName());
|
||||
}
|
||||
|
||||
service.checkout(project.getLocation(), checkoutRequest).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
getBranches();
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_CHECKOUT_COMMAND_NAME);
|
||||
}
|
||||
});
|
||||
service.checkout(project.getLocation(), checkoutRequest)
|
||||
.then(ignored -> {
|
||||
getBranches();
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_CHECKOUT_COMMAND_NAME);
|
||||
});
|
||||
}
|
||||
|
||||
/** Get the list of branches. */
|
||||
private void getBranches() {
|
||||
service.branchList(project.getLocation(), LIST_ALL).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
if (branches.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(constant.branchTitle(),
|
||||
constant.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
view.setBranches(branches);
|
||||
view.showDialogIfClosed();
|
||||
}
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_LIST_COMMAND_NAME);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), LIST_ALL)
|
||||
.then(branches -> {
|
||||
if (branches.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(constant.branchTitle(),
|
||||
constant.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
view.setBranches(branches);
|
||||
view.showDialogIfClosed();
|
||||
}
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_LIST_COMMAND_NAME);
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCreateClicked() {
|
||||
dialogFactory.createInputDialog(constant.branchCreateNew(), constant.branchTypeNew(), new InputCallback() {
|
||||
@Override
|
||||
public void accepted(String value) {
|
||||
if (value.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
service.branchCreate(project.getLocation(), value, null).then(new Operation<Branch>() {
|
||||
@Override
|
||||
public void apply(Branch branch) throws OperationException {
|
||||
getBranches();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_CREATE_COMMAND_NAME);
|
||||
}
|
||||
});
|
||||
dialogFactory.createInputDialog(constant.branchCreateNew(), constant.branchTypeNew(), value -> {
|
||||
if (value.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
service.branchCreate(project.getLocation(), value, null)
|
||||
.then(branch -> {
|
||||
getBranches();
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_CREATE_COMMAND_NAME);
|
||||
});
|
||||
}, null).show();
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +212,6 @@ public class BranchPresenter implements BranchView.ActionDelegate {
|
|||
view.setEnableDeleteButton(false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onBranchSelected(@NotNull Branch branch) {
|
||||
selectedBranch = branch;
|
||||
|
|
|
|||
|
|
@ -14,14 +14,10 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.git.shared.CheckoutRequest;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsole;
|
||||
|
|
@ -88,29 +84,21 @@ public class CheckoutReferencePresenter implements CheckoutReferenceView.ActionD
|
|||
public void onCheckoutClicked(final String reference) {
|
||||
|
||||
service.checkout(project.getLocation(), dtoFactory.createDto(CheckoutRequest.class).withName(reference))
|
||||
.then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void arg) throws OperationException {
|
||||
project.synchronize().then(new Operation<Resource[]>() {
|
||||
@Override
|
||||
public void apply(Resource[] arg) throws OperationException {
|
||||
view.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
.then(branchName -> {
|
||||
appContext.getRootProject().synchronize()
|
||||
.then(arg -> {
|
||||
view.close();
|
||||
});
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
final String errorMessage = (error.getMessage() != null)
|
||||
? error.getMessage()
|
||||
: constant.checkoutFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(CHECKOUT_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.checkoutFailed(), FAIL, FLOAT_MODE);
|
||||
view.close();
|
||||
}
|
||||
.catchError(error -> {
|
||||
final String errorMessage = (error.getMessage() != null)
|
||||
? error.getMessage()
|
||||
: constant.checkoutFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(CHECKOUT_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.checkoutFailed(), FAIL, FLOAT_MODE);
|
||||
view.close();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ import org.eclipse.che.ide.commons.exception.ServerException;
|
|||
import org.eclipse.che.ide.ext.git.client.DateTimeFormatter;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.git.client.compare.FileStatus.Status;
|
||||
import org.eclipse.che.ide.ext.git.client.compare.changespanel.ChangesPanelPresenter;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsole;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsoleFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.compare.changespanel.ChangesPanelPresenter;
|
||||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
|
||||
|
|
@ -194,9 +194,8 @@ public class CommitPresenter implements CommitView.ActionDelegate {
|
|||
.then(arg -> {
|
||||
service.commit(location,
|
||||
view.getMessage(),
|
||||
false,
|
||||
filesToCommitArray,
|
||||
view.isAmend())
|
||||
view.isAmend(),
|
||||
filesToCommitArray)
|
||||
.then(revision -> {
|
||||
onCommitSuccess(revision);
|
||||
if (view.isPushAfterCommit()) {
|
||||
|
|
|
|||
|
|
@ -15,23 +15,19 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.api.git.shared.ShowFileContentResponse;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.CancelCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.api.event.FileContentUpdateEvent;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.Container;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.git.client.compare.FileStatus.Status;
|
||||
import org.eclipse.che.ide.api.dialogs.CancelCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.resource.Path;
|
||||
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.NOT_EMERGE_MODE;
|
||||
|
|
@ -109,39 +105,26 @@ public class ComparePresenter implements CompareView.ActionDelegate {
|
|||
|
||||
if (status.equals(DELETED)) {
|
||||
service.showFileContent(project.get().getLocation(), relPath, revision)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(ShowFileContentResponse content) throws OperationException {
|
||||
view.setTitle(file.getLocation().toString());
|
||||
view.setColumnTitles(locale.compareYourVersionTitle(), revision + locale.compareReadOnlyTitle());
|
||||
view.show(content.getContent(), "", file.getLocation().toString(), false);
|
||||
}
|
||||
.then(content -> {
|
||||
view.setTitle(file.getLocation().toString());
|
||||
view.setColumnTitles(locale.compareYourVersionTitle(), revision + locale.compareReadOnlyTitle());
|
||||
view.show(content.getContent(), "", file.getLocation().toString(), false);
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
} else {
|
||||
service.showFileContent(project.get().getLocation(), relPath, revision)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(ShowFileContentResponse content) throws OperationException {
|
||||
showCompare(content.getContent());
|
||||
}
|
||||
.then(content -> {
|
||||
showCompare(content.getContent());
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param file
|
||||
* path of the file
|
||||
* @param status
|
||||
|
|
@ -164,56 +147,35 @@ public class ComparePresenter implements CompareView.ActionDelegate {
|
|||
view.setTitle(file.toString());
|
||||
if (status == Status.ADDED) {
|
||||
service.showFileContent(projectLocation, file, revisionB)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(ShowFileContentResponse response) throws OperationException {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(),
|
||||
revisionA == null ? "" : revisionA + locale.compareReadOnlyTitle());
|
||||
view.show("", response.getContent(), file.toString(), true);
|
||||
}
|
||||
.then(response -> {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(),
|
||||
revisionA == null ? "" : revisionA + locale.compareReadOnlyTitle());
|
||||
view.show("", response.getContent(), file.toString(), true);
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
} else if (status == Status.DELETED) {
|
||||
service.showFileContent(projectLocation, file, revisionA)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(ShowFileContentResponse response) throws OperationException {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(), revisionA + locale.compareReadOnlyTitle());
|
||||
view.show(response.getContent(), "", file.toString(), true);
|
||||
}
|
||||
.then(response -> {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(), revisionA + locale.compareReadOnlyTitle());
|
||||
view.show(response.getContent(), "", file.toString(), true);
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
} else {
|
||||
service.showFileContent(projectLocation, file, revisionA)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(final ShowFileContentResponse contentAResponse) throws OperationException {
|
||||
service.showFileContent(projectLocation, file, revisionB)
|
||||
.then(new Operation<ShowFileContentResponse>() {
|
||||
@Override
|
||||
public void apply(ShowFileContentResponse contentBResponse) throws OperationException {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(),
|
||||
revisionA + locale.compareReadOnlyTitle());
|
||||
view.show(contentAResponse.getContent(), contentBResponse.getContent(), file.toString(), true);
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
});
|
||||
}
|
||||
.then(contentAResponse -> {
|
||||
service.showFileContent(projectLocation, file, revisionB)
|
||||
.then(contentBResponse -> {
|
||||
view.setColumnTitles(revisionB + locale.compareReadOnlyTitle(),
|
||||
revisionA + locale.compareReadOnlyTitle());
|
||||
view.show(contentAResponse.getContent(), contentBResponse.getContent(), file.toString(), true);
|
||||
})
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(error.getMessage(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -225,46 +187,32 @@ public class ComparePresenter implements CompareView.ActionDelegate {
|
|||
return;
|
||||
}
|
||||
|
||||
ConfirmCallback confirmCallback = new ConfirmCallback() {
|
||||
@Override
|
||||
public void accepted() {
|
||||
comparedFile.updateContent(newContent).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
final Container parent = comparedFile.getParent();
|
||||
ConfirmCallback confirmCallback = () -> comparedFile.updateContent(newContent)
|
||||
.then(ignored -> {
|
||||
final Container parent = comparedFile.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
parent.synchronize();
|
||||
}
|
||||
if (parent != null) {
|
||||
parent.synchronize();
|
||||
}
|
||||
|
||||
eventBus.fireEvent(new FileContentUpdateEvent(comparedFile.getLocation().toString()));
|
||||
view.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
eventBus.fireEvent(new FileContentUpdateEvent(comparedFile.getLocation()
|
||||
.toString()));
|
||||
view.hide();
|
||||
});
|
||||
|
||||
CancelCallback cancelCallback = new CancelCallback() {
|
||||
@Override
|
||||
public void cancelled() {
|
||||
view.hide();
|
||||
}
|
||||
};
|
||||
CancelCallback cancelCallback = view::hide;
|
||||
|
||||
dialogFactory.createConfirmDialog(locale.compareSaveTitle(), locale.compareSaveQuestion(), locale.buttonYes(), locale.buttonNo(),
|
||||
confirmCallback, cancelCallback).show();
|
||||
}
|
||||
|
||||
private void showCompare(final String remoteContent) {
|
||||
comparedFile.getContent().then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(String local) throws OperationException {
|
||||
localContent = local;
|
||||
final String path = comparedFile.getLocation().removeFirstSegments(1).toString();
|
||||
view.setTitle(path);
|
||||
view.setColumnTitles(locale.compareYourVersionTitle(), revision + locale.compareReadOnlyTitle());
|
||||
view.show(remoteContent, localContent, path, false);
|
||||
}
|
||||
comparedFile.getContent().then(local -> {
|
||||
localContent = local;
|
||||
final String path = comparedFile.getLocation().removeFirstSegments(1).toString();
|
||||
view.setTitle(path);
|
||||
view.setColumnTitles(locale.compareYourVersionTitle(), revision + locale.compareReadOnlyTitle());
|
||||
view.show(remoteContent, localContent, path, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,19 +10,14 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.git.client.compare.branchlist;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
import org.eclipse.che.ide.api.resources.Resource;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
|
|
@ -35,7 +30,6 @@ import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
|||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
|
@ -105,13 +99,11 @@ public class BranchListPresenter implements BranchListView.ActionDelegate {
|
|||
getBranches();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCloseClicked() {
|
||||
view.close();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCompareClicked() {
|
||||
|
||||
|
|
@ -120,61 +112,49 @@ public class BranchListPresenter implements BranchListView.ActionDelegate {
|
|||
.removeTrailingSeparator()
|
||||
.toString();
|
||||
|
||||
service.diff(
|
||||
project.getLocation(),
|
||||
service.diff(project.getLocation(),
|
||||
selectedItemPath.isEmpty() ? null : singletonList(selectedItemPath),
|
||||
NAME_STATUS,
|
||||
false,
|
||||
0,
|
||||
selectedBranch.getName(),
|
||||
false)
|
||||
.then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(String diff) throws OperationException {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
project.getFile(changedFiles[0].substring(2)).then(new Operation<Optional<File>>() {
|
||||
@Override
|
||||
public void apply(Optional<File> file) throws OperationException {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(),
|
||||
defineStatus(changedFiles[0].substring(0, 1)),
|
||||
selectedBranch.getName());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Map<String, Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
.then(diff -> {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
project.getFile(changedFiles[0].substring(2)).then(file -> {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(),
|
||||
defineStatus(changedFiles[0].substring(0, 1)),
|
||||
selectedBranch.getName());
|
||||
}
|
||||
changesListPresenter.show(items, selectedBranch.getName(), null, project);
|
||||
});
|
||||
} else {
|
||||
Map<String, Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
}
|
||||
changesListPresenter.show(items, selectedBranch.getName(), null, project);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
|
||||
view.close();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onBranchUnselected() {
|
||||
selectedBranch = null;
|
||||
view.setEnableCompareButton(false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onBranchSelected(@NotNull Branch branch) {
|
||||
selectedBranch = branch;
|
||||
|
|
@ -184,21 +164,17 @@ public class BranchListPresenter implements BranchListView.ActionDelegate {
|
|||
|
||||
/** Get list of branches from selected project. */
|
||||
private void getBranches() {
|
||||
service.branchList(project.getLocation(), LIST_ALL).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
view.setBranches(branches);
|
||||
view.showDialog();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
final String errorMessage = (error.getMessage() != null) ? error.getMessage() : locale.branchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(BRANCH_LIST_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(locale.branchesListFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), LIST_ALL)
|
||||
.then(branches -> {
|
||||
view.setBranches(branches);
|
||||
view.showDialog();
|
||||
})
|
||||
.catchError(error -> {
|
||||
final String errorMessage = (error.getMessage() != null) ? error.getMessage() : locale.branchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(BRANCH_LIST_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(locale.branchesListFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,18 +10,13 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.git.client.compare.revisionslist;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.api.git.shared.LogResponse;
|
||||
import org.eclipse.che.api.git.shared.Revision;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.File;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
|
@ -127,60 +122,45 @@ public class RevisionListPresenter implements RevisionListView.ActionDelegate {
|
|||
|
||||
/** Get list of revisions. */
|
||||
private void getRevisions() {
|
||||
service.log(project.getLocation(), new Path[]{selectedFilePath}, false)
|
||||
.then(new Operation<LogResponse>() {
|
||||
@Override
|
||||
public void apply(LogResponse log) throws OperationException {
|
||||
view.setRevisions(log.getCommits());
|
||||
view.showDialog();
|
||||
service.log(project.getLocation(), new Path[]{selectedFilePath}, -1, -1, false)
|
||||
.then(log -> {
|
||||
view.setRevisions(log.getCommits());
|
||||
view.showDialog();
|
||||
}).catchError(error -> {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(locale.compareWithRevisionTitle(),
|
||||
locale.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
notificationManager.notify(locale.logFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(locale.compareWithRevisionTitle(),
|
||||
locale.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
notificationManager.notify(locale.logFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void compare() {
|
||||
service.diff(
|
||||
project.getLocation(),
|
||||
service.diff(project.getLocation(),
|
||||
singletonList(selectedFilePath.toString()),
|
||||
NAME_STATUS,
|
||||
false,
|
||||
0,
|
||||
selectedRevision.getId(),
|
||||
false)
|
||||
.then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(final String diff) throws OperationException {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
project.getFile(diff.substring(2)).then(new Operation<Optional<File>>() {
|
||||
@Override
|
||||
public void apply(Optional<File> file) throws OperationException {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(), defineStatus(diff.substring(0, 1)), selectedRevision.getId());
|
||||
}
|
||||
}
|
||||
});
|
||||
.then(diff -> {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.compareMessageIdenticalContentTitle(),
|
||||
locale.compareMessageIdenticalContentText(), null).show();
|
||||
} else {
|
||||
appContext.getRootProject().getFile(diff.substring(2)).then(file -> {
|
||||
if (file.isPresent()) {
|
||||
comparePresenter.showCompareWithLatest(file.get(), defineStatus(diff.substring(0, 1)),
|
||||
selectedRevision.getId());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError arg) throws OperationException {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
}
|
||||
.catchError(arg -> {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, NOT_EMERGE_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ package org.eclipse.che.ide.ext.git.client.delete;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -36,7 +33,7 @@ import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAI
|
|||
*/
|
||||
@Singleton
|
||||
public class DeleteRepositoryPresenter {
|
||||
public static final String DELETE_REPO_COMMAND_NAME = "Git delete repository";
|
||||
private static final String DELETE_REPO_COMMAND_NAME = "Git delete repository";
|
||||
|
||||
private final GitServiceClient service;
|
||||
private final GitLocalizationConstant constant;
|
||||
|
|
@ -61,25 +58,19 @@ public class DeleteRepositoryPresenter {
|
|||
}
|
||||
|
||||
/** Delete Git repository. */
|
||||
public void deleteRepository(final Project project) {
|
||||
public void deleteRepository(Project project) {
|
||||
final GitOutputConsole console = gitOutputConsoleFactory.create(DELETE_REPO_COMMAND_NAME);
|
||||
|
||||
service.deleteRepository(project.getLocation()).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.deleteGitRepositorySuccess());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.deleteGitRepositorySuccess());
|
||||
service.deleteRepository(project.getLocation()).then(ignored -> {
|
||||
console.print(constant.deleteGitRepositorySuccess());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.deleteGitRepositorySuccess());
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.failedToDeleteRepository(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
appContext.getRootProject().synchronize();
|
||||
}).catchError(error -> {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.failedToDeleteRepository(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ import com.google.inject.Singleton;
|
|||
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
|
||||
import org.eclipse.che.api.git.shared.BranchListMode;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.Remote;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -101,24 +97,20 @@ public class FetchPresenter implements FetchView.ActionDelegate {
|
|||
* local).
|
||||
*/
|
||||
private void updateRemotes() {
|
||||
service.remoteList(project.getLocation(), null, true).then(new Operation<List<Remote>>() {
|
||||
@Override
|
||||
public void apply(List<Remote> remotes) throws OperationException {
|
||||
view.setRepositories(remotes);
|
||||
updateBranches(LIST_REMOTE);
|
||||
view.setEnableFetchButton(!remotes.isEmpty());
|
||||
view.showDialog();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(FETCH_COMMAND_NAME);
|
||||
console.printError(constant.remoteListFailed());
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.remoteListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnableFetchButton(false);
|
||||
}
|
||||
});
|
||||
service.remoteList(project.getLocation(), null, true)
|
||||
.then(remotes -> {
|
||||
view.setRepositories(remotes);
|
||||
updateBranches(LIST_REMOTE);
|
||||
view.setEnableFetchButton(!remotes.isEmpty());
|
||||
view.showDialog();
|
||||
})
|
||||
.catchError(error -> {
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(FETCH_COMMAND_NAME);
|
||||
console.printError(constant.remoteListFailed());
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.remoteListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnableFetchButton(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,33 +120,29 @@ public class FetchPresenter implements FetchView.ActionDelegate {
|
|||
* is a remote mode
|
||||
*/
|
||||
private void updateBranches(@NotNull final BranchListMode remoteMode) {
|
||||
service.branchList(project.getLocation(), remoteMode).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
if (LIST_REMOTE.equals(remoteMode)) {
|
||||
view.setRemoteBranches(branchSearcher.getRemoteBranchesToDisplay(view.getRepositoryName(), branches));
|
||||
updateBranches(LIST_LOCAL);
|
||||
} else {
|
||||
view.setLocalBranches(branchSearcher.getLocalBranchesToDisplay(branches));
|
||||
for (Branch branch : branches) {
|
||||
if (branch.isActive()) {
|
||||
view.selectRemoteBranch(branch.getDisplayName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
final String errorMessage = error.getMessage() != null ? error.getMessage() : constant.branchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(FETCH_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnableFetchButton(false);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), remoteMode)
|
||||
.then(branches -> {
|
||||
if (LIST_REMOTE.equals(remoteMode)) {
|
||||
view.setRemoteBranches(branchSearcher.getRemoteBranchesToDisplay(view.getRepositoryName(), branches));
|
||||
updateBranches(LIST_LOCAL);
|
||||
} else {
|
||||
view.setLocalBranches(branchSearcher.getLocalBranchesToDisplay(branches));
|
||||
for (Branch branch : branches) {
|
||||
if (branch.isActive()) {
|
||||
view.selectRemoteBranch(branch.getDisplayName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(error -> {
|
||||
final String errorMessage = error.getMessage() != null ? error.getMessage() : constant.branchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(FETCH_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnableFetchButton(false);
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
@ -166,22 +154,16 @@ public class FetchPresenter implements FetchView.ActionDelegate {
|
|||
final GitOutputConsole console = gitOutputConsoleFactory.create(FETCH_COMMAND_NAME);
|
||||
|
||||
service.fetch(project.getLocation(), view.getRepositoryName(), getRefs(), view.isRemoveDeletedRefs())
|
||||
.then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.fetchSuccess(remoteUrl));
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
notification.setStatus(SUCCESS);
|
||||
notification.setTitle(constant.fetchSuccess(remoteUrl));
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), remoteUrl, notification, console);
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
}
|
||||
});
|
||||
.then(ignored -> {
|
||||
console.print(constant.fetchSuccess(remoteUrl));
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notification.setStatus(SUCCESS);
|
||||
notification.setTitle(constant.fetchSuccess(remoteUrl));
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), remoteUrl, notification, console);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
});
|
||||
view.close();
|
||||
}
|
||||
|
||||
|
|
@ -231,13 +213,11 @@ public class FetchPresenter implements FetchView.ActionDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCancelClicked() {
|
||||
view.close();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onValueChanged() {
|
||||
boolean isFetchAll = view.isFetchAllBranches();
|
||||
|
|
@ -245,13 +225,11 @@ public class FetchPresenter implements FetchView.ActionDelegate {
|
|||
view.setEnableRemoteBranchField(!isFetchAll);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onRemoteBranchChanged() {
|
||||
view.selectLocalBranch(view.getRemoteBranch());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onRemoteRepositoryChanged() {
|
||||
updateBranches(LIST_REMOTE);
|
||||
|
|
|
|||
|
|
@ -14,11 +14,7 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.api.git.shared.LogResponse;
|
||||
import org.eclipse.che.api.git.shared.Revision;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
|
|
@ -136,34 +132,26 @@ public class HistoryPresenter implements HistoryView.ActionDelegate {
|
|||
}
|
||||
|
||||
private void fetchRevisions() {
|
||||
service.log(
|
||||
project.getLocation(),
|
||||
selectedPath.isEmpty() ? null : new Path[]{selectedPath},
|
||||
service.log(project.getLocation(), selectedPath.isEmpty() ? null : new Path[]{selectedPath},
|
||||
skip,
|
||||
DEFAULT_PAGE_SIZE,
|
||||
false)
|
||||
.then(new Operation<LogResponse>() {
|
||||
@Override
|
||||
public void apply(LogResponse log) throws OperationException {
|
||||
List<Revision> commits = log.getCommits();
|
||||
if (!commits.isEmpty()) {
|
||||
skip += commits.size();
|
||||
revisions.addAll(commits);
|
||||
view.setRevisions(revisions);
|
||||
view.showDialog();
|
||||
}
|
||||
.then(log -> {
|
||||
List<Revision> commits = log.getCommits();
|
||||
if (!commits.isEmpty()) {
|
||||
skip += commits.size();
|
||||
revisions.addAll(commits);
|
||||
view.setRevisions(revisions);
|
||||
view.showDialog();
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(locale.historyTitle(),
|
||||
locale.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
notificationManager.notify(locale.logFailed(), FAIL, EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(locale.historyTitle(),
|
||||
locale.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
} else {
|
||||
notificationManager.notify(locale.logFailed(), FAIL, EMERGE_MODE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -172,40 +160,33 @@ public class HistoryPresenter implements HistoryView.ActionDelegate {
|
|||
final String revisionA = revisions.indexOf(selectedRevision) + 1 == revisions.size() ? null :
|
||||
revisions.get(revisions.indexOf(selectedRevision) + 1).getId();
|
||||
final String revisionB = selectedRevision.getId();
|
||||
service.diff(project.getLocation(),
|
||||
singletonList(selectedPath.toString()),
|
||||
service.diff(project.getLocation(), singletonList(selectedPath.toString()),
|
||||
NAME_STATUS,
|
||||
true,
|
||||
0,
|
||||
revisionA,
|
||||
revisionB)
|
||||
.then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(final String diff) throws OperationException {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.historyTitle(), locale.historyNothingToDisplay(), null).show();
|
||||
return;
|
||||
}
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
comparePresenter.showCompareBetweenRevisions(Path.valueOf(diff.substring(2)),
|
||||
defineStatus(diff.substring(0, 1)),
|
||||
revisionA,
|
||||
revisionB);
|
||||
} else {
|
||||
Map<String, FileStatus.Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
}
|
||||
changesListPresenter.show(items, revisionA, revisionB, project);
|
||||
.then(diff -> {
|
||||
if (diff.isEmpty()) {
|
||||
dialogFactory.createMessageDialog(locale.historyTitle(), locale.historyNothingToDisplay(), null).show();
|
||||
return;
|
||||
}
|
||||
final String[] changedFiles = diff.split("\n");
|
||||
if (changedFiles.length == 1) {
|
||||
comparePresenter.showCompareBetweenRevisions(Path.valueOf(diff.substring(2)),
|
||||
defineStatus(diff.substring(0, 1)),
|
||||
revisionA,
|
||||
revisionB);
|
||||
} else {
|
||||
Map<String, FileStatus.Status> items = new HashMap<>();
|
||||
for (String item : changedFiles) {
|
||||
items.put(item.substring(2, item.length()), defineStatus(item.substring(0, 1)));
|
||||
}
|
||||
changesListPresenter.show(items, revisionA, revisionB, project);
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, EMERGE_MODE);
|
||||
}
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(locale.diffFailed(), FAIL, EMERGE_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ package org.eclipse.che.ide.ext.git.client.init;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -66,22 +63,18 @@ public class InitRepositoryPresenter {
|
|||
public void initRepository(final Project project) {
|
||||
final GitOutputConsole console = gitOutputConsoleFactory.create(INIT_COMMAND_NAME);
|
||||
|
||||
service.init(project.getLocation(), false).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.initSuccess());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.initSuccess());
|
||||
service.init(project.getLocation(), false)
|
||||
.then(ignored -> {
|
||||
console.print(constant.initSuccess());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.initSuccess());
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), console);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
}
|
||||
});
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), console);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,11 +16,7 @@ import com.google.inject.Singleton;
|
|||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.MergeResult;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -95,59 +91,49 @@ public class MergePresenter implements MergeView.ActionDelegate {
|
|||
selectedReference = null;
|
||||
view.setEnableMergeButton(false);
|
||||
|
||||
service.branchList(project.getLocation(), LIST_LOCAL).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
List<Reference> references = new ArrayList<>();
|
||||
for (Branch branch : branches) {
|
||||
if (!branch.isActive()) {
|
||||
Reference reference = new Reference(branch.getName(), branch.getDisplayName(), LOCAL_BRANCH);
|
||||
references.add(reference);
|
||||
}
|
||||
}
|
||||
view.setLocalBranches(references);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), LIST_LOCAL)
|
||||
.then(branches -> {
|
||||
List<Reference> references = new ArrayList<>();
|
||||
for (Branch branch : branches) {
|
||||
if (!branch.isActive()) {
|
||||
Reference reference = new Reference(branch.getName(), branch.getDisplayName(), LOCAL_BRANCH);
|
||||
references.add(reference);
|
||||
}
|
||||
}
|
||||
view.setLocalBranches(references);
|
||||
})
|
||||
.catchError(error -> {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
|
||||
service.branchList(project.getLocation(), LIST_REMOTE).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
List<Reference> references = new ArrayList<>();
|
||||
for (Branch branch : branches) {
|
||||
if (!branch.isActive()) {
|
||||
Reference reference =
|
||||
new Reference(branch.getName(), branch.getDisplayName(), REMOTE_BRANCH);
|
||||
references.add(reference);
|
||||
}
|
||||
}
|
||||
view.setRemoteBranches(references);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), LIST_REMOTE)
|
||||
.then(branches -> {
|
||||
List<Reference> references = new ArrayList<>();
|
||||
for (Branch branch : branches) {
|
||||
if (!branch.isActive()) {
|
||||
Reference reference =
|
||||
new Reference(branch.getName(), branch.getDisplayName(), REMOTE_BRANCH);
|
||||
references.add(reference);
|
||||
}
|
||||
}
|
||||
view.setRemoteBranches(references);
|
||||
})
|
||||
.catchError(error -> {
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.branchesListFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
|
||||
view.showDialog();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCancelClicked() {
|
||||
view.close();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onMergeClicked() {
|
||||
view.close();
|
||||
|
|
@ -155,34 +141,26 @@ public class MergePresenter implements MergeView.ActionDelegate {
|
|||
final GitOutputConsole console = gitOutputConsoleFactory.create(MERGE_COMMAND_NAME);
|
||||
|
||||
service.merge(project.getLocation(), selectedReference.getDisplayName())
|
||||
.then(new Operation<MergeResult>() {
|
||||
@Override
|
||||
public void apply(MergeResult result) throws OperationException {
|
||||
console.print(formMergeMessage(result));
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(formMergeMessage(result));
|
||||
.then(result -> {
|
||||
console.print(formMergeMessage(result));
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(formMergeMessage(result));
|
||||
|
||||
project.synchronize();
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
if (error.getCause() instanceof ServerException &&
|
||||
((ServerException)error.getCause()).getErrorCode() == ErrorCodes.NO_COMMITTER_NAME_OR_EMAIL_DEFINED) {
|
||||
dialogFactory.createMessageDialog(constant.mergeTitle(), constant.committerIdentityInfoEmpty(),
|
||||
() -> {
|
||||
//do nothing
|
||||
}).show();
|
||||
return;
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
if (error.getCause() instanceof ServerException &&
|
||||
((ServerException)error.getCause()).getErrorCode() == ErrorCodes.NO_COMMITTER_NAME_OR_EMAIL_DEFINED) {
|
||||
dialogFactory.createMessageDialog(constant.mergeTitle(), constant.committerIdentityInfoEmpty(),
|
||||
new ConfirmCallback() {
|
||||
@Override
|
||||
public void accepted() {
|
||||
//do nothing
|
||||
}
|
||||
}).show();
|
||||
return;
|
||||
}
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.mergeFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
console.printError(error.getMessage());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.mergeFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,11 +16,6 @@ import com.google.inject.Singleton;
|
|||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.api.git.shared.BranchListMode;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.PullResponse;
|
||||
import org.eclipse.che.api.git.shared.Remote;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
|
|
@ -34,7 +29,6 @@ import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsoleFactory;
|
|||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.che.api.git.shared.BranchListMode.LIST_LOCAL;
|
||||
import static org.eclipse.che.api.git.shared.BranchListMode.LIST_REMOTE;
|
||||
|
|
@ -98,21 +92,15 @@ public class PullPresenter implements PullView.ActionDelegate {
|
|||
view.setEnablePullButton(false);
|
||||
|
||||
service.remoteList(project.getLocation(), null, true)
|
||||
.then(new Operation<List<Remote>>() {
|
||||
@Override
|
||||
public void apply(List<Remote> remotes) throws OperationException {
|
||||
updateBranches(LIST_REMOTE);
|
||||
view.setRepositories(remotes);
|
||||
view.setEnablePullButton(!remotes.isEmpty());
|
||||
view.showDialog();
|
||||
}
|
||||
.then(remotes -> {
|
||||
updateBranches(LIST_REMOTE);
|
||||
view.setRepositories(remotes);
|
||||
view.setEnablePullButton(!remotes.isEmpty());
|
||||
view.showDialog();
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), REMOTE_REPO_COMMAND_NAME);
|
||||
view.setEnablePullButton(false);
|
||||
}
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), REMOTE_REPO_COMMAND_NAME);
|
||||
view.setEnablePullButton(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -125,29 +113,25 @@ public class PullPresenter implements PullView.ActionDelegate {
|
|||
*/
|
||||
private void updateBranches(@NotNull final BranchListMode remoteMode) {
|
||||
|
||||
service.branchList(project.getLocation(), remoteMode).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
if (LIST_REMOTE.equals(remoteMode)) {
|
||||
view.setRemoteBranches(branchSearcher.getRemoteBranchesToDisplay(view.getRepositoryName(), branches));
|
||||
updateBranches(LIST_LOCAL);
|
||||
} else {
|
||||
view.setLocalBranches(branchSearcher.getLocalBranchesToDisplay(branches));
|
||||
for (Branch branch : branches) {
|
||||
if (branch.isActive()) {
|
||||
view.selectRemoteBranch(branch.getDisplayName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), BRANCH_LIST_COMMAND_NAME);
|
||||
view.setEnablePullButton(false);
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), remoteMode)
|
||||
.then(branches -> {
|
||||
if (LIST_REMOTE.equals(remoteMode)) {
|
||||
view.setRemoteBranches(branchSearcher.getRemoteBranchesToDisplay(view.getRepositoryName(), branches));
|
||||
updateBranches(LIST_LOCAL);
|
||||
} else {
|
||||
view.setLocalBranches(branchSearcher.getLocalBranchesToDisplay(branches));
|
||||
for (Branch branch : branches) {
|
||||
if (branch.isActive()) {
|
||||
view.selectRemoteBranch(branch.getDisplayName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), BRANCH_LIST_COMMAND_NAME);
|
||||
view.setEnablePullButton(false);
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
@ -158,30 +142,26 @@ public class PullPresenter implements PullView.ActionDelegate {
|
|||
final StatusNotification notification =
|
||||
notificationManager.notify(constant.pullProcess(), PROGRESS, FLOAT_MODE);
|
||||
|
||||
service.pull(project.getLocation(), getRefs(), view.getRepositoryName()).then(new Operation<PullResponse>() {
|
||||
@Override
|
||||
public void apply(PullResponse response) throws OperationException {
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(PULL_COMMAND_NAME);
|
||||
console.print(response.getCommandOutput(), GREEN_COLOR);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notification.setStatus(SUCCESS);
|
||||
if (response.getCommandOutput().contains("Already up-to-date")) {
|
||||
notification.setTitle(constant.pullUpToDate());
|
||||
} else {
|
||||
project.synchronize();
|
||||
notification.setTitle(constant.pullSuccess(view.getRepositoryUrl()));
|
||||
}
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notification.setStatus(FAIL);
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.MERGE_CONFLICT) {
|
||||
project.synchronize();
|
||||
}
|
||||
handleError(error.getCause(), PULL_COMMAND_NAME);
|
||||
}
|
||||
});
|
||||
service.pull(project.getLocation(), getRefs(), view.getRepositoryName())
|
||||
.then(response -> {
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(PULL_COMMAND_NAME);
|
||||
console.print(response.getCommandOutput(), GREEN_COLOR);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notification.setStatus(SUCCESS);
|
||||
if (response.getCommandOutput().contains("Already up-to-date")) {
|
||||
notification.setTitle(constant.pullUpToDate());
|
||||
} else {
|
||||
project.synchronize();
|
||||
notification.setTitle(constant.pullSuccess(view.getRepositoryUrl()));
|
||||
}
|
||||
})
|
||||
.catchError(error -> {
|
||||
notification.setStatus(FAIL);
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.MERGE_CONFLICT) {
|
||||
project.synchronize();
|
||||
}
|
||||
handleError(error.getCause(), PULL_COMMAND_NAME);
|
||||
});
|
||||
}
|
||||
|
||||
/** @return list of refs to fetch */
|
||||
|
|
|
|||
|
|
@ -15,12 +15,9 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.api.git.shared.BranchListMode;
|
||||
import org.eclipse.che.api.git.shared.Remote;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.api.git.shared.Branch;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.notification.StatusNotification;
|
||||
|
|
@ -30,7 +27,6 @@ import org.eclipse.che.ide.dto.DtoFactory;
|
|||
import org.eclipse.che.ide.ext.git.client.BranchFilterByRemote;
|
||||
import org.eclipse.che.ide.ext.git.client.BranchSearcher;
|
||||
import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsole;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsoleFactory;
|
||||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
|
|
@ -38,7 +34,6 @@ import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
|||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.api.git.shared.BranchListMode.LIST_LOCAL;
|
||||
|
|
@ -106,26 +101,22 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
* If remote repositories are found, then get the list of branches (remote and local).
|
||||
*/
|
||||
void updateRemotes() {
|
||||
service.remoteList(project.getLocation(), null, true).then(new Operation<List<Remote>>() {
|
||||
@Override
|
||||
public void apply(List<Remote> remotes) throws OperationException {
|
||||
updateLocalBranches();
|
||||
view.setRepositories(remotes);
|
||||
view.setEnablePushButton(!remotes.isEmpty());
|
||||
view.setSelectedForcePushCheckBox(false);
|
||||
view.showDialog();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(REMOTE_REPO_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.remoteListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnablePushButton(false);
|
||||
}
|
||||
});
|
||||
service.remoteList(project.getLocation(), null, true)
|
||||
.then(remotes -> {
|
||||
updateLocalBranches();
|
||||
view.setRepositories(remotes);
|
||||
view.setEnablePushButton(!remotes.isEmpty());
|
||||
view.setSelectedForcePushCheckBox(false);
|
||||
view.showDialog();
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(REMOTE_REPO_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.remoteListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnablePushButton(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,7 +146,7 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
String errorMessage = exception.getMessage() != null ? exception.getMessage() : constant.localBranchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(BRANCH_LIST_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.localBranchesListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnablePushButton(false);
|
||||
}
|
||||
|
|
@ -205,7 +196,7 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
public void onFailure(Throwable caught) {
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(CONFIG_COMMAND_NAME);
|
||||
console.printError(constant.failedGettingConfig());
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.failedGettingConfig(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
|
|
@ -216,7 +207,7 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
String errorMessage = exception.getMessage() != null ? exception.getMessage() : constant.remoteBranchesListFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(BRANCH_LIST_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
processesPanelPresenter.addCommandOutput(console);
|
||||
processesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
|
||||
notificationManager.notify(constant.remoteBranchesListFailed(), FAIL, FLOAT_MODE);
|
||||
view.setEnablePushButton(false);
|
||||
}
|
||||
|
|
@ -233,28 +224,23 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
final String configBranchRemote = "branch." + view.getLocalBranch() + ".remote";
|
||||
final String configUpstreamBranch = "branch." + view.getLocalBranch() + ".merge";
|
||||
service.config(project.getLocation(), Arrays.asList(configUpstreamBranch, configBranchRemote))
|
||||
.then(new Operation<Map<String, String>>() {
|
||||
@Override
|
||||
public void apply(Map<String, String> configs) throws OperationException {
|
||||
if (configs.containsKey(configBranchRemote) && configs.containsKey(configUpstreamBranch)) {
|
||||
String displayName = configs.get(configBranchRemote) + "/" + configs.get(configUpstreamBranch);
|
||||
Branch upstream = dtoFactory.createDto(Branch.class)
|
||||
.withActive(false)
|
||||
.withRemote(true)
|
||||
.withDisplayName(displayName)
|
||||
.withName("refs/remotes/" + displayName);
|
||||
.then(configs -> {
|
||||
if (configs.containsKey(configBranchRemote) && configs.containsKey(configUpstreamBranch)) {
|
||||
String displayName = configs.get(configBranchRemote) + "/" + configs.get(configUpstreamBranch);
|
||||
Branch upstream = dtoFactory.createDto(Branch.class)
|
||||
.withActive(false)
|
||||
.withRemote(true)
|
||||
.withDisplayName(displayName)
|
||||
.withName("refs/remotes/" + displayName);
|
||||
|
||||
result.onSuccess(upstream);
|
||||
} else {
|
||||
result.onSuccess(null);
|
||||
}
|
||||
result.onSuccess(upstream);
|
||||
} else {
|
||||
result.onSuccess(null);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
result.onFailure(error.getCause());
|
||||
}
|
||||
});
|
||||
})
|
||||
.catchError(error -> {
|
||||
result.onFailure(error.getCause());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -264,17 +250,13 @@ public class PushToRemotePresenter implements PushToRemoteView.ActionDelegate {
|
|||
* is a remote mode
|
||||
*/
|
||||
void getBranchesForCurrentProject(@NotNull final BranchListMode remoteMode, final AsyncCallback<List<Branch>> asyncResult) {
|
||||
service.branchList(project.getLocation(), remoteMode).then(new Operation<List<Branch>>() {
|
||||
@Override
|
||||
public void apply(List<Branch> branches) throws OperationException {
|
||||
asyncResult.onSuccess(branches);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
asyncResult.onFailure(error.getCause());
|
||||
}
|
||||
});
|
||||
service.branchList(project.getLocation(), remoteMode)
|
||||
.then(branches -> {
|
||||
asyncResult.onSuccess(branches);
|
||||
})
|
||||
.catchError(error -> {
|
||||
asyncResult.onFailure(error.getCause());
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.git.shared.Remote;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -29,7 +26,6 @@ import org.eclipse.che.ide.ext.git.client.remote.add.AddRemoteRepositoryPresente
|
|||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
|
||||
|
|
@ -89,22 +85,18 @@ public class RemotePresenter implements RemoteView.ActionDelegate {
|
|||
* then get the list of branches (remote and local).
|
||||
*/
|
||||
private void getRemotes() {
|
||||
service.remoteList(project.getLocation(), null, true).then(new Operation<List<Remote>>() {
|
||||
@Override
|
||||
public void apply(List<Remote> remotes) throws OperationException {
|
||||
view.setEnableDeleteButton(selectedRemote != null);
|
||||
view.setRemotes(remotes);
|
||||
if (!view.isShown()) {
|
||||
view.showDialog();
|
||||
}
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteListFailed();
|
||||
handleError(errorMessage);
|
||||
}
|
||||
});
|
||||
service.remoteList(project.getLocation(), null, true)
|
||||
.then(remotes -> {
|
||||
view.setEnableDeleteButton(selectedRemote != null);
|
||||
view.setRemotes(remotes);
|
||||
if (!view.isShown()) {
|
||||
view.showDialog();
|
||||
}
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteListFailed();
|
||||
handleError(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,23 +141,19 @@ public class RemotePresenter implements RemoteView.ActionDelegate {
|
|||
return;
|
||||
}
|
||||
|
||||
service.remoteDelete(project.getLocation(), selectedRemote.getName()).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
getRemotes();
|
||||
service.remoteDelete(project.getLocation(), selectedRemote.getName())
|
||||
.then(ignored -> {
|
||||
getRemotes();
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteDeleteFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(REMOTE_REPO_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.remoteDeleteFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMessage = error.getMessage() != null ? error.getMessage() : constant.remoteDeleteFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(REMOTE_REPO_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.remoteDeleteFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
|
@ -67,18 +64,14 @@ public class AddRemoteRepositoryPresenter implements AddRemoteRepositoryView.Act
|
|||
final String url = view.getUrl().trim();
|
||||
final Project project = appContext.getRootProject();
|
||||
|
||||
service.remoteAdd(project.getLocation(), name, url).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void arg) throws OperationException {
|
||||
callback.onSuccess(null);
|
||||
view.close();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
callback.onFailure(error.getCause());
|
||||
}
|
||||
});
|
||||
service.remoteAdd(project.getLocation(), name, url)
|
||||
.then(arg -> {
|
||||
callback.onSuccess(null);
|
||||
view.close();
|
||||
})
|
||||
.catchError(error -> {
|
||||
callback.onFailure(error.getCause());
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ package org.eclipse.che.ide.ext.git.client.remove;
|
|||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
|
|
@ -99,22 +96,18 @@ public class RemoveFromIndexPresenter implements RemoveFromIndexView.ActionDeleg
|
|||
|
||||
checkState(!isNullOrEmpty(resources));
|
||||
|
||||
service.remove(project.getLocation(), toRelativePaths(resources), view.isRemoved()).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.removeFilesSuccessfull());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.removeFilesSuccessfull());
|
||||
service.remove(project.getLocation(), toRelativePaths(resources), view.isRemoved())
|
||||
.then(ignored -> {
|
||||
console.print(constant.removeFilesSuccessfull());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.removeFilesSuccessfull());
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
handleError(error.getCause(), console);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
}
|
||||
});
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
handleError(error.getCause(), console);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
});
|
||||
|
||||
view.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,8 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.ErrorCodes;
|
||||
import org.eclipse.che.api.git.shared.LogResponse;
|
||||
import org.eclipse.che.api.git.shared.ResetRequest;
|
||||
import org.eclipse.che.api.git.shared.Revision;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
|
|
@ -82,32 +78,28 @@ public class ResetToCommitPresenter implements ResetToCommitView.ActionDelegate
|
|||
public void showDialog(final Project project) {
|
||||
this.project = project;
|
||||
|
||||
service.log(project.getLocation(), null, false).then(new Operation<LogResponse>() {
|
||||
@Override
|
||||
public void apply(LogResponse log) throws OperationException {
|
||||
view.setRevisions(log.getCommits());
|
||||
view.setMixMode(true);
|
||||
view.setEnableResetButton(selectedRevision != null);
|
||||
view.showDialog();
|
||||
service.log(project.getLocation(), null, -1, -1, false)
|
||||
.then(log -> {
|
||||
view.setRevisions(log.getCommits());
|
||||
view.setMixMode(true);
|
||||
view.setEnableResetButton(selectedRevision != null);
|
||||
view.showDialog();
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(constant.resetCommitViewTitle(),
|
||||
constant.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
return;
|
||||
}
|
||||
String errorMessage = (error.getMessage() != null) ? error.getMessage() : constant.logFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(LOG_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.logFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
if (getErrorCode(error.getCause()) == ErrorCodes.INIT_COMMIT_WAS_NOT_PERFORMED) {
|
||||
dialogFactory.createMessageDialog(constant.resetCommitViewTitle(),
|
||||
constant.initCommitWasNotPerformed(),
|
||||
null).show();
|
||||
return;
|
||||
}
|
||||
String errorMessage = (error.getMessage() != null) ? error.getMessage() : constant.logFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(LOG_COMMAND_NAME);
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.logFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,24 +138,20 @@ public class ResetToCommitPresenter implements ResetToCommitView.ActionDelegate
|
|||
|
||||
final GitOutputConsole console = gitOutputConsoleFactory.create(RESET_COMMAND_NAME);
|
||||
|
||||
service.reset(project.getLocation(), selectedRevision.getId(), type, null).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.resetSuccessfully());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetSuccessfully());
|
||||
service.reset(project.getLocation(), selectedRevision.getId(), type, null)
|
||||
.then(ignored -> {
|
||||
console.print(constant.resetSuccessfully());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetSuccessfully());
|
||||
|
||||
project.synchronize();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMessage = (error.getMessage() != null) ? error.getMessage() : constant.resetFail();
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetFail(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
project.synchronize();
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMessage = (error.getMessage() != null) ? error.getMessage() : constant.resetFail();
|
||||
console.printError(errorMessage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetFail(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.git.shared.IndexFile;
|
||||
import org.eclipse.che.api.git.shared.Status;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.dialogs.DialogFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
|
|
@ -90,58 +86,54 @@ public class ResetFilesPresenter implements ResetFilesView.ActionDelegate {
|
|||
public void showDialog(Project project) {
|
||||
this.project = project;
|
||||
|
||||
service.getStatus(project.getLocation()).then(new Operation<Status>() {
|
||||
@Override
|
||||
public void apply(Status status) throws OperationException {
|
||||
if (status.isClean()) {
|
||||
dialogFactory.createMessageDialog(constant.messagesWarningTitle(), constant.indexIsEmpty(), null).show();
|
||||
return;
|
||||
}
|
||||
service.getStatus(project.getLocation())
|
||||
.then(status -> {
|
||||
if (status.isClean()) {
|
||||
dialogFactory.createMessageDialog(constant.messagesWarningTitle(), constant.indexIsEmpty(), null).show();
|
||||
return;
|
||||
}
|
||||
|
||||
indexedFiles = new IndexFile[0];
|
||||
indexedFiles = new IndexFile[0];
|
||||
|
||||
for (String path : status.getAdded()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
for (String path : status.getAdded()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
|
||||
for (String path : status.getChanged()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
for (String path : status.getChanged()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
|
||||
for (String path : status.getRemoved()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
for (String path : status.getRemoved()) {
|
||||
indexedFiles = add(indexedFiles, wrap(path));
|
||||
}
|
||||
|
||||
if (indexedFiles.length == 0) {
|
||||
dialogFactory.createMessageDialog(constant.messagesWarningTitle(), constant.indexIsEmpty(), null).show();
|
||||
return;
|
||||
}
|
||||
if (indexedFiles.length == 0) {
|
||||
dialogFactory.createMessageDialog(constant.messagesWarningTitle(), constant.indexIsEmpty(), null).show();
|
||||
return;
|
||||
}
|
||||
|
||||
//Mark selected items to reset from index
|
||||
Resource[] resources = appContext.getResources();
|
||||
if (resources != null) {
|
||||
for (Resource selectedItem : resources) {
|
||||
String selectedItemPath = selectedItem.getLocation().removeFirstSegments(1).toString();
|
||||
for (IndexFile file : indexedFiles)
|
||||
if (file.getPath().startsWith(selectedItemPath)) {
|
||||
file.setIndexed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Mark selected items to reset from index
|
||||
Resource[] resources = appContext.getResources();
|
||||
if (resources != null) {
|
||||
for (Resource selectedItem : resources) {
|
||||
String selectedItemPath = selectedItem.getLocation().removeFirstSegments(1).toString();
|
||||
for (IndexFile file : indexedFiles)
|
||||
if (file.getPath().startsWith(selectedItemPath)) {
|
||||
file.setIndexed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view.setIndexedFiles(indexedFiles);
|
||||
view.showDialog();
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMassage = error.getMessage() != null ? error.getMessage() : constant.statusFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(STATUS_COMMAND_NAME);
|
||||
console.printError(errorMassage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(errorMassage);
|
||||
}
|
||||
});
|
||||
view.setIndexedFiles(indexedFiles);
|
||||
view.showDialog();
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMassage = error.getMessage() != null ? error.getMessage() : constant.statusFailed();
|
||||
GitOutputConsole console = gitOutputConsoleFactory.create(STATUS_COMMAND_NAME);
|
||||
console.printError(errorMassage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(errorMassage);
|
||||
});
|
||||
}
|
||||
|
||||
protected IndexFile wrap(String path) {
|
||||
|
|
@ -169,22 +161,18 @@ public class ResetFilesPresenter implements ResetFilesView.ActionDelegate {
|
|||
}
|
||||
view.close();
|
||||
|
||||
service.reset(project.getLocation(), "HEAD", ResetType.MIXED, paths).then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void ignored) throws OperationException {
|
||||
console.print(constant.resetFilesSuccessfully());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetFilesSuccessfully());
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
String errorMassage = error.getMessage() != null ? error.getMessage() : constant.resetFilesFailed();
|
||||
console.printError(errorMassage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(errorMassage);
|
||||
}
|
||||
});
|
||||
service.reset(project.getLocation(), "HEAD", ResetType.MIXED, paths)
|
||||
.then(ignored -> {
|
||||
console.print(constant.resetFilesSuccessfully());
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(constant.resetFilesSuccessfully());
|
||||
})
|
||||
.catchError(error -> {
|
||||
String errorMassage = error.getMessage() != null ? error.getMessage() : constant.resetFilesFailed();
|
||||
console.printError(errorMassage);
|
||||
consolesPanelPresenter.addCommandOutput(console);
|
||||
notificationManager.notify(errorMassage);
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
|
|||
|
|
@ -13,10 +13,6 @@ package org.eclipse.che.ide.ext.git.client.status;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.git.client.GitServiceClient;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.resources.Project;
|
||||
|
|
@ -44,7 +40,6 @@ public class StatusCommandPresenter {
|
|||
public static final String STATUS_COMMAND_NAME = "Git status";
|
||||
|
||||
private final GitServiceClient service;
|
||||
private final AppContext appContext;
|
||||
private final GitOutputConsoleFactory gitOutputConsoleFactory;
|
||||
private final ProcessesPanelPresenter consolesPanelPresenter;
|
||||
private final GitLocalizationConstant constant;
|
||||
|
|
@ -55,13 +50,11 @@ public class StatusCommandPresenter {
|
|||
*/
|
||||
@Inject
|
||||
public StatusCommandPresenter(GitServiceClient service,
|
||||
AppContext appContext,
|
||||
GitOutputConsoleFactory gitOutputConsoleFactory,
|
||||
ProcessesPanelPresenter processesPanelPresenter,
|
||||
GitLocalizationConstant constant,
|
||||
NotificationManager notificationManager) {
|
||||
this.service = service;
|
||||
this.appContext = appContext;
|
||||
this.gitOutputConsoleFactory = gitOutputConsoleFactory;
|
||||
this.consolesPanelPresenter = processesPanelPresenter;
|
||||
this.constant = constant;
|
||||
|
|
@ -70,17 +63,13 @@ public class StatusCommandPresenter {
|
|||
|
||||
/** Show status. */
|
||||
public void showStatus(Project project) {
|
||||
service.statusText(project.getLocation(), LONG).then(new Operation<String>() {
|
||||
@Override
|
||||
public void apply(String status) throws OperationException {
|
||||
printGitStatus(status);
|
||||
}
|
||||
}).catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError error) throws OperationException {
|
||||
notificationManager.notify(constant.statusFailed(), FAIL, FLOAT_MODE);
|
||||
}
|
||||
});
|
||||
service.statusText(project.getLocation(), LONG)
|
||||
.then(status -> {
|
||||
printGitStatus(status);
|
||||
})
|
||||
.catchError(error -> {
|
||||
notificationManager.notify(constant.statusFailed(), FAIL, FLOAT_MODE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import org.eclipse.che.api.git.shared.Branch;
|
|||
import org.eclipse.che.api.git.shared.CheckoutRequest;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
|
||||
import org.eclipse.che.ide.api.parts.WorkspaceAgent;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.git.client.BaseTest;
|
||||
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
|
||||
|
|
@ -69,8 +68,6 @@ public class BranchPresenterTest extends BaseTest {
|
|||
@Mock
|
||||
private Branch selectedBranch;
|
||||
@Mock
|
||||
private WorkspaceAgent workspaceAgent;
|
||||
@Mock
|
||||
private DialogFactory dialogFactory;
|
||||
@Mock
|
||||
private DtoFactory dtoFactory;
|
||||
|
|
@ -224,9 +221,9 @@ public class BranchPresenterTest extends BaseTest {
|
|||
|
||||
@Test
|
||||
public void testOnCheckoutClickedWhenSelectedNotRemoteBranch() throws Exception {
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.then(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.catchError(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.then(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.catchError(any(Operation.class))).thenReturn(stringPromise);
|
||||
|
||||
when(selectedBranch.isRemote()).thenReturn(false);
|
||||
when(dtoFactory.createDto(CheckoutRequest.class)).thenReturn(checkoutRequest);
|
||||
|
|
@ -234,8 +231,8 @@ public class BranchPresenterTest extends BaseTest {
|
|||
selectBranch();
|
||||
presenter.onCheckoutClicked();
|
||||
|
||||
verify(voidPromise).then(voidPromiseCaptor.capture());
|
||||
voidPromiseCaptor.getValue().apply(null);
|
||||
verify(stringPromise).then(stringCaptor.capture());
|
||||
stringCaptor.getValue().apply(null);
|
||||
|
||||
verify(checkoutRequest).setName(eq(BRANCH_NAME));
|
||||
verifyNoMoreInteractions(checkoutRequest);
|
||||
|
|
@ -243,17 +240,17 @@ public class BranchPresenterTest extends BaseTest {
|
|||
|
||||
@Test
|
||||
public void testOnCheckoutClickedWhenSelectedRemoteBranch() throws Exception {
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.then(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.catchError(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.then(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.catchError(any(Operation.class))).thenReturn(stringPromise);
|
||||
|
||||
when(dtoFactory.createDto(CheckoutRequest.class)).thenReturn(checkoutRequest);
|
||||
|
||||
selectBranch();
|
||||
presenter.onCheckoutClicked();
|
||||
|
||||
verify(voidPromise).then(voidPromiseCaptor.capture());
|
||||
voidPromiseCaptor.getValue().apply(null);
|
||||
verify(stringPromise).then(stringCaptor.capture());
|
||||
stringCaptor.getValue().apply(null);
|
||||
|
||||
verify(checkoutRequest).setTrackBranch(eq(BRANCH_NAME));
|
||||
verifyNoMoreInteractions(checkoutRequest);
|
||||
|
|
|
|||
|
|
@ -102,20 +102,21 @@ public class CheckoutReferenceTest extends BaseTest {
|
|||
|
||||
@Test
|
||||
public void onEnterClickedWhenValueIsCorrect() throws Exception {
|
||||
when(appContext.getRootProject()).thenReturn(project);
|
||||
when(dtoFactory.createDto(CheckoutRequest.class)).thenReturn(checkoutRequest);
|
||||
when(checkoutRequest.withName(anyString())).thenReturn(checkoutRequest);
|
||||
when(checkoutRequest.withCreateNew(anyBoolean())).thenReturn(checkoutRequest);
|
||||
reset(service);
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.then(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(voidPromise.catchError(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(service.checkout(any(Path.class), any(CheckoutRequest.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.then(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.catchError(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(view.getReference()).thenReturn(CORRECT_REFERENCE);
|
||||
|
||||
presenter.showDialog(project);
|
||||
presenter.onEnterClicked();
|
||||
|
||||
verify(voidPromise).then(voidPromiseCaptor.capture());
|
||||
voidPromiseCaptor.getValue().apply(null);
|
||||
verify(stringPromise).then(stringCaptor.capture());
|
||||
stringCaptor.getValue().apply(null);
|
||||
|
||||
verify(synchronizePromise).then(synchronizeCaptor.capture());
|
||||
synchronizeCaptor.getValue().apply(new Resource[0]);
|
||||
|
|
|
|||
|
|
@ -98,8 +98,6 @@ public class CommitPresenterTest extends BaseTest {
|
|||
when(voidPromise.catchError(any(Operation.class))).thenReturn(voidPromise);
|
||||
when(revisionPromise.then(any(Operation.class))).thenReturn(revisionPromise);
|
||||
when(revisionPromise.catchError(any(Operation.class))).thenReturn(revisionPromise);
|
||||
when(service.add(any(Path.class), anyBoolean(), any(Path[].class))).thenReturn(voidPromise);
|
||||
when(service.commit(any(Path.class), anyString(), anyBoolean(), any(Path[].class), anyBoolean())).thenReturn(revisionPromise);
|
||||
when(stringPromise.then(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(stringPromise.catchError(any(Operation.class))).thenReturn(stringPromise);
|
||||
when(branchListPromise.then(any(Operation.class))).thenReturn(branchListPromise);
|
||||
|
|
@ -109,7 +107,7 @@ public class CommitPresenterTest extends BaseTest {
|
|||
when(logPromise.catchError(any(Operation.class))).thenReturn(logPromise);
|
||||
when(statusPromise.then(any(Operation.class))).thenReturn(statusPromise);
|
||||
when(service.add(any(Path.class), anyBoolean(), any(Path[].class))).thenReturn(voidPromise);
|
||||
when(service.commit(any(Path.class), anyString(), anyBoolean(), any(Path[].class), anyBoolean()))
|
||||
when(service.commit(any(Path.class), anyString(), anyBoolean(), any(Path[].class)))
|
||||
.thenReturn(revisionPromise);
|
||||
when(service.diff(any(Path.class),
|
||||
eq(null),
|
||||
|
|
|
|||
|
|
@ -68,15 +68,13 @@ public class HistoryPresenterTest extends BaseTest {
|
|||
when(appContext.getResource()).thenReturn(resource);
|
||||
when(appContext.getRootProject()).thenReturn(project);
|
||||
|
||||
when(service.log(
|
||||
any(Path.class),
|
||||
when(service.log(any(Path.class),
|
||||
any(Path[].class),
|
||||
anyInt(),
|
||||
anyInt(),
|
||||
anyBoolean()))
|
||||
.thenReturn(logPromise);
|
||||
when(service.diff(
|
||||
any(Path.class),
|
||||
when(service.diff(any(Path.class),
|
||||
anyList(),
|
||||
any(DiffType.class),
|
||||
anyBoolean(),
|
||||
|
|
@ -84,8 +82,7 @@ public class HistoryPresenterTest extends BaseTest {
|
|||
anyString(),
|
||||
anyString()))
|
||||
.thenReturn(stringPromise);
|
||||
when(service.showFileContent(
|
||||
any(Path.class),
|
||||
when(service.showFileContent(any(Path.class),
|
||||
any(Path.class),
|
||||
anyString()))
|
||||
.thenReturn(showPromise);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ package org.eclipse.che.ide.ext.git.client.status;
|
|||
import org.eclipse.che.api.git.shared.StatusFormat;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.ide.api.notification.StatusNotification;
|
||||
import org.eclipse.che.ide.api.parts.WorkspaceAgent;
|
||||
import org.eclipse.che.ide.ext.git.client.BaseTest;
|
||||
import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputConsoleFactory;
|
||||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
|
|
@ -39,9 +38,6 @@ public class StatusCommandPresenterTest extends BaseTest {
|
|||
@InjectMocks
|
||||
private StatusCommandPresenter presenter;
|
||||
|
||||
@Mock
|
||||
private WorkspaceAgent workspaceAgent;
|
||||
|
||||
@Mock
|
||||
private GitOutputConsoleFactory gitOutputConsoleFactory;
|
||||
|
||||
|
|
@ -53,7 +49,6 @@ public class StatusCommandPresenterTest extends BaseTest {
|
|||
super.disarm();
|
||||
|
||||
presenter = new StatusCommandPresenter(service,
|
||||
appContext,
|
||||
gitOutputConsoleFactory,
|
||||
processesPanelPresenter,
|
||||
constant,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import org.eclipse.che.ide.api.event.ng.DeletedFilesController;
|
|||
import org.eclipse.che.ide.api.parts.PartPresenter;
|
||||
import org.eclipse.che.ide.api.parts.WorkspaceAgent;
|
||||
import org.eclipse.che.ide.api.resources.ExternalResourceDelta;
|
||||
import org.eclipse.che.ide.api.resources.ModificationTracker;
|
||||
import org.eclipse.che.ide.api.resources.ResourceDelta;
|
||||
import org.eclipse.che.ide.api.resources.VirtualFile;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.refactoring.ChangeInfo;
|
||||
|
|
@ -167,12 +166,6 @@ public class RefactoringUpdater {
|
|||
private void updateFileContent(VirtualFile virtualFile) {
|
||||
String path = virtualFile.getLocation().toString();
|
||||
|
||||
if (virtualFile instanceof ModificationTracker) {
|
||||
String modificationStamp = ((ModificationTracker)virtualFile).getModificationStamp();
|
||||
eventBus.fireEvent(new FileContentUpdateEvent(path, modificationStamp));
|
||||
return;
|
||||
}
|
||||
|
||||
eventBus.fireEvent(new FileContentUpdateEvent(path));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,18 @@
|
|||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
package org.eclipse.che.plugin.maven.generator.archetype;
|
||||
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.util.AbstractLineConsumer;
|
||||
import org.eclipse.che.api.core.util.CommandLine;
|
||||
import org.eclipse.che.api.core.util.LineConsumer;
|
||||
import org.eclipse.che.api.core.util.ProcessUtil;
|
||||
import org.eclipse.che.api.core.util.ValueHolder;
|
||||
import org.eclipse.che.api.core.util.Watchdog;
|
||||
import org.eclipse.che.api.core.util.WebsocketMessageConsumer;
|
||||
import org.eclipse.che.ide.maven.tools.MavenArtifact;
|
||||
import org.eclipse.che.ide.maven.tools.MavenUtils;
|
||||
import org.eclipse.che.plugin.maven.shared.MavenArchetype;
|
||||
|
|
@ -25,6 +25,7 @@ import org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.File;
|
||||
|
|
@ -35,7 +36,8 @@ import java.util.Map;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_NAME;
|
||||
import static org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput.State.DONE;
|
||||
import static org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput.State.ERROR;
|
||||
|
||||
/**
|
||||
* Generates projects with maven-archetype-plugin.
|
||||
|
|
@ -46,6 +48,13 @@ import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYP
|
|||
public class ArchetypeGenerator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ArchetypeGenerator.class);
|
||||
|
||||
private EventService eventService;
|
||||
|
||||
@Inject
|
||||
public ArchetypeGenerator(EventService eventService) {
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new project from the specified archetype by given maven artifact descriptor.
|
||||
* @param workDir
|
||||
|
|
@ -100,12 +109,13 @@ public class ArchetypeGenerator {
|
|||
*/
|
||||
private void execute(String[] commandLine, File workDir) throws TimeoutException, IOException, InterruptedException {
|
||||
ProcessBuilder pb = new ProcessBuilder(commandLine).redirectErrorStream(true).directory(workDir);
|
||||
WebsocketMessageConsumer<ArchetypeOutput> websocketMessageConsumer = new WebsocketMessageConsumer(MAVEN_ARCHETYPE_CHANEL_NAME);
|
||||
websocketMessageConsumer.consume(new ArchetypeOutputImpl("Start Project generation", ArchetypeOutput.State.START));
|
||||
|
||||
eventService.publish(new ArchetypeOutputImpl("Start Project generation", ArchetypeOutput.State.START));
|
||||
|
||||
LineConsumer lineConsumer = new AbstractLineConsumer() {
|
||||
@Override
|
||||
public void writeLine(String line) throws IOException {
|
||||
websocketMessageConsumer.consume(new ArchetypeOutputImpl(line, ArchetypeOutput.State.IN_PROGRESS));
|
||||
eventService.publish(new ArchetypeOutputImpl(line, ArchetypeOutput.State.IN_PROGRESS));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -122,14 +132,14 @@ public class ArchetypeGenerator {
|
|||
// consume logs until process ends
|
||||
ProcessUtil.process(process, lineConsumer);
|
||||
process.waitFor();
|
||||
websocketMessageConsumer.consume(new ArchetypeOutputImpl("Done", ArchetypeOutput.State.DONE));
|
||||
eventService.publish(new ArchetypeOutputImpl("Done", DONE));
|
||||
if (isTimeoutExceeded.get()) {
|
||||
LOG.error("Generation project time expired : command-line " + Arrays.toString(commandLine));
|
||||
websocketMessageConsumer.consume(new ArchetypeOutputImpl("Generation project time expired", ArchetypeOutput.State.ERROR));
|
||||
eventService.publish(new ArchetypeOutputImpl("Generation project time expired", ERROR));
|
||||
throw new TimeoutException();
|
||||
} else if (process.exitValue() != 0) {
|
||||
LOG.error("Generation project fail : command-line " + Arrays.toString(commandLine));
|
||||
websocketMessageConsumer.consume(new ArchetypeOutputImpl("Generation project occurs error", ArchetypeOutput.State.ERROR));
|
||||
eventService.publish(new ArchetypeOutputImpl("Generation project occurs error", ERROR));
|
||||
throw new IOException("Process failed. Exit code " + process.exitValue() + " command-line : " + Arrays.toString(commandLine));
|
||||
}
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -13,14 +13,12 @@ package org.eclipse.che.plugin.maven.generator.archetype;
|
|||
import org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput;
|
||||
|
||||
/**
|
||||
* Describes information about output object of maven archetype project generation.
|
||||
*
|
||||
* @author Vitalii Parfonov
|
||||
*/
|
||||
public class ArchetypeOutputImpl implements ArchetypeOutput {
|
||||
|
||||
|
||||
private String output;
|
||||
|
||||
private State state;
|
||||
|
||||
public ArchetypeOutputImpl(String output, State state) {
|
||||
|
|
@ -37,4 +35,14 @@ public class ArchetypeOutputImpl implements ArchetypeOutput {
|
|||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(String output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.generator.archetype;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.notification.EventSubscriber;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newConcurrentHashSet;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_OUTPUT;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_SUBSCRIBE;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_UNSUBSCRIBE;
|
||||
|
||||
/**
|
||||
* Mechanism which sends events of maven archetype generation by using JSON RPC to the client.
|
||||
*/
|
||||
@Singleton
|
||||
public class MavenArchetypeJsonRpcMessenger implements EventSubscriber<ArchetypeOutput> {
|
||||
private final Set<String> endpointIds = newConcurrentHashSet();
|
||||
private EventService eventService;
|
||||
private RequestTransmitter transmitter;
|
||||
|
||||
@Inject
|
||||
public MavenArchetypeJsonRpcMessenger(EventService eventService, RequestTransmitter transmitter) {
|
||||
this.eventService = eventService;
|
||||
this.transmitter = transmitter;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void subscribe() {
|
||||
eventService.subscribe(this);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void unsubscribe() {
|
||||
eventService.unsubscribe(this);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void configureHandlers(RequestHandlerConfigurator configurator) {
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_ARCHETYPE_CHANEL_SUBSCRIBE)
|
||||
.noParams()
|
||||
.noResult()
|
||||
.withConsumer(endpointIds::add);
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_ARCHETYPE_CHANEL_UNSUBSCRIBE)
|
||||
.noParams()
|
||||
.noResult()
|
||||
.withConsumer(endpointIds::remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(ArchetypeOutput event) {
|
||||
ArchetypeOutput archetypeOutput = DtoFactory.newDto(ArchetypeOutput.class);
|
||||
archetypeOutput.setOutput(event.getOutput());
|
||||
archetypeOutput.setState(event.getState());
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_ARCHETYPE_CHANEL_OUTPUT)
|
||||
.paramsAsDto(archetypeOutput)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.generator.archetype;
|
||||
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.ide.maven.tools.MavenArtifact;
|
||||
import org.eclipse.che.plugin.maven.shared.MavenArchetype;
|
||||
|
|
@ -26,6 +27,7 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Test for {@link ArchetypeGenerator}
|
||||
*
|
||||
* @author Vitalii Parfonov
|
||||
*/
|
||||
|
|
@ -36,11 +38,12 @@ public class ArchetypeGeneratorTest {
|
|||
@Ignore
|
||||
public void generateFromArchetype() throws Exception {
|
||||
MavenArchetype mavenArchetype = mock(MavenArchetype.class);
|
||||
EventService eventService = mock(EventService.class);
|
||||
when(mavenArchetype.getArtifactId()).thenReturn("tomee-webapp-archetype");
|
||||
when(mavenArchetype.getGroupId()).thenReturn("org.apache.openejb.maven");
|
||||
when(mavenArchetype.getVersion()).thenReturn("1.7.1");
|
||||
File workDir = Files.createTempDirectory("workDir").toFile();
|
||||
ArchetypeGenerator archetypeGenerator = new ArchetypeGenerator();
|
||||
ArchetypeGenerator archetypeGenerator = new ArchetypeGenerator(eventService);
|
||||
String artifactId = NameGenerator.generate("artifactId", 5);
|
||||
String groupId = NameGenerator.generate("groupId", 5);
|
||||
MavenArtifact mavenArtifact = new MavenArtifact();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.client;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentUndefinedMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ProjectsUpdateMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.StartStopNotification;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.TextMessageDto;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_OUTPUT;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_SUBSCRIBE;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_SUBSCRIBE;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_PERCENT_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_PERCENT_UNDEFINED_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_START_STOP_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_TEXT_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_UPDATE_METHOD;
|
||||
|
||||
/**
|
||||
* A mechanism for handling all messages from the Maven server and applying registered consumers.
|
||||
*/
|
||||
@Singleton
|
||||
public class MavenJsonRpcHandler {
|
||||
private static final String WS_AGENT_ENDPOINT = "ws-agent";
|
||||
|
||||
private RequestHandlerConfigurator configurator;
|
||||
|
||||
private Set<Consumer<TextMessageDto>> textConsumers = new HashSet<>();
|
||||
private Set<Consumer<StartStopNotification>> startStopConsumers = new HashSet<>();
|
||||
private Set<Consumer<PercentUndefinedMessageDto>> percentUndefinedConsumers = new HashSet<>();
|
||||
private Set<Consumer<PercentMessageDto>> percentConsumers = new HashSet<>();
|
||||
private Set<Consumer<ProjectsUpdateMessage>> projectsUpdateConsumers = new HashSet<>();
|
||||
private Set<Consumer<ArchetypeOutput>> archetypeOutputConsumers = new HashSet<>();
|
||||
|
||||
private boolean isSubscribed = false;
|
||||
|
||||
@Inject
|
||||
public MavenJsonRpcHandler(RequestHandlerConfigurator configurator) {
|
||||
this.configurator = configurator;
|
||||
|
||||
handleMavenServerMessages();
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void subscribe(RequestTransmitter requestTransmitter) {
|
||||
if (isSubscribed) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(WS_AGENT_ENDPOINT)
|
||||
.methodName(MAVEN_CHANEL_SUBSCRIBE)
|
||||
.noParams()
|
||||
.sendAndSkipResult();
|
||||
|
||||
requestTransmitter.newRequest()
|
||||
.endpointId(WS_AGENT_ENDPOINT)
|
||||
.methodName(MAVEN_ARCHETYPE_CHANEL_SUBSCRIBE)
|
||||
.noParams()
|
||||
.sendAndSkipResult();
|
||||
|
||||
isSubscribed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link TextMessageDto}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addTextHandler(Consumer<TextMessageDto> consumer) {
|
||||
textConsumers.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link StartStopNotification}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addStartStopHandler(Consumer<StartStopNotification> consumer) {
|
||||
startStopConsumers.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link PercentUndefinedMessageDto}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addPercentUndefinedHandler(Consumer<PercentUndefinedMessageDto> consumer) {
|
||||
percentUndefinedConsumers.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link PercentMessageDto}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addPercentHandler(Consumer<PercentMessageDto> consumer) {
|
||||
percentConsumers.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link ProjectsUpdateMessage}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addProjectsUpdateHandler(Consumer<ProjectsUpdateMessage> consumer) {
|
||||
projectsUpdateConsumers.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds consumer for the event with {@link ArchetypeOutput}.
|
||||
*
|
||||
* @param consumer
|
||||
* new consumer
|
||||
*/
|
||||
public void addArchetypeOutputHandler(Consumer<ArchetypeOutput> consumer) {
|
||||
archetypeOutputConsumers.add(consumer);
|
||||
}
|
||||
|
||||
private void handleMavenServerMessages() {
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_OUTPUT_TEXT_METHOD)
|
||||
.paramsAsDto(TextMessageDto.class)
|
||||
.noResult()
|
||||
.withConsumer(textNotification -> textConsumers.forEach(it -> it.accept(textNotification)));
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_OUTPUT_PERCENT_UNDEFINED_METHOD)
|
||||
.paramsAsDto(PercentUndefinedMessageDto.class)
|
||||
.noResult()
|
||||
.withConsumer(percentUndefinedMessage -> percentUndefinedConsumers.forEach(it -> it.accept(percentUndefinedMessage)));
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_OUTPUT_PERCENT_METHOD)
|
||||
.paramsAsDto(PercentMessageDto.class)
|
||||
.noResult()
|
||||
.withConsumer(percentMessage -> percentConsumers.forEach(it -> it.accept(percentMessage)));
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_OUTPUT_START_STOP_METHOD)
|
||||
.paramsAsDto(StartStopNotification.class)
|
||||
.noResult()
|
||||
.withConsumer(startStopNotification -> startStopConsumers.forEach(it -> it.accept(startStopNotification)));
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_OUTPUT_UPDATE_METHOD)
|
||||
.paramsAsDto(ProjectsUpdateMessage.class)
|
||||
.noResult()
|
||||
.withConsumer(projectsUpdateMessage -> projectsUpdateConsumers.forEach(it -> it.accept(projectsUpdateMessage)));
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_ARCHETYPE_CHANEL_OUTPUT)
|
||||
.paramsAsDto(ArchetypeOutput.class)
|
||||
.noResult()
|
||||
.withConsumer(archetypeOutput -> archetypeOutputConsumers.forEach(it -> it.accept(archetypeOutput)));
|
||||
}
|
||||
}
|
||||
|
|
@ -10,41 +10,27 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.client.comunnication;
|
||||
|
||||
import elemental.json.Json;
|
||||
import elemental.json.JsonObject;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.machine.WsAgentStateController;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateEvent;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateHandler;
|
||||
import org.eclipse.che.ide.api.workspace.event.WorkspaceStoppedEvent;
|
||||
import org.eclipse.che.ide.console.CommandConsoleFactory;
|
||||
import org.eclipse.che.ide.console.DefaultOutputConsole;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
import org.eclipse.che.ide.websocket.MessageBus;
|
||||
import org.eclipse.che.ide.websocket.WebSocketException;
|
||||
import org.eclipse.che.ide.websocket.events.MessageHandler;
|
||||
import org.eclipse.che.plugin.maven.client.MavenJsonRpcHandler;
|
||||
import org.eclipse.che.plugin.maven.client.comunnication.progressor.background.BackgroundLoaderPresenter;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ArchetypeOutput;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.NotificationMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ProjectsUpdateMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.StartStopNotification;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.TextMessageDto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ARCHETYPE_CHANEL_NAME;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_NAME;
|
||||
|
||||
/**
|
||||
* Handler which receives messages from the maven server.
|
||||
|
|
@ -54,127 +40,70 @@ import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_N
|
|||
*/
|
||||
@Singleton
|
||||
public class MavenMessagesHandler {
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final DtoFactory factory;
|
||||
private final BackgroundLoaderPresenter dependencyResolver;
|
||||
private final PomEditorReconciler pomEditorReconciler;
|
||||
private final ProcessesPanelPresenter processesPanelPresenter;
|
||||
private final CommandConsoleFactory commandConsoleFactory;
|
||||
private final AppContext appContext;
|
||||
|
||||
private DefaultOutputConsole outputConsole;
|
||||
|
||||
@Inject
|
||||
public MavenMessagesHandler(EventBus eventBus,
|
||||
DtoFactory factory,
|
||||
MavenJsonRpcHandler mavenJsonRpcHandler,
|
||||
BackgroundLoaderPresenter dependencyResolver,
|
||||
PomEditorReconciler pomEditorReconciler,
|
||||
WsAgentStateController wsAgentStateController,
|
||||
ProcessesPanelPresenter processesPanelPresenter,
|
||||
CommandConsoleFactory commandConsoleFactory,
|
||||
AppContext appContext) {
|
||||
this.eventBus = eventBus;
|
||||
this.factory = factory;
|
||||
|
||||
this.dependencyResolver = dependencyResolver;
|
||||
this.pomEditorReconciler = pomEditorReconciler;
|
||||
this.processesPanelPresenter = processesPanelPresenter;
|
||||
this.commandConsoleFactory = commandConsoleFactory;
|
||||
this.appContext = appContext;
|
||||
|
||||
handleOperations(wsAgentStateController);
|
||||
mavenJsonRpcHandler.addTextHandler(this::handleTextNotification);
|
||||
mavenJsonRpcHandler.addStartStopHandler(this::handleStartStop);
|
||||
mavenJsonRpcHandler.addPercentHandler(this::handlePercentNotification);
|
||||
mavenJsonRpcHandler.addProjectsUpdateHandler(this::handleUpdate);
|
||||
mavenJsonRpcHandler.addArchetypeOutputHandler(this::onMavenArchetypeReceive);
|
||||
|
||||
handleOperations();
|
||||
outputConsole = (DefaultOutputConsole)commandConsoleFactory.create("Maven Archetype");
|
||||
}
|
||||
|
||||
private void handleOperations(final WsAgentStateController wsAgentStateController) {
|
||||
eventBus.addHandler(WsAgentStateEvent.TYPE, new WsAgentStateHandler() {
|
||||
@Override
|
||||
public void onWsAgentStarted(WsAgentStateEvent event) {
|
||||
wsAgentStateController.getMessageBus().then(new Operation<MessageBus>() {
|
||||
@Override
|
||||
public void apply(MessageBus messageBus) throws OperationException {
|
||||
try {
|
||||
handleMavenServerEvents(messageBus);
|
||||
handleMavenArchetype(messageBus);
|
||||
} catch (WebSocketException e) {
|
||||
dependencyResolver.hide();
|
||||
Log.error(getClass(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWsAgentStopped(WsAgentStateEvent event) {
|
||||
dependencyResolver.hide();
|
||||
}
|
||||
});
|
||||
|
||||
private void handleOperations() {
|
||||
eventBus.addHandler(WorkspaceStoppedEvent.TYPE, event -> dependencyResolver.hide());
|
||||
}
|
||||
|
||||
|
||||
private void handleMavenServerEvents(final MessageBus messageBus) throws WebSocketException {
|
||||
messageBus.subscribe(MAVEN_CHANEL_NAME, new MessageHandler() {
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
final JsonObject jsonObject = Json.parse(message);
|
||||
final int type = (int)jsonObject.getNumber("$type");
|
||||
MessageType messageType = MessageType.valueOf(type);
|
||||
switch (messageType) {
|
||||
case NOTIFICATION:
|
||||
NotificationMessage dto = factory.createDtoFromJson(message, NotificationMessage.class);
|
||||
handleNotification(dto);
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
handleUpdate(factory.createDtoFromJson(message, ProjectsUpdateMessage.class));
|
||||
break;
|
||||
|
||||
case START_STOP:
|
||||
handleStartStop(factory.createDtoFromJson(message, StartStopNotification.class));
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.error(getClass(), "Unknown message type:" + messageType);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Updates progress bar when the percent of project resolving is changed.
|
||||
*
|
||||
* @param percentMessageDto
|
||||
* object with value of percent
|
||||
*/
|
||||
protected void handlePercentNotification(PercentMessageDto percentMessageDto) {
|
||||
dependencyResolver.updateProgressBar((int)(percentMessageDto.getPercent() * 100));
|
||||
}
|
||||
|
||||
private void handleMavenArchetype(final MessageBus messageBus) {
|
||||
final DefaultOutputConsole outputConsole = (DefaultOutputConsole)commandConsoleFactory.create("Maven Archetype");
|
||||
|
||||
try {
|
||||
messageBus.subscribe(MAVEN_ARCHETYPE_CHANEL_NAME, new MessageHandler() {
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
Log.info(getClass(), message);
|
||||
ArchetypeOutput archetypeOutput = factory.createDtoFromJson(message, ArchetypeOutput.class);
|
||||
processesPanelPresenter.addCommandOutput(outputConsole);
|
||||
switch (archetypeOutput.getState()) {
|
||||
case START:
|
||||
outputConsole.clearOutputsButtonClicked();
|
||||
outputConsole.printText(archetypeOutput.getOutput(), "green");
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
outputConsole.printText(archetypeOutput.getOutput());
|
||||
break;
|
||||
case DONE:
|
||||
outputConsole.printText(archetypeOutput.getOutput(), "green");
|
||||
break;
|
||||
case ERROR:
|
||||
outputConsole.printText(archetypeOutput.getOutput(), "red");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (WebSocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/**
|
||||
* Updates progress label when the resolved project is changed.
|
||||
*
|
||||
* @param textMessageDto
|
||||
* object with name of new label
|
||||
*/
|
||||
protected void handleTextNotification(TextMessageDto textMessageDto) {
|
||||
dependencyResolver.show();
|
||||
dependencyResolver.setProgressLabel(textMessageDto.getText());
|
||||
}
|
||||
|
||||
private void handleStartStop(StartStopNotification dto) {
|
||||
/**
|
||||
* Hides or shows a progress bar.
|
||||
*
|
||||
* @param dto
|
||||
* describes a state of the project resolving
|
||||
*/
|
||||
protected void handleStartStop(StartStopNotification dto) {
|
||||
if (dto.isStart()) {
|
||||
dependencyResolver.show();
|
||||
} else {
|
||||
|
|
@ -182,7 +111,13 @@ public class MavenMessagesHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleUpdate(ProjectsUpdateMessage dto) {
|
||||
/**
|
||||
* Updates the tree of projects which were modified.
|
||||
*
|
||||
* @param dto
|
||||
* describes a projects which were modified
|
||||
*/
|
||||
protected void handleUpdate(ProjectsUpdateMessage dto) {
|
||||
List<String> updatedProjects = dto.getUpdatedProjects();
|
||||
Set<String> projectToRefresh = computeUniqueHiLevelProjects(updatedProjects);
|
||||
for (final String path : projectToRefresh) {
|
||||
|
|
@ -196,24 +131,38 @@ public class MavenMessagesHandler {
|
|||
pomEditorReconciler.reconcilePoms(updatedProjects);
|
||||
}
|
||||
|
||||
private void onMavenArchetypeReceive(ArchetypeOutput output) {
|
||||
String message = output.getOutput();
|
||||
switch (output.getState()) {
|
||||
case START:
|
||||
processesPanelPresenter.addCommandOutput(outputConsole);
|
||||
outputConsole.clearOutputsButtonClicked();
|
||||
outputConsole.printText(message, "green");
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
outputConsole.printText(message);
|
||||
break;
|
||||
case DONE:
|
||||
outputConsole.printText(message, "green");
|
||||
break;
|
||||
case ERROR:
|
||||
outputConsole.printText(message, "red");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> computeUniqueHiLevelProjects(List<String> updatedProjects) {
|
||||
return updatedProjects.stream().filter(each -> shouldBeUpdated(updatedProjects, each)).collect(toSet());
|
||||
}
|
||||
|
||||
private boolean shouldBeUpdated(List<String> updatedProjects, String project) {
|
||||
for (String each : updatedProjects) {
|
||||
if (!project.equals(each) && project.startsWith(each)){
|
||||
if (!project.equals(each) && project.startsWith(each)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleNotification(NotificationMessage message) {
|
||||
if (message.getPercent() != 0) {
|
||||
dependencyResolver.updateProgressBar((int)(message.getPercent() * 100));
|
||||
} else {
|
||||
dependencyResolver.setProgressLabel(message.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,19 +15,8 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.ide.api.machine.WsAgentStateController;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateEvent;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateHandler;
|
||||
import org.eclipse.che.ide.collections.Jso;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.project.ResolvingProjectStateHolder;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
import org.eclipse.che.ide.websocket.MessageBus;
|
||||
import org.eclipse.che.ide.websocket.WebSocketException;
|
||||
import org.eclipse.che.ide.websocket.events.MessageHandler;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.client.MavenJsonRpcHandler;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.StartStopNotification;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
|
@ -35,9 +24,7 @@ import java.util.HashSet;
|
|||
import static org.eclipse.che.ide.project.ResolvingProjectStateHolder.ResolvingProjectState.IN_PROGRESS;
|
||||
import static org.eclipse.che.ide.project.ResolvingProjectStateHolder.ResolvingProjectState.NOT_RESOLVED;
|
||||
import static org.eclipse.che.ide.project.ResolvingProjectStateHolder.ResolvingProjectState.RESOLVED;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_NAME;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ID;
|
||||
import static org.eclipse.che.plugin.maven.shared.MessageType.START_STOP;
|
||||
|
||||
/**
|
||||
* Keeper for the state of Resolving Project process.
|
||||
|
|
@ -51,22 +38,16 @@ import static org.eclipse.che.plugin.maven.shared.MessageType.START_STOP;
|
|||
* @author Roman Nikitenko
|
||||
*/
|
||||
@Singleton
|
||||
public class ResolvingMavenProjectStateHolder implements ResolvingProjectStateHolder, WsAgentStateHandler {
|
||||
private final DtoFactory factory;
|
||||
private final WsAgentStateController wsAgentStateController;
|
||||
public class ResolvingMavenProjectStateHolder implements ResolvingProjectStateHolder {
|
||||
private ResolvingProjectState state;
|
||||
private HashSet<ResolvingProjectStateListener> listeners;
|
||||
|
||||
@Inject
|
||||
public ResolvingMavenProjectStateHolder(DtoFactory factory,
|
||||
EventBus eventBus,
|
||||
WsAgentStateController wsAgentStateController) {
|
||||
this.factory = factory;
|
||||
this.wsAgentStateController = wsAgentStateController;
|
||||
public ResolvingMavenProjectStateHolder(MavenJsonRpcHandler mavenJsonRpcHandler, EventBus eventBus) {
|
||||
this.state = NOT_RESOLVED;
|
||||
this.listeners = new HashSet<>();
|
||||
|
||||
eventBus.addHandler(WsAgentStateEvent.TYPE, this);
|
||||
mavenJsonRpcHandler.addStartStopHandler(this::handleStartStop);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -89,36 +70,6 @@ public class ResolvingMavenProjectStateHolder implements ResolvingProjectStateHo
|
|||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWsAgentStarted(WsAgentStateEvent event) {
|
||||
wsAgentStateController.getMessageBus().then(new Operation<MessageBus>() {
|
||||
@Override
|
||||
public void apply(MessageBus messageBus) throws OperationException {
|
||||
try {
|
||||
messageBus.subscribe(MAVEN_CHANEL_NAME, new MessageHandler() {
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
Jso jso = Jso.deserialize(message);
|
||||
int type = jso.getFieldCastedToInteger("$type");
|
||||
MessageType messageType = MessageType.valueOf(type);
|
||||
|
||||
if (messageType == START_STOP) {
|
||||
handleStartStop(factory.createDtoFromJson(message, StartStopNotification.class));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (WebSocketException e) {
|
||||
Log.error(getClass(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWsAgentStopped(WsAgentStateEvent event) {
|
||||
|
||||
}
|
||||
|
||||
private void handleStartStop(StartStopNotification startStopNotification) {
|
||||
if (startStopNotification.isStart()) {
|
||||
state = IN_PROGRESS;
|
||||
|
|
@ -138,4 +89,5 @@ public class ResolvingMavenProjectStateHolder implements ResolvingProjectStateHo
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,107 +13,69 @@ package org.eclipse.che.plugin.maven.client.comunnication;
|
|||
import com.google.common.base.Optional;
|
||||
import com.google.web.bindery.event.shared.EventBus;
|
||||
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.machine.WsAgentStateController;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateEvent;
|
||||
import org.eclipse.che.ide.api.machine.events.WsAgentStateHandler;
|
||||
import org.eclipse.che.ide.api.resources.Container;
|
||||
import org.eclipse.che.ide.console.CommandConsoleFactory;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
|
||||
import org.eclipse.che.ide.websocket.MessageBus;
|
||||
import org.eclipse.che.ide.websocket.events.MessageHandler;
|
||||
import org.eclipse.che.plugin.maven.client.MavenJsonRpcHandler;
|
||||
import org.eclipse.che.plugin.maven.client.comunnication.progressor.background.BackgroundLoaderPresenter;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ProjectsUpdateMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.TextMessageDto;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_NAME;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MavenMessagesHandlerTest {
|
||||
private static final String JSON_MESSAGE = "{\n" +
|
||||
" \"deletedProjects\": [],\n" +
|
||||
" \"updatedProjects\": [\n" +
|
||||
" \"/che/core\",\n" +
|
||||
" \"/project\",\n" +
|
||||
" \"/che/core/che-core-db-vendor-postgresql\",\n" +
|
||||
" \"/che/plugins/plugin-svn\",\n" +
|
||||
" \"/che/samples/sample-plugin-json\",\n" +
|
||||
" \"/che/wsmaster/che-core-api-auth\",\n" +
|
||||
" \"/project/api\",\n" +
|
||||
" \"/che/wsagent\",\n" +
|
||||
" \"/che\",\n" +
|
||||
" \"/che/plugins/plugin-github/che-plugin-github-pullrequest\",\n" +
|
||||
" \"/che/plugins/plugin-java-debugger\"\n" +
|
||||
" ],\n" +
|
||||
" \"$type\": 2\n" +
|
||||
"}";
|
||||
@Mock
|
||||
private EventBus eventBus;
|
||||
@Mock
|
||||
private DtoFactory factory;
|
||||
@Mock
|
||||
private BackgroundLoaderPresenter dependencyResolver;
|
||||
@Mock
|
||||
private PomEditorReconciler pomEditorReconciler;
|
||||
@Mock
|
||||
private WsAgentStateController wsAgentStateController;
|
||||
@Mock
|
||||
private ProcessesPanelPresenter processesPanelPresenter;
|
||||
@Mock
|
||||
private CommandConsoleFactory commandConsoleFactory;
|
||||
@Mock
|
||||
private MavenJsonRpcHandler mavenJsonRpcHandler;
|
||||
@Mock
|
||||
private AppContext appContext;
|
||||
|
||||
@Mock
|
||||
private WsAgentStateEvent wsAgentStateEvent;
|
||||
private ProjectsUpdateMessage projectsUpdateMessage;
|
||||
@Mock
|
||||
private ProjectsUpdateMessage projectsUpdateMessage;
|
||||
private Promise<Optional<Container>> optionalContainer;
|
||||
@Mock
|
||||
private Promise<MessageBus> messageBusPromise;
|
||||
@Mock
|
||||
private Promise<Optional<Container>> optionalContainer;
|
||||
@Mock
|
||||
private MessageBus messageBus;
|
||||
@Mock
|
||||
private Container rootContainer;
|
||||
@Captor
|
||||
private ArgumentCaptor<WsAgentStateHandler> wsAgentStateHandlerArgumentCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<Operation<MessageBus>> operationArgumentCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<MessageHandler> messageHandlerArgumentCaptor;
|
||||
private Container rootContainer;
|
||||
|
||||
private MavenMessagesHandler mavenMessagesHandler;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
when(wsAgentStateController.getMessageBus()).thenReturn(messageBusPromise);
|
||||
when(appContext.getWorkspaceRoot()).thenReturn(rootContainer);
|
||||
|
||||
new MavenMessagesHandler(eventBus,
|
||||
factory,
|
||||
dependencyResolver,
|
||||
pomEditorReconciler,
|
||||
wsAgentStateController,
|
||||
processesPanelPresenter,
|
||||
commandConsoleFactory,
|
||||
appContext);
|
||||
|
||||
|
||||
mavenMessagesHandler = new MavenMessagesHandler(eventBus,
|
||||
mavenJsonRpcHandler,
|
||||
dependencyResolver,
|
||||
pomEditorReconciler,
|
||||
processesPanelPresenter,
|
||||
commandConsoleFactory,
|
||||
appContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -130,22 +92,34 @@ public class MavenMessagesHandlerTest {
|
|||
"/che/plugins/plugin-github/che-plugin-github-pullrequest",
|
||||
"/che/plugins/plugin-java-debugger");
|
||||
|
||||
when(factory.createDtoFromJson(eq(JSON_MESSAGE), eq(ProjectsUpdateMessage.class))).thenReturn(projectsUpdateMessage);
|
||||
when(projectsUpdateMessage.getUpdatedProjects()).thenReturn(updatedProjects);
|
||||
when(rootContainer.getContainer(anyString())).thenReturn(optionalContainer);
|
||||
|
||||
verify(eventBus).addHandler(eq(WsAgentStateEvent.TYPE), wsAgentStateHandlerArgumentCaptor.capture());
|
||||
wsAgentStateHandlerArgumentCaptor.getValue().onWsAgentStarted(wsAgentStateEvent);
|
||||
mavenMessagesHandler.handleUpdate(projectsUpdateMessage);
|
||||
|
||||
verify(messageBusPromise).then(operationArgumentCaptor.capture());
|
||||
operationArgumentCaptor.getValue().apply(messageBus);
|
||||
|
||||
verify(messageBus).subscribe(eq(MAVEN_CHANEL_NAME), messageHandlerArgumentCaptor.capture());
|
||||
messageHandlerArgumentCaptor.getValue().onMessage(JSON_MESSAGE);
|
||||
|
||||
verify(factory).createDtoFromJson(JSON_MESSAGE, ProjectsUpdateMessage.class);
|
||||
verify(pomEditorReconciler).reconcilePoms(updatedProjects);
|
||||
verify(rootContainer).getContainer(eq("/che"));
|
||||
verify(rootContainer).getContainer(eq("/project"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentNotificationShouldBeHandled() throws Exception {
|
||||
PercentMessageDto percentMessageDto = Mockito.mock(PercentMessageDto.class);
|
||||
when(percentMessageDto.getPercent()).thenReturn(0.7);
|
||||
|
||||
mavenMessagesHandler.handlePercentNotification(percentMessageDto);
|
||||
|
||||
verify(dependencyResolver).updateProgressBar(70);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textNotificationShouldBeUpdated() throws Exception {
|
||||
TextMessageDto textMessageDto = mock(TextMessageDto.class);
|
||||
String textMessage = "textMessage";
|
||||
when(textMessageDto.getText()).thenReturn(textMessage);
|
||||
|
||||
mavenMessagesHandler.handleTextNotification(textMessageDto);
|
||||
|
||||
verify(dependencyResolver).setProgressLabel(textMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import java.util.Set;
|
|||
* @author Evgen Vidolob
|
||||
*/
|
||||
@ImplementedBy(MavenWebSocketCommunication.class)
|
||||
@Deprecated
|
||||
public interface MavenCommunication {
|
||||
|
||||
void sendUpdateMassage(Set<MavenProject> updated, List<MavenProject> removed);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.server.core;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.notification.EventSubscriber;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.PercentUndefinedMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.ProjectsUpdateMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.StartStopNotification;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.TextMessageDto;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenPercentMessageEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenPercentUndefinedEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenStartStopEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenTextMessageEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenUpdateEvent;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newConcurrentHashSet;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_SUBSCRIBE;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_CHANEL_UNSUBSCRIBE;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_PERCENT_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_PERCENT_UNDEFINED_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_START_STOP_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_TEXT_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_OUTPUT_UPDATE_METHOD;
|
||||
import static org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent.TYPE.PERCENT;
|
||||
import static org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent.TYPE.PERCENT_UNDEFINED;
|
||||
import static org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent.TYPE.START_STOP;
|
||||
|
||||
/**
|
||||
* Send maven events using JSON RPC to the clients.
|
||||
*/
|
||||
@Singleton
|
||||
public class MavenJsonRpcCommunication implements EventSubscriber<MavenOutputEvent> {
|
||||
private final Set<String> endpointIds = newConcurrentHashSet();
|
||||
private EventService eventService;
|
||||
private RequestTransmitter transmitter;
|
||||
|
||||
@Inject
|
||||
public MavenJsonRpcCommunication(EventService eventService, RequestTransmitter transmitter) {
|
||||
this.eventService = eventService;
|
||||
this.transmitter = transmitter;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void subscribe() {
|
||||
eventService.subscribe(this);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void unsubscribe() {
|
||||
eventService.unsubscribe(this);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void configureHandlers(RequestHandlerConfigurator configurator) {
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_CHANEL_SUBSCRIBE)
|
||||
.noParams()
|
||||
.noResult()
|
||||
.withConsumer(endpointIds::add);
|
||||
|
||||
configurator.newConfiguration()
|
||||
.methodName(MAVEN_CHANEL_UNSUBSCRIBE)
|
||||
.noParams()
|
||||
.noResult()
|
||||
.withConsumer(endpointIds::remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(MavenOutputEvent event) {
|
||||
switch (event.getType()) {
|
||||
case TEXT:
|
||||
sendTextNotification((MavenTextMessageEvent)event);
|
||||
break;
|
||||
case UPDATE:
|
||||
sendUpdateNotification((MavenUpdateEvent)event);
|
||||
break;
|
||||
case START_STOP:
|
||||
sendStartStopNotification((MavenStartStopEvent)event);
|
||||
break;
|
||||
case PERCENT:
|
||||
senPercentNotification((MavenPercentMessageEvent)event);
|
||||
break;
|
||||
case PERCENT_UNDEFINED:
|
||||
sendPercentUndefinedNotification((MavenPercentUndefinedEvent)event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void senPercentNotification(MavenPercentMessageEvent event) {
|
||||
PercentMessageDto percentMessageDto = DtoFactory.newDto(PercentMessageDto.class).withPercent(event.getPercent());
|
||||
percentMessageDto.setType(PERCENT);
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_OUTPUT_PERCENT_METHOD)
|
||||
.paramsAsDto(percentMessageDto)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
|
||||
private void sendPercentUndefinedNotification(MavenPercentUndefinedEvent event) {
|
||||
PercentUndefinedMessageDto percentUndefinedMessageDto = DtoFactory.newDto(PercentUndefinedMessageDto.class);
|
||||
percentUndefinedMessageDto.setPercentUndefined(event.isPercentUndefined());
|
||||
percentUndefinedMessageDto.setType(PERCENT_UNDEFINED);
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_OUTPUT_PERCENT_UNDEFINED_METHOD)
|
||||
.paramsAsDto(percentUndefinedMessageDto)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
|
||||
private void sendStartStopNotification(MavenStartStopEvent event) {
|
||||
StartStopNotification startEventDto = DtoFactory.newDto(StartStopNotification.class);
|
||||
startEventDto.setStart(event.isStart());
|
||||
startEventDto.setType(START_STOP);
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_OUTPUT_START_STOP_METHOD)
|
||||
.paramsAsDto(startEventDto)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
|
||||
private void sendUpdateNotification(MavenUpdateEvent event) {
|
||||
ProjectsUpdateMessage updateEventDto = DtoFactory.newDto(ProjectsUpdateMessage.class);
|
||||
List<String> updatedPaths = event.getUpdatedProjects();
|
||||
List<String> removedPaths = event.getRemovedProjects();
|
||||
updateEventDto.setUpdatedProjects(updatedPaths);
|
||||
updateEventDto.setDeletedProjects(removedPaths);
|
||||
|
||||
updateEventDto.setType(MavenOutputEvent.TYPE.UPDATE);
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_OUTPUT_UPDATE_METHOD)
|
||||
.paramsAsDto(updateEventDto)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
|
||||
private void sendTextNotification(MavenTextMessageEvent event) {
|
||||
TextMessageDto notification = DtoFactory.newDto(TextMessageDto.class).withText(event.getMessage());
|
||||
notification.setType(MavenOutputEvent.TYPE.TEXT);
|
||||
|
||||
endpointIds.forEach(it -> transmitter.newRequest()
|
||||
.endpointId(it)
|
||||
.methodName(MAVEN_OUTPUT_TEXT_METHOD)
|
||||
.paramsAsDto(notification)
|
||||
.sendAndSkipResult());
|
||||
}
|
||||
}
|
||||
|
|
@ -13,11 +13,13 @@ package org.eclipse.che.plugin.maven.server.core;
|
|||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.NotificationMessage;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.StartStopNotification;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.maven.server.MavenServerProgressNotifier;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.impl.MavenPercentEventImpl;
|
||||
import org.eclipse.che.plugin.maven.shared.impl.MavenPercentUndefinedEventImpl;
|
||||
import org.eclipse.che.plugin.maven.shared.impl.MavenStartStopEventImpl;
|
||||
import org.eclipse.che.plugin.maven.shared.impl.MavenTextMessageEventImpl;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MavenServerProgressNotifier}
|
||||
|
|
@ -27,32 +29,26 @@ import org.eclipse.che.maven.server.MavenServerProgressNotifier;
|
|||
@Singleton
|
||||
public class MavenServerNotifier implements MavenProgressNotifier {
|
||||
|
||||
private final MavenCommunication communication;
|
||||
private EventService eventService;
|
||||
|
||||
@Inject
|
||||
public MavenServerNotifier(MavenCommunication communication) {
|
||||
this.communication = communication;
|
||||
public MavenServerNotifier(EventService eventService) {
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
NotificationMessage dto = DtoFactory.newDto(NotificationMessage.class);
|
||||
dto.setText(text);
|
||||
communication.sendNotification(dto);
|
||||
eventService.publish(new MavenTextMessageEventImpl(text, MavenOutputEvent.TYPE.TEXT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPercent(double percent) {
|
||||
NotificationMessage dto = DtoFactory.newDto(NotificationMessage.class);
|
||||
dto.setPercent(percent);
|
||||
communication.sendNotification(dto);
|
||||
eventService.publish(new MavenPercentEventImpl(percent, MavenOutputEvent.TYPE.PERCENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPercentUndefined(boolean undefined) {
|
||||
NotificationMessage dto = DtoFactory.newDto(NotificationMessage.class);
|
||||
dto.setPercentUndefined(undefined);
|
||||
communication.sendNotification(dto);
|
||||
eventService.publish(new MavenPercentUndefinedEventImpl(undefined, MavenOutputEvent.TYPE.PERCENT_UNDEFINED));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -66,9 +62,7 @@ public class MavenServerNotifier implements MavenProgressNotifier {
|
|||
}
|
||||
|
||||
private void sendStartStop(boolean isStart) {
|
||||
StartStopNotification dto = DtoFactory.newDto(StartStopNotification.class);
|
||||
dto.setStart(isStart);
|
||||
communication.send(DtoFactory.getInstance().toJsonElement(dto).getAsJsonObject(), MessageType.START_STOP);
|
||||
eventService.publish(new MavenStartStopEventImpl(isStart, MavenOutputEvent.TYPE.START_STOP));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import java.util.stream.Collectors;
|
|||
* @author Evgen Vidolob
|
||||
*/
|
||||
@Singleton
|
||||
@Deprecated
|
||||
public class MavenWebSocketCommunication implements MavenCommunication {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MavenWebSocketCommunication.class);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ import org.eclipse.che.plugin.maven.server.core.classpath.ClasspathManager;
|
|||
import org.eclipse.che.plugin.maven.server.core.project.MavenProject;
|
||||
import org.eclipse.che.plugin.maven.server.core.project.MavenProjectModifications;
|
||||
import org.eclipse.che.plugin.maven.shared.MavenAttributes;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent;
|
||||
import org.eclipse.che.plugin.maven.shared.impl.MavenUpdateEventImpl;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.jdt.core.IJavaModelStatusConstants;
|
||||
|
|
@ -50,6 +53,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.che.plugin.maven.shared.MavenAttributes.MAVEN_ID;
|
||||
|
||||
/**
|
||||
|
|
@ -62,7 +66,6 @@ public class MavenWorkspace {
|
|||
|
||||
private final MavenProjectManager manager;
|
||||
private final Provider<ProjectRegistry> projectRegistryProvider;
|
||||
private final MavenCommunication communication;
|
||||
private final ClasspathManager classpathManager;
|
||||
|
||||
private MavenTaskExecutor resolveExecutor;
|
||||
|
|
@ -76,12 +79,10 @@ public class MavenWorkspace {
|
|||
MavenProgressNotifier notifier,
|
||||
MavenExecutorService executorService,
|
||||
Provider<ProjectRegistry> projectRegistryProvider,
|
||||
MavenCommunication communication,
|
||||
ClasspathManager classpathManager,
|
||||
EventService eventService,
|
||||
EclipseWorkspaceProvider workspaceProvider) {
|
||||
this.projectRegistryProvider = projectRegistryProvider;
|
||||
this.communication = communication;
|
||||
this.classpathManager = classpathManager;
|
||||
this.manager = manager;
|
||||
resolveExecutor = new MavenTaskExecutor(executorService, notifier);
|
||||
|
|
@ -110,9 +111,20 @@ public class MavenWorkspace {
|
|||
List<MavenProject> needResolve = manager.findDependentProjects(allChangedProjects);
|
||||
needResolve.addAll(updated.keySet());
|
||||
|
||||
List<String> updatedPaths = updated.keySet().stream()
|
||||
.map(MavenProject::getProject)
|
||||
.map(IResource::getFullPath)
|
||||
.map(IPath::toOSString)
|
||||
.collect(toList());
|
||||
List<String> removedPaths = removed.stream()
|
||||
.map(MavenProject::getProject)
|
||||
.map(IResource::getFullPath)
|
||||
.map(IPath::toOSString)
|
||||
.collect(toList());
|
||||
|
||||
addResolveProjects(needResolve);
|
||||
|
||||
communication.sendUpdateMassage(updated.keySet(), removed);
|
||||
eventService.publish(new MavenUpdateEventImpl(updatedPaths, removedPaths, MavenOutputEvent.TYPE.UPDATE));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ import org.eclipse.che.api.project.server.type.ProjectTypeDef;
|
|||
import org.eclipse.che.api.project.server.type.ValueProviderFactory;
|
||||
import org.eclipse.che.inject.DynaModule;
|
||||
import org.eclipse.che.maven.server.MavenTerminal;
|
||||
import org.eclipse.che.plugin.maven.generator.archetype.MavenArchetypeJsonRpcMessenger;
|
||||
import org.eclipse.che.plugin.maven.server.PomModificationDetector;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenJsonRpcCommunication;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenProgressNotifier;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenServerNotifier;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenTerminalImpl;
|
||||
|
|
@ -60,6 +62,8 @@ public class MavenModule extends AbstractModule {
|
|||
bind(MavenProgressNotifier.class).to(MavenServerNotifier.class).in(Singleton.class);
|
||||
|
||||
bind(MavenServerService.class);
|
||||
bind(MavenJsonRpcCommunication.class);
|
||||
bind(MavenArchetypeJsonRpcMessenger.class);
|
||||
|
||||
bind(PomChangeListener.class).asEagerSingleton();
|
||||
bind(PomModificationDetector.class).asEagerSingleton();
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.server;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.che.api.project.server.FolderEntry;
|
||||
import org.eclipse.che.api.project.server.ProjectRegistry;
|
||||
import org.eclipse.che.api.project.server.RegisteredProject;
|
||||
|
|
@ -22,15 +22,12 @@ import org.eclipse.che.maven.data.MavenArtifact;
|
|||
import org.eclipse.che.maven.data.MavenKey;
|
||||
import org.eclipse.che.maven.server.MavenTerminal;
|
||||
import org.eclipse.che.plugin.maven.server.core.EclipseWorkspaceProvider;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenCommunication;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenExecutorService;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenProjectManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenWorkspace;
|
||||
import org.eclipse.che.plugin.maven.server.core.classpath.ClasspathManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.project.MavenProject;
|
||||
import org.eclipse.che.plugin.maven.server.rmi.MavenServerManagerTest;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.NotificationMessage;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
|
@ -51,7 +48,6 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
@ -92,22 +88,7 @@ public class WorkspaceTest extends BaseTest {
|
|||
mavenNotifier,
|
||||
new MavenExecutorService(),
|
||||
projectRegistryProvider,
|
||||
new MavenCommunication() {
|
||||
@Override
|
||||
public void sendUpdateMassage(Set<MavenProject> updated, List<MavenProject> removed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendNotification(NotificationMessage message) {
|
||||
System.out.println(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(JsonObject object, MessageType type) {
|
||||
|
||||
}
|
||||
}, new ClasspathManager(root.getAbsolutePath(), wrapperManager, mavenProjectManager, terminal,
|
||||
new ClasspathManager(root.getAbsolutePath(), wrapperManager, mavenProjectManager, terminal,
|
||||
mavenNotifier), eventService, new EclipseWorkspaceProvider());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,24 +10,19 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.server.classpath;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.che.api.project.server.ProjectRegistry;
|
||||
import org.eclipse.che.commons.lang.IoUtil;
|
||||
import org.eclipse.che.maven.server.MavenTerminal;
|
||||
import org.eclipse.che.plugin.maven.server.BaseTest;
|
||||
import org.eclipse.che.plugin.maven.server.MavenWrapperManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.EclipseWorkspaceProvider;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenCommunication;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenExecutorService;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenProjectManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenWorkspace;
|
||||
import org.eclipse.che.plugin.maven.server.core.classpath.ClasspathManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.project.MavenProject;
|
||||
import org.eclipse.che.plugin.maven.server.rmi.MavenServerManagerTest;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.NotificationMessage;
|
||||
import org.eclipse.che.maven.server.MavenTerminal;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
|
|
@ -40,8 +35,6 @@ import org.testng.annotations.Test;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
@ -81,22 +74,7 @@ public class ClasspathManagerTest extends BaseTest {
|
|||
new MavenProjectManager(wrapperManager, mavenServerManager, terminal, mavenNotifier, new EclipseWorkspaceProvider());
|
||||
classpathManager = new ClasspathManager(root.getAbsolutePath(), wrapperManager, mavenProjectManager, terminal, mavenNotifier);
|
||||
mavenWorkspace = new MavenWorkspace(mavenProjectManager, mavenNotifier, new MavenExecutorService(), projectRegistryProvider,
|
||||
new MavenCommunication() {
|
||||
@Override
|
||||
public void sendUpdateMassage(Set<MavenProject> updated, List<MavenProject> removed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendNotification(NotificationMessage message) {
|
||||
System.out.println(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(JsonObject object, MessageType type) {
|
||||
|
||||
}
|
||||
}, classpathManager, eventService, new EclipseWorkspaceProvider());
|
||||
classpathManager, eventService, new EclipseWorkspaceProvider());
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.server.core.reconcile;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
|
||||
|
|
@ -24,15 +23,11 @@ import org.eclipse.che.maven.server.MavenTerminal;
|
|||
import org.eclipse.che.plugin.maven.server.BaseTest;
|
||||
import org.eclipse.che.plugin.maven.server.MavenWrapperManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.EclipseWorkspaceProvider;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenCommunication;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenExecutorService;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenProjectManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.MavenWorkspace;
|
||||
import org.eclipse.che.plugin.maven.server.core.classpath.ClasspathManager;
|
||||
import org.eclipse.che.plugin.maven.server.core.project.MavenProject;
|
||||
import org.eclipse.che.plugin.maven.server.rmi.MavenServerManagerTest;
|
||||
import org.eclipse.che.plugin.maven.shared.MessageType;
|
||||
import org.eclipse.che.plugin.maven.shared.dto.NotificationMessage;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
|
@ -42,7 +37,6 @@ import java.io.File;
|
|||
import java.rmi.RemoteException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
|
@ -89,23 +83,13 @@ public class PomReconcilerTest extends BaseTest {
|
|||
ClasspathManager classpathManager =
|
||||
new ClasspathManager(root.getAbsolutePath(), wrapperManager, mavenProjectManager, terminal, mavenNotifier);
|
||||
|
||||
mavenWorkspace = new MavenWorkspace(mavenProjectManager, mavenNotifier, new MavenExecutorService(), projectRegistryProvider,
|
||||
new MavenCommunication() {
|
||||
@Override
|
||||
public void sendUpdateMassage(Set<MavenProject> updated, List<MavenProject> removed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendNotification(NotificationMessage message) {
|
||||
System.out.println(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(JsonObject object, MessageType type) {
|
||||
|
||||
}
|
||||
}, classpathManager, eventService, new EclipseWorkspaceProvider());
|
||||
mavenWorkspace = new MavenWorkspace(mavenProjectManager,
|
||||
mavenNotifier,
|
||||
new MavenExecutorService(),
|
||||
projectRegistryProvider,
|
||||
classpathManager,
|
||||
eventService,
|
||||
new EclipseWorkspaceProvider());
|
||||
EditorWorkingCopyManager editorWorkingCopyManager =
|
||||
new EditorWorkingCopyManager(projectManagerProvider, eventService, requestTransmitter);
|
||||
pomReconciler =
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public interface MavenAttributes {
|
|||
String PARENT_VERSION = "maven.parent.version";
|
||||
|
||||
String TEST_SOURCE_FOLDER = "maven.test.source.folder";
|
||||
String RESOURCE_FOLDER = "maven.resource.folder";
|
||||
String RESOURCE_FOLDER = "maven.resource.folder";
|
||||
|
||||
String DEFAULT_SOURCE_FOLDER = "src/main/java";
|
||||
String DEFAULT_RESOURCES_FOLDER = "src/main/resources";
|
||||
|
|
@ -50,6 +50,17 @@ public interface MavenAttributes {
|
|||
|
||||
/** Name of WebSocket chanel */
|
||||
String MAVEN_CHANEL_NAME = "maven:workspace";
|
||||
/** Name of WebSocket chanel for Maven Archetype output */
|
||||
String MAVEN_ARCHETYPE_CHANEL_NAME = "maven:archetype:output";
|
||||
|
||||
|
||||
String MAVEN_CHANEL_UNSUBSCRIBE = "mavenOutput/subscribe";
|
||||
String MAVEN_CHANEL_SUBSCRIBE = "mavenOutput/unsubscribe";
|
||||
String MAVEN_OUTPUT_TEXT_METHOD = "mavenOutput/text";
|
||||
String MAVEN_OUTPUT_UPDATE_METHOD = "mavenOutput/update";
|
||||
String MAVEN_OUTPUT_START_STOP_METHOD = "mavenOutput/start_stop";
|
||||
String MAVEN_OUTPUT_PERCENT_METHOD = "mavenOutput/percent";
|
||||
String MAVEN_OUTPUT_PERCENT_UNDEFINED_METHOD = "mavenOutput/percentUndefined";
|
||||
|
||||
String MAVEN_ARCHETYPE_CHANEL_UNSUBSCRIBE = "mavenArchetype/unsubscribe";
|
||||
String MAVEN_ARCHETYPE_CHANEL_SUBSCRIBE = "mavenArchetype/subscribe";
|
||||
String MAVEN_ARCHETYPE_CHANEL_OUTPUT = "mavenArchetype/output";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,4 +41,7 @@ public interface ArchetypeOutput {
|
|||
*/
|
||||
State getState();
|
||||
|
||||
void setOutput(String output);
|
||||
|
||||
void setState(State state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2017 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.maven.shared.dto;
|
||||
|
||||
import org.eclipse.che.dto.shared.DTO;
|
||||
import org.eclipse.che.plugin.maven.shared.event.MavenOutputEvent;
|
||||
|
||||
/**
|
||||
* DTO object which describes base maven output event.
|
||||
*/
|
||||
@DTO
|
||||
public interface MavenOutputEventDto extends MavenOutputEvent {
|
||||
|
||||
TYPE getType();
|
||||
|
||||
/** Returns a type of the output event. */
|
||||
void setType(TYPE type);
|
||||
|
||||
MavenOutputEventDto withType(TYPE type);
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import org.eclipse.che.dto.shared.DTO;
|
|||
* @author Evgen Vidolob
|
||||
*/
|
||||
@DTO
|
||||
@Deprecated
|
||||
public interface NotificationMessage {
|
||||
|
||||
String getText();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue