grading
Version:
Grading of student submissions, in particular programming tests.
88 lines (78 loc) • 4.12 kB
text/typescript
import { OptionValues } from 'commander';
import path from 'path';
import { folderExists, readDir } from '../fsUtil';
import { gitBranches, gitDiff, hasLocalGitRepository } from '../gitCommands';
import { debug, error, isSubmissionSelected, log, parseSubmitter, retrieveSelectedFilter, verb, verbosity, warn } from './cliUtil';
/**
* Basically calls `git diff --no-color --binary --output submission.patch main grading`.
*
* @param options
* @returns
*/
export async function cmdDiff(options: OptionValues) {
verbosity(options);
const submissionsDir: string = options.submissionsDir;
const patchFolder: string = options.patchFolder;
const patchSubmissionBranches: string[] = options.patchSubmissionBranches;
const patchGradingBranch: string = options.patchGradingBranch;
const selected = retrieveSelectedFilter(options);
const dry = options.dry;
try {
if (! await folderExists(submissionsDir, "submissionsDir")) {
program.error(`Submissions folder ${submissionsDir} does not exist yet, first run check (at least with --prepareSubmission).`);
}
const submissionDirs = await readDir(submissionsDir, 'dir', false, 'Diff submissions folder.');
if (submissionDirs.length == 0) {
program.error(`No submissions found in ${submissionsDir}`)
}
verb(`Found ${submissionDirs.length} submissions.`);
let name = "", subId = ""; // define here for catch block
for (let counter = 0; counter < submissionDirs.length; counter++) {
try {
const subDir = submissionDirs[counter];
({ name, submissionId: subId } = parseSubmitter(subDir));
if (!isSubmissionSelected(selected, [], name, subId)) {
verb(`Skip user ${name}, id ${subId}`);
continue;
}
const absSubDir = path.join(submissionsDir, subDir);
verb(`\nProcessing submission ${counter + 1} of ${submissionDirs.length}: ${subId} ${name}\n`);
const wsDir = path.join(submissionsDir, subDir, 'ws' + (name ? "_" + name.replace(/ /g, '_') : ""));
if (! await folderExists(wsDir, 'workspace folder')) {
warn(`Skipping submission of ${name}, workspace folder not unzipped yet.`);
continue;
}
if (! await hasLocalGitRepository(wsDir)) {
warn(`Skipping submission of ${name}, no local git repository found.`);
continue;
}
const branches = await gitBranches(wsDir);
const submissionBranch =
patchSubmissionBranches.find(subBranch => branches.find(br => br === subBranch));
const gradingBranch = branches.find(br => br === patchGradingBranch);
if (!submissionBranch) {
warn(`Skipping submission of ${name}, no matching submission branch found, branches found: ${branches.join()}.`);
continue;
}
if (!gradingBranch) {
verb(`Skipping submission of ${name}, no matching grading branch found, branches found: ${branches.join()}.`);
continue;
}
log(`Create patch file for submission ${name} with difference between ${submissionBranch} and grading branch ${gradingBranch}.`);
if (! dry) {
await gitDiff(wsDir, submissionBranch, gradingBranch, patchFolder, name, subId);
} else {
log(`Dry run: Would run git diff for submission ${name} with diff between ${submissionBranch} and ${gradingBranch}.`);
}
} catch (err) {
const msg = `${name}: ${err instanceof Error ? err.message : err}`
error(`${msg}`)
debug(err)
error(`Continue with next submission.`)
}
}
} catch (err) {
error(`${SEP}`);
program.error(String(err));
}
}