Source file diffSerializer.ml
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
127
open Diff
let is_empty = function [] -> true | _ :: _ -> false
let serialize_line = function
| `ContextLine content -> Printf.sprintf " %s" content
| `RemovedLine content -> Printf.sprintf "-%s" content
| `AddedLine content -> Printf.sprintf "+%s" content
let serialize_deleted_file (file : deleted_file) =
let =
Printf.sprintf {|diff --git a/%s b/%s
deleted file mode 100644
--- a/%s
+++ /dev/null|}
file.path file.path file.path
in
let = Printf.sprintf "@@ -1,%d +0,0 @@" (List.length file.lines) in
let lines = file.lines |> List.map serialize_line in
file_header :: hunk_header :: lines |> String.concat "\n"
let serialize_created_file (file : created_file) =
let =
Printf.sprintf {|diff --git a/%s b/%s
new file mode 100644
--- /dev/null
+++ b/%s|} file.path
file.path file.path
in
let = Printf.sprintf "@@ -0,0 +1,%d @@" (List.length file.lines) in
let lines = file.lines |> List.map serialize_line in
file_header :: hunk_header :: lines |> String.concat "\n"
let count_left_lines lines =
lines
|> List.fold_left
(fun count line ->
match line with
| `ContextLine _ -> count + 1
| `RemovedLine _ -> count + 1
| `AddedLine _ -> count)
0
let count_right_lines lines =
lines
|> List.fold_left
(fun count line ->
match line with
| `ContextLine _ -> count + 1
| `RemovedLine _ -> count
| `AddedLine _ -> count + 1)
0
let serialize_hunk hunk right_offset =
let left_start_line = hunk.starting_line in
let left_line_count = count_left_lines hunk.lines in
let right_start_line = left_start_line + right_offset in
let right_line_count = count_right_lines hunk.lines in
let left_lines =
if left_line_count = 1 then Printf.sprintf "-%d" left_start_line
else Printf.sprintf "-%d,%d" left_start_line left_line_count
in
let right_lines =
if right_line_count = 1 then Printf.sprintf "+%d" right_start_line
else Printf.sprintf "+%d,%d" right_start_line right_line_count
in
let context_snippet =
match hunk.context_snippet with None -> "" | Some snippet -> Printf.sprintf " %s" snippet
in
let = Printf.sprintf "@@ %s %s @@%s" left_lines right_lines context_snippet in
let lines = hunk.lines |> List.map serialize_line in
hunk_header :: lines |> String.concat "\n"
let serialize_changed_file (file : changed_file) =
let =
Printf.sprintf {|diff --git a/%s b/%s
--- a/%s
+++ b/%s|} file.path file.path file.path
file.path
in
let _, hunks =
file.hunks
|> List.fold_left_map
(fun acc (hunk : hunk) ->
let left_lines = count_left_lines hunk.lines in
let right_lines = count_right_lines hunk.lines in
(acc + right_lines - left_lines, serialize_hunk hunk acc))
0
in
file_header :: hunks |> String.concat "\n"
let serialize_renamed_file (file : renamed_file) =
let =
Printf.sprintf {|diff --git a/%s b/%s
similarity index 100%%
rename from %s
rename to %s|}
file.old_path file.new_path file.old_path file.new_path
in
let _, hunks =
file.hunks
|> List.fold_left_map
(fun acc (hunk : hunk) ->
let left_lines = count_left_lines hunk.lines in
let right_lines = count_right_lines hunk.lines in
(acc + right_lines - left_lines, serialize_hunk hunk acc))
0
in
let foo =
if is_empty hunks then ""
else
Printf.sprintf "\n--- a/%s\n+++ b/%s\n%s" file.old_path file.new_path
(String.concat "\n" hunks)
in
file_header ^ foo
let serialize_file = function
| DeletedFile file -> serialize_deleted_file file
| CreatedFile file -> serialize_created_file file
| ChangedFile file -> serialize_changed_file file
| RenamedFile file -> serialize_renamed_file file
let serialize diff = diff.files |> List.map serialize_file |> String.concat "\n"