diff --git a/packages/hydrooj/src/entry/master.ts b/packages/hydrooj/src/entry/master.ts index 686937bb..72df7aec 100644 --- a/packages/hydrooj/src/entry/master.ts +++ b/packages/hydrooj/src/entry/master.ts @@ -75,7 +75,10 @@ export async function load(call: Entry) { logger.info('Upgrading database: from %d to %d', dbVer, expected); if (isFresh) { const func = scripts[dbVer].toString(); - if (func.includes('_FRESH_INSTALL_IGNORE')) continue; + if (func.includes('_FRESH_INSTALL_IGNORE')) { + dbVer++; + continue; + } } const result = await scripts[dbVer](); if (!result) break; diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 2786792b..2a31eae6 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -92,7 +92,7 @@ export interface User extends Dictionary { export type Udict = NumericDictionary; -export interface ProblemData { +export interface FileInfo { name: string, size: number, } @@ -172,7 +172,8 @@ declare module './model/problem' { nAccept: number, tag: string[], category: string[], - data: ProblemData[], + data: FileInfo[], + additional_file: FileInfo[], hidden: boolean, acMsg?: string, html?: boolean, diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index ecebc18c..71b1e116 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -158,6 +158,18 @@ export async function delTestdata(domainId: string, pid: number, name: string | await pull(domainId, pid, 'data', names); } +export async function addAdditionalFile(domainId: string, pid: number, name: string, f: Readable | Buffer | string) { + await storage.put(`problem/${domainId}/${pid}/additional_file/${name}`, f); + const meta = await storage.getMeta(`problem/${domainId}/${pid}/additional_file/${name}`); + return await push(domainId, pid, 'additional_file', meta); +} + +export async function delAdditionalFile(domainId: string, pid: number, name: string | string[]) { + const names = name instanceof Array ? name : [name]; + await storage.del(names.map((t) => `problem/${domainId}/${pid}/additional_file/${t}`)); + await pull(domainId, pid, 'additional_file', names); +} + export async function random(domainId: string, query: FilterQuery): Promise { const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query); const pcount = await cursor.count(); @@ -239,6 +251,8 @@ global.Hydro.model.problem = { random, addTestdata, delTestdata, + addAdditionalFile, + delAdditionalFile, getMulti, getList, getListStatus, diff --git a/packages/hydrooj/src/upgrade.ts b/packages/hydrooj/src/upgrade.ts index 55207187..8aecc61b 100644 --- a/packages/hydrooj/src/upgrade.ts +++ b/packages/hydrooj/src/upgrade.ts @@ -119,33 +119,6 @@ const scripts: UpgradeScript[] = [ } domainProgress.stop(); } - const udocs = await user.getMulti().project({ _id: 1, uname: 1 }).toArray(); - const userfileProgress = Progress.create({ - items: udocs.length, title: 'Users', y: 3, - }); - for (const udoc of udocs) { - userfileProgress.startItem(`${udoc._id}: ${udoc.uname}`); - const ufdocs = await coll.find({ owner: udoc._id }).toArray(); - const currentUser = Progress.create({ - items: ufdocs.length, title: `${udoc._id}: ${udoc.uname}`, y: 4, eta: true, - }); - const namelist = []; - for (const ufdoc of ufdocs) { - currentUser.startItem(`${ufdoc._id}: ${ufdoc.filename || ''}`); - ufdoc.filename = ufdoc.filename || ufdoc._id.toHexString(); - const file = await streamToBuffer(gridfs.openDownloadStream(ufdoc._id)); - if (!namelist.includes(ufdoc.filename)) { - await storage.put(`user/${udoc._id}/${ufdoc.filename}`, file); - } else { - await storage.put(`user/${udoc._id}/${ufdoc._id}`, file); - } - namelist.push(ufdoc.filename); - currentUser.itemDone(`${ufdoc._id}: ${ufdoc.filename || ''}`); - } - currentUser.stop(); - userfileProgress.itemDone(`${udoc._id}: ${udoc.uname}`); - } - userfileProgress.stop(); logger.success('Files copied successfully. You can now remove collection `file` `fs.files` `fs.chunks` in the database.'); return true; }, @@ -176,7 +149,7 @@ const scripts: UpgradeScript[] = [ await storage.get(dst) .catch(() => { const cfg = yaml.dump(pdoc.config); - return storage.put(dst, Buffer.from(cfg)); + return problem.addTestdata(pdoc.domainId, pdoc.docId, 'config.yaml', Buffer.from(cfg)); }); }); return true; diff --git a/packages/import-qduoj/handler.ts b/packages/import-qduoj/handler.ts index c8bdcecc..87befb79 100644 --- a/packages/import-qduoj/handler.ts +++ b/packages/import-qduoj/handler.ts @@ -82,14 +82,16 @@ class ImportQduojHandler extends Handler { subtasks: [], }; for (const tc of pdoc.test_case_score) { - await storage.put( - `problem/${domainId}/${pid}/testdata/${tc.input_name}`, - path.join(tmp, folder, 'testcase', tc.input_name), - ); - await storage.put( - `problem/${domainId}/${pid}/testdata/${tc.output_name}`, - path.join(tmp, folder, 'testcase', tc.output_name), - ); + await Promise.all([ + problem.addTestdata( + domainId, pid, tc.input_name, + path.join(tmp, folder, 'testcase', tc.input_name), + ), + problem.addTestdata( + domainId, pid, tc.output_name, + path.join(tmp, folder, 'testcase', tc.output_name), + ), + ]); config.subtasks.push({ score: tc.score, cases: [{ @@ -98,12 +100,10 @@ class ImportQduojHandler extends Handler { }], }); } - await storage.put( - `problem/${domainId}/${pid}/testdata/config.yaml`, - Buffer.from(yaml.dump(config)), - ); - const data = await storage.list(`problem/${domainId}/${pid}/testdata/`, true); - await problem.edit(domainId, pid, { html: true, data }); + await Promise.all([ + problem.addTestdata(domainId, pid, 'config.yaml', Buffer.from(yaml.dump(config))), + problem.edit(domainId, pid, { html: true }), + ]); } } catch (e) { console.error(e);