@matheusbsbs / matheus-bagliano / commits / d3f131b57e
Fork 0

vcs-svn: let deltas use data from postimage

The copyfrom_target instruction copies appends data that is already present in the current output view to the end of output. (The offset argument is relative to the beginning of output produced in the current window.) The region copied is allowed to run past the end of the existing output. To support that case, copy one character at a time rather than calling memcpy or memmove. This allows copyfrom_target to be used once to repeat a string many times. For example: COPYFROM_DATA 2 COPYFROM_OUTPUT 10, 0 DATA "ab" would produce the output "ababababababababababab". Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Acked-by: Ramkumar Ramachandra <artagnon@gmail.com>

Jonathan Nieder committed Oct 13, 2010 at 04:50 UTC d3f131b57ec0e69a37bca882fa6bf39aa4c1c387
2 files changed +68 -2
t/t9011-svn-da.sh
+42
@@ -168,4 +168,46 @@ test_expect_success 'catch attempt to copy missing data' '
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_done
vcs-svn/svndiff.c
+26 -2
@@ -21,7 +21,12 @@
21 * | packed_view_selector int
22 * | packed_copyfrom_data
23 * ;
24 + * view_selector ::= copyfrom_source
25 + * | copyfrom_target
26 + * ;
27 + * copyfrom_target ::= # binary 01 000000;
28 * copyfrom_data ::= # binary 10 000000;
29 + * packed_view_selector ::= # view_selector OR-ed with 6 bit value;
30 * packed_copyfrom_data ::= # copyfrom_data OR-ed with 6 bit value;
31 * int ::= highdigit* lowdigit;
32 * highdigit ::= # binary 1000 0000 OR-ed with 7 bit value;
@@ -29,6 +34,7 @@
34 */
35
36 #define INSN_MASK 0xc0
37 +#define INSN_COPYFROM_TARGET 0x40
38 #define INSN_COPYFROM_DATA 0x80
39 #define OPERAND_MASK 0x3f
40
@@ -155,6 +161,19 @@ static int read_length(struct line_buffer *in, size_t *result, off_t *len)
161 return 0;
162 }
163
164 +static int copyfrom_target(struct window *ctx, const char **instructions,
165 + size_t nbytes, const char *instructions_end)
166 +{
167 + size_t offset;
168 + if (parse_int(instructions, &offset, instructions_end))
169 + return -1;
170 + if (offset >= ctx->out.len)
171 + return error("invalid delta: copies from the future");
172 + for (; nbytes > 0; nbytes--)
173 + strbuf_addch(&ctx->out, ctx->out.buf[offset++]);
174 + return 0;
175 +}
176 +
177 static int copyfrom_data(struct window *ctx, size_t *data_pos, size_t nbytes)
178 {
179 const size_t pos = *data_pos;
@@ -189,9 +208,14 @@ static int execute_one_instruction(struct window *ctx,
208 instruction = (unsigned char) **instructions;
209 if (parse_first_operand(instructions, &nbytes, insns_end))
210 return -1;
192 - if ((instruction & INSN_MASK) != INSN_COPYFROM_DATA)
211 + switch (instruction & INSN_MASK) {
212 + case INSN_COPYFROM_TARGET:
213 + return copyfrom_target(ctx, instructions, nbytes, insns_end);
214 + case INSN_COPYFROM_DATA:
215 + return copyfrom_data(ctx, data_pos, nbytes);
216 + default:
217 return error("Unknown instruction %x", instruction);
194 - return copyfrom_data(ctx, data_pos, nbytes);
218 + }
219 }
220
221 static int apply_window_in_core(struct window *ctx)