Skip to content

Commit af2b339

Browse files
committed
multi-source patch
1 parent 4bfea2e commit af2b339

9 files changed

Lines changed: 1067 additions & 96 deletions

File tree

CMakeLists.txt

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
1212
# separate sha256 for windows, because both stdout shell redirect
1313
# and piping stdout onward are in _TEXT
1414

15+
# single patched file, directly taken from Gemini 2.5 copy button
16+
1517
add_test(NAME lws1
1618
COMMAND ${CMAKE_COMMAND}
1719
-DCMD=$<TARGET_FILE:${PROJECT_NAME}>
@@ -22,14 +24,49 @@ add_test(NAME lws1
2224
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest.cmake
2325
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/1)
2426

27+
# two concatenated single file patches
28+
2529
add_test(NAME lws2
2630
COMMAND ${CMAKE_COMMAND}
2731
-DCMD=$<TARGET_FILE:${PROJECT_NAME}>
2832
-DSRC=deaddrop.js
2933
-DSRC1=protocol_lws_deaddrop.c
3034
-DPATCH=gemini.patch
31-
-DEXPSHA=0f988ae2f642a825188448e4bee9db8943050e80e075dbcd6fc4ed9ada87f6fb
32-
-DEXPSHA_WIN=2e6b9b12ae0128c9edfc109744b9c67848712b0521c322a45104895aa4cbc3b1
35+
-DEXPSHA=41e61ec55614da2edef64618cd60977b9403fe0d9fdd9b04d89ae38e38896799
36+
-DEXPSHA1=c742cdad75b3f4f1d742b4cf135079ba319f9b85ce8615799e2ed4baa4e12b97
37+
-DEXPSHA_WIN=2b8657443708a63097ade2a800cbcf95a23d40526b9c2173b2980b6773e8ab39
38+
-DEXPSHA1_WIN=dadd4162eee0c8acdbdeb43cb9e97c448c766dbab2bec9d866fcd5a76243b593
39+
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest.cmake
40+
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/2)
41+
42+
# two concatenated patches using git style diff and index lines (otherwise same as above)
43+
44+
add_test(NAME lws2a
45+
COMMAND ${CMAKE_COMMAND}
46+
-DCMD=$<TARGET_FILE:${PROJECT_NAME}>
47+
-DSRC=deaddrop.js
48+
-DSRC1=protocol_lws_deaddrop.c
49+
-DPATCH=gemini2.patch
50+
-DEXPSHA=41e61ec55614da2edef64618cd60977b9403fe0d9fdd9b04d89ae38e38896799
51+
-DEXPSHA1=c742cdad75b3f4f1d742b4cf135079ba319f9b85ce8615799e2ed4baa4e12b97
52+
-DEXPSHA_WIN=2b8657443708a63097ade2a800cbcf95a23d40526b9c2173b2980b6773e8ab39
53+
-DEXPSHA1_WIN=dadd4162eee0c8acdbdeb43cb9e97c448c766dbab2bec9d866fcd5a76243b593
54+
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest.cmake
55+
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/2)
56+
57+
# two concatenated patches using git style diff and index lines with extra newline at end
58+
# (otherwise same as above)
59+
60+
add_test(NAME lws2b
61+
COMMAND ${CMAKE_COMMAND}
62+
-DCMD=$<TARGET_FILE:${PROJECT_NAME}>
63+
-DSRC=deaddrop.js
64+
-DSRC1=protocol_lws_deaddrop.c
65+
-DPATCH=gemini3.patch
66+
-DEXPSHA=41e61ec55614da2edef64618cd60977b9403fe0d9fdd9b04d89ae38e38896799
67+
-DEXPSHA1=c742cdad75b3f4f1d742b4cf135079ba319f9b85ce8615799e2ed4baa4e12b97
68+
-DEXPSHA_WIN=2b8657443708a63097ade2a800cbcf95a23d40526b9c2173b2980b6773e8ab39
69+
-DEXPSHA1_WIN=dadd4162eee0c8acdbdeb43cb9e97c448c766dbab2bec9d866fcd5a76243b593
3370
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest.cmake
3471
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/2)
3572

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ legible diffs.
2929
This utility adjusts the diff stanzas sent to it on stdin and produces new stanza
3030
headers with accurate line counts on stdout.
3131

32-
It covers:
32+
It silently repairs:
3333

3434
- wrong "before" line in original stanza header
3535
- wrong "before" line count in original stanza header
@@ -44,7 +44,13 @@ It finds and scans the sources the patches apply to and uses the diff stanza to
4444
find the original line it applied to by itself, along with the original line
4545
count and, considering earlier stanzas, the line in the modified file it appears
4646
at and the new line count for the stanza. Thus, it does not use the incoming
47-
broken stanza header information at all and replaces all the @@ lines.
47+
broken stanza header information at all and replaces all the @@ lines with
48+
correct numbers according to the changed and unchanged sources, and the actual
49+
diff contents inside the stanza.
50+
51+
It handles diffs starting with --- as produced by most LLMs, also those with
52+
diff and index headers, and supports any combination of concatenated diffs
53+
targeting different files in one step.
4854

4955
## Building
5056

@@ -64,3 +70,5 @@ $ cmake ..
6470
$ make && sudo make install
6571
```
6672

73+
Selftests can be run after build with `ctest --output-on-failure`.
74+

fixdiff.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,6 @@ fixdiff_find_original(dp_t *pdp, int *line_start)
395395
if (hit)
396396
break;
397397

398-
fprintf(stderr, "'%s' '%s\n", in_temp + 1, in_src);
399-
400398
if (fixdiff_strcmp(in_temp + 1, lt - 1, &let, in_src, ls, &les))
401399
break;
402400
}
@@ -700,6 +698,8 @@ main(int argc, char *argv[])
700698
in[2] == '-' &&
701699
in[3] == ' ') {
702700
dp.d = DSS_MUST_PPP;
701+
if (fixdiff_stanza_end(&dp))
702+
goto bail;
703703
break;
704704
}
705705

@@ -737,6 +737,13 @@ main(int argc, char *argv[])
737737
goto bail;
738738
break;
739739
}
740+
741+
if (in[0] == 0xa) {
742+
/* we can often find this from extra lines at EOT */
743+
fprintf(stderr, "Skipping unexpected newline\n");
744+
continue;
745+
}
746+
740747
fprintf(stderr, "'%c' (0x%x)\n", in[0], in[0]);
741748
dp.reason = "unexpected character in stanza";
742749
goto bail;

tests/2/deaddrop.js-orig

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(function() {
22

3-
var server_max_size = 0, ws;
3+
var server_max_size = 0, username = "", ws;
44

55
function san(s)
66
{
@@ -16,7 +16,7 @@
1616

1717
function pad(n) {
1818
return n < 10 ? '0' + n : n;
19-
}
19+
}
2020

2121
function lws_urlencode(s)
2222
{
@@ -68,15 +68,15 @@
6868
{
6969
var da = document.getElementById("da");
7070

71-
e.preventDefault();
71+
e.preventDefault();
7272
da.classList.remove("trot");
7373
}
7474

7575
function da_over(e)
7676
{
7777
var da = document.getElementById("da");
7878

79-
e.preventDefault();
79+
e.preventDefault();
8080
da.classList.add("trot");
8181
}
8282

@@ -88,39 +88,38 @@
8888
t.deleteRow(n);
8989
}
9090

91-
function do_upload(file) {
92-
var formData = new FormData();
91+
/*
92+
* Generic uploader: takes FormData, a display name and a display size
93+
*/
94+
function _do_upload(formData, displayName, displaySize) {
9395
var t = document.getElementById("ongoing");
94-
95-
formData.append("file", file);
96-
9796
var row = t.insertRow(0), c1 = row.insertCell(0),
98-
c2 = row.insertCell(1), c3 = row.insertCell(2);
97+
c2 = row.insertCell(1), c3 = row.insertCell(2);
9998

10099
c1.classList.add("ogn");
101100
c1.classList.add("r");
102101

103-
if (file.size > server_max_size) {
102+
if (displaySize > server_max_size) {
104103
c1.innerHTML = "Too Large";
105104
c1.classList.add("err");
106105
} else
107106
c1.innerHTML = "<img class=\"working\">";
108107

109108
c2.classList.add("ogn");
110109
c2.classList.add("r");
111-
c2.innerHTML = humanize(file.size);
110+
c2.innerHTML = humanize(displaySize);
112111

113112
c3.classList.add("ogn");
114-
c3.innerHTML = san(file.name);
113+
c3.innerHTML = san(displayName);
115114

116-
if (file.size > server_max_size)
115+
if (displaySize > server_max_size)
117116
return;
118117

119-
fetch("upload/" + lws_urlencode(file.name), {
118+
fetch("upload/" + lws_urlencode(displayName), {
120119
method: "POST",
121120
body: formData
122121
})
123-
.then((e) => { /* this just means we got a response code */
122+
.then((e) => { /* this just means we got a response code */
124123
var us = e.url.split("/"), ul = us[us.length - 1], n;
125124

126125
for (n = 0; n < t.rows.length; n++)
@@ -149,10 +148,16 @@
149148
});
150149
}
151150

151+
function do_upload(file) {
152+
var formData = new FormData();
153+
formData.append("file", file);
154+
_do_upload(formData, file.name, file.size);
155+
}
156+
152157
function da_drop(e) {
153158
var da = document.getElementById("da");
154159

155-
e.preventDefault();
160+
e.preventDefault();
156161
da.classList.remove("trot");
157162

158163
clear_errors();
@@ -169,24 +174,48 @@
169174
([...fi.files]).forEach(do_upload);
170175
}
171176

172-
function body_drop(e) {
177+
function upl_text_button(e) {
178+
var content = document.getElementById("text_content"),
179+
d = new Date(),
180+
ts = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' +
181+
pad(d.getDate()) + '_' + pad(d.getHours()) + '-' +
182+
pad(d.getMinutes()) + '-' + pad(d.getSeconds()),
183+
generated_filename = ts + (username ? '_' + username : '') + '.txt',
184+
formData = new FormData(), blob;
185+
173186
e.preventDefault();
174-
}
187+
clear_errors();
175188

176-
function inp() {
177-
var fi = document.getElementById("file"),
178-
upl = document.getElementById("upl");
179-
console.log("inp");
180-
upl.disabled = !fi.files.length;
189+
blob = new Blob([content.value], { type: "text/plain" });
190+
formData.append("file", blob, generated_filename);
191+
192+
_do_upload(formData, generated_filename, blob.size);
193+
content.value = "";
194+
text_inp(); // Manually update button state after clearing
181195
}
182196

183197
function delfile(e)
184198
{
185199
e.stopPropagation();
186200
e.preventDefault();
187201

188-
ws.send("{\"del\":\"" + decodeURI(e.target.getAttribute("file")) +
189-
"\"}");
202+
ws.send("{\"del\":\"" + e.target.getAttribute("file") + "\"}");
203+
}
204+
205+
function body_drop(e) {
206+
e.preventDefault();
207+
}
208+
209+
function file_inp() {
210+
var fi = document.getElementById("file"),
211+
upl = document.getElementById("upl");
212+
upl.disabled = !fi.files.length;
213+
}
214+
215+
function text_inp() {
216+
var content = document.getElementById("text_content"),
217+
upl_text = document.getElementById("upl_text");
218+
upl_text.disabled = !content.value.length;
190219
}
191220

192221
function get_appropriate_ws_url(extra_url)
@@ -222,16 +251,21 @@
222251

223252
document.addEventListener("DOMContentLoaded", function() {
224253
var da = document.getElementById("da"),
225-
fi = document.getElementById("file"),
226-
upl = document.getElementById("upl");
254+
fi = document.getElementById("file"),
255+
upl = document.getElementById("upl"),
256+
text_content = document.getElementById("text_content"),
257+
upl_text = document.getElementById("upl_text");
227258

228259
da.addEventListener("dragenter", da_enter, false);
229260
da.addEventListener("dragleave", da_leave, false);
230261
da.addEventListener("dragover", da_over, false);
231262
da.addEventListener("drop", da_drop, false);
232263

233-
upl.addEventListener("click", upl_button, false);
234-
fi.addEventListener("change", inp, false);
264+
upl.addEventListener("click", upl_button, false);
265+
fi.addEventListener("change", file_inp, false);
266+
267+
upl_text.addEventListener("click", upl_text_button, false);
268+
text_content.addEventListener("input", text_inp, false);
235269

236270
window.addEventListener("dragover", body_drop, false);
237271
window.addEventListener("drop", body_drop, false);
@@ -250,6 +284,7 @@
250284
var j = JSON.parse(msg.data), s = "", n,
251285
t = document.getElementById("dd-list");
252286

287+
username = j.user || "";
253288
server_max_size = j.max_size;
254289
document.getElementById("size").innerHTML =
255290
"Server maximum file size " +
@@ -262,12 +297,12 @@
262297
humanize(j.files[n].size) +
263298
"</td><td class=\"dow\">" +
264299
date.toDateString() + " " +
265-
date.toLocaleTimeString() +
266-
"</td><td>";
267-
if (j.files[n].yours === 1)
300+
date.toLocaleTimeString() + "</td><td>";
301+
302+
if (username) /* any authenticated user can delete */
268303
s += "<img id=\"d" + n +
269304
"\" class=\"delbtn\" file=\"" +
270-
lws_urlencode(san(j.files[n].name)) + "\">";
305+
san(j.files[n].name) + "\">";
271306
else
272307
s += " ";
273308

@@ -278,13 +313,12 @@
278313
}
279314
s += "</table>";
280315

281-
t.innerHTML = san(s);
316+
t.innerHTML = s;
282317

283318
for (n = 0; n < j.files.length; n++) {
284319
var d = document.getElementById("d" + n);
285320
if (d)
286-
d.addEventListener("click",
287-
delfile, false);
321+
d.addEventListener("click", delfile, false);
288322
}
289323
};
290324

@@ -301,3 +335,4 @@
301335

302336
});
303337
}());
338+

0 commit comments

Comments
 (0)