aboutsummaryrefslogtreecommitdiff
path: root/packages/server/src/git
diff options
context:
space:
mode:
Diffstat (limited to 'packages/server/src/git')
-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
9 files changed, 145 insertions, 37 deletions
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