From 8d42b6f44ca5b0eeb54938e1cf9509d1f8294f00 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 29 Jul 2021 15:39:31 +0200 Subject: Refactored & improved the backend yet again --- packages/server/src/git/blob.ts | 2 +- packages/server/src/git/tag.ts | 58 +++++++++++++++----------------------- packages/server/src/git/tree.ts | 36 ++++++++++++++++++++--- packages/server/src/routes/repo.ts | 4 +-- packages/server/tsconfig.json | 2 +- 5 files changed, 58 insertions(+), 44 deletions(-) diff --git a/packages/server/src/git/blob.ts b/packages/server/src/git/blob.ts index 4dadc01..5d1d892 100644 --- a/packages/server/src/git/blob.ts +++ b/packages/server/src/git/blob.ts @@ -23,7 +23,7 @@ export class Blob { * Returns the blob's content */ public async content(): Promise { - return (await this._tree_entry.ng_tree_entry.getBlob()).content.toString(); + return (await this._tree_entry.ng_tree_entry.getBlob()).content().toString(); } /** diff --git a/packages/server/src/git/tag.ts b/packages/server/src/git/tag.ts index b01ac98..2c1f6ae 100644 --- a/packages/server/src/git/tag.ts +++ b/packages/server/src/git/tag.ts @@ -1,33 +1,13 @@ import { Object as NodeGitObject, Tag as NodeGitTag } from "nodegit"; -import { Pack, pack } from "tar-stream"; import { Commit } from "./commit"; import { FastifyReply } from "fastify"; import { Reference } from "./reference"; import { Repository } from "./repository"; -import { BlobTreeEntry, TreeEntry } from "./tree_entry"; import { createGzip } from "zlib"; import { pipeline } from "stream"; import { createError, TagError } from "./error"; import { Author } from "../../../shared_types/src"; -import { Tree } from "./tree"; - -/** - * Recursively go through a repository and add it's content to a archive - * - * @param tree - A tree to add archive entries from - * @param repository - The repository which the tree is in - * @param archive - A tar archive pack - */ -async function addArchiveEntries(tree: Tree, repository: string, archive: Pack) { - for(const tree_entry of tree.entries()) { - if(tree_entry instanceof BlobTreeEntry) { - archive.entry({ name: `${repository}/${tree_entry.path}` }, (await (await tree_entry.blob()).content())); - } - else if(tree_entry instanceof TreeEntry) { - await addArchiveEntries((await tree_entry.tree()), repository, archive); - } - } -} +import { promisify } from "util"; /** * A representation of a tag @@ -67,29 +47,35 @@ export class Tag extends Reference { const commit = await Commit.lookup(this._owner, (await this._ng_reference.peel(NodeGitObject.TYPE.COMMIT)).id()); const tree = await commit.tree(); - const archive = pack(); - const gzip = createGzip(); - reply.raw.writeHead(200, { "Content-Encoding": "gzip", "Content-Type": "application/gzip", "Content-Disposition": `attachment; filename="${this._owner.name.short}-${this._owner.name.short}.tar.gz"` }); - pipeline(archive, gzip, reply.raw, () => reply.raw.end()); + const archive = await tree.createArchive().catch((err: Error) => err); + + if(archive instanceof Error) { + console.log(archive); + reply.raw.end(); + return; + } + + const gzip = createGzip(); + + promisify(pipeline)(archive, gzip, reply.raw); - gzip.on("close", () => reply.raw.end()); - gzip.on("error", () => reply.raw.end()); - archive.on("error", () => reply.raw.end()); + // Gzip error + gzip.on("error", err => { + console.log(err); + reply.raw.end(); + }); - addArchiveEntries(tree, this._owner.name.short, archive) - .then(() => { - archive.finalize(); - }) - .catch(() => { - archive.finalize(); - reply.raw.end(); - }); + // Tar error + archive.on("error", err => { + console.log(err); + reply.raw.end(); + }); } /** diff --git a/packages/server/src/git/tree.ts b/packages/server/src/git/tree.ts index 6c08e1a..2d3888e 100644 --- a/packages/server/src/git/tree.ts +++ b/packages/server/src/git/tree.ts @@ -1,7 +1,8 @@ import { Tree as NodeGitTree } from "nodegit"; import { Repository } from "./repository"; -import { BaseTreeEntry, createTreeEntry, TreeEntry } from "./tree_entry"; +import { BaseTreeEntry, BlobTreeEntry, createTreeEntry, TreeEntry } from "./tree_entry"; import { createError, TreeError } from "./error"; +import { pack, Pack } from "tar-stream"; /** * A representation of a git tree @@ -27,8 +28,8 @@ export class Tree { * * @returns An array of tree entry instances */ - public entries(): TreeEntry[] { - return this._ng_tree.entries().map(entry => new TreeEntry(this._owner, entry)); + public entries(): BaseTreeEntry[] { + return this._ng_tree.entries().map(entry => createTreeEntry(this._owner, entry)); } /** @@ -40,7 +41,7 @@ export class Tree { public async find(path: string): Promise { const entry = await this._ng_tree.getEntry(path).catch(err => { if(err.errno === -3) { - throw(createError(TreeError, 404, "Path not found")); + throw(createError(TreeError, 404, `Path '${path}' not found`)); } throw(createError(TreeError, 500, "Failed to get tree path")); }); @@ -60,6 +61,33 @@ export class Tree { .catch(() => false); } + /** + * Returns an archive made from the tree + * + * @returns An instance of a tar pack + */ + async createArchive(): Promise { + const archive = pack(); + const repository = this._owner.name.short; + + async function addEntries(tree: Tree) { + for(const tree_entry of tree.entries()) { + if(tree_entry instanceof BlobTreeEntry) { + archive.entry({ name: `${repository}/${tree_entry.path}` }, (await (await tree_entry.blob()).content())); + } + else if(tree_entry instanceof TreeEntry) { + await addEntries(await tree_entry.tree()); + } + } + } + + await addEntries(this); + + archive.finalize(); + + return archive; + } + /** * Returns the tree of a repository * diff --git a/packages/server/src/routes/repo.ts b/packages/server/src/routes/repo.ts index ce81dcd..99c2295 100644 --- a/packages/server/src/routes/repo.ts +++ b/packages/server/src/routes/repo.ts @@ -62,14 +62,14 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do method: "GET", url: "/refs/tags/:tag", handler: async(req, reply) => { - const repository: Repository | BaseError = await Repository.open(opts.settings.base_dir, req.params.repo).catch(err => err); + const repository = await Repository.open(opts.config.settings.base_dir, req.params.repo).catch((err: BaseError) => err); if(repository instanceof BaseError) { reply.code(repository.code).send(repository.message); return; } - const tag = await Tag.lookup(repository, req.params.tag).catch(err => err); + const tag = await Tag.lookup(repository, req.params.tag).catch((err: BaseError) => err); if(tag instanceof BaseError) { reply.code(tag.code).send(tag.message); diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index 9fdaf11..272318b 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "ES2020", - "module": "ES2020", + "module": "CommonJS", "outDir": "dist", "strict": true, "esModuleInterop": true, -- cgit v1.2.3-18-g5258