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
|
import { Diff } from "./diff";
import { ConvenientPatch as NodeGitPatch } from "nodegit";
type Hunk = {
new_start: number,
new_lines_cnt: number,
old_start: number,
old_lines_cnt: number,
new_lines: number[],
deleted_lines: number[],
hunk: string
}
type Hunks = {
prev: null | number,
hunks: Hunk[]
}
function getHunkContent(hunk: string[]) {
interface Lines {
new_lines: number[],
deleted_lines: number[]
}
const lines = hunk.reduce((result: Lines, line, index) => {
if(line.charAt(0) === "+") {
hunk[index] = line.slice(1);
result.new_lines.push(index);
}
else if(line.charAt(0) === "-") {
hunk[index] = line.slice(1);
result.deleted_lines.push(index);
}
return result;
}, { new_lines: [], deleted_lines: [] });
return { ...lines, hunk: hunk.join("\n") };
}
export class Patch {
private _ng_patch: NodeGitPatch;
public from: string;
public to: string;
public additions: number;
public deletions: number;
public too_large = false;
public content: string | null = null;
constructor(diff: Diff, patch: NodeGitPatch, index: number) {
this._ng_patch = patch;
this.from = patch.oldFile().path();
this.to = patch.newFile().path();
this.additions = patch.lineStats()["total_additions"];
this.deletions = patch.lineStats()["total_deletions"];
const raw_patches_arr = diff.raw_patches.split("\n");
const start = diff.patch_header_indexes[index] + diff.patch_header_lengths[index];
const end = (typeof diff.patch_header_indexes[index + 1] === "undefined") ? raw_patches_arr.length - 1 : diff.patch_header_indexes[index + 1];
const patch_content = raw_patches_arr.slice(start, end);
if(patch_content.length !== 0) {
this.content = patch_content.join("\n");
const line_lengths = patch_content.map(line => line.length).reduce((result, length) => result + length);
if(patch_content.length > 5000 || line_lengths > 5000) {
this.too_large = true;
}
}
}
async getHunks(): Promise<Hunk[] | null> {
if(!this.content) {
return null;
}
const content = this.content.split("\n");
const hunks = await this._ng_patch.hunks();
const hunks_data = hunks.reduce((result: Hunks, hunk, hunk_index) => {
const hunk_header = hunk.header();
const hunk_header_index = content.indexOf(hunk_header.replace(/\n/gu, ""));
if(result.prev !== null) {
const prev_hunk = hunks[hunk_index - 1];
result.hunks.push({
new_start: prev_hunk.newStart(),
new_lines_cnt: prev_hunk.newLines(),
old_start: prev_hunk.oldStart(),
old_lines_cnt: prev_hunk.oldLines(),
...getHunkContent(content.slice(result.prev, hunk_header_index))
});
}
result.prev = hunk_header_index;
return result;
}, { prev: null, hunks: [] });
const prev_hunk = hunks[hunks.length - 1];
hunks_data.hunks.push({
new_start: prev_hunk.newStart(),
new_lines_cnt: prev_hunk.newLines(),
old_start: prev_hunk.oldStart(),
old_lines_cnt: prev_hunk.oldLines(),
...getHunkContent(content.slice(<number>hunks_data.prev))
});
return hunks_data.hunks;
}
}
|