package jetbrains.mps.vcs.plugin;
/*Generated by MPS */
import jetbrains.mps.workbench.action.BaseAction;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import javax.swing.Icon;
import com.intellij.openapi.actionSystem.AnActionEvent;
import java.util.Map;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import jetbrains.mps.extapi.persistence.FileDataSource;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import jetbrains.mps.ide.vfs.VirtualFileUtils;
import jetbrains.mps.internal.collections.runtime.Sequence;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.ide.actions.MPSCommonDataKeys;
import org.jetbrains.mps.openapi.model.EditableSModel;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import java.io.File;
import jetbrains.mps.vcs.platform.util.MergeBackupUtil;
import jetbrains.mps.vcs.util.MergeVersion;
import org.jetbrains.mps.openapi.model.SModelReference;
import jetbrains.mps.vcspersistence.VCSPersistenceSupport;
import org.xml.sax.InputSource;
import java.io.StringReader;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import jetbrains.mps.smodel.persistence.def.ModelPersistence;
import jetbrains.mps.extapi.model.SModelBase;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import com.intellij.diff.merge.MergeRequest;
import com.intellij.diff.DiffRequestFactory;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.diff.DiffManager;
import java.io.IOException;
import org.apache.log4j.Level;
import com.intellij.diff.InvalidDiffRequestException;
import com.intellij.openapi.ui.Messages;
import jetbrains.mps.vfs.IFile;
import jetbrains.mps.generator.ModelDigestUtil;
public class ReRunMergeFromBackup_Action extends BaseAction {
private static final Logger LOG = LogManager.getLogger(ReRunMergeFromBackup_Action.class);
private static final Icon ICON = null;
public ReRunMergeFromBackup_Action() {
super("Rerun Merge from Backup", "", ICON);
this.setIsAlwaysVisible(false);
this.setExecuteOutsideCommand(true);
}
@Override
public boolean isDumbAware() {
return true;
}
@Override
public boolean isApplicable(AnActionEvent event, final Map<String, Object> _params) {
if (!(((SModel) MapSequence.fromMap(_params).get("model")).getSource() instanceof FileDataSource)) {
return false;
}
ProjectLevelVcsManager manager = ProjectLevelVcsManager.getInstance(((Project) MapSequence.fromMap(_params).get("project")));
if (manager.getAllVersionedRoots().length == 0) {
return false;
}
VirtualFile file = VirtualFileUtils.getProjectVirtualFile(ReRunMergeFromBackup_Action.this.getModelFile(_params));
if (file == null) {
return false;
}
return manager.getVcsFor(file) != null && Sequence.fromIterable(ReRunMergeFromBackup_Action.this.getBackupFiles(_params)).isNotEmpty();
}
@Override
public void doUpdate(@NotNull AnActionEvent event, final Map<String, Object> _params) {
this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params));
}
@Override
protected boolean collectActionData(AnActionEvent event, final Map<String, Object> _params) {
if (!(super.collectActionData(event, _params))) {
return false;
}
{
SModel p = event.getData(MPSCommonDataKeys.MODEL);
MapSequence.fromMap(_params).put("model", p);
if (p == null) {
return false;
}
if (!(p instanceof EditableSModel) || p.isReadOnly()) {
return false;
}
}
{
Project p = event.getData(CommonDataKeys.PROJECT);
MapSequence.fromMap(_params).put("project", p);
if (p == null) {
return false;
}
}
return true;
}
@Override
public void doExecute(@NotNull final AnActionEvent event, final Map<String, Object> _params) {
for (File backupFile : Sequence.fromIterable(ReRunMergeFromBackup_Action.this.getBackupFiles(_params))) {
try {
String[] modelsAsText = MergeBackupUtil.loadZippedModelsAsText(backupFile, MergeVersion.values());
String mine = modelsAsText[MergeVersion.MINE.ordinal()];
String base = modelsAsText[MergeVersion.BASE.ordinal()];
String repository = modelsAsText[MergeVersion.REPOSITORY.ordinal()];
SModelReference uid = VCSPersistenceSupport.loadDescriptor(new InputSource(new StringReader(mine))).getModelReference();
if (uid == null || !(uid.equals(((SModel) MapSequence.fromMap(_params).get("model")).getReference()))) {
continue;
}
// this.model came from repo, so it must be supported by ModelPersistence
final Wrappers._T<String> modelData = new Wrappers._T<String>();
((SModel) MapSequence.fromMap(_params).get("model")).getRepository().getModelAccess().runReadAction(new Runnable() {
public void run() {
modelData.value = ModelPersistence.modelToString(((SModelBase) ((SModel) MapSequence.fromMap(_params).get("model"))).getSModelInternal());
}
});
mine = ReRunMergeFromBackup_Action.this.selectMineModel(modelData.value, mine, _params);
if (mine == null) {
return;
}
VirtualFile file = VirtualFileUtils.getProjectVirtualFile(ReRunMergeFromBackup_Action.this.getModelFile(_params));
assert file != null;
List<String> contents = ListSequence.fromListAndArray(new ArrayList<String>(), mine, base, repository);
List<String> titles = ListSequence.fromListAndArray(new ArrayList<String>(), "Mine", "Base version", "Repository");
MergeRequest request = DiffRequestFactory.getInstance().createMergeRequest(((Project) MapSequence.fromMap(_params).get("project")), file.getFileType(), FileDocumentManager.getInstance().getDocument(file), contents, null, titles, null);
DiffManager.getInstance().showMerge(((Project) MapSequence.fromMap(_params).get("project")), request);
return;
} catch (IOException e) {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("", e);
}
// Skip this backup
continue;
} catch (InvalidDiffRequestException e) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("", e);
}
}
}
Messages.showInfoMessage("No suitable backup files for " + ((SModel) MapSequence.fromMap(_params).get("model")).getReference().getModelName() + "was not found.", "No Backup Files Found");
}
private Iterable<File> getBackupFiles(final Map<String, Object> _params) {
return MergeBackupUtil.findZipFilesForModelFile(ReRunMergeFromBackup_Action.this.getModelFile(_params).getName());
}
private IFile getModelFile(final Map<String, Object> _params) {
return ((FileDataSource) ((SModel) MapSequence.fromMap(_params).get("model")).getSource()).getFile();
}
private String selectMineModel(String currentModel, String backUpModel, final Map<String, Object> _params) {
if (ModelDigestUtil.hashText(currentModel).equals(ModelDigestUtil.hashText(backUpModel))) {
return backUpModel;
} else {
String current = "Currently Loaded Model";
String backup = "Backed Up Model";
String[] options = {current, backup};
int result = Messages.showDialog("Backed up \"mine\" model is different from current model.\n Which version would you like to use?", "Current model differs from backup.", options, 0, Messages.getQuestionIcon());
if (result == -1) {
return null;
} else if (options[result].equals(current)) {
return currentModel;
} else {
return backUpModel;
}
}
}
}