UnitTestUpload.java 5.73 KB
Newer Older
Dominik Vayhinger's avatar
Dominik Vayhinger committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package de.hftstuttgart.rest.v1.unittest;

import de.hftstuttgart.config.ModocotProperties;
import de.hftstuttgart.utils.BackendUtil;
import de.hftstuttgart.utils.FileUtil;
import de.hftstuttgart.utils.GitTeaUtil;
import de.hftstuttgart.utils.JGitUtil;
import de.hftstuttgart.utils.UnzipUtil;
import io.gitea.model.Repository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jgit.transport.PushResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.annotation.MultipartConfig;
import java.io.File;
import java.io.IOException;
import java.util.List;
Kammleiter's avatar
Kammleiter committed
23
import java.util.Objects;
Dominik Vayhinger's avatar
Dominik Vayhinger committed
24
import java.util.UUID;
Kammleiter's avatar
Kammleiter committed
25
26
import java.util.stream.Collectors;
import java.util.stream.Stream;
Dominik Vayhinger's avatar
Dominik Vayhinger committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

/**
 * Rest controller for anything related to the TEST files.
 */
@RestController
@RequestMapping("/v1/unittest")
@MultipartConfig
public class UnitTestUpload {

    private static final Logger LOG = LogManager.getLogger(UnitTestUpload.class);

    private final ModocotProperties modocotProperties;
    private final GitTeaUtil gitTeaUtil;
    private final JGitUtil jGitUtil;
    private final String assignmentBasePath;

    public UnitTestUpload(ModocotProperties modocotProperties,
                          GitTeaUtil gitTeaUtil,
                          JGitUtil jGitUtil) {
        this.modocotProperties = modocotProperties;
        this.gitTeaUtil = gitTeaUtil;
        this.jGitUtil = jGitUtil;
        this.assignmentBasePath =
                modocotProperties.getModocotParentDirectory()
                + File.separator
                + modocotProperties.getModocotAssignmentFolderPrefix();
    }

    /**
     * Create a subfolder for the specific assignment.
     * This is called when the teacher creates an assignment and uploads the JUnit test files
     *
     * @param unitTestFileRef The zip file which contains the JUnit tests
     * @param assignmentId    ID of the created assignment. Generated by Moodle
     */
    @RequestMapping(method = RequestMethod.POST)
    public void uploadUnitTestFile(@RequestParam("unitTestFile") MultipartFile unitTestFileRef, @RequestParam("assignmentId") String assignmentId) throws IOException {

        // path to the directory in which we will be working
        String subFolderPath = this.assignmentBasePath + assignmentId;

        LOG.info("work-directory: " + subFolderPath);
        // creating the work-directory
        File workDirectory = new File(subFolderPath);
        workDirectory.mkdirs();

        // creating the file which the unitTestFileRef will be transferred into
        File file = new File(subFolderPath, String.valueOf(UUID.randomUUID()));

        // transferring MultipartFile into temporary file
        unitTestFileRef.transferTo(file);

        // unzipping temporary file to work-directory
        List<File> zipFiles = UnzipUtil.unzip(file);

        // unzipping temporary file (not needed anymore)
        if (file.exists()) file.delete();

        // check if any extracted files are named repo.txt
        if (zipFiles.stream().anyMatch(zipFile -> zipFile.getName().equalsIgnoreCase("repo.txt"))) {
            // reading all from the  repo.txt
            List<String> lines = BackendUtil.extractLinesFromRepoFile(zipFiles, "repo.txt");
            // either set the first line of repo.txt or ""
            String repoUrl = (lines.size() > 0 && !lines.get(0).equals("")) ?
                    lines.get(0) : "";
Kammleiter's avatar
Kammleiter committed
92
            LOG.info("repoUrl: " + repoUrl);
Dominik Vayhinger's avatar
Dominik Vayhinger committed
93
94
95
            // either set the second line of repo.txt or null
            String credentials = ((lines.size() > 1) && !lines.get(1).equals("")) ?
                    lines.get(1) : null;
Kammleiter's avatar
Kammleiter committed
96
            LOG.info("credentials: " + credentials);
Dominik Vayhinger's avatar
Dominik Vayhinger committed
97
            // cloning repository repoUrl into work-directory, using credentials from second line in repo.txt
Kammleiter's avatar
Kammleiter committed
98
            this.jGitUtil.cloneRepository(repoUrl, workDirectory, credentials, credentials != null,true);
Dominik Vayhinger's avatar
Dominik Vayhinger committed
99
100
        }

Kammleiter's avatar
Kammleiter committed
101
102
103
        Stream.of(Objects.requireNonNull(workDirectory.listFiles()))
                .forEach(fi -> System.out.println(fi.getAbsolutePath()));

Dominik Vayhinger's avatar
Dominik Vayhinger committed
104
105
        // creating repository on internal giTea, name = assignmentId
        Repository repo = this.gitTeaUtil.createRepository(assignmentId);
Kammleiter's avatar
Kammleiter committed
106
        System.out.println(repo);
Dominik Vayhinger's avatar
Dominik Vayhinger committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
        // giTea runs in docker and returns CloneUrl as localhost, replacing localhost with docker-host ip
        repo.setCloneUrl(repo.getCloneUrl().replace("localhost", modocotProperties.getDockerHostIp()));

        // committing everything in work-directory and push to created repository
        Iterable<PushResult> pushResults = this.jGitUtil.commitAllAndPush(workDirectory, repo, false);
        if (pushResults != null) {
            for (PushResult pushResult : pushResults) {
                LOG.info("Push-Result: " + pushResult.getMessages());
            }
        }
        // deleting created work-directory
        FileUtil.deleteFolderRecursively(workDirectory);

        LOG.info("Uploaded unit test file: " + workDirectory);
    }

    /**
     * Delete the folder for the assignment.
     * Called when the teacher deletes the JUnitTest assignment
     * <p>
     * {{url}}:8080/v1/unittest?assignmentId=111
     *
     * @param assignmentId ID of the assignment to delete. Generated by Moodle
     */
    @RequestMapping(method = RequestMethod.DELETE)
    public void deleteUnitTestFiles(@RequestParam("assignmentId") String assignmentId) {
        String path = this.assignmentBasePath + assignmentId;
        File dir = new File(path);
        FileUtil.deleteFolderRecursively(dir);
    }
}