aboutsummaryrefslogtreecommitdiff
path: root/packages/server/src/git/tag.ts
blob: 7d8c5dceaa1e9cb4ce68b3f66ab91cef0a5fdaaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { Object as NodeGitObject, Tag as NodeGitTag } from "nodegit";
import { Commit } from "./commit";
import { FastifyReply } from "fastify";
import { Reference } from "./reference";
import { Repository } from "./repository";
import { createGzip } from "zlib";
import { pipeline } from "stream";
import { createError, ErrorWhere, FailedError, NotFoundError } from "./error";
import { Author } from "../../../api/src";
import { promisify } from "util";

/**
 * 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.ng_repository, this._ng_reference.target())).tagger();
		return {
			name: tagger.name(),
			email: tagger.email()
		};
	}

	/**
	 * 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.ng_repository, 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();

		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"`
		});

		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 error
		gzip.on("error", err => {
			console.log(err);
			reply.raw.end();
		});

		// Tar error
		archive.on("error", err => {
			console.log(err);
			reply.raw.end();
		});
	}

	/**
	 * Lookup a tag
	 *
	 * @param owner - The repository which the tag is in
	 * @param tag - The name 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.ng_repository.getReference(tag).catch(err => {
			if(err.errno === -3) {
				throw(createError(ErrorWhere.Tag, NotFoundError, "Tag"));
			}

			throw(createError(ErrorWhere.Tag, FailedError, "get tag"));
		});

		return new Tag(owner, reference);
	}

	/**
	 * Returns all of a repository's tags
	 *
	 * @param owner - An instance of a repository
	 * @returns An array of tag instances
	 */
	public static async getAll(owner: Repository): Promise<Tag[]> {
		const references = await owner.ng_repository.getReferences();

		return references.filter(ref => ref.isTag()).map(ref => new Tag(owner, ref));
	}
}