package jetbrains.mps.vcs.changesmanager; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import org.jetbrains.annotations.NotNull; import com.intellij.openapi.vcs.FileStatus; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.project.Project; import jetbrains.mps.smodel.ModelAccess; import org.apache.log4j.Level; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.diff.DiffProvider; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.BinaryContentRevision; import com.intellij.openapi.vcs.VcsException; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.persistence.DataSource; import jetbrains.mps.extapi.persistence.FileDataSource; import jetbrains.mps.vfs.IFile; import jetbrains.mps.ide.vfs.VirtualFileUtils; import com.intellij.openapi.vcs.FileStatusManager; import jetbrains.mps.util.FileUtil; import jetbrains.mps.vcspersistence.VCSPersistenceUtil; import jetbrains.mps.persistence.FilePerRootDataSource; import java.util.Map; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.project.MPSExtentions; import org.jetbrains.mps.openapi.persistence.ModelFactory; import jetbrains.mps.extapi.persistence.ModelFactoryService; import jetbrains.mps.persistence.PreinstalledModelFactoryTypes; import jetbrains.mps.persistence.PersistenceUtil; import org.jetbrains.mps.openapi.persistence.datasource.DataSourceType; import java.io.InputStream; import java.io.IOException; import java.io.ByteArrayInputStream; import java.util.Collections; public class BaseVersionUtil { private static final Logger LOG = LogManager.getLogger(BaseVersionUtil.class); private BaseVersionUtil() { } public static boolean isAddedFileStatus(@NotNull FileStatus status) { return status == FileStatus.ADDED || status == FileStatus.UNKNOWN || status == FileStatus.IGNORED; } @Nullable public static Object getBaseVersionContent(@NotNull VirtualFile file, @NotNull Project project) { if (ModelAccess.instance().canRead()) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("BaseVersionUtil.getBaseVersionContent() is invoked from read action: possible deadlock", new IllegalStateException()); } } try { AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file); if (vcs == null) { return null; } DiffProvider diffProvider = vcs.getDiffProvider(); if (diffProvider == null) { return null; } VcsRevisionNumber revisionNumber = diffProvider.getCurrentRevision(file); if (revisionNumber == null) { return null; } ContentRevision revision = diffProvider.createFileContent(revisionNumber, file); if (revision == null) { return null; } if (revision instanceof BinaryContentRevision) { return ((BinaryContentRevision) revision).getBinaryContent(); } return revision.getContent(); } catch (VcsException ex) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("VcsException during getting base version content: ", ex); } return null; } } @Nullable public static SModel getBaseVersionModel(SModel model, Project project) { DataSource ds = model.getSource(); if (ds instanceof FileDataSource) { IFile file = ((FileDataSource) ds).getFile(); if (!(file.exists())) { return null; } VirtualFile vFile = VirtualFileUtils.getProjectVirtualFile(file); if (vFile == null || ProjectLevelVcsManager.getInstance(project).getVcsFor(vFile) == null) { return null; } Object content = BaseVersionUtil.getBaseVersionContent(vFile, project); if (content == null) { FileStatus status = FileStatusManager.getInstance(project).getStatus(vFile); if (status != FileStatus.NOT_CHANGED) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Base version content is null while file status is " + status); } } return null; } String ext = vFile.getExtension(); byte[] modelData = (content instanceof String ? ((String) content).getBytes(FileUtil.DEFAULT_CHARSET) : (byte[]) content); return VCSPersistenceUtil.loadModel(modelData, ext); } else if (ds instanceof FilePerRootDataSource) { FilePerRootDataSource rds = (FilePerRootDataSource) ds; Map<String, Object> content = MapSequence.fromMap(new HashMap<String, Object>()); for (String stream : rds.getAvailableStreams()) { IFile file = rds.getFile(stream); VirtualFile vFile = VirtualFileUtils.getProjectVirtualFile(file); if (vFile == null) { continue; } Object o = BaseVersionUtil.getBaseVersionContent(vFile, project); if (o == null) { continue; } MapSequence.fromMap(content).put(stream, o); } if (MapSequence.fromMap(content).containsKey(MPSExtentions.DOT_MODEL_HEADER)) { // no base version for ".model" file means there was no model return loadPerRootModel(content); } } return null; } private static SModel loadPerRootModel(final Map<String, Object> content) { ModelFactory factory = ModelFactoryService.getInstance().getFactoryByType(PreinstalledModelFactoryTypes.PER_ROOT_XML); if (factory == null || factory.isBinary()) { return null; } try { SModel model = factory.load(new PersistenceUtil.MultiStreamDataSourceBase() { @Override public DataSourceType getType() { return null; } @NotNull @Override public Iterable<String> getAvailableStreams() { return content.keySet(); } @NotNull @Override public InputStream openInputStream(String name) throws IOException { Object data = content.get(name); if (data instanceof String) { return new ByteArrayInputStream(((String) data).getBytes(FileUtil.DEFAULT_CHARSET)); } else if (data instanceof byte[]) { return new ByteArrayInputStream((byte[]) data); } throw new UnsupportedOperationException("Unknown content type : " + content + "; name of the stream: " + name); } }, Collections.<String,String>emptyMap()); model.load(); return model; } catch (IOException ex) { return null; } } }