Skip to content

Commit a8d3d26

Browse files
committed
Merge branch 'db/delta-applier' into svn-fe
* db/delta-applier: vcs-svn: cap number of bytes read from sliding view test-svn-fe: split off "test-svn-fe -d" into a separate function vcs-svn: let deltas use data from preimage vcs-svn: let deltas use data from postimage vcs-svn: verify that deltas consume all inline data vcs-svn: implement copyfrom_data delta instruction vcs-svn: read instructions from deltas vcs-svn: read inline data from deltas vcs-svn: read the preimage when applying deltas vcs-svn: parse svndiff0 window header vcs-svn: skeleton of an svn delta parser vcs-svn: make buffer_read_binary API more convenient vcs-svn: learn to maintain a sliding view of a file Makefile: list one vcs-svn/xdiff object or header per line Conflicts: Makefile vcs-svn/LICENSE
2 parents c19d653 + fbdd4f6 commit a8d3d26

File tree

10 files changed

+753
-25
lines changed

10 files changed

+753
-25
lines changed

Makefile

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ BUILTIN_OBJS =
342342
BUILT_INS =
343343
COMPAT_CFLAGS =
344344
COMPAT_OBJS =
345+
XDIFF_H =
346+
XDIFF_OBJS =
347+
VCSSVN_H =
348+
VCSSVN_OBJS =
349+
VCSSVN_TEST_OBJS =
345350
EXTRA_CPPFLAGS =
346351
LIB_H =
347352
LIB_OBJS =
@@ -1832,11 +1837,23 @@ GIT_OBJS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
18321837
ifndef NO_CURL
18331838
GIT_OBJS += http.o http-walker.o remote-curl.o
18341839
endif
1835-
XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
1836-
xdiff/xmerge.o xdiff/xpatience.o
1837-
VCSSVN_OBJS = vcs-svn/line_buffer.o vcs-svn/repo_tree.o \
1838-
vcs-svn/fast_export.o vcs-svn/svndump.o
1839-
VCSSVN_TEST_OBJS = test-line-buffer.o
1840+
1841+
XDIFF_OBJS += xdiff/xdiffi.o
1842+
XDIFF_OBJS += xdiff/xprepare.o
1843+
XDIFF_OBJS += xdiff/xutils.o
1844+
XDIFF_OBJS += xdiff/xemit.o
1845+
XDIFF_OBJS += xdiff/xmerge.o
1846+
XDIFF_OBJS += xdiff/xpatience.o
1847+
1848+
VCSSVN_OBJS += vcs-svn/line_buffer.o
1849+
VCSSVN_OBJS += vcs-svn/sliding_window.o
1850+
VCSSVN_OBJS += vcs-svn/repo_tree.o
1851+
VCSSVN_OBJS += vcs-svn/fast_export.o
1852+
VCSSVN_OBJS += vcs-svn/svndiff.o
1853+
VCSSVN_OBJS += vcs-svn/svndump.o
1854+
1855+
VCSSVN_TEST_OBJS += test-line-buffer.o
1856+
18401857
OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) $(VCSSVN_OBJS)
18411858

18421859
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
@@ -1955,15 +1972,25 @@ connect.o transport.o http-backend.o: url.h
19551972
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
19561973
http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h url.h
19571974

