|
|
@@ -12,6 +12,7 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Optional;
|
|
|
import java.util.Set;
|
|
|
+import java.util.concurrent.ThreadPoolExecutor;
|
|
|
import java.util.function.Function;
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
@@ -52,18 +53,18 @@ public class SubmissionSetBuilder {
|
|
|
* @throws ExitException if the directory cannot be read.
|
|
|
*/
|
|
|
public SubmissionSet buildSubmissionSet() throws ExitException {
|
|
|
- Set<File> submissionDirectories = verifyRootDirectories(options.submissionDirectories(), true);
|
|
|
- Set<File> oldSubmissionDirectories = verifyRootDirectories(options.oldSubmissionDirectories(), false);
|
|
|
- checkForNonOverlappingRootDirectories(submissionDirectories, oldSubmissionDirectories);
|
|
|
+ Set<File> submissionDirectories = verifyRootDirectories(options.submissionDirectories(), true); // 检测根目录是否存在、根目录去重
|
|
|
+ Set<File> oldSubmissionDirectories = verifyRootDirectories(options.oldSubmissionDirectories(), false); // 同上
|
|
|
+ checkForNonOverlappingRootDirectories(submissionDirectories, oldSubmissionDirectories); // old目录中去掉交集
|
|
|
|
|
|
// For backward compatibility, don't prefix submission names with their root directory
|
|
|
// if there is only one root directory.
|
|
|
- int numberOfRootDirectories = submissionDirectories.size() + oldSubmissionDirectories.size();
|
|
|
+ int numberOfRootDirectories = submissionDirectories.size() + oldSubmissionDirectories.size(); // 所有的根目录数量
|
|
|
boolean multipleRoots = (numberOfRootDirectories > 1);
|
|
|
|
|
|
// Collect valid looking entries from the root directories.
|
|
|
Map<File, Submission> foundSubmissions = new HashMap<>();
|
|
|
- for (File directory : submissionDirectories) {
|
|
|
+ for (File directory : submissionDirectories) { // 对于每个根目录,找到符合条件的二级目录,构造submission(二级目录往下递归),填充foundSubmissions
|
|
|
processRootDirectoryEntries(directory, multipleRoots, foundSubmissions, true);
|
|
|
}
|
|
|
for (File oldDirectory : oldSubmissionDirectories) {
|
|
|
@@ -71,7 +72,7 @@ public class SubmissionSetBuilder {
|
|
|
}
|
|
|
|
|
|
Optional<Submission> baseCodeSubmission = loadBaseCode();
|
|
|
- baseCodeSubmission.ifPresent(baseSubmission -> foundSubmissions.remove(baseSubmission.getRoot()));
|
|
|
+ baseCodeSubmission.ifPresent(baseSubmission -> foundSubmissions.remove(baseSubmission.getRoot())); // foundSubmissions里面去除掉baseSubmission
|
|
|
|
|
|
// Merge everything in a submission set.
|
|
|
List<Submission> submissions = new ArrayList<>(foundSubmissions.values());
|
|
|
@@ -111,14 +112,15 @@ public class SubmissionSetBuilder {
|
|
|
private void checkForNonOverlappingRootDirectories(Set<File> submissionDirectories, Set<File> oldSubmissionDirectories) {
|
|
|
|
|
|
Set<File> commonRootdirectories = new HashSet<>(submissionDirectories);
|
|
|
- commonRootdirectories.retainAll(oldSubmissionDirectories);
|
|
|
- if (commonRootdirectories.isEmpty()) {
|
|
|
+ commonRootdirectories.retainAll(oldSubmissionDirectories); // 新旧根目录取交集
|
|
|
+ if (commonRootdirectories.isEmpty()) { // 没有交集就不管
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// As old submission directories are only read while new submission directories are both read and checked, the
|
|
|
// former use can be removed without affecting the result of the checks.
|
|
|
- oldSubmissionDirectories.removeAll(commonRootdirectories);
|
|
|
+ // 由于旧的提交目录只被读取,而新的提交目录同时被读取和检查,因此可以在不影响检查结果的情况下删除旧的使用
|
|
|
+ oldSubmissionDirectories.removeAll(commonRootdirectories); // 旧的根目录中去掉交集
|
|
|
for (File rootDirectory : commonRootdirectories) {
|
|
|
logger.warn(
|
|
|
"Root directory \"{}\" is specified both for plagiarism checking and for prior submissions, will perform plagiarism checking only.",
|
|
|
@@ -175,11 +177,11 @@ public class SubmissionSetBuilder {
|
|
|
* @return Error message if the entry should be ignored.
|
|
|
*/
|
|
|
private String isExcludedEntry(File submissionEntry) {
|
|
|
- if (isFileExcluded(submissionEntry)) {
|
|
|
+ if (isFileExcluded(submissionEntry)) { // 排除掉excludedFileNames里面的文件/文件夹
|
|
|
return "Exclude submission: " + submissionEntry.getName();
|
|
|
}
|
|
|
|
|
|
- if (submissionEntry.isFile() && !hasValidSuffix(submissionEntry)) {
|
|
|
+ if (submissionEntry.isFile() && !hasValidSuffix(submissionEntry)) { // 保留后缀匹配的文件
|
|
|
return "Ignore submission with invalid suffix: " + submissionEntry.getName();
|
|
|
}
|
|
|
return null;
|
|
|
@@ -194,9 +196,9 @@ public class SubmissionSetBuilder {
|
|
|
*/
|
|
|
private Submission processSubmission(String submissionName, File submissionFile, boolean isNew) throws ExitException {
|
|
|
|
|
|
- if (submissionFile.isDirectory() && options.subdirectoryName() != null) {
|
|
|
+ if (submissionFile.isDirectory() && options.subdirectoryName() != null) { // 如指定了要处理的文件夹(比如src/)
|
|
|
// Use subdirectory instead
|
|
|
- submissionFile = new File(submissionFile, options.subdirectoryName());
|
|
|
+ submissionFile = new File(submissionFile, options.subdirectoryName()); // 则处理该三级文件夹
|
|
|
|
|
|
if (!submissionFile.exists()) {
|
|
|
throw new SubmissionException(
|
|
|
@@ -208,6 +210,7 @@ public class SubmissionSetBuilder {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 将文件路径转化为的绝对路径
|
|
|
submissionFile = makeCanonical(submissionFile, it -> new SubmissionException("Cannot create submission: " + submissionName, it));
|
|
|
return new Submission(submissionName, submissionFile, isNew, parseFilesRecursively(submissionFile), language);
|
|
|
}
|
|
|
@@ -220,13 +223,17 @@ public class SubmissionSetBuilder {
|
|
|
*/
|
|
|
private void processRootDirectoryEntries(File rootDirectory, boolean multipleRoots, Map<File, Submission> foundSubmissions, boolean isNew)
|
|
|
throws ExitException {
|
|
|
- for (String fileName : listSubmissionFiles(rootDirectory)) {
|
|
|
- File submissionFile = new File(rootDirectory, fileName);
|
|
|
+ for (String fileName : listSubmissionFiles(rootDirectory)) { // 列出根目录下所有二级目录的文件、文件夹
|
|
|
+ File submissionFile = new File(rootDirectory, fileName); // 构造二级目录所代表的文件
|
|
|
|
|
|
- String errorMessage = isExcludedEntry(submissionFile);
|
|
|
+ String errorMessage = isExcludedEntry(submissionFile); // 排除掉部分无效文件/文件夹(二级目录)
|
|
|
if (errorMessage == null) {
|
|
|
- String rootDirectoryPrefix = multipleRoots ? (rootDirectory.getName() + File.separator) : "";
|
|
|
+ String rootDirectoryPrefix = multipleRoots ? (rootDirectory.getName() + File.separator) : ""; // 拼接根目录
|
|
|
String submissionName = rootDirectoryPrefix + fileName;
|
|
|
+ /*
|
|
|
+ * submissionName: 二级目录/文件名(从根路径拼接的相对路径)
|
|
|
+ * submissionFile: 二级目录/文件
|
|
|
+ * */
|
|
|
Submission submission = processSubmission(submissionName, submissionFile, isNew);
|
|
|
foundSubmissions.put(submission.getRoot(), submission);
|
|
|
} else {
|
|
|
@@ -265,11 +272,11 @@ public class SubmissionSetBuilder {
|
|
|
* @return a list of nested files.
|
|
|
*/
|
|
|
private Collection<File> parseFilesRecursively(File file) {
|
|
|
- if (isFileExcluded(file)) {
|
|
|
+ if (isFileExcluded(file)) { // 排除文件/文件夹
|
|
|
return Collections.emptyList();
|
|
|
}
|
|
|
|
|
|
- if (file.isFile() && hasValidSuffix(file)) {
|
|
|
+ if (file.isFile() && hasValidSuffix(file)) { // 保留后缀匹配的文件
|
|
|
return Collections.singletonList(file);
|
|
|
}
|
|
|
|