Skip to content

Commit 058ec9d

Browse files
Added function for applying a patch
1 parent 2823392 commit 058ec9d

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

patch.sql

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
create or replace function apply_hunk(original text[], hunk text[],
2+
start int DEFAULT 1, reverse boolean DEFAULT FALSE) returns text[] as $$
3+
declare
4+
result text[];
5+
orig_length int;
6+
hunk_length int;
7+
orig_ptr int := 1;
8+
hunk_ptr int := 1;
9+
orig_line text;
10+
hunk_line text;
11+
hunk_content text;
12+
marker char(1);
13+
begin
14+
orig_length := array_length(original, 1);
15+
hunk_length := array_length(hunk, 1);
16+
IF orig_length IS NULL OR hunk_length IS NULL THEN
17+
RETURN original;
18+
END IF;
19+
IF start < 1 THEN
20+
RAISE 'start is %, but must be greater than 0', start;
21+
END IF;
22+
IF start > 1 THEN
23+
result := original[1:start-1];
24+
END IF;
25+
orig_ptr := start;
26+
orig_line := original[orig_ptr];
27+
hunk_line := hunk[hunk_ptr];
28+
29+
LOOP
30+
RAISE notice 'op = %, hp = %, ol = %, hl = %', orig_ptr, hunk_ptr, orig_line, hunk_line;
31+
IF hunk_line IS NULL THEN
32+
-- End of the hunk. Wrap up the rest, and leave.
33+
RETURN result || original[orig_ptr:orig_length];
34+
END IF;
35+
marker := left(hunk_line, 1);
36+
hunk_content := substring(hunk_line from 2);
37+
IF marker = ' ' THEN
38+
IF hunk_content = orig_line THEN
39+
result := result || hunk_content;
40+
orig_ptr := orig_ptr + 1;
41+
hunk_ptr := hunk_ptr + 1;
42+
orig_line := original[orig_ptr];
43+
hunk_line := hunk[hunk_ptr];
44+
ELSE
45+
RAISE 'line % of hunk is a context line, but does not match. "%" != "%"', hunk_ptr, hunk_content, orig_line;
46+
END IF;
47+
ELSIF (marker = '+' and not reverse) or (marker = '-' and reverse) THEN
48+
result := result || hunk_content;
49+
hunk_ptr := hunk_ptr + 1;
50+
hunk_line := hunk[hunk_ptr];
51+
ELSIF (marker = '-' and not reverse) or (marker = '+' and reverse) THEN
52+
IF hunk_content != orig_line THEN
53+
RAISE 'line % of hunk is a removal line, but does not match. "%" != "%"', hunk_ptr, hunk_content, orig_line;
54+
ELSE
55+
orig_ptr := orig_ptr + 1;
56+
hunk_ptr := hunk_ptr + 1;
57+
hunk_line := hunk[hunk_ptr];
58+
orig_line := original[orig_ptr];
59+
END IF;
60+
ELSE
61+
RAISE 'unknown marker "%" on line %', marker, hunk_ptr;
62+
END IF;
63+
END LOOP;
64+
end;
65+
$$ language plpgsql
66+
IMMUTABLE;
67+
68+
create or replace function apply_hunk(original text, hunk text,
69+
start int DEFAULT 1, reverse boolean DEFAULT FALSE) returns text as $$
70+
begin
71+
RETURN array_to_string(apply_hunk(
72+
string_to_array(original, E'\n'),
73+
string_to_array(hunk, E'\n'),
74+
start, reverse),
75+
E'\n');
76+
end;
77+
$$ language plpgsql
78+
IMMUTABLE;

0 commit comments

Comments
 (0)