Skip to content

Commit d3f131b

Browse files
committed
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>
1 parent 4c9b93e commit d3f131b

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

t/t9011-svn-da.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,46 @@ test_expect_success 'catch attempt to copy missing data' '
168168
test_must_fail test-svn-fe -d preimage copy.incomplete $len
169169
'
170170

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+
171213
test_done

vcs-svn/svndiff.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,20 @@
2121
* | packed_view_selector int
2222
* | packed_copyfrom_data
2323
* ;
24+
* view_selector ::= copyfrom_source
25+
* | copyfrom_target
26+
* ;
27+
* copyfrom_target ::= # binary 01 000000;
2428
* copyfrom_data ::= # binary 10 000000;
29+
* packed_view_selector ::= # view_selector OR-ed with 6 bit value;
2530
* packed_copyfrom_data ::= # copyfrom_data OR-ed with 6 bit value;
2631
* int ::= highdigit* lowdigit;
2732
* highdigit ::= # binary 1000 0000 OR-ed with 7 bit value;
2833
* lowdigit ::= # 7 bit value;
2934
*/
3035

3136
#define INSN_MASK 0xc0
37+
#define INSN_COPYFROM_TARGET 0x40
3238
#define INSN_COPYFROM_DATA 0x80
3339
#define OPERAND_MASK 0x3f
3440

@@ -155,6 +161,19 @@ static int read_length(struct line_buffer *in, size_t *result, off_t *len)
155161
return 0;
156162
}
157163

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+
158177
static int copyfrom_data(struct window *ctx, size_t *data_pos, size_t nbytes)
159178
{
160179
const size_t pos = *data_pos;
@@ -189,9 +208,14 @@ static int execute_one_instruction(struct window *ctx,
189208
instruction = (unsigned char) **instructions;
190209
if (parse_first_operand(instructions, &nbytes, insns_end))
191210
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:
193217
return error("Unknown instruction %x", instruction);
194-
return copyfrom_data(ctx, data_pos, nbytes);
218+
}
195219
}
196220

197221
static int apply_window_in_core(struct window *ctx)

0 commit comments

Comments
 (0)