mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
EDU-547 Get rid of answer extension for Task Files
Create special invisible excluded directory to perform all the replacement inside it
This commit is contained in:
+3
@@ -25,6 +25,9 @@ class CCFileDeletedListener extends VirtualFileAdapter {
|
||||
return;
|
||||
}
|
||||
VirtualFile removedFile = event.getFile();
|
||||
if (removedFile.getPath().contains(CCUtils.GENERATED_FILES_FOLDER)) {
|
||||
return;
|
||||
}
|
||||
final TaskFile taskFile = CCProjectService.getInstance(myProject).getTaskFile(removedFile);
|
||||
if (taskFile != null) {
|
||||
deleteAnswerFile(removedFile, taskFile);
|
||||
|
||||
+46
@@ -2,9 +2,18 @@ package com.jetbrains.edu.coursecreator;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.intellij.ide.projectView.actions.MarkRootActionBase;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.DumbModePermission;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -24,6 +33,7 @@ import java.util.Comparator;
|
||||
|
||||
public class CCUtils {
|
||||
private static final Logger LOG = Logger.getInstance(CCUtils.class);
|
||||
public static final String GENERATED_FILES_FOLDER = ".coursecreator";
|
||||
|
||||
@Nullable
|
||||
public static CCLanguageManager getStudyLanguageManager(@NotNull final Course course) {
|
||||
@@ -103,4 +113,40 @@ public class CCUtils {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static VirtualFile getGeneratedFilesFolder(@NotNull Project project, @NotNull Module module) {
|
||||
VirtualFile baseDir = project.getBaseDir();
|
||||
VirtualFile folder = baseDir.findChild(GENERATED_FILES_FOLDER);
|
||||
if (folder != null) {
|
||||
return folder;
|
||||
}
|
||||
final Ref<VirtualFile> generatedRoot = new Ref<>();
|
||||
DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
generatedRoot.set(baseDir.createChildDirectory(this, GENERATED_FILES_FOLDER));
|
||||
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
|
||||
ContentEntry entry = MarkRootActionBase.findContentEntry(model, generatedRoot.get());
|
||||
if (entry == null) {
|
||||
LOG.info("Failed to find contentEntry for archive folder");
|
||||
return;
|
||||
}
|
||||
entry.addExcludeFolder(generatedRoot.get());
|
||||
model.commit();
|
||||
module.getProject().save();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Failed to create folder for generated files", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return generatedRoot.get();
|
||||
}
|
||||
}
|
||||
|
||||
+126
-38
@@ -6,16 +6,21 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import com.jetbrains.edu.EduNames;
|
||||
import com.jetbrains.edu.EduUtils;
|
||||
@@ -28,6 +33,7 @@ import com.jetbrains.edu.coursecreator.CCProjectService;
|
||||
import com.jetbrains.edu.coursecreator.CCUtils;
|
||||
import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
@@ -59,13 +65,14 @@ public class CCCreateCourseArchive extends DumbAwareAction {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
final Module module = e.getData(LangDataKeys.MODULE);
|
||||
if (project == null || module == null) {
|
||||
return;
|
||||
}
|
||||
createCourseArchive(project);
|
||||
createCourseArchive(project, module);
|
||||
}
|
||||
|
||||
private void createCourseArchive(final Project project) {
|
||||
private void createCourseArchive(final Project project, Module module) {
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
if (course == null) return;
|
||||
@@ -75,36 +82,129 @@ public class CCCreateCourseArchive extends DumbAwareAction {
|
||||
return;
|
||||
}
|
||||
final VirtualFile baseDir = project.getBaseDir();
|
||||
|
||||
VirtualFile archiveFolder = getArchiveFolder(project, module);
|
||||
if (archiveFolder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CCLanguageManager manager = CCUtils.getStudyLanguageManager(course);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
FileFilter filter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return !manager.doNotPackFile(pathname);
|
||||
}
|
||||
};
|
||||
|
||||
for (VirtualFile child : baseDir.getChildren()) {
|
||||
String name = child.getName();
|
||||
File fromFile = new File(child.getPath());
|
||||
if (CCUtils.GENERATED_FILES_FOLDER.equals(name) || ".idea".equals(name)
|
||||
|| name.contains("iml") || manager.doNotPackFile(fromFile)) {
|
||||
continue;
|
||||
}
|
||||
copyChild(archiveFolder, filter, child, fromFile);
|
||||
}
|
||||
|
||||
final List<Lesson> lessons = course.getLessons();
|
||||
|
||||
final Map<TaskFile, TaskFile> savedTaskFiles = new HashMap<TaskFile, TaskFile>();
|
||||
for (Lesson lesson : lessons) {
|
||||
final VirtualFile lessonDir = baseDir.findChild(EduNames.LESSON + String.valueOf(lesson.getIndex()));
|
||||
if (lessonDir == null) continue;
|
||||
for (Task task : lesson.getTaskList()) {
|
||||
final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(task.getIndex()));
|
||||
if (taskDir == null) continue;
|
||||
for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Map<TaskFile, TaskFile> savedTaskFiles = new HashMap<TaskFile, TaskFile>();
|
||||
replaceAnswerFilesWithTaskFiles(savedTaskFiles);
|
||||
generateJson(project, archiveFolder);
|
||||
resetTaskFiles(savedTaskFiles);
|
||||
VirtualFileManager.getInstance().refreshWithoutFileWatcher(false);
|
||||
packCourse(archiveFolder);
|
||||
synchronize(project);
|
||||
}
|
||||
|
||||
private void replaceAnswerFilesWithTaskFiles(Map<TaskFile, TaskFile> savedTaskFiles) {
|
||||
for (Lesson lesson : lessons) {
|
||||
final VirtualFile lessonDir = baseDir.findChild(EduNames.LESSON + String.valueOf(lesson.getIndex()));
|
||||
if (lessonDir == null) continue;
|
||||
for (Task task : lesson.getTaskList()) {
|
||||
final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + String.valueOf(task.getIndex()));
|
||||
if (taskDir == null) continue;
|
||||
for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
|
||||
TaskFile taskFileCopy = new TaskFile();
|
||||
TaskFile taskFile = entry.getValue();
|
||||
TaskFile.copy(taskFile, taskFileCopy);
|
||||
savedTaskFiles.put(taskFile, taskFileCopy);
|
||||
EduUtils.createStudentFileFromAnswer(project, taskDir, taskDir, entry.getKey(), taskFile);
|
||||
|
||||
VirtualFile userFileDir = VfsUtil.findRelativeFile(archiveFolder, lessonDir.getName(), taskDir.getName());
|
||||
if (userFileDir == null) {
|
||||
continue;
|
||||
}
|
||||
String taskFileName = entry.getKey();
|
||||
EduUtils.createStudentFileFromAnswer(project, userFileDir, taskDir, taskFileName, taskFile);
|
||||
VirtualFile answerFile = userFileDir.findChild(
|
||||
FileUtilRt.getNameWithoutExtension(taskFileName) + ".answer." + FileUtilRt.getExtension(taskFileName));
|
||||
if (answerFile != null) {
|
||||
try {
|
||||
answerFile.delete(this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void copyChild(VirtualFile archiveFolder, FileFilter filter, VirtualFile child, File fromFile) {
|
||||
File toFile = new File(archiveFolder.getPath(), child.getName());
|
||||
|
||||
try {
|
||||
if (child.isDirectory()) {
|
||||
FileUtil.copyDir(fromFile, toFile, filter);
|
||||
}
|
||||
else {
|
||||
if (filter.accept(fromFile)) {
|
||||
FileUtil.copy(fromFile, toFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
generateJson(project);
|
||||
VirtualFileManager.getInstance().refreshWithoutFileWatcher(false);
|
||||
packCourse(baseDir, course);
|
||||
synchronize(project);
|
||||
resetTaskFiles(savedTaskFiles);
|
||||
catch (IOException e) {
|
||||
LOG.info("Failed to copy" + fromFile.getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getArchiveFolder(@NotNull Project project, @NotNull Module module) {
|
||||
VirtualFile generatedFilesRoot = CCUtils.getGeneratedFilesFolder(project, module);
|
||||
if (generatedFilesRoot == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile zipRoot = generatedFilesRoot.findChild(myZipName);
|
||||
final Ref<VirtualFile> archiveFolder = new Ref<>();
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (zipRoot != null) {
|
||||
zipRoot.delete(this);
|
||||
}
|
||||
archiveFolder.set(generatedFilesRoot.createChildDirectory(this, myZipName));
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Failed to get zip root for " + myZipName, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return archiveFolder.get();
|
||||
}
|
||||
|
||||
|
||||
private static void resetTaskFiles(Map<TaskFile, TaskFile> savedTaskFiles) {
|
||||
for (Map.Entry<TaskFile, TaskFile> entry : savedTaskFiles.entrySet()) {
|
||||
entry.getKey().setAnswerPlaceholders(entry.getValue().getAnswerPlaceholders());
|
||||
@@ -116,25 +216,13 @@ public class CCCreateCourseArchive extends DumbAwareAction {
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
|
||||
private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Course course) {
|
||||
private void packCourse(@NotNull final VirtualFile baseDir) {
|
||||
try {
|
||||
final File zipFile = new File(myLocationDir, myZipName + ".zip");
|
||||
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
|
||||
final CCLanguageManager manager = CCUtils.getStudyLanguageManager(course);
|
||||
VirtualFile[] courseFiles = baseDir.getChildren();
|
||||
for (VirtualFile file : courseFiles) {
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(file.getPath()), file.getName(), new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
String name = pathname.getName();
|
||||
String nameWithoutExtension = FileUtil.getNameWithoutExtension(pathname);
|
||||
if (nameWithoutExtension.endsWith(".answer") || name.contains(EduNames.WINDOWS_POSTFIX) || name.contains(".idea")
|
||||
|| FileUtil.filesEqual(pathname, zipFile)) {
|
||||
return false;
|
||||
}
|
||||
return manager != null && !manager.doNotPackFile(pathname);
|
||||
}
|
||||
}, null);
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(file.getPath()), file.getName(), null, null);
|
||||
}
|
||||
zos.close();
|
||||
Messages.showInfoMessage("Course archive was saved to " + zipFile.getPath(), "Course Archive Was Created Successfully");
|
||||
@@ -145,12 +233,12 @@ public class CCCreateCourseArchive extends DumbAwareAction {
|
||||
}
|
||||
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
private static void generateJson(@NotNull final Project project) {
|
||||
private static void generateJson(@NotNull final Project project, VirtualFile parentDir) {
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
|
||||
final String json = gson.toJson(course);
|
||||
final File courseJson = new File(project.getBasePath(), EduNames.COURSE_META_FILE);
|
||||
final File courseJson = new File(parentDir.getPath(), EduNames.COURSE_META_FILE);
|
||||
OutputStreamWriter outputStreamWriter = null;
|
||||
try {
|
||||
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(courseJson), "UTF-8");
|
||||
|
||||
+5
@@ -10,6 +10,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.jetbrains.edu.EduNames;
|
||||
import com.jetbrains.edu.coursecreator.CCProjectService;
|
||||
import com.jetbrains.edu.coursecreator.CCUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -30,6 +31,10 @@ public class CCTreeStructureProvider implements TreeStructureProvider, DumbAware
|
||||
Project project = node.getProject();
|
||||
if (project != null) {
|
||||
if (node.getValue() instanceof PsiDirectory) {
|
||||
String name = ((PsiDirectory)node.getValue()).getName();
|
||||
if (CCUtils.GENERATED_FILES_FOLDER.equals(name)) {
|
||||
continue;
|
||||
}
|
||||
PsiDirectory directory = (PsiDirectory)node.getValue();
|
||||
nodes.add(new CCDirectoryNode(project, directory, settings));
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user