blob: a509fc6fe523607a5eabba59bf950dcb6a60ac53 [file] [log] [blame]
package com.google.gct.idea.settings;
import com.google.common.annotations.VisibleForTesting;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.actions.ImportSettingsFilenameFilter;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ExportableApplicationComponent;
import com.intellij.openapi.components.ExportableComponent;
import com.intellij.openapi.components.ServiceBean;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.ZipUtil;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
/**
* Provides functionality to update IDEA setting from a jar containing new settings
*/
public class ImportSettings {
private static final String DIALOG_TITLE = "Setting Synchronization";
public static final String SETTINGS_JAR_MARKER = "IntelliJ IDEA Global Settings";
/**
* Parse and update the IDEA settings in the jar at <code>path</code>.
* Note: This function might require a restart of the application.
* @param path The location of the jar with the new IDEA settings.
*/
public static void doImport(String path) {
final File saveFile = new File(path);
try {
if (!saveFile.exists()) {
Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)), DIALOG_TITLE);
return;
}
// What is this file used for?
final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(SETTINGS_JAR_MARKER);
if (magicEntry == null) {
Messages.showErrorDialog("The file " + presentableFileName(saveFile) + " contains no settings to import",
DIALOG_TITLE);
return;
}
final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>(
Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
registeredComponents.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
List<ExportableComponent> storedComponents = getComponentsStored(saveFile, registeredComponents);
Set<String> relativeNamesToExtract = new HashSet<String>();
for (final ExportableComponent aComponent : storedComponents) {
final File[] exportFiles = aComponent.getExportFiles();
for (File exportFile : exportFiles) {
final File configPath = new File(PathManager.getConfigPath());
final String rPath = FileUtil.getRelativePath(configPath, exportFile);
assert rPath != null;
final String relativePath = FileUtil.toSystemIndependentName(rPath);
relativeNamesToExtract.add(relativePath);
}
}
relativeNamesToExtract.add(PluginManager.INSTALLED_TXT);
final File tempFile = new File(PathManager.getPluginTempPath() + "/" + saveFile.getName());
FileUtil.copy(saveFile, tempFile);
File outDir = new File(PathManager.getConfigPath());
final ImportSettingsFilenameFilter filenameFilter = new ImportSettingsFilenameFilter(relativeNamesToExtract);
StartupActionScriptManager.ActionCommand unzip = new StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter);
StartupActionScriptManager.addActionCommand(unzip);
// remove temp file
StartupActionScriptManager.ActionCommand deleteTemp = new StartupActionScriptManager.DeleteCommand(tempFile);
StartupActionScriptManager.addActionCommand(deleteTemp);
UpdateSettings.getInstance().forceCheckForUpdateAfterRestart();
String key = ApplicationManager.getApplication().isRestartCapable()
? "message.settings.imported.successfully.restart"
: "message.settings.imported.successfully";
final int ret = Messages.showOkCancelDialog(IdeBundle.message(key,
ApplicationNamesInfo.getInstance().getProductName(),
ApplicationNamesInfo.getInstance().getFullProductName()),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon());
if (ret == Messages.OK) {
((ApplicationEx)ApplicationManager.getApplication()).restart(true);
}
}
catch (ZipException e1) {
Messages.showErrorDialog(
"Error reading file " + presentableFileName(saveFile) + ".\\nThere was " + e1.getMessage(),
DIALOG_TITLE);
}
catch (IOException e1) {
Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
DIALOG_TITLE);
}
}
private static String presentableFileName(final File file) {
return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'";
}
private static List<ExportableComponent> getComponentsStored(File zipFile,
ArrayList<ExportableComponent> registeredComponents)
throws IOException {
final File configPath = new File(PathManager.getConfigPath());
final ArrayList<ExportableComponent> components = new ArrayList<ExportableComponent>();
for (ExportableComponent component : registeredComponents) {
final File[] exportFiles = component.getExportFiles();
for (File exportFile : exportFiles) {
final String rPath = FileUtil.getRelativePath(configPath, exportFile);
assert rPath != null;
String relativePath = FileUtil.toSystemIndependentName(rPath);
if (exportFile.isDirectory()) relativePath += "/";
if (ZipUtil.isZipContainsEntry(zipFile, relativePath)) {
components.add(component);
break;
}
}
}
return components;
}
}