1958-
xdiff-interface.o $(XDIFF_OBJS): \
1959-
xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
1960-
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
1961-
1962-
$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) \
1963-
vcs-svn/line_buffer.h vcs-svn/repo_tree.h vcs-svn/fast_export.h \
1964-
vcs-svn/svndump.h
1965-
1966-
test-svn-fe.o: vcs-svn/svndump.h
1975+
XDIFF_H += xdiff/xinclude.h
1976+
XDIFF_H += xdiff/xmacros.h
1977+
XDIFF_H += xdiff/xdiff.h
1978+
XDIFF_H += xdiff/xtypes.h
1979+
XDIFF_H += xdiff/xutils.h
1980+
XDIFF_H += xdiff/xprepare.h
1981+
XDIFF_H += xdiff/xdiffi.h
1982+
XDIFF_H += xdiff/xemit.h
1983+
1984+
xdiff-interface.o $(XDIFF_OBJS): $(XDIFF_H)
1985+
1986+
VCSSVN_H += vcs-svn/line_buffer.h
1987+
VCSSVN_H += vcs-svn/sliding_window.h
1988+
VCSSVN_H += vcs-svn/repo_tree.h
1989+
VCSSVN_H += vcs-svn/fast_export.h
1990+
VCSSVN_H += vcs-svn/svndiff.h
1991+
VCSSVN_H += vcs-svn/svndump.h
1992+
1993+
$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) $(VCSSVN_H)
19671994
endif
19681995

19691996
exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \

