-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathblob.ts
83 lines (75 loc) · 2.28 KB
/
blob.ts
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
import * as fs from "fs";
import { Readable } from "stream";
import { join } from "path";
import { Base64Encode } from "base64-stream";
import MultiStream from "multistream";
import Resource from "./resource";
import { Repo } from "./repo";
export class Blob extends Resource {
readonly type: string = "blob";
readonly absoluteFilePath: string;
readonly mode: string;
sha: string;
constructor(
readonly repo: Repo,
readonly baseDir: string,
readonly file: string
) {
super();
this.absoluteFilePath = join(baseDir, file);
// Reject files that don't exist
if (!fs.existsSync(this.absoluteFilePath)) {
throw new Error(`File does not exist: ${this.absoluteFilePath}.`);
}
// Set the file's mode, this should be represented as an octal string
this.mode = fs.statSync(this.absoluteFilePath).mode.toString(8);
}
/**
* Produces a stream that conforms to the shape expected
* by the POST /repos/{owner}/{repo}/git/blobs GitHub API
*
* For example, streams produced by this class will resolve to a shape like:
* {
* "encoding": "base64",
* "content": "SGFsZiBtZWFzdXJlcyBhcmUgYXMgYmFkIGFzIG5vdGhpbmcgYXQgYWxsLg=="
* }
*
* See: https://docs.github.com/rest/reference/git#create-a-blob
*/
get stream(): Readable {
const streams: Readable[] = [
Readable.from('{"encoding":"base64","content":"'),
fs.createReadStream(this.absoluteFilePath).pipe(new Base64Encode()),
Readable.from('"}'),
];
// Produces the JSON body as a stream, so that we don't have to read (
// potentially very large) files into memory
return new MultiStream(streams);
}
get path(): string {
return this.file;
}
async save(): Promise<void> {
const response = await this.github.post(
`/repos/${this.repo.nameWithOwner}/git/blobs`,
this.stream
);
this.sha = response.data.sha;
this.debug(`Sha for blob ${this.file}: ${this.sha}.`);
}
}
export interface Options {
/** Optional. Default base dir to use when expanding a set of files. */
baseDir?: string;
}
export function getBlobsFromFiles(
repo: Repo,
files: string,
options: Options = {}
): Blob[] {
const { baseDir } = options;
return files
.trim()
.split("\n")
.map((file) => new Blob(repo, baseDir, file));
}