-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathgit.ts
100 lines (92 loc) · 2.65 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
import { exec, ExecOptions } from '@actions/exec'
import { statSync } from 'fs'
import path from 'path'
import * as core from '@actions/core'
export type GitStatus = {
flag: string
path: string
}
export async function gitStatus(): Promise<GitStatus[]> {
core.debug('Getting gitStatus()')
let output = ''
await exec('git', ['status', '-s'], {
listeners: {
stdout: (data: Buffer) => {
output += data.toString()
},
},
})
core.debug(`=== output was:\n${output}`)
return output
.split('\n')
.filter(l => l != '')
.map(l => {
const chunks = l.trim().split(/\s+/)
return {
flag: chunks[0],
path: chunks[1],
} as GitStatus
})
}
async function getHeadSize(path: string): Promise<number | undefined> {
let raw = ''
const exitcode = await exec('git', ['cat-file', '-s', `HEAD:${path}`], {
listeners: {
stdline: (data: string) => {
raw += data
},
},
})
core.debug(`raw cat-file output: ${exitcode} '${raw}'`)
if (exitcode === 0) {
return parseInt(raw, 10)
}
}
async function diffSize(file: GitStatus): Promise<number> {
switch (file.flag) {
case 'M': {
const stat = statSync(file.path)
core.debug(
`Calculating diff for ${JSON.stringify(file)}, with size ${stat.size}b`
)
// get old size and compare
const oldSize = await getHeadSize(file.path)
const delta = oldSize === undefined ? stat.size : stat.size - oldSize
core.debug(
` ==> ${file.path} modified: old ${oldSize}, new ${stat.size}, delta ${delta}b `
)
return delta
}
case 'A': {
const stat = statSync(file.path)
core.debug(
`Calculating diff for ${JSON.stringify(file)}, with size ${stat.size}b`
)
core.debug(` ==> ${file.path} added: delta ${stat.size}b`)
return stat.size
}
case 'D': {
const oldSize = await getHeadSize(file.path)
const delta = oldSize === undefined ? 0 : oldSize
core.debug(` ==> ${file.path} deleted: delta ${delta}b`)
return delta
}
default: {
throw new Error(
`Encountered an unexpected file status in git: ${file.flag} ${file.path}`
)
}
}
}
export async function diff(filename: string): Promise<number> {
const statuses = await gitStatus()
core.debug(
`Parsed statuses: ${statuses.map(s => JSON.stringify(s)).join(', ')}`
)
const status = statuses.find(s => path.relative(s.path, filename) === '')
if (typeof status === 'undefined') {
core.info(`No status found for ${filename}, aborting.`)
return 0 // there's no change to the specified file
}
return await diffSize(status)
}