diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsHandler.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsHandler.java index 47c5bbfe71f..506b8ee9aa7 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsHandler.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsHandler.java @@ -16,12 +16,15 @@ import java.util.Set; import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator; import org.eclipse.che.api.git.shared.FileChangedEventDto; +import org.eclipse.che.api.git.shared.RepositoryDeletedEventDto; +import org.eclipse.che.api.git.shared.RepositoryInitializedEventDto; import org.eclipse.che.api.git.shared.StatusChangedEventDto; import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; /** - * Receives git events from server side. To avoid a risk of IDE slow down this handler bypasses - * event bus because of heavy load. + * Receives git events from server side. + * + *

To avoid a risk of IDE slow down this handler bypasses event bus because of heavy load. * * @author Igor Vinokur * @author Mykola Morhun @@ -30,8 +33,10 @@ public class GitEventsHandler implements GitEventSubscribable { private static final String EVENT_GIT_FILE_CHANGED = "event/git-change"; - private static final String EVENT_GIT_STATUS_CHANGED = "event/git/statusChanged"; + private static final String EVENT_GIT_STATUS_CHANGED = "event/git/status-changed"; private static final String EVENT_GIT_CHECKOUT = "event/git-checkout"; + private static final String EVENT_GIT_REPOSITORY_INITIALIZED = "event/git/initialized"; + private static final String EVENT_GIT_REPOSITORY_DELETED = "event/git/deleted"; private final Set subscribers = new HashSet<>(); @@ -61,6 +66,20 @@ private void configureHandlers(RequestHandlerConfigurator configurator) { .paramsAsDto(GitCheckoutEventDto.class) .noResult() .withBiConsumer(this::onCheckoutHandler); + + configurator + .newConfiguration() + .methodName(EVENT_GIT_REPOSITORY_INITIALIZED) + .paramsAsDto(RepositoryInitializedEventDto.class) + .noResult() + .withBiConsumer(this::onRepositoryInitializedHandler); + + configurator + .newConfiguration() + .methodName(EVENT_GIT_REPOSITORY_DELETED) + .paramsAsDto(RepositoryDeletedEventDto.class) + .noResult() + .withBiConsumer(this::onRepositoryDeletedHandler); } private void onFileChangedHandler(String endpointId, FileChangedEventDto fileChangedEventDto) { @@ -82,6 +101,20 @@ private void onCheckoutHandler(String endpointId, GitCheckoutEventDto gitCheckou } } + private void onRepositoryInitializedHandler( + String endpointId, RepositoryInitializedEventDto repositoryInitializedEvent) { + for (GitEventsSubscriber subscriber : subscribers) { + subscriber.onGitRepositoryInitialized(endpointId, repositoryInitializedEvent); + } + } + + private void onRepositoryDeletedHandler( + String endpointId, RepositoryDeletedEventDto repositoryDeletedEvent) { + for (GitEventsSubscriber subscriber : subscribers) { + subscriber.onGitRepositoryDeleted(endpointId, repositoryDeletedEvent); + } + } + @Override public void addSubscriber(GitEventsSubscriber subscriber) { subscribers.add(subscriber); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsSubscriber.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsSubscriber.java index e4054adc761..00ee85a871e 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsSubscriber.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitEventsSubscriber.java @@ -11,6 +11,8 @@ package org.eclipse.che.ide.ext.git.client; import org.eclipse.che.api.git.shared.FileChangedEventDto; +import org.eclipse.che.api.git.shared.RepositoryDeletedEventDto; +import org.eclipse.che.api.git.shared.RepositoryInitializedEventDto; import org.eclipse.che.api.git.shared.StatusChangedEventDto; import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; @@ -22,7 +24,7 @@ public interface GitEventsSubscriber { /** Invoked when a project file was changed */ - void onFileChanged(String endpointId, FileChangedEventDto dto); + default void onFileChanged(String endpointId, FileChangedEventDto dto) {} // TODO change method name or behaviour. It is not git status actually. // For example, this even won't be fired when: @@ -31,8 +33,16 @@ public interface GitEventsSubscriber { // - delete a committed file // And maybe some others /** Invoked when git status of project was changed */ - void onGitStatusChanged(String endpointId, StatusChangedEventDto dto); + default void onGitStatusChanged(String endpointId, StatusChangedEventDto dto) {} /** Invoked when git checkout was performed */ - void onGitCheckout(String endpointId, GitCheckoutEventDto dto); + default void onGitCheckout(String endpointId, GitCheckoutEventDto dto) {} + + /** Invoked when git repository was initialized inside an existing project. */ + default void onGitRepositoryInitialized( + String endpointId, RepositoryInitializedEventDto gitRepositoryInitializedEventDto) {} + + /** Invoked when git repository was deleted inside an existing project. */ + default void onGitRepositoryDeleted( + String endpointId, RepositoryDeletedEventDto repositoryDeletedEventDto) {} } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitExtension.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitExtension.java index 4f589b9adbf..eb514d8895c 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitExtension.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitExtension.java @@ -101,6 +101,7 @@ public GitExtension( KeyBindingAgent keyBinding) { resources.gitCSS().ensureInjected(); + resources.gitPanelCss().ensureInjected(); DefaultActionGroup mainMenu = (DefaultActionGroup) actionManager.getAction(GROUP_MAIN_MENU); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.java index f2ec23c407a..681a9940006 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.java @@ -652,13 +652,16 @@ public interface GitLocalizationConstant extends Messages { @Key("checkout.reference.message") String checkoutReferenceMessage(); - // Panel + /* Panel */ @Key("panel.title") String panelTitle(); @Key("panel.title.tooltip") String panelTitleToolTip(); + @Key("panel.repositories") + String repositories(); + /* Controls */ @Key("control.branches.title") String branchesControlTitle(); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitResources.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitResources.java index 86ca607cd95..b8466181e49 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitResources.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/GitResources.java @@ -33,6 +33,23 @@ interface GitCSS extends CssResource { String spacing(); } + interface GitPanelCss extends CssResource { + @ClassName("git-panel-full-height") + String fullHeight(); + + @ClassName("git-panel-panel-top-indent") + String topIndent(); + + @ClassName("git-panel-panel-bottom-indent") + String bottomIndent(); + + @ClassName("git-panel-vertical-items") + String verticalItems(); + + @ClassName("git-panel-repository-changes-label") + String repositoryChangesLabel(); + } + interface Css extends CssResource { String insertion(); @@ -50,12 +67,21 @@ interface Css extends CssResource { @Source({"git.css", "org/eclipse/che/ide/api/ui/style.css"}) GitCSS gitCSS(); + @Source("panel/gitPanel.css") + GitPanelCss gitPanelCss(); + @Source({"changeMarkers.css", "org/eclipse/che/ide/api/ui/style.css"}) Css changeMarkersCSS(); @Source("panel/git.svg") SVGResource git(); + @Source("panel/git-logo.svg") + SVGResource gitLogo(); + + @Source("panel/repository.svg") + SVGResource repository(); + @Source("push/arrow.svg") SVGResource arrow(); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/MutableAlteredFiles.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/MutableAlteredFiles.java index 6f9892e7e43..14f9428ded9 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/MutableAlteredFiles.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/MutableAlteredFiles.java @@ -30,6 +30,18 @@ public MutableAlteredFiles(Project project, String diff) { super(project, diff); } + /** + * Created mutable altered files list based on changes from another project. + * + * @param project the project under diff operation + * @param alteredFiles changes from another project + */ + public MutableAlteredFiles(Project project, AlteredFiles alteredFiles) { + super(project, ""); + this.alteredFilesStatuses.putAll(alteredFiles.alteredFilesStatuses); + this.alteredFilesList.addAll(alteredFiles.alteredFilesList); + } + /** * Creates an empty list of altered files. * @@ -40,7 +52,7 @@ public MutableAlteredFiles(Project project) { } /** - * Adds a file to altered file list. If given file is already exists + * Adds a file to altered file list. If given file is already exists does nothing. * * @param file full path to file and its name relatively to project root * @param status git status of the file @@ -57,10 +69,10 @@ public boolean addFile(String file, Status status) { } /** - * Removes given file from the altered files list. + * Removes given file from the altered files list. If given file isn't present does nothing. * * @param file full path to file and its name relatively to project root - * @return true if the file as deleted and false otherwise + * @return true if the file was deleted and false otherwise */ public boolean removeFile(String file) { alteredFilesStatuses.remove(file); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/changespanel/ChangesPanelPresenter.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/changespanel/ChangesPanelPresenter.java index 7409b373960..c1a8d7fcd5a 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/changespanel/ChangesPanelPresenter.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/compare/changespanel/ChangesPanelPresenter.java @@ -53,7 +53,7 @@ public ChangesPanelPresenter( * Show panel with changed files. If empty map with changed files is received, all buttons would * be disabled. * - * @param changedFiles Map with files and their status + * @param changedFiles altered files to show */ public void show(AlteredFiles changedFiles) { this.changedFiles = changedFiles; diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/inject/GitGinModule.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/inject/GitGinModule.java index 8c3a122f91a..7120c61cf08 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/inject/GitGinModule.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/inject/GitGinModule.java @@ -50,6 +50,7 @@ import org.eclipse.che.ide.ext.git.client.outputconsole.GitOutputPartViewImpl; import org.eclipse.che.ide.ext.git.client.panel.GitPanelView; import org.eclipse.che.ide.ext.git.client.panel.GitPanelViewImpl; +import org.eclipse.che.ide.ext.git.client.panel.RepositoryNodeFactory; import org.eclipse.che.ide.ext.git.client.plugins.EditorTabsColorizer; import org.eclipse.che.ide.ext.git.client.plugins.GitChangeMarkerManager; import org.eclipse.che.ide.ext.git.client.plugins.ProjectExplorerTreeColorizer; @@ -116,6 +117,7 @@ protected void configure() { new GinFactoryModuleBuilder() .implement(GitOutputConsole.class, GitOutputConsolePresenter.class) .build(GitOutputConsoleFactory.class)); + install(new GinFactoryModuleBuilder().build(RepositoryNodeFactory.class)); bind(GitEventsHandler.class).asEagerSingleton(); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelPresenter.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelPresenter.java index ef5a19fce3d..2ff8636af17 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelPresenter.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelPresenter.java @@ -13,12 +13,19 @@ import static org.eclipse.che.api.git.shared.DiffType.NAME_STATUS; import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.NOT_EMERGE_MODE; import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL; +import static org.eclipse.che.ide.api.resources.ResourceDelta.MOVED_FROM; +import static org.eclipse.che.ide.api.resources.ResourceDelta.MOVED_TO; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.IsWidget; import com.google.inject.Inject; import com.google.inject.Singleton; +import com.google.web.bindery.event.shared.EventBus; +import java.util.HashMap; +import java.util.Map; import org.eclipse.che.api.git.shared.FileChangedEventDto; +import org.eclipse.che.api.git.shared.RepositoryDeletedEventDto; +import org.eclipse.che.api.git.shared.RepositoryInitializedEventDto; import org.eclipse.che.api.git.shared.StatusChangedEventDto; import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; import org.eclipse.che.ide.api.app.AppContext; @@ -28,6 +35,10 @@ import org.eclipse.che.ide.api.parts.WorkspaceAgent; import org.eclipse.che.ide.api.parts.base.BasePresenter; import org.eclipse.che.ide.api.resources.Project; +import org.eclipse.che.ide.api.resources.Resource; +import org.eclipse.che.ide.api.resources.ResourceChangedEvent; +import org.eclipse.che.ide.api.resources.ResourceChangedEvent.ResourceChangedHandler; +import org.eclipse.che.ide.api.resources.ResourceDelta; import org.eclipse.che.ide.ext.git.client.GitEventSubscribable; import org.eclipse.che.ide.ext.git.client.GitEventsSubscriber; import org.eclipse.che.ide.ext.git.client.GitLocalizationConstant; @@ -45,20 +56,24 @@ */ @Singleton public class GitPanelPresenter extends BasePresenter - implements GitPanelView.ActionDelegate, GitEventsSubscriber { + implements GitPanelView.ActionDelegate, GitEventsSubscriber, ResourceChangedHandler { + private static final String VCS_GIT = "git"; private static final String REVISION = "HEAD"; private final GitPanelView view; private final GitServiceClient service; private final ChangesPanelPresenter changesPanelPresenter; private final AppContext appContext; + private final EventBus eventBus; private final NotificationManager notificationManager; + private final GitEventSubscribable subscribeToGitEvents; private final GitResources gitResources; private final GitLocalizationConstant locale; - private Project currentProject; - private MutableAlteredFiles alteredFiles; + private boolean initialized; + private Map changes; + private String selectedProjectName; @Inject public GitPanelPresenter( @@ -67,6 +82,7 @@ public GitPanelPresenter( ChangesPanelPresenter changesPanelPresenter, WorkspaceAgent workspaceAgent, AppContext appContext, + EventBus eventBus, GitEventSubscribable subscribeToGitEvents, NotificationManager notificationManager, GitResources gitResources, @@ -75,6 +91,8 @@ public GitPanelPresenter( this.service = service; this.changesPanelPresenter = changesPanelPresenter; this.appContext = appContext; + this.eventBus = eventBus; + this.subscribeToGitEvents = subscribeToGitEvents; this.notificationManager = notificationManager; this.gitResources = gitResources; this.locale = locale; @@ -82,38 +100,54 @@ public GitPanelPresenter( this.view.setDelegate(this); this.view.setChangesPanelView(this.changesPanelPresenter.getView()); - this.currentProject = appContext.getRootProject(); - this.alteredFiles = new MutableAlteredFiles(currentProject); - if (partStack == null || !partStack.containsPart(this)) { workspaceAgent.openPart(this, PartStackType.NAVIGATION); } + this.initialized = false; + } + + private void registerEventHandlers() { + eventBus.addHandler(ResourceChangedEvent.getType(), this); + subscribeToGitEvents.addSubscriber(this); } /** Invoked each time when panel is activated. */ @Override public void onOpen() { - // Update file list according to project explorer selection - Project selectedProject = appContext.getRootProject(); + if (!initialized) { + loadPanelData(); + registerEventHandlers(); - if (selectedProject == null) { - updateChangedFiles(null); - return; - } else if (selectedProject != currentProject) { - currentProject = selectedProject; - reloadChangedFilesList(); + initialized = true; + } + } + + /** Queries from server all data needed to initialize the panel. */ + private void loadPanelData() { + this.changes = new HashMap<>(); + + for (Project project : appContext.getProjects()) { + if (projectUnderGit(project)) { + view.addRepository(project.getName()); + reloadRepositoryData(project); + } } } - private void reloadChangedFilesList() { + private void reloadRepositoryData(Project project) { service - .diff(currentProject.getLocation(), null, NAME_STATUS, false, 0, REVISION, false) + .diff(project.getLocation(), null, NAME_STATUS, false, 0, REVISION, false) .then( diff -> { - alteredFiles = new MutableAlteredFiles(currentProject, diff); - updateChangedFiles(alteredFiles); + MutableAlteredFiles alteredFiles = new MutableAlteredFiles(project, diff); + changes.put(project.getName(), alteredFiles); + view.updateRepositoryChanges(project.getName(), alteredFiles.getFilesQuantity()); + // update changed files list if this repository is selected + if (project.getName().equals(view.getSelectedRepository())) { + updateChangedFiles(alteredFiles); + } }) .catchError( arg -> { @@ -121,10 +155,6 @@ private void reloadChangedFilesList() { }); } - private void updateChangedFiles(AlteredFiles alteredFiles) { - changesPanelPresenter.show(alteredFiles); - } - @Override public String getTitle() { return locale.panelTitle(); @@ -164,15 +194,24 @@ public boolean isOpened() { @Override public void onFileChanged(String endpointId, FileChangedEventDto dto) { + String projectName = extractProjectName(dto.getPath()); + MutableAlteredFiles alteredFiles = changes.get(projectName); + switch (dto.getStatus()) { case MODIFIED: if (alteredFiles.addFile(removeProjectName(dto.getPath()), Status.MODIFIED)) { - updateChangedFiles(alteredFiles); + view.updateRepositoryChanges(projectName, alteredFiles.getFilesQuantity()); + if (projectName.equals(selectedProjectName)) { + updateChangedFiles(alteredFiles); + } } break; case NOT_MODIFIED: if (alteredFiles.removeFile(removeProjectName(dto.getPath()))) { - updateChangedFiles(alteredFiles); + view.updateRepositoryChanges(projectName, alteredFiles.getFilesQuantity()); + if (projectName.equals(selectedProjectName)) { + updateChangedFiles(alteredFiles); + } } break; default: @@ -180,18 +219,128 @@ public void onFileChanged(String endpointId, FileChangedEventDto dto) { } } + /** Handles creation and deletion of projects. */ + @Override + public void onResourceChanged(ResourceChangedEvent event) { + ResourceDelta delta = event.getDelta(); + Resource resource = delta.getResource(); + if (resource.isProject() && resource.getLocation().segmentCount() == 1) { + // resource is a root project + if (projectUnderGit(resource.asProject())) { + if (delta.getKind() == ResourceDelta.ADDED) { + if ((delta.getFlags() & (MOVED_FROM | MOVED_TO)) != 0) { + // project renamed + String oldProjectName = delta.getFromPath().segment(0); + String newProjectName = delta.getToPath().segment(0); + MutableAlteredFiles alteredFiles = + new MutableAlteredFiles( + findProjectByName(newProjectName), changes.remove(oldProjectName)); + + changes.put(newProjectName, alteredFiles); + // TODO uncomment rename and delete code below after fixing of events problem: + // It is fired: Added at first, then Renamed for project under rename + // view.renameRepository(oldProjectName, newProjectName); + view.removeRepository(oldProjectName); + view.updateRepositoryChanges(newProjectName, alteredFiles.getFilesQuantity()); + } else { + // TODO delete this if statement code. There is a bug when Create project event is fired + // twice. + if (changes.containsKey(resource.getName())) { + return; + } + + // project created + changes.put(resource.getName(), new MutableAlteredFiles(resource.asProject())); + view.addRepository(resource.getName()); + } + } else if (delta.getKind() == ResourceDelta.REMOVED) { + // project deleted + changes.remove(resource.getName()); + view.removeRepository(resource.getName()); + } + } + } + } + + @Override + public void onGitRepositoryInitialized( + String endpointId, RepositoryInitializedEventDto repositoryInitializedEventDto) { + String projectName = repositoryInitializedEventDto.getProjectName(); + changes.put(projectName, new MutableAlteredFiles(findProjectByName(projectName))); + view.addRepository(projectName); + } + + @Override + public void onGitRepositoryDeleted( + String endpointId, RepositoryDeletedEventDto repositoryDeletedEventDto) { + String projectName = repositoryDeletedEventDto.getProjectName(); + changes.remove(projectName); + view.removeRepository(projectName); + } + @Override public void onGitStatusChanged(String endpointId, StatusChangedEventDto dto) { - reloadChangedFilesList(); + updateRepositoryData(dto.getProjectName()); } @Override public void onGitCheckout(String endpointId, GitCheckoutEventDto dto) { - reloadChangedFilesList(); + // this update is needed to correctly handle checkout with force + updateRepositoryData(dto.getProjectName()); } /** Removes first segment from given path. */ private String removeProjectName(String path) { return path.substring(path.indexOf('/', 1) + 1); } + + /** Returns name of project in which given file is located. */ + private String extractProjectName(String path) { + return path.substring(1, path.indexOf('/', 1)); + } + + @Override + public void onRepositorySelectionChanged(String selectedProjectName) { + this.selectedProjectName = selectedProjectName; + if (selectedProjectName == null) { + updateChangedFiles(new MutableAlteredFiles(null)); + return; + } + + AlteredFiles alteredFilesToShow = changes.get(selectedProjectName); + if (alteredFilesToShow == null) { + alteredFilesToShow = new MutableAlteredFiles(null); + } + updateChangedFiles(alteredFilesToShow); + } + + private void updateChangedFiles(AlteredFiles alteredFiles) { + changesPanelPresenter.show(alteredFiles); + } + + /** + * Reloads information about specified project and updates the panel. Does nothing if project is + * not under git or doesn't exist. + */ + private void updateRepositoryData(String projectName) { + Project project = findProjectByName(projectName); + if (project != null && projectUnderGit(project)) { + reloadRepositoryData(project); + } + } + + /** Returns project by its name or null if project with specified name doesn't exist. */ + private Project findProjectByName(String projectName) { + for (Project project : appContext.getProjects()) { + if (projectName.equals(project.getName())) { + return project; + } + } + return null; + } + + /** Returns true if given project is under git version control system, false otherwise. */ + private boolean projectUnderGit(Project project) { + return VCS_GIT.equals(project.getAttribute("vcs.provider.name")); + } } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelView.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelView.java index b39c1d01755..3f0e07ada9e 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelView.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelView.java @@ -17,8 +17,51 @@ /** @author Mykola Morhun */ public interface GitPanelView extends View { + /** + * Adds new repository into the repositories list. + * + * @param repository new repository + */ + void addRepository(String repository); + + /** + * Removes given repository from panel. + * + * @param repository name of repository to remove from panel + */ + void removeRepository(String repository); + + /** + * Changes repository title in the git panel. + * + * @param oldRepositoryName name of repository before rename + * @param newRepositoryName name of repository after rename + */ + void renameRepository(String oldRepositoryName, String newRepositoryName); + + /** + * Updates label with changes number of the specified repository. + * + * @param repository name of repository + * @param changes number of changed files in the git repository + */ + void updateRepositoryChanges(String repository, int changes); + + /** + * Returns repository which is selected in the repositories list. If nothing selected null will be + * returned. + */ + String getSelectedRepository(); + /** Embed changed files panel ui */ void setChangesPanelView(ChangesPanelView changesPanelView); - interface ActionDelegate extends BaseActionDelegate {} + interface ActionDelegate extends BaseActionDelegate { + + /** + * Invoked each time when user changes selection in repositories list. Returns null if no + * selected items. + */ + void onRepositorySelectionChanged(String selectedRepository); + } } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.java index 3494a70942a..db80828d4d1 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.java @@ -10,32 +10,134 @@ */ package org.eclipse.che.ide.ext.git.client.panel; +import static com.google.common.collect.Iterables.getFirst; + import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; +import java.util.Comparator; +import java.util.List; import javax.inject.Inject; +import org.eclipse.che.ide.api.data.tree.Node; import org.eclipse.che.ide.api.parts.PartStackUIResources; import org.eclipse.che.ide.api.parts.base.BaseView; +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.compare.changespanel.ChangesPanelView; import org.eclipse.che.ide.ext.git.client.panel.GitPanelView.ActionDelegate; +import org.eclipse.che.ide.ui.smartTree.NodeLoader; +import org.eclipse.che.ide.ui.smartTree.NodeStorage; +import org.eclipse.che.ide.ui.smartTree.NodeStorage.StoreSortInfo; +import org.eclipse.che.ide.ui.smartTree.SelectionModel; +import org.eclipse.che.ide.ui.smartTree.SortDir; +import org.eclipse.che.ide.ui.smartTree.Tree; /** @author Mykola Morhun */ public class GitPanelViewImpl extends BaseView implements GitPanelView { interface GitPanelViewImplUiBinder extends UiBinder {} - @UiField FlowPanel changesPanel; + @UiField SimplePanel changesPanel; + + @UiField(provided = true) + final GitResources gitResources; + + @UiField(provided = true) + final GitLocalizationConstant locale; + + @UiField(provided = true) + Tree repositoriesList; + + private final RepositoryNodeFactory repositoryNodeFactory; @Inject public GitPanelViewImpl( - PartStackUIResources resources, GitPanelViewImpl.GitPanelViewImplUiBinder uiBinder) { + GitPanelViewImplUiBinder uiBinder, + RepositoryNodeFactory repositoryNodeFactory, + PartStackUIResources resources, + GitResources gitResources, + GitLocalizationConstant locale) { super(resources); + this.repositoryNodeFactory = repositoryNodeFactory; + this.gitResources = gitResources; + this.locale = locale; + + createRepositoriesList(); setContentWidget(uiBinder.createAndBindUi(this)); } + private void createRepositoriesList() { + NodeStorage nodeStorage = new NodeStorage(); + NodeLoader nodeLoader = new NodeLoader(); + repositoriesList = new Tree(nodeStorage, nodeLoader); + repositoriesList.getElement().getStyle().setProperty("maxHeight", "200px"); + repositoriesList + .getNodeStorage() + .addSortInfo(new StoreSortInfo(Comparator.comparing(Node::getName), SortDir.ASC)); + SelectionModel selectionModel = repositoriesList.getSelectionModel(); + selectionModel.setSelectionMode(SelectionModel.Mode.SINGLE); + selectionModel.addSelectionChangedHandler( + event -> { + Node node = getFirst(event.getSelection(), null); + if (node == null) { + delegate.onRepositorySelectionChanged(null); + } else { + delegate.onRepositorySelectionChanged(node.getName()); + } + }); + } + @Override public void setChangesPanelView(ChangesPanelView changesPanelView) { this.changesPanel.add(changesPanelView); } + + @Override + public void addRepository(String repository) { + repositoriesList.getNodeStorage().add(repositoryNodeFactory.newRepositoryNode(repository, 0)); + } + + @Override + public void removeRepository(String repository) { + repositoriesList.getNodeStorage().remove(findNode(repository)); + } + + @Override + public void renameRepository(String oldRepositoryName, String newRepositoryName) { + RepositoryNode node = findNode(oldRepositoryName); + if (node != null) { + NodeStorage nodeStorage = repositoriesList.getNodeStorage(); + nodeStorage.remove(node); + nodeStorage.add( + repositoryNodeFactory.newRepositoryNode(newRepositoryName, node.getChanges())); + } + } + + @Override + public void updateRepositoryChanges(String repository, int changes) { + RepositoryNode node = findNode(repository); + if (node != null) { + node.setChanges(changes); + repositoriesList.refresh(node); + } + } + + @Override + public String getSelectedRepository() { + List selection = repositoriesList.getSelectionModel().getSelectedNodes(); + if (selection.isEmpty()) { + return null; + } + return selection.get(0).getName(); + } + + private RepositoryNode findNode(String repositoryName) { + for (Node node : repositoriesList.getNodeStorage().getAll()) { + if (repositoryName.equals(node.getName())) { + return (RepositoryNode) node; + } + } + return null; + } } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.ui.xml b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.ui.xml index f17fe502bbe..b8d96de3e66 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.ui.xml +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/GitPanelViewImpl.ui.xml @@ -11,14 +11,23 @@ --> - + + - - - - - - + + + + + + + + + + + diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNode.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNode.java new file mode 100644 index 00000000000..3d62707db75 --- /dev/null +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNode.java @@ -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.ide.ext.git.client.panel; + +import com.google.gwt.dom.client.Element; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import elemental.html.SpanElement; +import java.util.List; +import org.eclipse.che.api.promises.client.Promise; +import org.eclipse.che.ide.api.data.tree.AbstractTreeNode; +import org.eclipse.che.ide.api.data.tree.Node; +import org.eclipse.che.ide.ext.git.client.GitResources; +import org.eclipse.che.ide.ui.smartTree.presentation.HasNewPresentation; +import org.eclipse.che.ide.ui.smartTree.presentation.NewNodePresentation; +import org.eclipse.che.ide.ui.smartTree.presentation.StyleConfigurator; +import org.eclipse.che.ide.util.dom.Elements; + +/** + * Represents an item in the repositories list. + * + * @author Mykola Morhun + */ +public class RepositoryNode extends AbstractTreeNode implements HasNewPresentation { + private static final String CHANGES_PREFIX = "\u2213"; // minus-plus sign '∓' + + private final GitResources gitResources; + + private NewNodePresentation.Builder nodePresentationBuilder; + + private final String repository; + private int changes; + + /** + * Creates new repository entry. + * + * @param repository repository name + * @param changes number of changed file in the repository + */ + @Inject + public RepositoryNode( + @Assisted String repository, @Assisted Integer changes, GitResources gitResources) { + this.repository = repository; + this.changes = changes; + + this.gitResources = gitResources; + + createBaseNodePresentation(); + } + + public String getRepository() { + return repository; + } + + public int getChanges() { + return changes; + } + + public void setChanges(int changes) { + this.changes = changes; + } + + private void createBaseNodePresentation() { + StyleConfigurator.Builder styleBuilder = new StyleConfigurator.Builder(); + styleBuilder.withProperty("marginLeft", "2px"); + StyleConfigurator repositoryNodeStyle = styleBuilder.build(); + + nodePresentationBuilder = new NewNodePresentation.Builder(); + nodePresentationBuilder + .withNodeText(repository) + .withNodeTextStyle(repositoryNodeStyle) + .withIcon(gitResources.gitLogo()); + } + + @Override + public NewNodePresentation getPresentation() { + // Immutable part of node presentation is cached in nodePresentationBuilder field. + // Every time here should be set variable parts of the node builder. + if (changes > 0) { + SpanElement spanElement = + Elements.createSpanElement(gitResources.gitPanelCss().repositoryChangesLabel()); + spanElement.setInnerText(CHANGES_PREFIX + changes); + nodePresentationBuilder.withUserElement((Element) spanElement); + } else { + nodePresentationBuilder.withUserElement(null); // remove label from node + } + + return nodePresentationBuilder.build(); + } + + @Override + public String getName() { + return repository; + } + + @Override + public boolean isLeaf() { + return true; + } + + @Override + protected Promise> getChildrenImpl() { + // no children are supported + return null; + } +} diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNodeFactory.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNodeFactory.java new file mode 100644 index 00000000000..f57db9fb64a --- /dev/null +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/panel/RepositoryNodeFactory.java @@ -0,0 +1,22 @@ +/* + * 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.ide.ext.git.client.panel; + +/** @author Mykola Morhun */ +public interface RepositoryNodeFactory { + /** + * Creates new repository entry. + * + * @param repository repository name + * @param changes number of changed file in the repository + */ + RepositoryNode newRepositoryNode(String repository, int changes); +} diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/EditorTabsColorizer.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/EditorTabsColorizer.java index 9700c30e21c..07d9d3122b8 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/EditorTabsColorizer.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/EditorTabsColorizer.java @@ -20,7 +20,6 @@ import org.eclipse.che.api.git.shared.FileChangedEventDto; import org.eclipse.che.api.git.shared.Status; import org.eclipse.che.api.git.shared.StatusChangedEventDto; -import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; import org.eclipse.che.ide.api.editor.EditorAgent; import org.eclipse.che.ide.api.parts.EditorMultiPartStack; import org.eclipse.che.ide.api.parts.EditorTab; @@ -99,7 +98,4 @@ public void onGitStatusChanged(String endpointId, StatusChangedEventDto statusCh } }); } - - @Override - public void onGitCheckout(String endpointId, GitCheckoutEventDto dto) {} } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitChangeMarkerManager.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitChangeMarkerManager.java index 99187d0be9b..83ad559eb57 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitChangeMarkerManager.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitChangeMarkerManager.java @@ -20,7 +20,6 @@ import org.eclipse.che.api.git.shared.EditedRegion; import org.eclipse.che.api.git.shared.FileChangedEventDto; import org.eclipse.che.api.git.shared.StatusChangedEventDto; -import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; import org.eclipse.che.ide.api.editor.EditorAgent; import org.eclipse.che.ide.api.editor.EditorOpenedEvent; import org.eclipse.che.ide.api.git.GitServiceClient; @@ -116,7 +115,4 @@ public void onGitStatusChanged(String endpointId, StatusChangedEventDto statusCh } }); } - - @Override - public void onGitCheckout(String endpointId, GitCheckoutEventDto dto) {} } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitCheckoutNotifier.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitCheckoutNotifier.java index 02c01d9347c..c0b00ff9b1c 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitCheckoutNotifier.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/GitCheckoutNotifier.java @@ -16,8 +16,6 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import org.eclipse.che.api.git.shared.FileChangedEventDto; -import org.eclipse.che.api.git.shared.StatusChangedEventDto; import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto.Type; import org.eclipse.che.ide.api.app.AppContext; @@ -51,12 +49,6 @@ public GitCheckoutNotifier( subscribeToGitEvents.addSubscriber(this); } - @Override - public void onFileChanged(String endpointId, FileChangedEventDto dto) {} - - @Override - public void onGitStatusChanged(String endpointId, StatusChangedEventDto statusChangedEventDto) {} - @Override public void onGitCheckout(String endpointId, GitCheckoutEventDto gitCheckoutEventDto) { final Type type = gitCheckoutEventDto.getType(); diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/ProjectExplorerTreeColorizer.java b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/ProjectExplorerTreeColorizer.java index 61ac5f6ba3f..473b46f297a 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/ProjectExplorerTreeColorizer.java +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/java/org/eclipse/che/ide/ext/git/client/plugins/ProjectExplorerTreeColorizer.java @@ -21,7 +21,6 @@ import org.eclipse.che.api.git.shared.FileChangedEventDto; import org.eclipse.che.api.git.shared.Status; import org.eclipse.che.api.git.shared.StatusChangedEventDto; -import org.eclipse.che.api.project.shared.dto.event.GitCheckoutEventDto; import org.eclipse.che.ide.api.resources.File; import org.eclipse.che.ide.api.resources.Resource; import org.eclipse.che.ide.api.vcs.VcsStatus; @@ -108,7 +107,4 @@ public void onGitStatusChanged(String endpointId, StatusChangedEventDto statusCh } }); } - - @Override - public void onGitCheckout(String endpointId, GitCheckoutEventDto dto) {} } diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.properties b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.properties index 2ae1ed8d854..797c48e9a25 100644 --- a/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.properties +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/GitLocalizationConstant.properties @@ -255,6 +255,7 @@ checkout.reference.message=Enter tag name or commit hash: #Panel panel.title=Git panel.title.tooltip=Contains git information and actions related to current project +panel.repositories=Repositories ############ CONTROLS ################ control.branches.title=Branches... diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/git-logo.svg b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/git-logo.svg new file mode 100644 index 00000000000..1dc8f09b413 --- /dev/null +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/git-logo.svg @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/gitPanel.css b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/gitPanel.css new file mode 100644 index 00000000000..73bff588146 --- /dev/null +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/gitPanel.css @@ -0,0 +1,42 @@ +/** + * 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 + */ + +.git-panel-full-height { + height: 100%; +} + +.git-panel-panel-top-indent { + margin-top: 5px; +} + +.git-panel-panel-bottom-indent { + margin-bottom: 5px; +} + +.git-panel-vertical-items { + width: 100%; + height: 100%; +} + +.git-panel-vertical-items > tbody > tr:first-child { + height: 20px; +} + +.git-panel-repository-changes-label { + float: right; + color: #252a38; + background-color: #969fad; + margin: 3px; + font-size: 10px; + padding-left: 5px; + padding-right: 5px; + border-radius: 4px; +} diff --git a/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/repository.svg b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/repository.svg new file mode 100644 index 00000000000..e8b9f06e4ee --- /dev/null +++ b/plugins/plugin-git/che-plugin-git-ext-git/src/main/resources/org/eclipse/che/ide/ext/git/client/panel/repository.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryDeletedEventDto.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryDeletedEventDto.java new file mode 100644 index 00000000000..1d379a9205f --- /dev/null +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryDeletedEventDto.java @@ -0,0 +1,24 @@ +/* + * 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.git.shared; + +import org.eclipse.che.dto.shared.DTO; + +/** @author Mykola Morhun */ +@DTO +public interface RepositoryDeletedEventDto { + /** Name of project in which git repository was deleted. */ + String getProjectName(); + + void setProjectName(String projectName); + + RepositoryDeletedEventDto withProjectName(String projectName); +} diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryInitializedEventDto.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryInitializedEventDto.java new file mode 100644 index 00000000000..166b61558b0 --- /dev/null +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/RepositoryInitializedEventDto.java @@ -0,0 +1,24 @@ +/* + * 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.git.shared; + +import org.eclipse.che.dto.shared.DTO; + +/** @author Mykola Morhun */ +@DTO +public interface RepositoryInitializedEventDto { + /** Name of project in which git repository was initialized. */ + String getProjectName(); + + void setProjectName(String projectName); + + RepositoryInitializedEventDto withProjectName(String projectName); +} diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/StatusChangedEventDto.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/StatusChangedEventDto.java index 56cd5965529..37e46f00db0 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/StatusChangedEventDto.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/StatusChangedEventDto.java @@ -22,6 +22,13 @@ @DTO public interface StatusChangedEventDto { + /** Name of project in which git status was changed. */ + String getProjectName(); + + void setProjectName(String projectName); + + StatusChangedEventDto withProjectName(String projectName); + /** Status of the repository. */ Status getStatus(); diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCheckoutEvent.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCheckoutEvent.java index 5206e483394..21f3faa65e9 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCheckoutEvent.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCheckoutEvent.java @@ -36,6 +36,7 @@ public interface GitCheckoutEvent extends GitEvent { GitCheckoutEvent withWorkspaceId(String workspaceId); + @Override String getProjectName(); void setProjectName(String projectName); diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCommitEvent.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCommitEvent.java index 6a5b72f8916..9820d3204b2 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCommitEvent.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitCommitEvent.java @@ -37,4 +37,11 @@ public interface GitCommitEvent extends GitEvent { void setModifiedFiles(Map> modifiedFiles); GitCommitEvent withModifiedFiles(Map> modifiedFiles); + + @Override + String getProjectName(); + + void setProjectName(String projectName); + + GitCommitEvent withProjectName(String projectName); } diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitEvent.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitEvent.java index 06961373e21..4fb944564fa 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitEvent.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitEvent.java @@ -10,4 +10,7 @@ */ package org.eclipse.che.api.git.shared.event; -public interface GitEvent {} +public interface GitEvent { + /** Returns name of project in which the event was fired. */ + String getProjectName(); +} diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryDeletedEvent.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryDeletedEvent.java index bcee0c9b389..8d7fc87706d 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryDeletedEvent.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryDeletedEvent.java @@ -18,4 +18,11 @@ * @author Igor Vinokur. */ @DTO -public interface GitRepositoryDeletedEvent extends GitEvent {} +public interface GitRepositoryDeletedEvent extends GitEvent { + @Override + String getProjectName(); + + void setProjectName(String projectName); + + GitRepositoryDeletedEvent withProjectName(String projectName); +} diff --git a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryInitializedEvent.java b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryInitializedEvent.java index 918f371feef..c50a1884d4f 100644 --- a/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryInitializedEvent.java +++ b/wsagent/che-core-api-git-shared/src/main/java/org/eclipse/che/api/git/shared/event/GitRepositoryInitializedEvent.java @@ -10,21 +10,20 @@ */ package org.eclipse.che.api.git.shared.event; -import org.eclipse.che.api.git.shared.Status; import org.eclipse.che.dto.shared.DTO; /** * Event for indicating that Git repository initialized. * - * @author Igor Vinokur. + * @author Igor Vinokur + * @author Mykola Morhun */ @DTO public interface GitRepositoryInitializedEvent extends GitEvent { + @Override + String getProjectName(); - /** Returns Git status */ - Status getStatus(); + void setProjectName(String projectName); - void setStatus(Status status); - - GitRepositoryInitializedEvent withStatus(Status status); + GitRepositoryInitializedEvent withProjectName(String projectName); } diff --git a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitCheckoutDetector.java b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitCheckoutDetector.java index efa17fe4683..2083b4a4da9 100644 --- a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitCheckoutDetector.java +++ b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitCheckoutDetector.java @@ -116,11 +116,12 @@ private Consumer fsEventConsumer() { vfsProvider.getVirtualFileSystem().getRoot().getChild(Path.of(it)).getContentAsString(); Type type = content.contains("ref:") ? BRANCH : REVISION; String name = type == REVISION ? content : PATTERN.split(content)[1]; + String project = it.substring(1, it.indexOf('/', 1)); // Update project attributes with new git values projectRegistry.setProjectType(it.split("/")[1], GitProjectType.TYPE_ID, true); - endpointIds.forEach(transmitConsumer(type, name)); + endpointIds.forEach(transmitConsumer(type, name, project)); } catch (ServerException | ForbiddenException e) { LOG.error("Error trying to read {} file and broadcast it", it, e); @@ -130,13 +131,17 @@ private Consumer fsEventConsumer() { }; } - private Consumer transmitConsumer(Type type, String name) { + private Consumer transmitConsumer(Type type, String name, String project) { return id -> transmitter .newRequest() .endpointId(id) .methodName(OUTGOING_METHOD) - .paramsAsDto(newDto(GitCheckoutEventDto.class).withName(name).withType(type)) + .paramsAsDto( + newDto(GitCheckoutEventDto.class) + .withName(name) + .withType(type) + .withProjectName(project)) .sendAndSkipResult(); } } diff --git a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitJsonRpcMessenger.java b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitJsonRpcMessenger.java index f32dbc2a2c6..76d21b2786e 100644 --- a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitJsonRpcMessenger.java +++ b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitJsonRpcMessenger.java @@ -13,8 +13,6 @@ import static com.google.common.collect.Sets.newConcurrentHashSet; import static org.eclipse.che.dto.server.DtoFactory.newDto; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -27,17 +25,18 @@ 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.api.git.shared.EditedRegion; -import org.eclipse.che.api.git.shared.Status; -import org.eclipse.che.api.git.shared.StatusChangedEventDto; +import org.eclipse.che.api.git.shared.RepositoryDeletedEventDto; +import org.eclipse.che.api.git.shared.RepositoryInitializedEventDto; import org.eclipse.che.api.git.shared.event.GitCheckoutEvent; -import org.eclipse.che.api.git.shared.event.GitCommitEvent; import org.eclipse.che.api.git.shared.event.GitEvent; import org.eclipse.che.api.git.shared.event.GitRepositoryDeletedEvent; import org.eclipse.che.api.git.shared.event.GitRepositoryInitializedEvent; @Singleton public class GitJsonRpcMessenger implements EventSubscriber { + private static final String GIT_REPOSITORY_INITIALIZED = "event/git/initialized"; + private static final String GIT_REPOSITORY_DELETED = "event/git/deleted"; + private final Map> endpointIdsWithWorkspaceIdAndProjectName = new ConcurrentHashMap<>(); private final Set endpointIds = newConcurrentHashSet(); @@ -65,10 +64,10 @@ private void unsubscribe() { public void onEvent(GitEvent event) { if (event instanceof GitCheckoutEvent) { handleCheckoutEvent((GitCheckoutEvent) event); - } else if (event instanceof GitCommitEvent - || event instanceof GitRepositoryInitializedEvent - || event instanceof GitRepositoryDeletedEvent) { - handleStatusChangedEvent(event); + } else if (event instanceof GitRepositoryInitializedEvent) { + handleRepositoryInitializedEvent((GitRepositoryInitializedEvent) event); + } else if (event instanceof GitRepositoryDeletedEvent) { + handleGitRepositoryDeletedEvent((GitRepositoryDeletedEvent) event); } } @@ -88,24 +87,30 @@ private void handleCheckoutEvent(GitCheckoutEvent event) { .sendAndSkipResult()); } - private void handleStatusChangedEvent(GitEvent event) { - Status status = newDto(Status.class); - Map> modifiedFiles = new HashMap<>(); - if (event instanceof GitCommitEvent) { - status = ((GitCommitEvent) event).getStatus(); - modifiedFiles = ((GitCommitEvent) event).getModifiedFiles(); - } else if (event instanceof GitRepositoryInitializedEvent) { - status = ((GitRepositoryInitializedEvent) event).getStatus(); + private void handleRepositoryInitializedEvent(GitRepositoryInitializedEvent event) { + RepositoryInitializedEventDto repositoryInitializedEventDto = + newDto(RepositoryInitializedEventDto.class).withProjectName(event.getProjectName()); + + for (String endpointId : endpointIds) { + transmitter + .newRequest() + .endpointId(endpointId) + .methodName(GIT_REPOSITORY_INITIALIZED) + .paramsAsDto(repositoryInitializedEventDto) + .sendAndSkipResult(); } + } + + private void handleGitRepositoryDeletedEvent(GitRepositoryDeletedEvent event) { + RepositoryDeletedEventDto repositoryDeletedEventDto = + newDto(RepositoryDeletedEventDto.class).withProjectName(event.getProjectName()); - StatusChangedEventDto statusChangeEventDto = - newDto(StatusChangedEventDto.class).withStatus(status).withModifiedFiles(modifiedFiles); for (String endpointId : endpointIds) { transmitter .newRequest() .endpointId(endpointId) - .methodName("event/git/statusChanged") - .paramsAsDto(statusChangeEventDto) + .methodName(GIT_REPOSITORY_DELETED) + .paramsAsDto(repositoryDeletedEventDto) .sendAndSkipResult(); } } diff --git a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitService.java b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitService.java index d9b445635f0..3b3861dd045 100644 --- a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitService.java +++ b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitService.java @@ -306,7 +306,8 @@ public void deleteRepository(@Context UriInfo uriInfo) throws ApiException { final FolderEntry gitFolder = project.getBaseFolder().getChildFolder(".git"); gitFolder.getVirtualFile().delete(); projectRegistry.removeProjectType(projectPath, GitProjectType.TYPE_ID); - eventService.publish(newDto(GitRepositoryDeletedEvent.class)); + eventService.publish( + newDto(GitRepositoryDeletedEvent.class).withProjectName(project.getName())); } @GET diff --git a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitStatusChangedDetector.java b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitStatusChangedDetector.java index 0d30b7bd6a2..047d839eb4d 100644 --- a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitStatusChangedDetector.java +++ b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/GitStatusChangedDetector.java @@ -50,7 +50,7 @@ public class GitStatusChangedDetector { private static final String INDEX_FILE = "index"; private static final String ORIG_HEAD_FILE = "ORIG_HEAD"; private static final String INCOMING_METHOD = "track/git-index"; - private static final String OUTGOING_METHOD = "event/git/statusChanged"; + private static final String OUTGOING_METHOD = "event/git/status-changed"; private final RequestTransmitter transmitter; private final FileWatcherManager manager; @@ -146,7 +146,10 @@ private Consumer transmitConsumer(String path) { } StatusChangedEventDto statusChangeEventDto = - newDto(StatusChangedEventDto.class).withStatus(status).withModifiedFiles(modifiedFiles); + newDto(StatusChangedEventDto.class) + .withProjectName(connection.getWorkingDir().getName()) + .withStatus(status) + .withModifiedFiles(modifiedFiles); transmitter .newRequest() .endpointId(id) diff --git a/wsagent/che-core-api-project-shared/src/main/java/org/eclipse/che/api/project/shared/dto/event/GitCheckoutEventDto.java b/wsagent/che-core-api-project-shared/src/main/java/org/eclipse/che/api/project/shared/dto/event/GitCheckoutEventDto.java index 064401a8036..b45e62b74ce 100644 --- a/wsagent/che-core-api-project-shared/src/main/java/org/eclipse/che/api/project/shared/dto/event/GitCheckoutEventDto.java +++ b/wsagent/che-core-api-project-shared/src/main/java/org/eclipse/che/api/project/shared/dto/event/GitCheckoutEventDto.java @@ -26,10 +26,14 @@ public interface GitCheckoutEventDto { String getName(); + String getProjectName(); + GitCheckoutEventDto withType(Type type); GitCheckoutEventDto withName(String name); + GitCheckoutEventDto withProjectName(String projectName); + enum Type { BRANCH, REVISION, diff --git a/wsagent/che-core-git-impl-jgit/src/main/java/org/eclipse/che/git/impl/jgit/JGitConnection.java b/wsagent/che-core-git-impl-jgit/src/main/java/org/eclipse/che/git/impl/jgit/JGitConnection.java index c7019c342ca..c877952b9d0 100644 --- a/wsagent/che-core-git-impl-jgit/src/main/java/org/eclipse/che/git/impl/jgit/JGitConnection.java +++ b/wsagent/che-core-git-impl-jgit/src/main/java/org/eclipse/che/git/impl/jgit/JGitConnection.java @@ -128,7 +128,6 @@ import org.eclipse.che.api.git.shared.ShowFileContentResponse; import org.eclipse.che.api.git.shared.Status; import org.eclipse.che.api.git.shared.Tag; -import org.eclipse.che.api.git.shared.event.GitCommitEvent; import org.eclipse.che.api.git.shared.event.GitRepositoryInitializedEvent; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.commons.proxy.ProxyAuthenticator; @@ -749,14 +748,6 @@ public Revision commit(CommitParams params) throws GitException { gerritSupportConfigValue != null ? Boolean.valueOf(gerritSupportConfigValue) : false; commitCommand.setInsertChangeId(isGerritSupportConfigured); RevCommit result = commitCommand.call(); - Map> modifiedFiles = new HashMap<>(); - for (String file : status.getChanged()) { - modifiedFiles.put(file, getEditedRegions(file)); - } - eventService.publish( - newDto(GitCommitEvent.class) - .withStatus(status(emptyList())) - .withModifiedFiles(modifiedFiles)); GitUser gitUser = newDto(GitUser.class).withName(committerName).withEmail(committerEmail); @@ -953,7 +944,8 @@ public void init(boolean isBare) throws GitException { try { repository.create(isBare); eventService.publish( - newDto(GitRepositoryInitializedEvent.class).withStatus(status(emptyList()))); + newDto(GitRepositoryInitializedEvent.class) + .withProjectName(repository.getWorkTree().getName())); } catch (IOException exception) { if (removeIfFailed) { deleteRepositoryFolder();