package org.wavescale.sourcesync.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.wavescale.sourcesync.api.ConnectionConfiguration; import org.wavescale.sourcesync.api.FileSynchronizer; import org.wavescale.sourcesync.api.SynchronizationQueue; import org.wavescale.sourcesync.api.Utils; import org.wavescale.sourcesync.factory.ConfigConnectionFactory; import org.wavescale.sourcesync.factory.ModuleConnectionConfig; import org.wavescale.sourcesync.logger.BalloonLogger; import org.wavescale.sourcesync.logger.EventDataLogger; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Semaphore; /** * **************************************************************************** * Copyright (c) 2005-2014 Faur Ioan-Aurel. * * All rights reserved. This program and the accompanying materials * * are made available under the terms of the MIT License * * which accompanies this distribution, and is available at * * http://opensource.org/licenses/MIT * * * * For any issues or questions send an email at: fioan89@gmail.com * * ***************************************************************************** */ public class ActionChangedFilesToRemote extends AnAction { public void actionPerformed(final AnActionEvent e) { // first check if there's a connection type associated to this module. If not alert the user // and get out Project currentProject = PlatformDataKeys.PROJECT.getData(e.getDataContext()); String moduleName = currentProject.getName(); String associationName = ModuleConnectionConfig.getInstance().getAssociationFor(moduleName); if (associationName == null) { Utils.showNoConnectionSpecifiedError(e, moduleName); return; } // there's this possibility that the project might not be versioned, therefore no changes can be detected. List<LocalChangeList> changeLists = ChangeListManager.getInstance(e.getProject()).getChangeLists(); if (!hasModifiedFiles(changeLists)) { StringBuilder builder = new StringBuilder("Could not find any changes on project <b>"); builder.append(e.getProject().getName()).append("</b>! You might want to check if this project is imported in any") .append(" version control system that is supported by IDEA!"); BalloonLogger.logBalloonInfo(builder.toString(), e.getProject()); EventDataLogger.logInfo(builder.toString(), e.getProject()); return; } // get a list of changed virtual files List<VirtualFile> changedFiles = new ArrayList<VirtualFile>(); for (LocalChangeList localChangeList : changeLists) { for (Change change : localChangeList.getChanges()) { changedFiles.add(change.getVirtualFile()); } } // start sync final ConnectionConfiguration connectionConfiguration = ConfigConnectionFactory.getInstance(). getConnectionConfiguration(associationName); final Semaphore semaphores = new Semaphore(connectionConfiguration.getSimultaneousJobs()); final int allowed_sessions = changedFiles.size() <= connectionConfiguration.getSimultaneousJobs() ? changedFiles.size() : connectionConfiguration.getSimultaneousJobs(); final SynchronizationQueue synchronizationQueue = new SynchronizationQueue(e.getProject(), connectionConfiguration, allowed_sessions); synchronizationQueue.startCountingTo(changedFiles.size()); final BlockingQueue<FileSynchronizer> queue = synchronizationQueue.getSyncQueue(); final String projectName = e.getProject().getName(); for (VirtualFile virtualFile : changedFiles) { if (virtualFile != null && Utils.canBeUploaded(virtualFile.getName(), connectionConfiguration.getExcludedFiles())) { final File relativeFile = new File(Utils.getUnixPath(virtualFile.getPath()).replaceFirst( Utils.getUnixPath(currentProject.getBasePath()), "")); ProgressManager.getInstance().run(new Task.Backgroundable(e.getProject(), "Uploading", false) { @Override public void run(@NotNull ProgressIndicator indicator) { FileSynchronizer fileSynchronizer = null; try { semaphores.acquire(); fileSynchronizer = queue.take(); fileSynchronizer.setIndicator(indicator); if (fileSynchronizer != null) { fileSynchronizer.connect(); // so final destination will look like this: // root_home/ + project_relative_path_to_file/ fileSynchronizer.syncFile(Utils.getUnixPath(relativeFile.getPath()), Utils.buildUnixPath(relativeFile.getParent().substring(1) /**Something like src/org/.../package**/)); } queue.put(fileSynchronizer); synchronizationQueue.count(); } catch (InterruptedException e1) { e1.printStackTrace(); } finally { semaphores.release(); } } }); } else { if (virtualFile != null) { EventDataLogger.logWarning("File <b>" + virtualFile.getName() + "</b> is filtered out!", e.getProject()); synchronizationQueue.count(); } } } } private boolean hasModifiedFiles(List<LocalChangeList> changeLists) { for (LocalChangeList changeList : changeLists) { Collection<Change> changes = changeList.getChanges(); for (Change change : changes) { if (change.getVirtualFile() != null) { return true; } } } return false; } }