Skip to content

Commit

Permalink
CODENVY-31: Replaced messages from git importer on error codes
Browse files Browse the repository at this point in the history
Also added git checkout event which goes through by websocket connection
  • Loading branch information
akorneta committed Feb 22, 2016
1 parent 1e8714a commit 1feeae7
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 29 deletions.
4 changes: 4 additions & 0 deletions core/che-core-git-impl-native/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-vfs-impl</artifactId>
</dependency>
<dependency>
<groupId>org.everrest</groupId>
<artifactId>everrest-websockets</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ private ErrorCodes() {
public static final int NO_COMMITTER_NAME_OR_EMAIL_DEFINED = 15216;
public static final int UNABLE_GET_PRIVATE_SSH_KEY = 32068;
public static final int UNAUTHORIZED_GIT_OPERATION = 32080;
public static final int FAILED_CHECKOUT = 32063;
public static final int FAILED_CHECKOUT_WITH_START_POINT = 32064;
}
9 changes: 9 additions & 0 deletions core/platform-api/che-core-api-git/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,19 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-vfs-impl</artifactId>
</dependency>
<dependency>
<groupId>org.everrest</groupId>
<artifactId>everrest-websockets</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ protected void configure() {
bind(RemoteListWriter.class);
bind(StatusPageWriter.class);
bind(TagListWriter.class);
bind(GitWebSocketMessenger.class);

//bind(GitConnectionFactory.class).to(NativeGitConnectionFactory.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.model.project.SourceStorage;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.core.util.FileCleaner;
import org.eclipse.che.api.core.util.LineConsumerFactory;
import org.eclipse.che.api.git.shared.Branch;
import org.eclipse.che.api.git.shared.BranchListRequest;
import org.eclipse.che.api.git.shared.CheckoutRequest;
import org.eclipse.che.api.git.shared.CloneRequest;
import org.eclipse.che.api.git.shared.FetchRequest;
import org.eclipse.che.api.git.shared.GitCheckoutEvent;
import org.eclipse.che.api.git.shared.InitRequest;
import org.eclipse.che.api.git.shared.RemoteAddRequest;
import org.eclipse.che.api.project.server.FolderEntry;
Expand All @@ -45,23 +47,30 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static org.eclipse.che.api.core.ErrorCodes.FAILED_CHECKOUT;
import static org.eclipse.che.api.core.ErrorCodes.FAILED_CHECKOUT_WITH_START_POINT;
import static org.eclipse.che.api.git.shared.BranchListRequest.LIST_ALL;

/**
* @author Vladyslav Zhukovskii
*/
@Singleton
public class GitProjectImporter implements ProjectImporter {
private static final Logger LOG = LoggerFactory.getLogger(GitProjectImporter.class);

private final GitConnectionFactory gitConnectionFactory;
private final LocalPathResolver localPathResolver;
private static final Logger LOG = LoggerFactory.getLogger(GitProjectImporter.class);
private final EventService eventService;

@Inject
public GitProjectImporter(GitConnectionFactory gitConnectionFactory, LocalPathResolver localPathResolver) {
public GitProjectImporter(GitConnectionFactory gitConnectionFactory,
LocalPathResolver localPathResolver,
EventService eventService) {
this.gitConnectionFactory = gitConnectionFactory;
this.localPathResolver = localPathResolver;
this.eventService = eventService;
}

@Override
Expand Down Expand Up @@ -136,14 +145,11 @@ public void importSources(FolderEntry baseFolder,
final String localPath = localPathResolver.resolve((VirtualFileImpl)baseFolder.getVirtualFile());
final DtoFactory dtoFactory = DtoFactory.getInstance();
final String location = storage.getLocation();
// it's needed for extract repository name from repository url e.g https://github.com/codenvy/che-core.git
// lastIndexOf('/') + 1 for not to capture slash and length - 4 for trim .git
final String repositoryName = location.substring(location.lastIndexOf('/') + 1, location.length() - 4);
if (keepDirectory != null) {
final File temp = Files.createTempDirectory(null).toFile();
try {
git = gitConnectionFactory.getConnection(temp, consumerFactory);
sparsecheckout(git, location, branch == null ? "master" : branch, startPoint, repositoryName, keepDirectory, dtoFactory);
sparsecheckout(git, location, branch == null ? "master" : branch, startPoint, keepDirectory, dtoFactory);
// Copy content of directory to the project folder.
final File projectDir = new File(localPath);
IoUtil.copy(temp, projectDir, IoUtil.ANY_FILTER);
Expand All @@ -160,10 +166,10 @@ public void importSources(FolderEntry baseFolder,
git.getConfig().add("remote.origin.fetch", remoteOriginFetch);
fetch(git, "origin", dtoFactory);
if (branch != null) {
checkoutBranch(git, branch, startPoint, repositoryName, dtoFactory);
checkoutBranch(git, branch, startPoint, dtoFactory);
}
} else if (branch != null) {
checkoutBranch(git, branch, startPoint, repositoryName, dtoFactory);
checkoutBranch(git, branch, startPoint, dtoFactory);
}
} else {
initRepository(git, dtoFactory);
Expand All @@ -175,14 +181,14 @@ public void importSources(FolderEntry baseFolder,
git.getConfig().add("remote.origin.fetch", remoteOriginFetch);
fetch(git, "origin", dtoFactory);
if (branch != null) {
checkoutBranch(git, branch, startPoint, repositoryName, dtoFactory);
checkoutBranch(git, branch, startPoint, dtoFactory);
}
} else {
fetchBranch(git, "origin", branch == null ? "*" : branch, dtoFactory);

List<Branch> branchList = git.branchList(dtoFactory.createDto(BranchListRequest.class).withListMode("r"));
if (!branchList.isEmpty()) {
checkoutBranch(git, branch == null ? "master" : branch, startPoint, repositoryName, dtoFactory);
checkoutBranch(git, branch == null ? "master" : branch, startPoint, dtoFactory);
}
}
}
Expand All @@ -193,7 +199,7 @@ public void importSources(FolderEntry baseFolder,
cleanGit(git.getWorkingDir());
}
}
} catch (URISyntaxException e) {
} catch (URISyntaxException e) {
throw new ServerException(
"Your project cannot be imported. The issue is either from git configuration, a malformed URL, " +
"or file system corruption. Please contact support for assistance.",
Expand Down Expand Up @@ -262,37 +268,34 @@ private void checkoutCommit(GitConnection git, String commit, DtoFactory dtoFact
private void checkoutBranch(GitConnection git,
String branchName,
String startPoint,
String repositoryName,
DtoFactory dtoFactory) throws GitException {
final CheckoutRequest request = dtoFactory.createDto(CheckoutRequest.class).withName(branchName);
final boolean branchExist = git.branchList(dtoFactory.createDto(BranchListRequest.class).withListMode(LIST_ALL))
.stream()
.anyMatch(branch -> branch.getName().equals(branchName));
final GitCheckoutEvent checkout = dtoFactory.createDto(GitCheckoutEvent.class);
if (startPoint != null) {
if (branchExist) {
git.checkout(request);

eventService.publish(checkout.withCheckoutOnly(true)
.withBranchRef(getRemoteBranch(dtoFactory, git, branchName)));
} else {
checkoutAndRethrow(git,
request.withCreateNew(true).withStartPoint(startPoint),
String.format("Cannot find remote branch %s and start point %s in repo %s",
branchName,
startPoint,
repositoryName));
checkoutAndRethrow(git, request.withCreateNew(true).withStartPoint(startPoint), FAILED_CHECKOUT_WITH_START_POINT);
eventService.publish(checkout.withCheckoutOnly(false));
}
} else {
checkoutAndRethrow(git,
request,
String.format("Cannot find remote branch %s in repo %s and start point undefined",
branchName,
repositoryName));
checkoutAndRethrow(git, request, FAILED_CHECKOUT);
eventService.publish(checkout.withCheckoutOnly(true)
.withBranchRef(getRemoteBranch(dtoFactory, git, branchName)));
}
}

private void checkoutAndRethrow(GitConnection git, CheckoutRequest request, String errorMessage) throws GitException {
private void checkoutAndRethrow(GitConnection git, CheckoutRequest request, int errorCode) throws GitException {
try {
git.checkout(request);
} catch (GitException ex) {
throw new GitException(errorMessage, ex);
throw new GitException(ex.getMessage(), errorCode);
}
}

Expand All @@ -301,7 +304,6 @@ private void sparsecheckout(GitConnection git,
String branch,
String startPoint,
String directory,
String repositoryName,
DtoFactory dtoFactory)
throws GitException, UnauthorizedException {
/*
Expand All @@ -323,11 +325,20 @@ private void sparsecheckout(GitConnection git,
throw new GitException(e);
}
fetchBranch(git, "origin", branch, dtoFactory);
checkoutBranch(git, branch, startPoint, repositoryName, dtoFactory);
checkoutBranch(git, branch, startPoint, dtoFactory);
}

private void cleanGit(File project) {
IoUtil.deleteRecursive(new File(project, ".git"));
new File(project, ".gitignore").delete();
}

private String getRemoteBranch(DtoFactory dtoFactory, GitConnection git, String branchName) throws GitException {
final List<Branch> remotes = git.branchList(dtoFactory.createDto(BranchListRequest.class)
.withListMode(BranchListRequest.LIST_REMOTE));
final Optional<Branch> first = remotes.stream()
.filter(br -> branchName.equals(br.getDisplayName()))
.findFirst();
return first.get().getName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2012-2016 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.api.git;

import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.core.notification.EventSubscriber;
import org.eclipse.che.api.git.shared.GitCheckoutEvent;
import org.eclipse.che.dto.server.DtoFactory;
import org.everrest.websockets.WSConnectionContext;
import org.everrest.websockets.message.ChannelBroadcastMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;

/**
* @author Anton Korneta.
*/
@Singleton
public class GitWebSocketMessenger implements EventSubscriber<GitCheckoutEvent> {
private static final Logger LOG = LoggerFactory.getLogger(GitWebSocketMessenger.class);
private static final String CHANNEL = "git:events:channel";

private final EventService eventService;

@Inject
public GitWebSocketMessenger(EventService eventService) {
this.eventService = eventService;
}

@PostConstruct
private void subscribe() {
eventService.subscribe(this);
}

@PreDestroy
private void unsubscribe() {
eventService.unsubscribe(this);
}

@Override
public void onEvent(GitCheckoutEvent event) {
try {
final ChannelBroadcastMessage bm = new ChannelBroadcastMessage();
bm.setChannel(CHANNEL);
bm.setBody(DtoFactory.getInstance().toJson(event));
WSConnectionContext.sendMessage(bm);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2012-2016 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.api.git.shared;

import org.eclipse.che.api.core.notification.EventOrigin;
import org.eclipse.che.dto.shared.DTO;

/**
* @author Anton Korneta.
*/
@EventOrigin("gitcheckout")
@DTO
public interface GitCheckoutEvent {

boolean isCheckoutOnly();

void setCheckoutOnly(boolean checkoutOnly);

GitCheckoutEvent withCheckoutOnly(boolean checkoutOnly);

String getBranchRef();

void setBranchRef(String branchRef);

GitCheckoutEvent withBranchRef(String branchRef);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.che.ide.ext.github.server;

import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.git.GitConnectionFactory;
import org.eclipse.che.api.git.GitProjectImporter;
import org.eclipse.che.vfs.impl.fs.LocalPathResolver;
Expand All @@ -24,8 +25,9 @@ public class GitHubProjectImporter extends GitProjectImporter {

@Inject
public GitHubProjectImporter(GitConnectionFactory gitConnectionFactory,
LocalPathResolver localPathResolver) {
super(gitConnectionFactory, localPathResolver);
LocalPathResolver localPathResolver,
EventService eventService) {
super(gitConnectionFactory, localPathResolver, eventService);
}

@Override
Expand Down

0 comments on commit 1feeae7

Please sign in to comment.