UNPKG

grading

Version:

Grading of student submissions, in particular programming tests.

104 lines (86 loc) 4.93 kB
import { OptionValues } from 'commander'; import * as fs from 'fs'; import path from 'path'; import { hrtime } from 'process'; import { absPath, createDir, ensureFileExists, ensureFolderExists, execShell, fileExists, findDirContainingFile, folderExists, isEmptyDir, readDir, rmDir, rmFile, timestamp, unzip } from '../fsUtil'; import { getPatchFileName, gitAddAndCommit, gitApplyPatch, gitCreateAndCheckoutBranch, hasLocalGitRepository } from '../gitCommands'; import { error, generateFileName, isSubmissionSelected, log, parseSubmitter, retrieveSelectedFilter, retrieveZipFile, substituteVariables, timeDiff, verb, verbosity, warn } from './cliUtil'; import { Submitter } from './submitter'; import { parsePrepareSubmissionCmd } from './cmdCheck'; export async function cmdPrepareAsPrevious(zipFile: string, options: OptionValues) { verbosity(options); log("Prepare submissions to be used as previous submissions in plagiary tool"); try { zipFile = await retrieveZipFile(zipFile, options); await ensureFileExists(zipFile, "Check zip file."); const dry = options.dry; const prevProjectsDir = options.prevProjectsDir; if (!prevProjectsDir) { program.error(`prevProjectsDir must be provided.`); } const prepareSubmissionCmd = parsePrepareSubmissionCmd(options.prepareSubmissionCmd); if (!prepareSubmissionCmd) { program.error(`prepareSubmissionCmd must be provided.`); } const projectFile = options.projectFile; const ignoredDirs = options.ignoredDirs; const submissionsDir = substituteVariables(prevProjectsDir, { zip: zipFile }); verb(`Extract submissions to ${submissionsDir}`); if (await folderExists(submissionsDir, 'submissionsDir')) { verb(`Remove submissions folder ${submissionsDir} (clean).`); await rmDir(submissionsDir); } await unzip(zipFile, submissionsDir); // we always unzip the big file const submissionDirs = await readDir(submissionsDir, 'dir', false, 'Check submissions folder.'); if (submissionDirs.length == 0) { program.error(`No submissions found in ${submissionsDir}`) } 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)); const absSubDir = path.join(submissionsDir, subDir); log(SEP); log(`\nProcessing submission ${counter + 1} of ${submissionDirs.length}: ${subId} ${name}\n`, options.colorSection); // find the submitted zip file: let submittedFiles = await readDir(absSubDir, 'file'); if (submittedFiles.length != 1) { log(`Warning: ${name} submitted ${submittedFiles.length} files`); if (submittedFiles.length > 1) { submittedFiles = submittedFiles.filter(f => f.endsWith('.zip')); if (submittedFiles.length != 1) { log(`Warning: ${name} submitted ${submittedFiles.length} zip-files, take first one.`); } submittedFiles = [submittedFiles[0]] } if (submittedFiles.length != 1) { log(`Warning: Skipping submission of ${name}.`); continue; } } // unzip the submitted zip file const wsDir = path.join(submissionsDir, subDir, 'ws' + (name ? "_" + name.replace(/ /g, '_') : "")); if (await folderExists(wsDir)) { log(`Remove workspace folder ${wsDir}.`) await rmDir(wsDir); } await createDir(wsDir); const subZip = path.join(absSubDir, submittedFiles[0]) await unzip(subZip, wsDir); // find project folder, usually the one folder contained in the submission const projectDir = await findDirContainingFile(wsDir, projectFile, ignoredDirs); // usually git reset --hard await execShell(prepareSubmissionCmd.cmd, prepareSubmissionCmd.args, { ...options, colored: options.colored || false, colorStandard: options.colorPre }, { indent: false, prefix: 'pre: ', cwd: projectDir }); } catch (err) { const msg = `${name}: ${err instanceof Error ? err.message : err}` error(`${msg}`) error(`Continue with next submission.`) } } } catch (err) { error(`${SEP}`); program.error(String(err)); } }