This repository has been archived by the owner on Oct 22, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
git.ts
126 lines (101 loc) · 3.54 KB
/
git.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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import debug from 'debug'
import fs from 'fs-extra'
import npath from 'path'
import shell from 'shelljs'
// tslint:disable-next-line:no-submodule-imports
import gitP from 'simple-git/promise'
import { SmartBuffer } from 'smart-buffer'
import zlib from 'zlib'
import Helper from '../helper'
const git = gitP()
export default class GitHelper {
public helper: Helper
public debug: any
// OK
constructor(helper: Helper) {
this.helper = helper
this.debug = debug('pando')
}
/***** core methods *****/
// OK
public async collect(oid: string, mapping: any): Promise<any> {
this.debug('collecting', oid)
const cid = this.helper.ipld.shaToCid(oid)
if (mapping[cid]) return mapping
const node: any = await this.load(oid)
if (node.gitType === 'commit') {
// node is a commit
const _mapping = await this.collect(this.helper.ipld.cidToSha(node.tree['/']), mapping)
return { ...mapping, ..._mapping, ...{ [cid]: node } }
} else if (Buffer.isBuffer(node)) {
// node is a blob
return { ...mapping, ...{ [cid]: node } }
} else {
// node is a tree
// tslint:disable-next-line:forin
for (const entry in node) {
const _mapping = await this.collect(this.helper.ipld.cidToSha(node[entry].hash['/']), mapping)
mapping = { ...mapping, ..._mapping }
}
return { ...mapping, ...{ [cid]: node } }
}
}
// OK
public async download(oid: any): Promise<void> {
this.debug('downloading', oid)
if (await this.exists(oid)) return
const cid = this.helper.ipld.shaToCid(oid)
const node = await this.helper.ipld.get(cid)
if (node.gitType === 'commit') {
// node is a commit
await this.download(this.helper.ipld.cidToSha(node.tree['/']))
for (const parent of node.parents) {
await this.download(this.helper.ipld.cidToSha(parent['/']))
}
await this.dump(oid, node)
} else if (Buffer.isBuffer(node)) {
// node is a blob
await this.dump(oid, node)
} else {
// node is a tree
// tslint:disable-next-line:forin
for (const entry in node) {
await this.download(await this.helper.ipld.cidToSha(node[entry].hash['/']))
}
await this.dump(oid, node)
}
}
/***** fs-related methods *****/
// OK
public async exists(oid: string): Promise<boolean> {
// modify this function to rely on git cat-file -e $sha^{commit}
// see https://stackoverflow.com/questions/18515488/how-to-check-if-the-commit-exists-in-a-git-repository-by-its-sha-1
return fs.pathExists(await this.path(oid))
}
// OK
public async load(oid: string): Promise<any> {
const type = shell.exec(`git cat-file -t ${oid}`, { silent: true }).stdout.trim()
const size = shell.exec(`git cat-file -s ${oid}`, { silent: true }).stdout.trim()
const data = await git.binaryCatFile([type, oid])
const raw = new SmartBuffer()
raw.writeString(`${type} `)
raw.writeString(size)
raw.writeUInt8(0)
raw.writeBuffer(data)
return this.helper.ipld.deserialize(raw.toBuffer())
}
// OK
public async dump(oid: string, node: any): Promise<void> {
const path = await this.path(oid)
const buffer = await this.helper.ipld.serialize(node)
await fs.ensureFile(path)
fs.writeFileSync(path, zlib.deflateSync(buffer))
}
/***** utility methods *****/
// OK
public async path(oid: string): Promise<string> {
const subdirectory = oid.substring(0, 2)
const filename = oid.substring(2)
return npath.join(this.helper.path, 'objects', subdirectory, filename)
}
}