From cb7383a437d9c4e1609fc531cb796064bd2d6127 Mon Sep 17 00:00:00 2001 From: orosmatthew Date: Tue, 17 Oct 2023 12:50:13 -0400 Subject: [PATCH] [extension] Fix submitting --- extension/bwcontest/src/problemPanel.ts | 237 +++++++++--------- extension/bwcontest/src/submit.ts | 85 +++---- .../webviews/components/ProblemPanel.svelte | 15 +- 3 files changed, 166 insertions(+), 171 deletions(-) diff --git a/extension/bwcontest/src/problemPanel.ts b/extension/bwcontest/src/problemPanel.ts index 65c1ed5..ede9f28 100644 --- a/extension/bwcontest/src/problemPanel.ts +++ b/extension/bwcontest/src/problemPanel.ts @@ -5,6 +5,7 @@ import { extensionSettings } from './extension'; import { runJava } from './run/java'; import { join } from 'path'; import { TeamData } from './SidebarProvider'; +import { submitProblem } from './submit'; export type ProblemData = { id: number; @@ -17,7 +18,8 @@ export type ProblemData = { export type MessageType = | { msg: 'onRequestProblemData' } | { msg: 'onRun'; data: { problemId: number; input: string } } - | { msg: 'onKill' }; + | { msg: 'onKill' } + | { msg: 'onSubmit'; data: { problemId: number } }; export type WebviewMessageType = | { msg: 'onProblemData'; data: ProblemData } | { msg: 'onRunning' } @@ -91,11 +93,124 @@ export class BWPanel { this.panel.webview.postMessage(m); } + private async handleSubmit(problemId: number) { + if (this.problemData === undefined) { + console.error('Problem data undefined'); + return; + } + const problem = this.problemData.find((p) => p.id === problemId); + if (problem === undefined) { + console.error('Invalid problem Id'); + return; + } + const sessionToken = this.context.globalState.get('token'); + if (sessionToken === undefined) { + console.error('No session token'); + return; + } + const teamData = this.context.globalState.get('teamData'); + if (teamData === undefined) { + console.error('No team data'); + return; + } + await vscode.workspace.saveAll(); + const ans = await vscode.window.showInformationMessage( + `Are you sure you want to submit ${problem.name}?`, + 'Yes', + 'No' + ); + if (ans !== 'Yes') { + return; + } + submitProblem(sessionToken, teamData.contestId, teamData.teamId, problemId).then((result) => { + if (result.success === true) { + vscode.window.showInformationMessage('Submitted!'); + } else { + vscode.window.showErrorMessage(`Error: ${result.message}`); + } + }); + } + + private async handleRun(problemId: number, input: string) { + const teamData: TeamData | undefined = this.context.globalState.get('teamData'); + if (teamData === undefined) { + return; + } + if (this.problemData === undefined) { + return; + } + if (this.runningProgram !== undefined) { + vscode.window.showErrorMessage('Already Running'); + return; + } + const problem = this.problemData.find((p) => (p.id = problemId)); + if (problem === undefined) { + return; + } + await vscode.workspace.saveAll(); + const repoDir = extensionSettings().repoClonePath; + const outputBuffer: string[] = []; + this.webviewPostMessage({ msg: 'onRunning' }); + this.webviewPostMessage({ msg: 'onRunningOutput', data: '[Compiling...]' }); + + const killFunc = await runJava( + join( + repoDir, + 'BWContest', + teamData.contestId.toString(), + teamData.teamId.toString(), + problem.pascalName + ), + join( + repoDir, + 'BWContest', + teamData.contestId.toString(), + teamData.teamId.toString(), + problem.pascalName, + `${problem.pascalName}.java` + ), + problem.pascalName, + input, + (data: string) => { + outputBuffer.push(data); + this.webviewPostMessage({ msg: 'onRunningOutput', data: outputBuffer.join('') }); + }, + () => { + this.runningProgram = undefined; + this.webviewPostMessage({ msg: 'onRunningDone' }); + } + ); + if (killFunc !== undefined) { + this.runningProgram = { + problemId: problemId, + outputBuffer: outputBuffer, + kill: killFunc + }; + } else { + this.webviewPostMessage({ msg: 'onRunningDone' }); + } + } + + private async handleRequestProblemData() { + const token: string | undefined = this.context.globalState.get('token'); + if (token !== undefined) { + const res = await fetch(urlJoin(this.webUrl, `/api/contest/${token}`)); + const data = await res.json(); + if (data.success === true) { + this.problemData = data.problems; + this.webviewPostMessage({ + msg: 'onProblemData', + data: data.problems + }); + } + } + } + private async update() { const webview = this.panel.webview; this.panel.webview.html = this._getHtmlForWebview(webview); - webview.onDidReceiveMessage(async (m: MessageType) => { + webview.onDidReceiveMessage((m: MessageType) => { switch (m.msg) { case 'onKill': { if (this.runningProgram !== undefined) { @@ -104,124 +219,18 @@ export class BWPanel { } break; } - // this.kill(); - // } - // case 'onSubmit': { - // await vscode.workspace.saveAll(); - // if (!data.value) { - // return; - // } - // const ans = await vscode.window.showInformationMessage( - // `Are you sure you want to submit ${data.value.problemName}?`, - // 'Yes', - // 'No' - // ); - // if (ans !== 'Yes') { - // break; - // } - // try { - // await submitProblem( - // data.value.sessionToken, - // data.value.contestId, - // data.value.teamId, - // data.value.problemId - // ); - // } catch (err: any) { - // vscode.window.showErrorMessage(err.message ?? 'Submission unsuccessful'); - // break; - // } - // vscode.window.showInformationMessage('Submitted!'); - // break; - // } + case 'onSubmit': { + this.handleSubmit(m.data.problemId); + break; + } case 'onRun': { - const teamData: TeamData | undefined = this.context.globalState.get('teamData'); - if (teamData === undefined) { - return; - } - if (this.problemData === undefined) { - return; - } - if (this.runningProgram !== undefined) { - vscode.window.showErrorMessage('Already Running'); - return; - } - const problem = this.problemData.find((p) => (p.id = m.data.problemId)); - if (problem === undefined) { - return; - } - await vscode.workspace.saveAll(); - const repoDir = extensionSettings().repoClonePath; - const outputBuffer: string[] = []; - this.webviewPostMessage({ msg: 'onRunning' }); - this.webviewPostMessage({ msg: 'onRunningOutput', data: '[Compiling...]' }); - - const killFunc = await runJava( - join( - repoDir, - 'BWContest', - teamData.contestId.toString(), - teamData.teamId.toString(), - problem.pascalName - ), - join( - repoDir, - 'BWContest', - teamData.contestId.toString(), - teamData.teamId.toString(), - problem.pascalName, - `${problem.pascalName}.java` - ), - problem.pascalName, - m.data.input, - (data: string) => { - outputBuffer.push(data); - this.webviewPostMessage({ msg: 'onRunningOutput', data: outputBuffer.join('') }); - }, - () => { - this.runningProgram = undefined; - this.webviewPostMessage({ msg: 'onRunningDone' }); - } - ); - if (killFunc !== undefined) { - this.runningProgram = { - problemId: m.data.problemId, - outputBuffer: outputBuffer, - kill: killFunc - }; - } else { - this.webviewPostMessage({ msg: 'onRunningDone' }); - } + this.handleRun(m.data.problemId, m.data.input); break; } case 'onRequestProblemData': { - const token: string | undefined = this.context.globalState.get('token'); - if (token !== undefined) { - const res = await fetch(urlJoin(this.webUrl, `/api/contest/${token}`)); - const data = await res.json(); - if (data.success === true) { - this.problemData = data.problems; - this.webviewPostMessage({ - msg: 'onProblemData', - data: data.problems - }); - } - } + this.handleRequestProblemData(); break; } - // case 'onInfo': { - // if (!data.value) { - // return; - // } - // vscode.window.showInformationMessage(data.value); - // break; - // } - // case 'onError': { - // if (!data.value) { - // return; - // } - // vscode.window.showErrorMessage(data.value); - // break; - // } } }); } diff --git a/extension/bwcontest/src/submit.ts b/extension/bwcontest/src/submit.ts index c386657..d87cd49 100644 --- a/extension/bwcontest/src/submit.ts +++ b/extension/bwcontest/src/submit.ts @@ -1,63 +1,58 @@ import { extensionSettings } from './extension'; -import { exec } from 'child_process'; -import util = require('node:util'); -import axios from 'axios'; - -const execPromise = util.promisify(exec); +import * as fs from 'fs-extra'; +import git from 'isomorphic-git'; +import path = require('path'); +import http from 'isomorphic-git/http/node'; +import urlJoin from 'url-join'; export async function submitProblem( sessionToken: string, contestId: number, teamId: number, problemId: number -) { +): Promise<{ success: true } | { success: false; message: string }> { const repoClonePath = extensionSettings().repoClonePath; - console.log(repoClonePath); - const clonedRepoPath = `${repoClonePath}/BWContest/${contestId.toString()}/${teamId.toString()}`; + const repoDir = path.join(repoClonePath, 'BWContest', contestId.toString(), teamId.toString()); + await git.add({ fs, dir: repoDir, filepath: '.' }); - let output: { stdout: string; stderr: string }; - output = await execPromise(`git add .`, { - cwd: clonedRepoPath + const hash = await git.commit({ + fs, + dir: repoDir, + author: { name: `Team ${teamId}` }, + message: `Submit problem ${problemId}` }); - if (output.stderr) { - console.error(output.stderr); + try { + const result = await git.push({ + fs, + http, + dir: repoDir + }); + if (result.ok !== true) { + return { success: false, message: 'Push failure' }; + } + } catch (error) { + return { success: false, message: 'Unable to push' }; } - output = await execPromise(`git commit -m "Submit problem ${problemId}"`, { - cwd: clonedRepoPath - }); - - if (output.stderr) { - console.error(output.stderr); - } - - output = await execPromise(`git push`, { - cwd: clonedRepoPath - }); - - if (output.stderr) { - console.error(output.stderr); - } - - output = await execPromise(`git rev-parse HEAD`, { - cwd: clonedRepoPath - }); - - if (output.stderr) { - console.error(output.stderr); - } - - const commitHash = output.stdout.toString().replace('\n', ''); - const res = await axios.post(`http://localhost:5173/api/team/${sessionToken}/submit`, { - commitHash: commitHash, - problemId: problemId - }); + const res = await fetch( + urlJoin(extensionSettings().webUrl, '/api/team', sessionToken, '/submit'), + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + commitHash: hash, + problemId: problemId + }) + } + ); if (res.status !== 200) { - throw Error('Failed to post submission'); + return { success: false, message: 'Submission POST failure' }; } - if (!res.data.success) { - throw Error(res.data.message ?? 'Unknown error'); + const resData = await res.json(); + if (resData.success !== true) { + return { success: false, message: resData.message }; } + return { success: true }; } diff --git a/extension/bwcontest/webviews/components/ProblemPanel.svelte b/extension/bwcontest/webviews/components/ProblemPanel.svelte index 3406476..984e1bf 100644 --- a/extension/bwcontest/webviews/components/ProblemPanel.svelte +++ b/extension/bwcontest/webviews/components/ProblemPanel.svelte @@ -50,18 +50,9 @@ } function onSubmit() { - // if (teamId && contestId && sessionToken) { - // postMessage({ - // type: 'onSubmit', - // value: { - // sessionToken: sessionToken, - // contestId: contestId, - // teamId: teamId, - // problemId: activeProblem.id, - // problemName: activeProblem.pascalName - // } - // }); - // } + if (problemData !== undefined) { + postMessage({ msg: 'onSubmit', data: { problemId: problemData[activeProblemIndex].id } }); + } } function onKill() {