Make repos work
This commit is contained in:
parent
d37b94c465
commit
29eaecc764
@ -1,2 +1 @@
|
||||
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
|
||||
GIT_REPO_DIR="./repo"
|
||||
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
|
1
web/.gitignore
vendored
1
web/.gitignore
vendored
@ -8,3 +8,4 @@ node_modules
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
temp
|
||||
|
136
web/package-lock.json
generated
136
web/package-lock.json
generated
@ -10,12 +10,15 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.13.0",
|
||||
"@sveltejs/adapter-node": "^1.2.4",
|
||||
"axios": "^1.4.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"diff": "^5.1.0",
|
||||
"diff2html": "^3.4.35",
|
||||
"highlight.js": "^11.8.0",
|
||||
"memfs": "^3.5.1",
|
||||
"node-git-server": "^1.0.0",
|
||||
"prisma": "^4.13.0",
|
||||
"simple-git": "^3.18.0",
|
||||
"uuid": "^9.0.0",
|
||||
"zod": "^3.21.4"
|
||||
},
|
||||
@ -489,6 +492,19 @@
|
||||
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@kwsites/file-exists": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
||||
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@kwsites/promise-deferred": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
|
||||
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@ -1124,6 +1140,21 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@ -1291,6 +1322,17 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
@ -1354,6 +1396,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-indent": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
|
||||
@ -1808,6 +1858,43 @@
|
||||
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-monkey": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
|
||||
"integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -2221,6 +2308,17 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/memfs": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz",
|
||||
"integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==",
|
||||
"dependencies": {
|
||||
"fs-monkey": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
@ -2254,6 +2352,25 @@
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/min-indent": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||
@ -2579,6 +2696,11 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
@ -2784,6 +2906,20 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-git": {
|
||||
"version": "3.18.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.18.0.tgz",
|
||||
"integrity": "sha512-Yt0GJ5aYrpPci3JyrYcsPz8Xc05Hi4JPSOb+Sgn/BmPX35fn/6Fp9Mef8eMBCrL2siY5w4j49TA5Q+bxPpri1Q==",
|
||||
"dependencies": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
"@kwsites/promise-deferred": "^1.1.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/steveukx/git-js?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/sirv": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz",
|
||||
|
@ -35,12 +35,15 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.13.0",
|
||||
"@sveltejs/adapter-node": "^1.2.4",
|
||||
"axios": "^1.4.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"diff": "^5.1.0",
|
||||
"diff2html": "^3.4.35",
|
||||
"highlight.js": "^11.8.0",
|
||||
"memfs": "^3.5.1",
|
||||
"node-git-server": "^1.0.0",
|
||||
"prisma": "^4.13.0",
|
||||
"simple-git": "^3.18.0",
|
||||
"uuid": "^9.0.0",
|
||||
"zod": "^3.21.4"
|
||||
}
|
||||
|
@ -13,24 +13,10 @@ export function startGitServer() {
|
||||
? 7006
|
||||
: parseInt(process.env.GIT_PORT);
|
||||
|
||||
if (!process.env.GIT_REPO_DIR) {
|
||||
throw error('GIT_REPO_DIR not specified in .env');
|
||||
}
|
||||
const repoDir = process.env.GIT_REPO_DIR;
|
||||
const repoDir = 'repo';
|
||||
|
||||
repos = new Git(join(repoDir), {
|
||||
autoCreate: false,
|
||||
authenticate: ({ type, user, repo }, next) => {
|
||||
if (type == 'push') {
|
||||
console.log(repo);
|
||||
user((username, password) => {
|
||||
console.log(username, password);
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
autoCreate: true,
|
||||
});
|
||||
|
||||
repos.on('push', (push) => {
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { db } from '$lib/server/prisma';
|
||||
import { join } from 'path';
|
||||
import path, { join } from 'path';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import fs from 'fs';
|
||||
import { error } from 'console';
|
||||
import { repos } from '$lib/server/gitserver';
|
||||
import { simpleGit } from 'simple-git';
|
||||
|
||||
export const load = (async () => {
|
||||
const teams = await db.team.findMany();
|
||||
@ -18,6 +17,22 @@ export const load = (async () => {
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
function copyFolderSync(source: string, target: string) {
|
||||
if (!fs.existsSync(target)) {
|
||||
fs.mkdirSync(target);
|
||||
}
|
||||
|
||||
fs.readdirSync(source).forEach((file) => {
|
||||
const sourcePath = path.join(source, file);
|
||||
const targetPath = path.join(target, file);
|
||||
|
||||
if (fs.lstatSync(sourcePath).isDirectory()) {
|
||||
copyFolderSync(sourcePath, targetPath);
|
||||
} else {
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
export const actions = {
|
||||
create: async ({ request, params }) => {
|
||||
const data = await request.formData();
|
||||
@ -45,28 +60,33 @@ export const actions = {
|
||||
})
|
||||
}
|
||||
},
|
||||
include: { teams: true }
|
||||
include: { teams: true, problems: true }
|
||||
});
|
||||
|
||||
// Create repos
|
||||
|
||||
const repoDir = process.env.GIT_REPO_DIR;
|
||||
if (!repoDir) {
|
||||
throw error(500, 'No repo directory specified in env');
|
||||
if (fs.existsSync('temp')) {
|
||||
fs.rmSync('temp', { recursive: true });
|
||||
}
|
||||
|
||||
if (fs.existsSync(join(repoDir, createdContest.id.toString()))) {
|
||||
fs.rmdirSync(join(repoDir, createdContest.id.toString()), { recursive: true });
|
||||
}
|
||||
|
||||
createdContest.teams.forEach((team) => {
|
||||
repos.create(join(createdContest.id.toString(), team.id.toString()), (e) => {
|
||||
if (e) {
|
||||
throw error(500, `Unable to create repo for team: ${team.name}: ${e.message}`);
|
||||
}
|
||||
fs.mkdirSync('temp');
|
||||
createdContest.teams.forEach(async (team) => {
|
||||
fs.mkdirSync(join('temp', team.id.toString()));
|
||||
const git = simpleGit({ baseDir: join('temp', team.id.toString()) });
|
||||
await git.init();
|
||||
await git.checkoutLocalBranch('master');
|
||||
createdContest.problems.forEach((problem) => {
|
||||
copyFolderSync(
|
||||
'templates/java/problem',
|
||||
join('temp', team.id.toString(), problem.friendlyName)
|
||||
);
|
||||
});
|
||||
await git.add('.');
|
||||
await git.commit('Initial');
|
||||
await git.push(
|
||||
'http://localhost:7006/' + createdContest.id.toString() + '/' + team.id.toString(),
|
||||
'master'
|
||||
);
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let updateInterval: number;
|
||||
let updateInterval: ReturnType<typeof setInterval>;
|
||||
let updating = false;
|
||||
|
||||
onMount(() => {
|
||||
|
@ -18,7 +18,7 @@ export const actions = {
|
||||
return { success: false };
|
||||
}
|
||||
try {
|
||||
await db.team.create({ data: { name: name.toString() } });
|
||||
await db.team.create({ data: { name: name.toString(), password: "thing" } });
|
||||
} catch {
|
||||
return { success: false };
|
||||
}
|
||||
|
@ -6,11 +6,9 @@
|
||||
export let form: Actions;
|
||||
|
||||
let adding = false;
|
||||
let deleting = false;
|
||||
|
||||
$: if (form && form.success) {
|
||||
adding = false;
|
||||
deleting = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -26,23 +24,6 @@
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="text-end">
|
||||
{#if !deleting}
|
||||
<button
|
||||
on:click={() => {
|
||||
deleting = true;
|
||||
}}
|
||||
type="button"
|
||||
class="btn btn-outline-danger">Delete</button
|
||||
>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
deleting = false;
|
||||
}}
|
||||
type="button"
|
||||
class="btn btn-outline-danger">Cancel</button
|
||||
>
|
||||
{/if}
|
||||
{#if !adding}
|
||||
<button
|
||||
on:click={() => {
|
||||
@ -77,21 +58,7 @@
|
||||
<div class="list-group">
|
||||
{#each data.teams as team}
|
||||
<a href={'/admin/teams/' + team.id.toString()} class="list-group-item list-group-item-action">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
{team.name}
|
||||
</div>
|
||||
<div class="col-6">
|
||||
{#if deleting}
|
||||
<form method="POST" action="?/delete" use:enhance>
|
||||
<div class="text-end">
|
||||
<input type="hidden" value={team.id} name="teamId" />
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{team.name}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -34,5 +34,13 @@ export const actions = {
|
||||
return { success: false };
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
delete: async ({ params }) => {
|
||||
try {
|
||||
await db.team.delete({ where: { id: parseInt(params.teamId) } });
|
||||
} catch {
|
||||
return { success: false };
|
||||
}
|
||||
throw redirect(302, '/admin/teams');
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
@ -18,7 +18,27 @@
|
||||
|
||||
<h1 style="text-align:center" class="mb-4">{data.team.name}</h1>
|
||||
|
||||
<a href="/admin/teams" class="mb-3 btn btn-outline-primary">All Teams</a>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<a href="/admin/teams" class="mb-3 btn btn-outline-primary">All Teams</a>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<form
|
||||
method="POST"
|
||||
action="?/delete"
|
||||
use:enhance={({ cancel }) => {
|
||||
if (!confirm('Are you sure?')) {
|
||||
cancel();
|
||||
}
|
||||
return async ({ update }) => {
|
||||
update();
|
||||
};
|
||||
}}
|
||||
>
|
||||
<button type="submit" class="mb-3 btn btn-outline-danger">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
|
5
web/templates/java/problem/Main.java
Normal file
5
web/templates/java/problem/Main.java
Normal file
@ -0,0 +1,5 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user