aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/server/src/api/util.ts26
-rw-r--r--packages/server/src/api/v1/index.ts15
-rw-r--r--packages/server/src/api/v1/repo/branches.ts4
-rw-r--r--packages/server/src/api/v1/repo/index.ts42
-rw-r--r--packages/server/src/api/v1/repo/log.ts6
-rw-r--r--packages/server/src/app.ts34
-rw-r--r--packages/server/src/git/blob.ts4
-rw-r--r--packages/server/src/git/branch.ts21
-rw-r--r--packages/server/src/git/commit.ts6
-rw-r--r--packages/server/src/git/error.ts49
-rw-r--r--packages/server/src/git/misc.ts5
-rw-r--r--packages/server/src/git/reference.ts15
-rw-r--r--packages/server/src/git/repository.ts54
-rw-r--r--packages/server/src/git/tag.ts12
-rw-r--r--packages/server/src/git/tree.ts16
15 files changed, 210 insertions, 99 deletions
diff --git a/packages/server/src/api/util.ts b/packages/server/src/api/util.ts
index e1eaa2c..e7e7657 100644
--- a/packages/server/src/api/util.ts
+++ b/packages/server/src/api/util.ts
@@ -26,30 +26,8 @@ export class VerificationResult {
message: string | null = null;
}
-export function verifyRepoName(base_dir: string, repo_name: string): Promise<VerificationResult> {
- return new Promise<VerificationResult>(resolve => {
- console.log(repo_name);
- const is_valid_repo_name = (/^[a-zA-Z0-9.\-_]+$/u).test(repo_name);
- if(!is_valid_repo_name) {
- resolve(new VerificationResult("INVALID", "repository"));
- return;
- }
-
- readdir(base_dir, (err, dir_content) => {
- if(err) {
- resolve(new VerificationResult("NOT_FOUND", "repository"));
- return;
- }
-
- const dir_content_repos = dir_content.filter(repo => repo.endsWith(".git"));
- if(!dir_content_repos.includes(repo_name + ".git")) {
- resolve(new VerificationResult("NOT_FOUND", "repository"));
- return;
- }
-
- resolve(new VerificationResult("SUCCESS"));
- });
- });
+export function verifyRepoName(repo_name: string): boolean {
+ return /^[a-zA-Z0-9.\-_]+$/u.test(repo_name);
}
export async function verifySHA(repository: Repository, sha: string): Promise<VerificationResult> {
diff --git a/packages/server/src/api/v1/index.ts b/packages/server/src/api/v1/index.ts
index c6b9187..169ba3a 100644
--- a/packages/server/src/api/v1/index.ts
+++ b/packages/server/src/api/v1/index.ts
@@ -4,6 +4,7 @@ import { Route } from "../../fastify_types";
import repo from "./repo";
import { verifyRepoName } from "../util";
import { Info as APIInfo, RepositorySummary as APIRepositorySummary, Repository as APIRepository } from "shared_types";
+import { BaseError } from "../../git/error";
function setHandlers(fastify: FastifyInstance): void {
fastify.setErrorHandler((err, req, reply) => {
@@ -32,7 +33,7 @@ function reposEndpoints(fastify: FastifyInstance, opts: FastifyPluginOptions, do
return <APIRepositorySummary>{
name: repository.name.short,
description: repository.description,
- last_updated: (await repository.latestCommit()).date
+ last_updated: (await repository.masterCommit()).date
};
}))
});
@@ -43,13 +44,17 @@ function reposEndpoints(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/repos/:repo",
handler: async(req, reply) => {
- const repo_verification = await verifyRepoName(opts.config.settings.base_dir, req.params.repo);
- if(repo_verification.success === false && repo_verification.code) {
- reply.code(repo_verification.code).send({ error: repo_verification.message });
+ if(!verifyRepoName(req.params.repo)) {
+ reply.code(400).send({ error: "Bad request" });
return;
}
- const repository = await Repository.open(opts.config.settings.base_dir, req.params.repo);
+ const repository = await Repository.open(opts.config.settings.base_dir, req.params.repo).catch(err => err);
+
+ if(repository instanceof BaseError) {
+ reply.code(repository.code).send({ error: repository.message });
+ return;
+ }
const data: APIRepository = {
name: repository.name.short,
diff --git a/packages/server/src/api/v1/repo/branches.ts b/packages/server/src/api/v1/repo/branches.ts
index b280a4a..c01e858 100644
--- a/packages/server/src/api/v1/repo/branches.ts
+++ b/packages/server/src/api/v1/repo/branches.ts
@@ -8,7 +8,7 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/branches",
handler: async(req, reply) => {
- const branches = await (await req.repository).branches();
+ const branches = await req.repository.branches();
reply.send({
data: branches.map(branch => {
@@ -25,7 +25,7 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/branches/:branch",
handler: async(req, reply) => {
- const branch = await Branch.lookup(await req.repository, req.params.branch);
+ const branch = await Branch.lookup(req.repository, req.params.branch);
if(!branch) {
reply.code(404).send({ error: "Branch not found!" });
diff --git a/packages/server/src/api/v1/repo/index.ts b/packages/server/src/api/v1/repo/index.ts
index 8fc9ac1..e33484a 100644
--- a/packages/server/src/api/v1/repo/index.ts
+++ b/packages/server/src/api/v1/repo/index.ts
@@ -9,26 +9,31 @@ import branches from "./branches";
import log from "./log";
import { verifyRepoName } from "../../util";
import { Tree as APITree, Tag as APITag, TreeEntry as APITreeEntry } from "shared_types";
+import { BaseError } from "../../../git/error";
+import { Tree } from "../../../git/tree";
declare module "fastify" {
interface FastifyRequest {
- repository: Promise<Repository>,
+ repository: Repository,
}
}
function addHooks(fastify: FastifyInstance, opts: FastifyPluginOptions): void {
- fastify.addHook("preHandler", (req: CoolFastifyRequest, reply, hookDone) => {
- req.repository = Repository.open(opts.config.settings.base_dir, req.params.repo);
+ fastify.addHook("preHandler", async(req: CoolFastifyRequest, reply) => {
+ const repository = await Repository.open(opts.config.settings.base_dir, req.params.repo, req.query.branch).catch((err: BaseError) => err);
- hookDone();
+ if(repository instanceof BaseError) {
+ reply.code(repository.code).send({ error: repository.message });
+ return;
+ }
+
+ req.repository = repository;
});
fastify.addHook("onRequest", async(req: CoolFastifyRequest, reply) => {
- const repo_verification = await verifyRepoName(opts.config.settings.base_dir, req.params.repo);
- if(repo_verification.success === false && repo_verification.code) {
- reply.code(repo_verification.code).send({ error: repo_verification.message });
+ if(!verifyRepoName(req.params.repo)) {
+ reply.code(400).send({ error: "Bad request" });
}
-
});
}
async function treeEntryMap(entry: TreeEntry) {
@@ -63,23 +68,28 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/tree",
handler: async(req, reply) => {
- const tree = await (await req.repository).tree();
+ const tree: Tree | BaseError = await req.repository.tree().catch(err => err);
+
+ if(tree instanceof BaseError) {
+ reply.code(tree.code).send({ error: tree.message });
+ return;
+ }
const tree_path = (Object.keys(req.query).length !== 0 && req.query.path) ? req.query.path : null;
let data: APITree;
if(tree_path) {
- const tree_found = await tree.find(tree_path);
+ const tree_path_entry: Tree | Blob | BaseError = await tree.find(tree_path).catch(err => err);
- if(!tree_found) {
- reply.code(404).send({ error: "Tree path not found!" });
+ if(tree_path_entry instanceof BaseError) {
+ reply.code(tree_path_entry.code).send({ error: tree_path_entry.message });
return;
}
- data = tree_found instanceof Blob
- ? { type: "blob", content: await tree_found.content() }
- : { type: "tree", content: await Promise.all(tree_found.entries().map(treeEntryMap)) };
+ data = tree_path_entry instanceof Blob
+ ? { type: "blob", content: await tree_path_entry.content() }
+ : { type: "tree", content: await Promise.all(tree_path_entry.entries().map(treeEntryMap)) };
}
else {
data = { type: "tree", content: await Promise.all(tree.entries().map(treeEntryMap)) };
@@ -93,7 +103,7 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/tags",
handler: async(req, reply) => {
- const tags = await (await req.repository).tags();
+ const tags = await req.repository.tags();
reply.send({
data: await Promise.all(tags.map(tagMap))
});
diff --git a/packages/server/src/api/v1/repo/log.ts b/packages/server/src/api/v1/repo/log.ts
index 8157696..fb876b8 100644
--- a/packages/server/src/api/v1/repo/log.ts
+++ b/packages/server/src/api/v1/repo/log.ts
@@ -37,7 +37,7 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/log",
handler: async(req, reply) => {
- const commits = (await (await req.repository).commits());
+ const commits = await req.repository.commits();
reply.send({
data: await Promise.all(commits.map(commitMap))
@@ -49,12 +49,12 @@ export default function(fastify: FastifyInstance, opts: FastifyPluginOptions, do
method: "GET",
url: "/log/:commit",
handler: async(req, reply) => {
- const commit_verification = await verifySHA(await req.repository, req.params.commit);
+ const commit_verification = await verifySHA(req.repository, req.params.commit);
if(commit_verification.success === false && commit_verification.code) {
reply.code(commit_verification.code).send({ error: commit_verification.message });
}
- const commit = await Commit.lookup(await req.repository, req.params.commit);
+ const commit = await Commit.lookup(req.repository, req.params.commit);
const stats = await commit.stats();
diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts
index 7bc66b2..ae220a9 100644
--- a/packages/server/src/app.ts
+++ b/packages/server/src/app.ts
@@ -9,6 +9,7 @@ import fastifyStatic from "fastify-static";
import { join } from "path";
import { load } from "js-yaml";
import { verifyRepoName } from "./api/util";
+import { BaseError } from "./git/error";
type Settings = {
host: string,
@@ -95,9 +96,9 @@ fastify.route<Route>({
handler: async(req, reply) => {
reply.header("Content-Type", "application/x-git-upload-pack-advertisement");
- const repo_verification = await verifyRepoName(settings.base_dir, req.params.repo);
- if(repo_verification.success === false && repo_verification.code) {
- reply.code(repo_verification.code).send(repo_verification.message);
+ if(!verifyRepoName(req.params.repo)) {
+ reply.code(400).send({ error: "Bad request" });
+ return;
}
if(!req.query.service) {
@@ -126,11 +127,9 @@ fastify.route<Route>({
method: "POST",
url: "/:repo([a-zA-Z0-9\\.\\-_]+)/git-upload-pack",
handler: async(req, reply) => {
- const repo_verification = await verifyRepoName(settings.base_dir, req.params.repo);
-
- if(repo_verification.success === false && repo_verification.code) {
- reply.header("Content-Type", "application/x-git-upload-pack-result");
- reply.code(repo_verification.code).send(repo_verification.message);
+ if(!verifyRepoName(req.params.repo)) {
+ reply.code(400).send({ error: "Bad request" });
+ return;
}
const repository = await Repository.open(settings.base_dir, req.params.repo);
@@ -151,11 +150,22 @@ fastify.route<Route>({
method: "GET",
url: "/:repo([a-zA-Z0-9\\.\\-_]+)/refs/tags/:tag",
handler: async(req, reply) => {
- const repository = await Repository.open(settings.base_dir, req.params.repo);
- const tag = await Tag.lookup(repository, req.params.tag);
+ if(!verifyRepoName(req.params.repo)) {
+ reply.code(400).send({ error: "Bad request" });
+ return;
+ }
+
+ const repository: Repository | BaseError = await Repository.open(settings.base_dir, req.params.repo).catch(err => 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);
- if(!tag) {
- reply.code(404).send("Tag not found!");
+ if(tag instanceof BaseError) {
+ reply.code(tag.code).send(tag.message);
return;
}
diff --git a/packages/server/src/git/blob.ts b/packages/server/src/git/blob.ts
index aeb1381..e44a979 100644
--- a/packages/server/src/git/blob.ts
+++ b/packages/server/src/git/blob.ts
@@ -1,4 +1,5 @@
import { TreeEntry as NodeGitTreeEntry } from "nodegit";
+import { BlobError, createError } from "./error";
export class Blob {
private _ng_tree_entry: NodeGitTreeEntry;
@@ -8,6 +9,9 @@ export class Blob {
}
public async content(): Promise<string> {
+ if(!this._ng_tree_entry.isBlob()) {
+ throw(createError(BlobError, 500, "Not a blob"));
+ }
return this._ng_tree_entry.isBlob() ? (await this._ng_tree_entry.getBlob()).toString() : "";
}
} \ No newline at end of file
diff --git a/packages/server/src/git/branch.ts b/packages/server/src/git/branch.ts
index 90241a0..163eca7 100644
--- a/packages/server/src/git/branch.ts
+++ b/packages/server/src/git/branch.ts
@@ -1,10 +1,15 @@
import { CommitSummary } from "./commit";
import { Reference } from "./reference";
import { Repository } from "./repository";
+import { Repository as NodeGitRepository } from "nodegit";
+import { BranchError, createError } from "./error";
export class Branch extends Reference {
public async latestCommit(): Promise<CommitSummary> {
- const latest_commit = this._owner.nodegitRepository.getBranchCommit(this._ng_reference);
+ const latest_commit = this._owner.nodegitRepository.getBranchCommit(this._ng_reference).catch(() => {
+ throw(createError(BranchError, 500, "Failed to get the latest commit"));
+ });
+
return {
id: (await latest_commit).sha(),
message: (await latest_commit).message(),
@@ -12,13 +17,19 @@ export class Branch extends Reference {
};
}
- public static async lookup(owner: Repository, branch: string): Promise<Branch | null> {
+ public static async lookup(owner: Repository, branch: string): Promise<Branch> {
const reference = await owner.nodegitRepository.getBranch(branch).catch(err => {
if(err.errno === -3) {
- return null;
+ throw(createError(BranchError, 404, "Branch not found!"));
}
- throw(err);
+ throw(createError(BranchError, 500, "Something went wrong."));
});
- return reference ? new Branch(owner, reference) : null;
+ return new Branch(owner, reference);
+ }
+
+ public static async lookupExists(ng_repository: NodeGitRepository, branch: string): Promise<boolean> {
+ return ng_repository.getBranch(branch)
+ .then(() => true)
+ .catch(() => false);
}
} \ No newline at end of file
diff --git a/packages/server/src/git/commit.ts b/packages/server/src/git/commit.ts
index 4b3e44b..94afda0 100644
--- a/packages/server/src/git/commit.ts
+++ b/packages/server/src/git/commit.ts
@@ -1,5 +1,5 @@
import { Commit as NodeGitCommit, Oid as NodeGitOid } from "nodegit";
-import { Author } from "./misc";
+import { Author } from "../../../shared_types/src";
import { Diff } from "./diff";
import { Repository } from "./repository";
import { Tree } from "./tree";
@@ -66,4 +66,8 @@ export class Commit {
.then(() => true)
.catch(() => false);
}
+
+ public static async masterCommit(owner: Repository): Promise<Commit> {
+ return new Commit(owner, await owner.nodegitRepository.getMasterCommit());
+ }
} \ No newline at end of file
diff --git a/packages/server/src/git/error.ts b/packages/server/src/git/error.ts
new file mode 100644
index 0000000..0429a6c
--- /dev/null
+++ b/packages/server/src/git/error.ts
@@ -0,0 +1,49 @@
+export abstract class BaseError implements Error {
+ code: number;
+ name: string;
+ message: string;
+ stack?: string | undefined;
+
+ constructor(code: number, message: string) {
+ this.name = "Githermit Error";
+
+ this.code = code;
+ this.message = message;
+ }
+}
+
+export class RepositoryError extends BaseError {
+ constructor(code: number, message: string) {
+ super(code, "A repository error has occured: " + message);
+ }
+}
+
+export class BranchError extends BaseError {
+ constructor(code: number, message: string) {
+ super(code, "A branch error has occured: " + message);
+ }
+}
+
+export class TagError extends BaseError {
+ constructor(code: number, message: string) {
+ super(code, "A tag error has occured: " + message);
+ }
+}
+
+export class TreeError extends BaseError {
+ constructor(code: number, message: string) {
+ super(code, "A tree error has occured: " + message);
+ }
+}
+
+export class BlobError extends BaseError {
+ constructor(code: number, message: string) {
+ super(code, "A blob error has occured: " + message);
+ }
+}
+
+type ErrorConstructorType<T> = new (code: number, message: string) => T;
+
+export function createError<E extends BaseError>(ErrorConstructor: ErrorConstructorType<E>, code: number, message: string): E {
+ return new ErrorConstructor(code, message);
+} \ No newline at end of file
diff --git a/packages/server/src/git/misc.ts b/packages/server/src/git/misc.ts
index fcfaf29..637cb8c 100644
--- a/packages/server/src/git/misc.ts
+++ b/packages/server/src/git/misc.ts
@@ -6,11 +6,6 @@ export async function findAsync<T>(arr: T[], callback: (t: T) => Promise<boolean
return arr[index];
}
-export type Author = {
- name: string,
- email: string
-}
-
export function getFile(base_dir: string, repository: string, file: string): Promise<string | null> {
return new Promise(resolve => {
readFile(`${base_dir}/${repository}/${file}`, (err, content) => {
diff --git a/packages/server/src/git/reference.ts b/packages/server/src/git/reference.ts
index 36f1312..b24f72d 100644
--- a/packages/server/src/git/reference.ts
+++ b/packages/server/src/git/reference.ts
@@ -1,6 +1,16 @@
import { Reference as NodeGitReference } from "nodegit";
import { Repository } from "./repository";
+type ReferenceClass<T> = new(owner: Repository, reference: NodeGitReference) => T;
+
+export function isNodeGitReferenceBranch(ref: NodeGitReference): boolean {
+ return Boolean(ref.isBranch());
+}
+
+export function isNodeGitReferenceTag(ref: NodeGitReference): boolean {
+ return Boolean(ref.isTag());
+}
+
export abstract class Reference {
protected _ng_reference: NodeGitReference;
protected _owner: Repository;
@@ -15,4 +25,9 @@ export abstract class Reference {
this.id = reference.target().tostrS();
this.name = reference.shorthand();
}
+
+ public static async all<T>(owner: Repository, Target: ReferenceClass<T>, ref_fn: (ref: NodeGitReference) => boolean): Promise<T[]> {
+ const references = await owner.nodegitRepository.getReferences();
+ return references.filter(ref_fn).map(ref => new Target(owner, ref));
+ }
} \ No newline at end of file
diff --git a/packages/server/src/git/repository.ts b/packages/server/src/git/repository.ts
index ff23761..c95edaa 100644
--- a/packages/server/src/git/repository.ts
+++ b/packages/server/src/git/repository.ts
@@ -7,6 +7,8 @@ import { Commit } from "./commit";
import { FastifyReply } from "fastify";
import { Tag } from "./tag";
import { Tree } from "./tree";
+import { BranchError, createError, RepositoryError } from "./error";
+import { isNodeGitReferenceBranch, isNodeGitReferenceTag, Reference } from "./reference";
function getFullRepositoryName(repo_name: string) {
return repo_name.endsWith(".git") ? repo_name : `${repo_name}.git`;
@@ -19,12 +21,21 @@ type RepositoryName = {
type RepositoryConstructorData = {
description: string | null,
- owner: string | null
+ owner: string | null,
+ branch: string
+}
+
+// This fucking shit isn't in the Nodegit documentation.
+interface WeirdNodeGitError extends Error {
+ errno: number;
+ errorFunction: string;
}
export class Repository {
private _ng_repository: NodeGitRepository;
+ private _branch: string;
+
public name: RepositoryName;
public base_dir: string;
public description: string | null;
@@ -39,6 +50,12 @@ export class Repository {
this.base_dir = dirname(repository.path());
this.description = data.description;
this.owner = data.owner;
+
+ this._branch = data.branch;
+ }
+
+ public branch(): Promise<Branch> {
+ return Branch.lookup(this, this._branch);
}
public async commits(): Promise<Commit[]> {
@@ -49,9 +66,7 @@ export class Repository {
}
public async tree(): Promise<Tree> {
- const master_commit = await this._ng_repository.getMasterCommit();
- const tree = await master_commit.getTree();
- return new Tree(this, tree);
+ return Tree.ofRepository(this);
}
public lookupExists(id: string): Promise<boolean> {
@@ -60,18 +75,16 @@ export class Repository {
.catch(() => false);
}
- public async branches(): Promise<Branch[]> {
- const references = await this._ng_repository.getReferences();
- return references.filter(ref => ref.isBranch()).map(branch => new Branch(this, branch));
+ public branches(): Promise<Branch[]> {
+ return Reference.all(this, Branch, isNodeGitReferenceBranch);
}
public async tags(): Promise<Tag[]> {
- const references = await this._ng_repository.getReferences();
- return references.filter(ref => ref.isTag()).map(tag => new Tag(this, tag));
+ return Reference.all(this, Tag, isNodeGitReferenceTag);
}
- public async latestCommit(): Promise<Commit> {
- return new Commit(this, await this._ng_repository.getMasterCommit());
+ public async masterCommit(): Promise<Commit> {
+ return Commit.masterCommit(this);
}
public HTTPconnect(req: Request, reply: FastifyReply): void {
@@ -82,12 +95,25 @@ export class Repository {
return this._ng_repository;
}
- public static async open(base_dir: string, repository: string): Promise<Repository> {
- const ng_repository = await NodeGitRepository.openBare(`${base_dir}/${getFullRepositoryName(repository)}`);
+ public static async open(base_dir: string, repository: string, branch?: string): Promise<Repository> {
+ let ng_repository = await NodeGitRepository.openBare(`${base_dir}/${getFullRepositoryName(repository)}`).catch((err: WeirdNodeGitError) => {
+ if(err.errno === -3) {
+ throw(createError(RepositoryError, 404, "Repository not found"));
+ }
+
+ throw(createError(RepositoryError, 500, "Unknown error"));
+ });
+
+ if(branch) {
+ if(!await Branch.lookupExists(ng_repository, branch)) {
+ throw(createError(BranchError, 404, "Branch not found!"));
+ }
+ }
return new Repository(ng_repository, {
description: await getFile(base_dir, getFullRepositoryName(repository), "description"),
- owner: await getFile(base_dir, getFullRepositoryName(repository), "owner")
+ owner: await getFile(base_dir, getFullRepositoryName(repository), "owner"),
+ branch: branch || "master"
});
}
diff --git a/packages/server/src/git/tag.ts b/packages/server/src/git/tag.ts
index 64828e7..3063a25 100644
--- a/packages/server/src/git/tag.ts
+++ b/packages/server/src/git/tag.ts
@@ -1,6 +1,5 @@
import { Object as NodeGitObject, Tag as NodeGitTag } from "nodegit";
import { Pack, pack } from "tar-stream";
-import { Author } from "./misc";
import { Blob } from "./blob";
import { Commit } from "./commit";
import { FastifyReply } from "fastify";
@@ -10,6 +9,8 @@ import { Tree } from "./tree";
import { TreeEntry } from "./tree_entry";
import { createGzip } from "zlib";
import { pipeline } from "stream";
+import { createError, TagError } from "./error";
+import { Author } from "../../../shared_types/src";
async function addArchiveEntries(entries: TreeEntry[], repository: string, archive: Pack) {
for(const tree_entry of entries) {
@@ -69,14 +70,15 @@ export class Tag extends Reference {
});
}
- public static async lookup(owner: Repository, tag: string): Promise<Tag | null> {
+ public static async lookup(owner: Repository, tag: string): Promise<Tag> {
const reference = await owner.nodegitRepository.getReference(tag).catch(err => {
if(err.errno === -3) {
- return null;
+ throw(createError(TagError, 404, "Tag not found"));
}
- throw(err);
+ throw(createError(TagError, 404, "Failed to get tag"));
});
- return reference ? new Tag(owner, reference) : null;
+
+ return new Tag(owner, reference);
}
} \ No newline at end of file
diff --git a/packages/server/src/git/tree.ts b/packages/server/src/git/tree.ts
index 8697010..2cec528 100644
--- a/packages/server/src/git/tree.ts
+++ b/packages/server/src/git/tree.ts
@@ -2,6 +2,7 @@ import { Blob } from "./blob";
import { Tree as NodeGitTree } from "nodegit";
import { Repository } from "./repository";
import { TreeEntry } from "./tree_entry";
+import { createError, TreeError } from "./error";
export class Tree {
private _ng_tree: NodeGitTree;
@@ -16,18 +17,14 @@ export class Tree {
return this._ng_tree.entries().map(entry => new TreeEntry(this._owner, entry));
}
- public async find(path: string): Promise<Blob | Tree | null> {
+ public async find(path: string): Promise<Blob | Tree> {
const entry = await this._ng_tree.getEntry(path).catch(err => {
if(err.errno === -3) {
- return null;
+ throw(createError(TreeError, 404, "Path not found"));
}
- throw(err);
+ throw(createError(TreeError, 500, "Failed to get tree path"));
});
- if(!entry) {
- return null;
- }
-
return entry.isBlob() ? new Blob(entry) : new Tree(this._owner, await entry.getTree());
}
@@ -36,4 +33,9 @@ export class Tree {
.then(() => true)
.catch(() => false);
}
+
+ public static async ofRepository(owner: Repository): Promise<Tree> {
+ const master_commit = await owner.masterCommit();
+ return master_commit.tree();
+ }
} \ No newline at end of file