forked from tinybeachthor/gitbot-format
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiff.ts
More file actions
96 lines (84 loc) · 2.57 KB
/
Copy pathdiff.ts
File metadata and controls
96 lines (84 loc) · 2.57 KB
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
import fs from 'fs'
import path from 'path'
import { spawn } from 'child_process'
import tempWrite from 'temp-write'
import { SpawnOptions } from 'child_process'
// '@@ -6,10 +6,9 @@ int checkEvenOrOdd() {' => {6, 10, 6, 9}
function parsePatchHeader (header: string): types.PatchRange {
const lineStats = (header.split('@@')[1]).split(' ')
const originalStats = lineStats[1].substr(1).split(',')
const editedStats = lineStats[2].substr(1).split(',')
return {
oldStart: parseInt(originalStats[0]),
oldLines: parseInt(originalStats[1]) || 0,
newStart: parseInt(editedStats[0]),
newLines: parseInt(editedStats[1]) || 0,
}
}
async function spawnAndGet (
command: string,
args: string[],
options: SpawnOptions
) : Promise<string> {
const p = spawn(command, args, options)
return new Promise((resolve, reject) => {
// wait for output
let output = ""
p.stdout && p.stdout.on('data', data => {
output += data
})
// check for errors
p.stderr && p.stderr.on('data', data => {
reject(data.toString())
})
// resolve on close
p.on('close', code => {
if (code === 0 || code === 1) {
resolve(output)
}
else {
reject(code)
}
})
})
}
async function generateDiff (edited: types.File, original: types.File) {
const editedFile = tempWrite.sync(edited.content, path.basename(edited.filename))
const originalFile = tempWrite.sync(original.content, path.basename(original.filename))
try {
const output = await spawnAndGet(
'git',
['diff', '--no-index', '--exit-code', '--unified=1', '--minimal',
originalFile, editedFile],
{ timeout: 10 * 1000 }
)
return output
.split('\n')
.filter(line => line.startsWith('@@'))
.map(parsePatchHeader)
}
finally {
// remove temp files
fs.unlink(editedFile, (err) => err && console.error(err))
fs.unlink(originalFile, (err) => err && console.error(err))
}
}
export default async function generateAnnotations (edited: types.File, original: types.File): Promise<types.Annotations> {
const hunks = await generateDiff(edited, original)
return hunks.reduce(({annotations, lines}: types.Annotations, {oldStart, oldLines}: types.PatchRange) => {
annotations.push({
path: original.filename,
start_line: oldStart,
end_line: oldStart + oldLines,
annotation_level: 'failure',
message: `Lines ${oldStart}-${oldStart+oldLines} need formatting.`,
})
return {
annotations,
lines: lines + oldLines,
}
}, {
annotations: [],
lines: 0,
})
}