t/t9011-svn-da.sh

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#!/bin/sh
2+
3+
test_description='test parsing of svndiff0 files
4+
5+
Using the "test-svn-fe -d" helper, check that svn-fe correctly
6+
interprets deltas using various facilities (some from the spec,
7+
some only learned from practice).
8+
'
9+
. ./test-lib.sh
10+
11+
>empty
12+
printf foo >preimage
13+
14+
test_expect_success 'reject empty delta' '
15+
test_must_fail test-svn-fe -d preimage empty 0
16+
'
17+
18+
test_expect_success 'delta can empty file' '
19+
printf "SVNQ" | q_to_nul >clear.delta &&
20+
test-svn-fe -d preimage clear.delta 4 >actual &&
21+
test_cmp empty actual
22+
'
23+
24+
test_expect_success 'reject svndiff2' '
25+
printf "SVN\002" >bad.filetype &&
26+
test_must_fail test-svn-fe -d preimage bad.filetype 4
27+
'
28+
29+
test_expect_success 'one-window empty delta' '
30+
printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow &&
31+
test-svn-fe -d preimage clear.onewindow 9 >actual &&
32+
test_cmp empty actual
33+
'
34+
35+
test_expect_success 'reject incomplete window header' '
36+
printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow &&
37+
printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow &&
38+
test_must_fail test-svn-fe -d preimage clear.onewindow 6 &&
39+
test_must_fail test-svn-fe -d preimage clear.partialwindow 6
40+
'
41+
42+
test_expect_success 'reject declared delta longer than actual delta' '
43+
printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow &&
44+
printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow &&
45+
test_must_fail test-svn-fe -d preimage clear.onewindow 14 &&
46+
test_must_fail test-svn-fe -d preimage clear.partialwindow 9
47+
'
48+
49+
test_expect_success 'two-window empty delta' '
50+
printf "SVNQ%s%s" "QQQQQ" "QQQQQ" | q_to_nul >clear.twowindow &&
51+
test-svn-fe -d preimage clear.twowindow 14 >actual &&
52+
test_must_fail test-svn-fe -d preimage clear.twowindow 13 &&
53+
test_cmp empty actual
54+
'
55+
56+
test_expect_success 'noisy zeroes' '
57+
printf "SVNQ%s" \
58+
"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQQQQQ" |
59+
tr R "\200" |
60+
q_to_nul >clear.noisy &&
61+
len=$(wc -c <clear.noisy) &&
62+
test-svn-fe -d preimage clear.noisy $len &&
63+
test_cmp empty actual
64+
'
65+
66+
test_expect_success 'reject variable-length int in magic' '
67+
printf "SVNRQ" | tr R "\200" | q_to_nul >clear.badmagic &&
68+
test_must_fail test-svn-fe -d preimage clear.badmagic 5
69+
'
70+
71+
test_expect_success 'reject truncated integer' '
72+
printf "SVNQ%s%s" "QQQQQ" "QQQQRRQ" |
73+
tr R "\200" |
74+
q_to_nul >clear.fullint &&
75+
printf "SVNQ%s%s" "QQQQQ" "QQQQRR" |
76+
tr RT "\201" |
77+
q_to_nul >clear.partialint &&
78+
test_must_fail test-svn-fe -d preimage clear.fullint 15 &&
79+
test-svn-fe -d preimage clear.fullint 16 &&
80+
test_must_fail test-svn-fe -d preimage clear.partialint 15
81+
'
82+
83+
test_expect_success 'nonempty (but unused) preimage view' '
84+
printf "SVNQ%b" "Q\003QQQ" | q_to_nul >clear.readpreimage &&
85+
test-svn-fe -d preimage clear.readpreimage 9 >actual &&
86+
test_cmp empty actual
87+
'
88+
89+
test_expect_success 'preimage view: right endpoint cannot backtrack' '
90+
printf "SVNQ%b%b" "Q\003QQQ" "Q\002QQQ" |
91+
q_to_nul >clear.backtrack &&
92+
test_must_fail test-svn-fe -d preimage clear.backtrack 14
93+
'
94+
95+
test_expect_success 'preimage view: left endpoint can advance' '
96+
printf "SVNQ%b%b" "Q\003QQQ" "\001\002QQQ" |
97+
q_to_nul >clear.preshrink &&
98+
printf "SVNQ%b%b" "Q\003QQQ" "\001\001QQQ" |
99+
q_to_nul >clear.shrinkbacktrack &&
100+
test-svn-fe -d preimage clear.preshrink 14 >actual &&
101+
test_must_fail test-svn-fe -d preimage clear.shrinkbacktrack 14 &&
102+
test_cmp empty actual
103+
'
104+
105+
test_expect_success 'preimage view: offsets compared by value' '
106+
printf "SVNQ%b%b" "\001\001QQQ" "\0200Q\003QQQ" |
107+
q_to_nul >clear.noisybacktrack &&
108+
printf "SVNQ%b%b" "\001\001QQQ" "\0200\001\002QQQ" |
109+
q_to_nul >clear.noisyadvance &&
110+
test_must_fail test-svn-fe -d preimage clear.noisybacktrack 15 &&
111+
test-svn-fe -d preimage clear.noisyadvance 15 &&
112+
test_cmp empty actual
113+
'
114+
115+
test_expect_success 'preimage view: reject truncated preimage' '
116+
printf "SVNQ%b" "\010QQQQ" | q_to_nul >clear.lateemptyread &&
117+
printf "SVNQ%b" "\010\001QQQ" | q_to_nul >clear.latenonemptyread &&
118+
printf "SVNQ%b" "\001\010QQQ" | q_to_nul >clear.longread &&
119+
test_must_fail test-svn-fe -d preimage clear.lateemptyread 9 &&
120+
test_must_fail test-svn-fe -d preimage clear.latenonemptyread 9 &&
121+
test_must_fail test-svn-fe -d preimage clear.longread 9
122+
'
123+
124+
test_expect_success 'forbid unconsumed inline data' '
125+
printf "SVNQ%b%s%b%s" "QQQQ\003" "bar" "QQQQ\001" "x" |
126+
q_to_nul >inline.clear &&
127+
test_must_fail test-svn-fe -d preimage inline.clear 18 >actual
128+
'
129+
130+
test_expect_success 'reject truncated inline data' '
131+
printf "SVNQ%b%s" "QQQQ\003" "b" | q_to_nul >inline.trunc &&
132+
test_must_fail test-svn-fe -d preimage inline.trunc 10
133+
'
134+
135+
test_expect_success 'reject truncated inline data (after instruction section)' '
136+
printf "SVNQ%b%b%s" "QQ\001\001\003" "\0201" "b" | q_to_nul >insn.trunc &&
137+
test_must_fail test-svn-fe -d preimage insn.trunc 11
138+
'
139+
140+
test_expect_success 'copyfrom_data' '
141+
echo hi >expect &&
142+
printf "SVNQ%b%b%b" "QQ\003\001\003" "\0203" "hi\n" | q_to_nul >copydat &&
143+
test-svn-fe -d preimage copydat 13 >actual &&
144+
test_cmp expect actual
145+
'
146+
147+
test_expect_success 'multiple copyfrom_data' '
148+
echo hi >expect &&
149+
printf "SVNQ%b%b%b%b%b" "QQ\003\002\003" "\0201\0202" "hi\n" \
150+
"QQQ\002Q" "\0200Q" | q_to_nul >copy.multi &&
151+
len=$(wc -c <copy.multi) &&
152+
test-svn-fe -d preimage copy.multi $len >actual &&
153+
test_cmp expect actual
154+
'
155+
156+
test_expect_success 'incomplete multiple insn' '
157+
printf "SVNQ%b%b%b" "QQ\003\002\003" "\0203\0200" "hi\n" |
158+
q_to_nul >copy.partial &&
159+
len=$(wc -c <copy.partial) &&
160+
test_must_fail test-svn-fe -d preimage copy.partial $len
161+
'
162+
163+
test_expect_success 'catch attempt to copy missing data' '
164+
printf "SVNQ%b%b%s%b%s" "QQ\002\002\001" "\0201\0201" "X" \
165+
"QQQQ\002" "YZ" |
166+
q_to_nul >copy.incomplete &&
167+
len=$(wc -c <copy.incomplete) &&
168+
test_must_fail test-svn-fe -d preimage copy.incomplete $len
169+
'
170+
171+
test_expect_success 'copyfrom target to repeat data' '
172+
printf foofoo >expect &&
173+
printf "SVNQ%b%b%s" "QQ\006\004\003" "\0203\0100\003Q" "foo" |
174+
q_to_nul >copytarget.repeat &&
175+
len=$(wc -c <copytarget.repeat) &&
176+
test-svn-fe -d preimage copytarget.repeat $len >actual &&
177+
test_cmp expect actual
178+
'
179+
180+
test_expect_success 'copyfrom target out of order' '
181+
printf foooof >expect &&
182+
printf "SVNQ%b%b%s" \
183+
"QQ\006\007\003" "\0203\0101\002\0101\001\0101Q" "foo" |
184+
q_to_nul >copytarget.reverse &&
185+
len=$(wc -c <copytarget.reverse) &&
186+
test-svn-fe -d preimage copytarget.reverse $len >actual &&
187+
test_cmp expect actual
188+
'
189+
190+
test_expect_success 'catch copyfrom future' '
191+
printf "SVNQ%b%b%s" "QQ\004\004\003" "\0202\0101\002\0201" "XYZ" |
192+
q_to_nul >copytarget.infuture &&
193+
len=$(wc -c <copytarget.infuture) &&
194+
test_must_fail test-svn-fe -d preimage copytarget.infuture $len
195+
'
196+
197+
test_expect_success 'copy to sustain' '
198+
printf XYXYXYXYXYXZ >expect &&
199+
printf "SVNQ%b%b%s" "QQ\014\004\003" "\0202\0111Q\0201" "XYZ" |
200+
q_to_nul >copytarget.sustain &&
201+
len=$(wc -c <copytarget.sustain) &&
202+
test-svn-fe -d preimage copytarget.sustain $len >actual &&
203+
test_cmp expect actual
204+
'
205+
206+
test_expect_success 'catch copy that overflows' '
207+
printf "SVNQ%b%b%s" "QQ\003\003\001" "\0201\0177Q" X |
208+
q_to_nul >copytarget.overflow &&
209+
len=$(wc -c <copytarget.overflow) &&
210+
test_must_fail test-svn-fe -d preimage copytarget.overflow $len
211+
'
212+
213+
test_expect_success 'copyfrom source' '
214+
printf foo >expect &&
215+
printf "SVNQ%b%b" "Q\003\003\002Q" "\003Q" | q_to_nul >copysource.all &&
216+
test-svn-fe -d preimage copysource.all 11 >actual &&
217+
test_cmp expect actual
218+
'
219+
220+
test_expect_success 'copy backwards' '
221+
printf oof >expect &&
222+
printf "SVNQ%b%b" "Q\003\003\006Q" "\001\002\001\001\001Q" |
223+
q_to_nul >copysource.rev &&
224+
test-svn-fe -d preimage copysource.rev 15 >actual &&
225+
test_cmp expect actual
226+
'
227+
228+
test_expect_success 'offsets are relative to window' '
229+
printf fo >expect &&
230+
printf "SVNQ%b%b%b%b" "Q\003\001\002Q" "\001Q" \
231+
"\002\001\001\002Q" "\001Q" |
232+
q_to_nul >copysource.two &&
233+
test-svn-fe -d preimage copysource.two 18 >actual &&
234+
test_cmp expect actual
235+
'
236+
237+
test_expect_success 'example from notes/svndiff' '
238+
printf aaaaccccdddddddd >expect &&
239+
printf aaaabbbbcccc >source &&
240+
printf "SVNQ%b%b%s" "Q\014\020\007\001" \
241+
"\004Q\004\010\0201\0107\010" d |
242+
q_to_nul >delta.example &&
243+
len=$(wc -c <delta.example) &&
244+
test-svn-fe -d source delta.example $len >actual &&
245+
test_cmp expect actual
246+
'
247+
248+
test_done

