/*******************************************************************************
* 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.pullrequest.client.steps;
import org.eclipse.che.plugin.pullrequest.client.ContributeMessages;
import org.eclipse.che.plugin.pullrequest.client.vcs.VcsServiceProvider;
import org.eclipse.che.plugin.pullrequest.client.workflow.Context;
import org.eclipse.che.plugin.pullrequest.client.workflow.Step;
import org.eclipse.che.plugin.pullrequest.client.workflow.WorkflowExecutor;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.assistedinject.Assisted;
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 javax.inject.Inject;
import java.util.List;
/**
* Adds the forked remote repository to the remotes of the project.
*/
public class AddForkRemoteStep implements Step {
private final static String ORIGIN_REMOTE_NAME = "origin";
private final static String FORK_REMOTE_NAME = "fork";
private final Step delegate;
private final String remoteUrl;
private final VcsServiceProvider vcsServiceProvider;
private final ContributeMessages messages;
@Inject
public AddForkRemoteStep(@Assisted("delegate") Step delegate,
@Assisted("remoteUrl") String remoteUrl,
final VcsServiceProvider vcsServiceProvider,
final ContributeMessages messages) {
this.delegate = delegate;
this.remoteUrl = remoteUrl;
this.vcsServiceProvider = vcsServiceProvider;
this.messages = messages;
}
@Override
public void execute(final WorkflowExecutor executor, final Context context) {
final String originRepositoryOwner = context.getOriginRepositoryOwner();
final String originRepositoryName = context.getOriginRepositoryName();
final String upstreamRepositoryOwner = context.getUpstreamRepositoryOwner();
final String upstreamRepositoryName = context.getUpstreamRepositoryName();
// the fork remote has to be added only if we cloned the upstream else it's origin
if (originRepositoryOwner.equalsIgnoreCase(upstreamRepositoryOwner) &&
originRepositoryName.equalsIgnoreCase(upstreamRepositoryName)) {
checkRemotePresent(executor, context, remoteUrl);
} else {
context.setForkedRemoteName(ORIGIN_REMOTE_NAME);
proceed(executor, context);
}
}
private void checkRemotePresent(final WorkflowExecutor executor, final Context context, final String remoteUrl) {
vcsServiceProvider.getVcsService(context.getProject()).listRemotes(context.getProject())
.then(new Operation<List<Remote>>() {
@Override
public void apply(List<Remote> result) throws OperationException {
for (final Remote remote : result) {
if (FORK_REMOTE_NAME.equals(remote.getName())) {
context.setForkedRemoteName(FORK_REMOTE_NAME);
if (remoteUrl.equals(remote.getUrl())) {
// all is correct, continue
proceed(executor, context);
} else {
replaceRemote(executor, context, remoteUrl);
}
// leave the method, do not go to addRemote(...)
return;
}
}
addRemote(executor, context, remoteUrl);
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError arg) throws OperationException {
executor.fail(delegate, context, messages.stepAddForkRemoteErrorCheckRemote());
}
});
}
/**
* Add the remote to the project.
*
* @param executor
* the {@link WorkflowExecutor}.
* @param remoteUrl
* the url of the remote
*/
private void addRemote(final WorkflowExecutor executor, final Context context, final String remoteUrl) {
vcsServiceProvider.getVcsService(context.getProject())
.addRemote(context.getProject(), FORK_REMOTE_NAME, remoteUrl, new AsyncCallback<Void>() {
@Override
public void onSuccess(final Void notUsed) {
context.setForkedRemoteName(FORK_REMOTE_NAME);
proceed(executor, context);
}
@Override
public void onFailure(final Throwable exception) {
executor.fail(delegate, context, messages.stepAddForkRemoteErrorAddFork());
}
});
}
/**
* Removes the fork remote from the project before adding it with the correct URL.
*
* @param executor
* the {@link WorkflowExecutor}.
* @param remoteUrl
* the url of the remote
*/
private void replaceRemote(final WorkflowExecutor executor, final Context context, final String remoteUrl) {
vcsServiceProvider.getVcsService(context.getProject())
.deleteRemote(context.getProject(), FORK_REMOTE_NAME, new AsyncCallback<Void>() {
@Override
public void onSuccess(final Void result) {
addRemote(executor, context, remoteUrl);
}
@Override
public void onFailure(final Throwable caught) {
executor.fail(delegate,
context,
messages.stepAddForkRemoteErrorSetForkedRepositoryRemote());
}
});
}
private void proceed(final WorkflowExecutor executor, final Context context) {
executor.done(delegate, context);
}
}