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.ts17
-rw-r--r--packages/server/src/git/branch.ts28
-rw-r--r--packages/server/src/git/commit.ts42
-rw-r--r--packages/server/src/git/diff.ts2
-rw-r--r--packages/server/src/git/error.ts8
-rw-r--r--packages/server/src/git/http.ts13
-rw-r--r--packages/server/src/git/misc.ts20
-rw-r--r--packages/server/src/git/patch.ts73
-rw-r--r--packages/server/src/git/reference.ts7
-rw-r--r--packages/server/src/git/repository.ts107
-rw-r--r--packages/server/src/git/tag.ts27
-rw-r--r--packages/server/src/git/tree.ts35
-rw-r--r--packages/server/src/git/tree_entry.ts33
13 files changed, 373 insertions, 39 deletions
diff --git a/packages/server/src/git/blob.ts b/packages/server/src/git/blob.ts
index ef9f9ab..eebd2d4 100644
--- a/packages/server/src/git/blob.ts
+++ b/packages/server/src/git/blob.ts
@@ -2,21 +2,38 @@ import { BlobError, createError } from "./error";
import { Tree } from "./tree";
import { BlobTreeEntry } from "./tree_entry";
+/**
+ * A representation of a blob
+ */
export class Blob {
private _tree_entry: BlobTreeEntry;
public path;
+ /**
+ * @param entry - A tree entry that's a blob
+ * @param path - A path
+ */
constructor(entry: BlobTreeEntry, path: string) {
this._tree_entry = entry;
this.path = path;
}
+ /**
+ * Returns the blob's content
+ */
public async content(): Promise<string> {
return this._tree_entry.content();
}
+ /**
+ * Returns a blob from a path in a tree
+ *
+ * @param tree - The tree to look in
+ * @param path - A path to a blob
+ * @returns An instance of a blob
+ */
public static async fromPath(tree: Tree, path: string): Promise<Blob> {
const entry = await tree.find(path);
diff --git a/packages/server/src/git/branch.ts b/packages/server/src/git/branch.ts
index 163eca7..7ddf672 100644
--- a/packages/server/src/git/branch.ts
+++ b/packages/server/src/git/branch.ts
@@ -4,7 +4,17 @@ import { Repository } from "./repository";
import { Repository as NodeGitRepository } from "nodegit";
import { BranchError, createError } from "./error";
+/**
+ * A representation of a branch
+ *
+ * @extends Reference
+ */
export class Branch extends Reference {
+ /**
+ * Returns the branch's latest commit
+ *
+ * @returns A commit summary instance
+ */
public async latestCommit(): Promise<CommitSummary> {
const latest_commit = this._owner.nodegitRepository.getBranchCommit(this._ng_reference).catch(() => {
throw(createError(BranchError, 500, "Failed to get the latest commit"));
@@ -17,6 +27,13 @@ export class Branch extends Reference {
};
}
+ /**
+ * Lookup a branch
+ *
+ * @param owner - The repository which the branch is in
+ * @param branch - The SHA of a branch
+ * @returns An instance of a branch
+ */
public static async lookup(owner: Repository, branch: string): Promise<Branch> {
const reference = await owner.nodegitRepository.getBranch(branch).catch(err => {
if(err.errno === -3) {
@@ -27,8 +44,15 @@ export class Branch extends Reference {
return new Branch(owner, reference);
}
- public static async lookupExists(ng_repository: NodeGitRepository, branch: string): Promise<boolean> {
- return ng_repository.getBranch(branch)
+ /**
+ * Returns if a branch exists or not
+ *
+ * @param owner - The repository which the branch is in
+ * @param branch - The SHA of a branch
+ * @returns Whether or not the branch exists
+ */
+ public static async lookupExists(owner: NodeGitRepository, branch: string): Promise<boolean> {
+ return owner.getBranch(branch)
.then(() => true)
.catch(() => false);
}
diff --git a/packages/server/src/git/commit.ts b/packages/server/src/git/commit.ts
index 94afda0..c49e5ec 100644
--- a/packages/server/src/git/commit.ts
+++ b/packages/server/src/git/commit.ts
@@ -16,6 +16,9 @@ type DiffStats = {
files_changed: number
}
+/**
+ * A representation of a commit
+ */
export class Commit {
private _ng_commit: NodeGitCommit;
private _owner: Repository;
@@ -25,6 +28,10 @@ export class Commit {
public date: number;
public message: string;
+ /**
+ * @param owner - The repository which the commit is in
+ * @param commit - An instance of a Nodegit commit
+ */
constructor(owner: Repository, commit: NodeGitCommit) {
this._ng_commit = commit;
this._owner = owner;
@@ -38,10 +45,20 @@ export class Commit {
this.message = commit.message();
}
+ /**
+ * Returns the commit's diff
+ *
+ * @returns An instance of a diff
+ */
public async diff(): Promise<Diff> {
return new Diff((await this._ng_commit.getDiff())[0]);
}
+ /**
+ * Returns the commit's stats
+ *
+ * @returns A diff stats instance
+ */
public async stats(): Promise<DiffStats> {
const stats = await (await this._ng_commit.getDiff())[0].getStats();
@@ -52,21 +69,46 @@ export class Commit {
};
}
+ /**
+ * Returns the commit's tree
+ *
+ * @returns An instance of a tree
+ */
public async tree(): Promise<Tree> {
return new Tree(this._owner, await this._ng_commit.getTree());
}
+ /**
+ * Lookup a commit
+ *
+ * @param repository - The repository which the commit is in
+ * @param id - The SHA of a commit
+ * @returns An instance of a commit
+ */
public static async lookup(repository: Repository, id: string | NodeGitOid): Promise<Commit> {
const commit = await NodeGitCommit.lookup(repository.nodegitRepository, id instanceof NodeGitOid ? id : NodeGitOid.fromString(id));
return new Commit(repository, commit);
}
+ /**
+ * Returns if an commit exists or not
+ *
+ * @param repository - The repository which the commit is in
+ * @param id - The sha of a commit
+ * @returns Whether or not the commit exists
+ */
public static lookupExists(repository: Repository, id: string): Promise<boolean> {
return NodeGitCommit.lookup(repository.nodegitRepository, NodeGitOid.fromString(id))
.then(() => true)
.catch(() => false);
}
+ /**
+ * Returns the master commit of a repository
+ *
+ * @param owner - A repository
+ * @returns An instance of a commit
+ */
public static async masterCommit(owner: Repository): Promise<Commit> {
return new Commit(owner, await owner.nodegitRepository.getMasterCommit());
}
diff --git a/packages/server/src/git/diff.ts b/packages/server/src/git/diff.ts
index 6cd38a3..2e88609 100644
--- a/packages/server/src/git/diff.ts
+++ b/packages/server/src/git/diff.ts
@@ -43,6 +43,6 @@ export class Diff {
}
public async patches(): Promise<Patch[]> {
- return (await this._ng_diff.patches()).map(patch => new Patch(this, patch));
+ return (await this._ng_diff.patches()).map((patch, index) => new Patch(this, patch, index));
}
} \ No newline at end of file
diff --git a/packages/server/src/git/error.ts b/packages/server/src/git/error.ts
index a07d349..fff16a4 100644
--- a/packages/server/src/git/error.ts
+++ b/packages/server/src/git/error.ts
@@ -50,6 +50,14 @@ export class MiscError extends BaseError {
type ErrorConstructorType<T> = new (code: number, message: string) => T;
+/**
+ * An error factory
+ *
+ * @param ErrorConstructor - The constructor for what error to create
+ * @param code - A HTTP code
+ * @param message - A error message
+ * @returns An instance of a error
+ */
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/http.ts b/packages/server/src/git/http.ts
index 36bae04..c2654e7 100644
--- a/packages/server/src/git/http.ts
+++ b/packages/server/src/git/http.ts
@@ -8,12 +8,25 @@ export interface Request extends FastifyRequest {
params: Route["Params"],
}
+/**
+ * Write the first part of a reference discovery reply
+ *
+ * @param service - The git service to write as
+ * @param reply - A Fastify reply
+ */
function writeRefDiscoveryFirstLine(service: string, reply: FastifyReply) {
const s = "# service=" + service + "\n";
const n = (4 + s.length).toString(16);
reply.raw.write(Buffer.from((Array(4 - n.length + 1).join("0") + n + s) + "0000"));
}
+/**
+ * Connect to the Git HTTP backend
+ *
+ * @param repository - The repository to use
+ * @param req - A Fastify request
+ * @param reply - A Fastify reply
+ */
export function connect(repository: Repository, req: Request, reply: FastifyReply): void {
const parsed_url = new URL(`${req.protocol}://${req.hostname}${req.url.replace(req.params.repo, repository.name.short)}`);
diff --git a/packages/server/src/git/misc.ts b/packages/server/src/git/misc.ts
index bd18322..da9b1ee 100644
--- a/packages/server/src/git/misc.ts
+++ b/packages/server/src/git/misc.ts
@@ -1,12 +1,26 @@
import { readFile, readdir } from "fs";
import { createError, MiscError } from "./error";
+/**
+ * Asynchronously find an item in an array that matches the requirements set by the callback
+ *
+ * @param arr - The array to look in
+ * @param callback - A callback that knowns what you're looking for
+ * @returns The item in the array you wanted to find
+ */
export async function findAsync<T>(arr: T[], callback: (t: T) => Promise<boolean>): Promise<T> {
const results = await Promise.all(arr.map(callback));
const index = results.findIndex(result => result);
return arr[index];
}
+/**
+ * Returns the content of a file inside a repository
+ *
+ * @param base_dir - The directory which the repository is in
+ * @param repository - The directory of a bare repository
+ * @param file - The path of a file
+ */
export function getFile(base_dir: string, repository: string, file: string): Promise<string> {
return new Promise((resolve, reject) => {
readFile(`${base_dir}/${repository}/${file}`, (err, content) => {
@@ -20,6 +34,12 @@ export function getFile(base_dir: string, repository: string, file: string): Pro
});
}
+/**
+ * Returns all of the files & folders inside of a directory
+ *
+ * @param directory - The directory to look in
+ * @returns An array of directory content
+ */
export function getDirectory(directory: string): Promise<string[]> {
return new Promise<string[]>((resolve, reject) => {
readdir(directory, (err, dir_content) => {
diff --git a/packages/server/src/git/patch.ts b/packages/server/src/git/patch.ts
index f7eb88e..7b695ff 100644
--- a/packages/server/src/git/patch.ts
+++ b/packages/server/src/git/patch.ts
@@ -21,13 +21,23 @@ type PatchBounds = {
end: number
}
-function getHunkContent(hunk: string[]) {
- interface Lines {
+interface HunkLines {
new_lines: number[],
deleted_lines: number[]
- }
+}
+
+interface ProcessedHunk extends HunkLines {
+ hunk: string
+}
- const lines = hunk.reduce((result: Lines, line, index) => {
+/**
+ * Prepare a hunk for further usage
+ *
+ * @param hunk - The hunk to process
+ * @returns A processed hunk
+ */
+function sliceAndCountHunk(hunk: string[]): ProcessedHunk {
+ const lines = hunk.reduce((result: HunkLines, line, index) => {
if(line.charAt(0) === "+") {
hunk[index] = line.slice(1);
result.new_lines.push(index);
@@ -42,18 +52,27 @@ function getHunkContent(hunk: string[]) {
return { ...lines, hunk: hunk.join("\n") };
}
+/**
+ * A representation of a patch
+ */
export class Patch {
private _ng_patch: NodeGitPatch;
private _diff: Diff;
+ private _index: number;
public from: string;
public to: string;
public additions: number;
public deletions: number;
- constructor(diff: Diff, patch: NodeGitPatch) {
+ /**
+ * @param diff - The commit diff that contains the patch
+ * @param patch - An instance of Nodegit patch
+ */
+ constructor(diff: Diff, patch: NodeGitPatch, index: number) {
this._ng_patch = patch;
this._diff = diff;
+ this._index = index;
this.from = patch.oldFile().path();
this.to = patch.newFile().path();
@@ -61,25 +80,42 @@ export class Patch {
this.deletions = patch.lineStats()["total_deletions"];
}
- private async bounds(index: number): Promise<PatchBounds> {
+ /**
+ * Returns patch's bounds
+ *
+ * @remarks
+ *
+ * These bounds are in the context of it's whole diff
+ *
+ * @returns A patch bounds instance which contains a start & an end property
+ */
+ private async _bounds(): Promise<PatchBounds> {
const raw_patches = (await this._diff.rawPatches()).split("\n");
const patch_header_data = await this._diff.patchHeaderData();
return {
- start: patch_header_data.indexes[index] + patch_header_data.lengths[index],
- end: (typeof patch_header_data.indexes[index + 1] === "undefined") ? raw_patches.length - 1 : patch_header_data.indexes[index + 1]
+ start: patch_header_data.indexes[this._index] + patch_header_data.lengths[this._index],
+ end: (typeof patch_header_data.indexes[this._index + 1] === "undefined") ? raw_patches.length - 1 : patch_header_data.indexes[this._index + 1]
};
}
- private async content(index: number): Promise<string> {
+ /**
+ * Returns the patch's content
+ */
+ private async _content(): Promise<string> {
const raw_patches = (await this._diff.rawPatches()).split("\n");
- const bounds = await this.bounds(index);
+ const bounds = await this._bounds();
return raw_patches.slice(bounds.start, bounds.end).join("\n");
}
- public async isTooLarge(index: number): Promise<boolean> {
- const content = (await this.content(index)).split("\n");
+ /**
+ * Returns if the patch is too large or not
+ *
+ * @returns Whether or not the patch is too large
+ */
+ public async isTooLarge(): Promise<boolean> {
+ const content = (await this._content()).split("\n");
const line_lengths = content.map(line => line.length).reduce((result, length) => result + length);
if(content.length > 5000 || line_lengths > 5000) {
@@ -89,8 +125,13 @@ export class Patch {
return false;
}
- public async getHunks(patch_index: number): Promise<Hunk[] | null> {
- const content = (await this.content(patch_index)).split("\n");
+ /**
+ * Returns the patch's hunks
+ *
+ * @returns An array of hunk instances
+ */
+ public async getHunks(): Promise<Hunk[] | null> {
+ const content = (await this._content()).split("\n");
const hunks = await this._ng_patch.hunks();
if(hunks.length === 0) {
@@ -108,7 +149,7 @@ export class Patch {
new_lines_cnt: prev_hunk.newLines(),
old_start: prev_hunk.oldStart(),
old_lines_cnt: prev_hunk.oldLines(),
- ...getHunkContent(content.slice(result.prev, hunk_header_index))
+ ...sliceAndCountHunk(content.slice(result.prev, hunk_header_index))
});
}
@@ -122,7 +163,7 @@ export class Patch {
new_lines_cnt: prev_hunk.newLines(),
old_start: prev_hunk.oldStart(),
old_lines_cnt: prev_hunk.oldLines(),
- ...getHunkContent(content.slice(<number>hunks_data.prev))
+ ...sliceAndCountHunk(content.slice(<number>hunks_data.prev))
});
return hunks_data.hunks;
diff --git a/packages/server/src/git/reference.ts b/packages/server/src/git/reference.ts
index b24f72d..4f4f5a0 100644
--- a/packages/server/src/git/reference.ts
+++ b/packages/server/src/git/reference.ts
@@ -11,6 +11,9 @@ export function isNodeGitReferenceTag(ref: NodeGitReference): boolean {
return Boolean(ref.isTag());
}
+/**
+ * A representation of a reference
+ */
export abstract class Reference {
protected _ng_reference: NodeGitReference;
protected _owner: Repository;
@@ -18,6 +21,10 @@ export abstract class Reference {
public id: string;
public name: string;
+ /**
+ * @param owner - The repository which the reference is in
+ * @param reference - An instance of a Nodegit reference
+ */
constructor(owner: Repository, reference: NodeGitReference) {
this._ng_reference = reference;
this._owner = owner;
diff --git a/packages/server/src/git/repository.ts b/packages/server/src/git/repository.ts
index 2b14e89..a67d6f7 100644
--- a/packages/server/src/git/repository.ts
+++ b/packages/server/src/git/repository.ts
@@ -7,9 +7,15 @@ import { Commit } from "./commit";
import { FastifyReply } from "fastify";
import { Tag } from "./tag";
import { Tree } from "./tree";
-import { BaseError, BranchError, createError, RepositoryError } from "./error";
+import { BranchError, createError, RepositoryError } from "./error";
import { isNodeGitReferenceBranch, isNodeGitReferenceTag, Reference } from "./reference";
+/**
+ * Returns the full name of a git repository
+ *
+ * @param repo_name - The name of a repository
+ * @returns The repository name ending with .git
+ */
function getFullRepositoryName(repo_name: string) {
return repo_name.endsWith(".git") ? repo_name : `${repo_name}.git`;
}
@@ -19,18 +25,15 @@ type RepositoryName = {
full: string,
}
-type RepositoryConstructorData = {
- description: string | null,
- owner: string | null,
- branch: string
-}
-
// This fucking shit isn't in the Nodegit documentation.
interface WeirdNodeGitError extends Error {
errno: number;
errorFunction: string;
}
+/**
+ * A representation of an bare git repository
+ */
export class Repository {
private _ng_repository: NodeGitRepository;
@@ -38,26 +41,50 @@ export class Repository {
public name: RepositoryName;
public base_dir: string;
- public description: string | null;
- public owner: string | null;
- constructor(repository: NodeGitRepository, data: RepositoryConstructorData) {
+ /**
+ * @param repository - An instance of a Nodegit repository
+ * @param branch - The branch to use
+ */
+ constructor(repository: NodeGitRepository, branch: string) {
this._ng_repository = repository;
this.name = {
short: basename(repository.path()).slice(0, -4),
full: basename(repository.path())
};
this.base_dir = dirname(repository.path());
- this.description = data.description;
- this.owner = data.owner;
- this._branch = data.branch;
+ this._branch = branch;
+ }
+
+ /**
+ * Returns the repository's description
+ */
+ public description(): Promise<string> {
+ return getFile(this.base_dir, this.name.full, "description");
}
+ /**
+ * Returns the repository's owner
+ */
+ public owner(): Promise<string> {
+ return getFile(this.base_dir, this.name.full, "owner");
+ }
+
+ /**
+ * Returns the repository's branch
+ *
+ * @returns An instance of a branch
+ */
public branch(): Promise<Branch> {
return Branch.lookup(this, this._branch);
}
+ /**
+ * Returns the repository's commits
+ *
+ * @returns An array of commit instances
+ */
public async commits(): Promise<Commit[]> {
const walker = NodeGitRevwalk.create(this._ng_repository);
walker.pushHead();
@@ -65,28 +92,60 @@ export class Repository {
return Promise.all((await walker.getCommitsUntil(() => true)).map(commit => new Commit(this, commit)));
}
+ /**
+ * Returns the repository's tree
+ *
+ * @returns An instance of a tree
+ */
public async tree(): Promise<Tree> {
return Tree.ofRepository(this);
}
+ /**
+ * Returns if an git object exists or not
+ *
+ * @param id - The SHA of a git object
+ * @returns Whether or not it exists
+ */
public lookupExists(id: string): Promise<boolean> {
return NodeGitObject.lookup(this._ng_repository, NodeGitOid.fromString(id), NodeGitObject.TYPE.ANY)
.then(() => true)
.catch(() => false);
}
+ /**
+ * Returns the repository's branches
+ *
+ * @returns An array of branch instances
+ */
public branches(): Promise<Branch[]> {
return Reference.all(this, Branch, isNodeGitReferenceBranch);
}
+ /**
+ * Returns the repository's tags
+ *
+ * @returns An array of tag instances
+ */
public async tags(): Promise<Tag[]> {
return Reference.all(this, Tag, isNodeGitReferenceTag);
}
+ /**
+ * Returns the repository's master commit
+ *
+ * @returns An instance of a commit
+ */
public async masterCommit(): Promise<Commit> {
return Commit.masterCommit(this);
}
+ /**
+ * Connect to the Git HTTP backend
+ *
+ * @param req - A Fastify request
+ * @param reply - A Fastify reply
+ */
public HTTPconnect(req: Request, reply: FastifyReply): void {
connect(this, req, reply);
}
@@ -95,6 +154,14 @@ export class Repository {
return this._ng_repository;
}
+ /**
+ * Opens a bare git repository
+ *
+ * @param base_dir - The directory that contains the repository
+ * @param repository - The directory of a bare repository
+ * @param branch - A branch to use
+ * @returns An instance of a git 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) {
@@ -110,15 +177,15 @@ export class Repository {
}
}
- const owner = await getFile(base_dir, getFullRepositoryName(repository), "owner").catch(err => err);
-
- return new Repository(ng_repository, {
- description: await getFile(base_dir, getFullRepositoryName(repository), "description"),
- owner: owner instanceof BaseError ? null : owner,
- branch: branch || "master"
- });
+ return new Repository(ng_repository, branch || "master");
}
+ /**
+ * Opens all of the git repositories inside a directory
+ *
+ * @param base_dir - The directory that contains the repositories
+ * @returns An array of repository instances
+ */
public static async openAll(base_dir: string): Promise<Repository[] | null> {
const dir_content = await getDirectory(base_dir);
diff --git a/packages/server/src/git/tag.ts b/packages/server/src/git/tag.ts
index 473c62d..31dfb41 100644
--- a/packages/server/src/git/tag.ts
+++ b/packages/server/src/git/tag.ts
@@ -21,7 +21,17 @@ async function addArchiveEntries(entries: BaseTreeEntry[], repository: string, a
}
}
+/**
+ * A representation of a tag
+ *
+ * @extends Reference
+ */
export class Tag extends Reference {
+ /**
+ * Returns the tag's author
+ *
+ * @returns An instance of an author
+ */
public async author(): Promise<Author> {
const tagger = (await NodeGitTag.lookup(this._owner.nodegitRepository, this._ng_reference.target())).tagger();
return {
@@ -30,11 +40,21 @@ export class Tag extends Reference {
};
}
+ /**
+ * Returns the tag's creation date
+ *
+ * @returns A Unix Epoch timestamp for the tag's date
+ */
public async date(): Promise<number> {
return (await NodeGitTag.lookup(this._owner.nodegitRepository, this._ng_reference.target())).tagger().when()
.time();
}
+ /**
+ * Download the tag's tarball
+ *
+ * @param reply - A Fastify reply
+ */
public async downloadTarball(reply: FastifyReply): Promise<void> {
const commit = await Commit.lookup(this._owner, (await this._ng_reference.peel(NodeGitObject.TYPE.COMMIT)).id());
const tree = await commit.tree();
@@ -64,6 +84,13 @@ export class Tag extends Reference {
});
}
+ /**
+ * Lookup a tag
+ *
+ * @param owner - The repository which the tag is in
+ * @param tag - The SHA of the tag to look for
+ * @returns An instance of a tag
+ */
public static async lookup(owner: Repository, tag: string): Promise<Tag> {
const reference = await owner.nodegitRepository.getReference(tag).catch(err => {
if(err.errno === -3) {
diff --git a/packages/server/src/git/tree.ts b/packages/server/src/git/tree.ts
index ca645ef..6c08e1a 100644
--- a/packages/server/src/git/tree.ts
+++ b/packages/server/src/git/tree.ts
@@ -3,22 +3,40 @@ import { Repository } from "./repository";
import { BaseTreeEntry, createTreeEntry, TreeEntry } from "./tree_entry";
import { createError, TreeError } from "./error";
+/**
+ * A representation of a git tree
+ */
export class Tree {
protected _owner: Repository;
protected _ng_tree: NodeGitTree;
public path: string;
+ /**
+ * @param owner The repository which the tree is in
+ * @param tree An instance of a Nodegit tree
+ */
constructor(owner: Repository, tree: NodeGitTree) {
this._owner = owner;
this._ng_tree = tree;
this.path = tree.path();
}
+ /**
+ * The tree's entries
+ *
+ * @returns An array of tree entry instances
+ */
public entries(): TreeEntry[] {
return this._ng_tree.entries().map(entry => new TreeEntry(this._owner, entry));
}
+ /**
+ * Returns the entry of a path
+ *
+ * @param path - The path of a blob or tree
+ * @returns An instance of an tree entry
+ */
public async find(path: string): Promise<BaseTreeEntry> {
const entry = await this._ng_tree.getEntry(path).catch(err => {
if(err.errno === -3) {
@@ -30,12 +48,29 @@ export class Tree {
return createTreeEntry(this._owner, entry);
}
+ /**
+ * Returns if a path exists or not
+ *
+ * @param path - The path to look for
+ * @returns Whether or not there exists an entry for the path
+ */
public findExists(path: string): Promise<boolean> {
return this._ng_tree.getEntry(path)
.then(() => true)
.catch(() => false);
}
+ /**
+ * Returns the tree of a repository
+ *
+ * @remarks
+ *
+ * Assumes that you want to use the master branch.
+ * This will be fixed in the future.
+ *
+ * @param owner The repository which the tree is in
+ * @returns An instance of a tree
+ */
public static async ofRepository(owner: Repository): Promise<Tree> {
const master_commit = await owner.masterCommit();
return master_commit.tree();
diff --git a/packages/server/src/git/tree_entry.ts b/packages/server/src/git/tree_entry.ts
index e4780c8..52f9988 100644
--- a/packages/server/src/git/tree_entry.ts
+++ b/packages/server/src/git/tree_entry.ts
@@ -5,12 +5,19 @@ import { dirname } from "path";
import { findAsync } from "./misc";
import { Tree } from "./tree";
+/**
+ * The core structure of a tree entry
+ */
export abstract class BaseTreeEntry {
protected _ng_tree_entry: NodeGitTreeEntry;
protected _owner: Repository;
public path: string;
+ /**
+ * @param owner - The repository which the tree entry is in
+ * @param entry - An instance of a Nodegit tree entry
+ */
constructor(owner: Repository, entry: NodeGitTreeEntry) {
this._ng_tree_entry = entry;
this._owner = owner;
@@ -18,6 +25,11 @@ export abstract class BaseTreeEntry {
this.path = entry.path();
}
+ /**
+ * Returns the tree entry's latest commit
+ *
+ * @returns An instance of a commit
+ */
public async latestCommit(): Promise<Commit> {
const commits = await this._owner.commits();
@@ -32,18 +44,39 @@ export abstract class BaseTreeEntry {
}
}
+/**
+ * A representation of a tree entry that's a tree
+ */
export class TreeEntry extends BaseTreeEntry {
+ /**
+ * Returns the tree of the tree entry
+ *
+ * @returns An instance of a tree
+ */
public async tree(): Promise<Tree> {
return new Tree(this._owner, await this._ng_tree_entry.getTree());
}
}
+/**
+ * A representation of a tree entry that's a blob
+ */
export class BlobTreeEntry extends BaseTreeEntry {
+ /**
+ * Returns the blob's content
+ */
public async content(): Promise<string> {
return (await this._ng_tree_entry.getBlob()).toString();
}
}
+/**
+ * A factory which creates a tree entry
+ *
+ * @param owner - The repository that the tree entry is in
+ * @param entry - An instance of a Nodegit tree entry
+ * @returns An instance of a tree entry
+ */
export function createTreeEntry(owner: Repository, entry: NodeGitTreeEntry): BaseTreeEntry {
return entry.isBlob()
? new BlobTreeEntry(owner, entry)