test-svn-fe.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,51 @@
44

55
#include "git-compat-util.h"
66
#include "vcs-svn/svndump.h"
7+
#include "vcs-svn/svndiff.h"
8+
#include "vcs-svn/sliding_window.h"
9+
#include "vcs-svn/line_buffer.h"
710

8-
int main(int argc, char *argv[])
11+
static const char test_svnfe_usage[] =
12+
"test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)";
13+
14+
static int apply_delta(int argc, char *argv[])
915
{
10-
if (argc != 2)
11-
usage("test-svn-fe <file>");
12-
if (svndump_init(argv[1]))
16+
struct line_buffer preimage = LINE_BUFFER_INIT;
17+
struct line_buffer delta = LINE_BUFFER_INIT;
18+
struct sliding_view preimage_view = SLIDING_VIEW_INIT(&preimage, -1);
19+
20+
if (argc != 5)
21+
usage(test_svnfe_usage);
22+
23+
if (buffer_init(&preimage, argv[2]))
24+
die_errno("cannot open preimage");
25+
if (buffer_init(&delta, argv[3]))
26+
die_errno("cannot open delta");
27+
if (svndiff0_apply(&delta, (off_t) strtoull(argv[4], NULL, 0),
28+
&preimage_view, stdout))
1329
return 1;
14-
svndump_read(NULL);
15-
svndump_deinit();
16-
svndump_reset();
30+
if (buffer_deinit(&preimage))
31+
die_errno("cannot close preimage");
32+
if (buffer_deinit(&delta))
33+
die_errno("cannot close delta");
34+
buffer_reset(&preimage);
35+
strbuf_release(&preimage_view.buf);
36+
buffer_reset(&delta);
1737
return 0;
1838
}
39+
40+
int main(int argc, char *argv[])
41+
{
42+
if (argc == 2) {
43+
if (svndump_init(argv[1]))
44+
return 1;
45+
svndump_read(NULL);
46+
svndump_deinit();
47+
svndump_reset();
48+
return 0;
49+
}
50+
51+
if (argc >= 2 && !strcmp(argv[1], "-d"))
52+
return apply_delta(argc, argv);
53+
usage(test_svnfe_usage);
54+
}

vcs-svn/LICENSE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Copyright (C) 2010 David Barr <[email protected]>.
22
All rights reserved.
33

4+
Copyright (C) 2010 Jonathan Nieder <[email protected]>.
5+
46
Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH,
57
Frankfurt/Main, Germany
68
and others, see http://svn2cc.sarovar.org

0 commit comments

Comments
 (0)