Fossil SCM

fossil-scm / src / deltacmd.c
Blame History Raw 199 lines
1
/*
2
** Copyright (c) 2006 D. Richard Hipp
3
**
4
** This program is free software; you can redistribute it and/or
5
** modify it under the terms of the Simplified BSD License (also
6
** known as the "2-Clause License" or "FreeBSD License".)
7
8
** This program is distributed in the hope that it will be useful,
9
** but without any warranty; without even the implied warranty of
10
** merchantability or fitness for a particular purpose.
11
**
12
** Author contact information:
13
** [email protected]
14
** http://www.hwaci.com/drh/
15
**
16
*******************************************************************************
17
**
18
** This module implements the interface to the delta generator.
19
*/
20
#include "config.h"
21
#include "deltacmd.h"
22
23
/*
24
** Create a delta that describes the change from pOriginal to pTarget
25
** and put that delta in pDelta. The pDelta blob is assumed to be
26
** uninitialized.
27
*/
28
int blob_delta_create(Blob *pOriginal, Blob *pTarget, Blob *pDelta){
29
const char *zOrig, *zTarg;
30
int lenOrig, lenTarg;
31
int len;
32
char *zRes;
33
blob_zero(pDelta);
34
zOrig = blob_materialize(pOriginal);
35
lenOrig = blob_size(pOriginal);
36
zTarg = blob_materialize(pTarget);
37
lenTarg = blob_size(pTarget);
38
blob_resize(pDelta, lenTarg+16);
39
zRes = blob_materialize(pDelta);
40
len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
41
blob_resize(pDelta, len);
42
return 0;
43
}
44
45
/*
46
** COMMAND: test-delta-create
47
**
48
** Usage: %fossil test-delta-create FILE1 FILE2 DELTA
49
**
50
** Create and output a delta that carries FILE1 into FILE2.
51
** Store the result in DELTA.
52
*/
53
void delta_create_cmd(void){
54
Blob orig, target, delta;
55
if( g.argc!=5 ){
56
usage("ORIGIN TARGET DELTA");
57
}
58
if( blob_read_from_file(&orig, g.argv[2], ExtFILE)<0 ){
59
fossil_fatal("cannot read %s", g.argv[2]);
60
}
61
if( blob_read_from_file(&target, g.argv[3], ExtFILE)<0 ){
62
fossil_fatal("cannot read %s", g.argv[3]);
63
}
64
blob_delta_create(&orig, &target, &delta);
65
if( blob_write_to_file(&delta, g.argv[4])<(int)blob_size(&delta) ){
66
fossil_fatal("cannot write %s", g.argv[4]);
67
}
68
blob_reset(&orig);
69
blob_reset(&target);
70
blob_reset(&delta);
71
}
72
73
/*
74
** COMMAND: test-delta-analyze
75
**
76
** Usage: %fossil test-delta-analyze FILE1 FILE2
77
**
78
** Create and a delta that carries FILE1 into FILE2. Print the
79
** number bytes copied and the number of bytes inserted.
80
*/
81
void delta_analyze_cmd(void){
82
Blob orig, target, delta;
83
int nCopy = 0;
84
int nInsert = 0;
85
int sz1, sz2, sz3;
86
if( g.argc!=4 ){
87
usage("ORIGIN TARGET");
88
}
89
if( blob_read_from_file(&orig, g.argv[2], ExtFILE)<0 ){
90
fossil_fatal("cannot read %s", g.argv[2]);
91
}
92
if( blob_read_from_file(&target, g.argv[3], ExtFILE)<0 ){
93
fossil_fatal("cannot read %s", g.argv[3]);
94
}
95
blob_delta_create(&orig, &target, &delta);
96
delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert);
97
sz1 = blob_size(&orig);
98
sz2 = blob_size(&target);
99
sz3 = blob_size(&delta);
100
blob_reset(&orig);
101
blob_reset(&target);
102
blob_reset(&delta);
103
fossil_print("original size: %8d\n", sz1);
104
fossil_print("bytes copied: %8d (%.2f%% of target)\n",
105
nCopy, (100.0*nCopy)/sz2);
106
fossil_print("bytes inserted: %8d (%.2f%% of target)\n",
107
nInsert, (100.0*nInsert)/sz2);
108
fossil_print("final size: %8d\n", sz2);
109
fossil_print("delta size: %8d\n", sz3);
110
}
111
112
/*
113
** Apply the delta in pDelta to the original file pOriginal to generate
114
** the target file pTarget. The pTarget blob is initialized by this
115
** routine.
116
**
117
** It works ok for pTarget and pOriginal to be the same blob.
118
**
119
** Return the length of the target. Return -1 if there is an error.
120
*/
121
int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
122
int len, n;
123
Blob out;
124
125
n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
126
blob_zero(&out);
127
if( n<0 ) return -1;
128
blob_resize(&out, n);
129
len = delta_apply(
130
blob_buffer(pOriginal), blob_size(pOriginal),
131
blob_buffer(pDelta), blob_size(pDelta),
132
blob_buffer(&out));
133
if( len<0 ){
134
blob_reset(&out);
135
}else if( len!=n ){
136
blob_resize(&out, len);
137
}
138
if( pTarget==pOriginal ){
139
blob_reset(pOriginal);
140
}
141
*pTarget = out;
142
return len;
143
}
144
145
/*
146
** COMMAND: test-delta-apply
147
**
148
** Usage: %fossil test-delta-apply FILE1 DELTA FILE2
149
**
150
** Apply DELTA to FILE1 and output the result in FILE2.
151
*/
152
void delta_apply_cmd(void){
153
Blob orig, target, delta;
154
if( g.argc!=5 ){
155
usage("ORIGIN DELTA TARGET");
156
}
157
if( blob_read_from_file(&orig, g.argv[2], ExtFILE)<0 ){
158
fossil_fatal("cannot read %s", g.argv[2]);
159
}
160
if( blob_read_from_file(&delta, g.argv[3], ExtFILE)<0 ){
161
fossil_fatal("cannot read %s", g.argv[3]);
162
}
163
blob_init(&target, 0, 0);
164
blob_delta_apply(&orig, &delta, &target);
165
if( blob_write_to_file(&target, g.argv[4])<(int)blob_size(&target) ){
166
fossil_fatal("cannot write %s", g.argv[4]);
167
}
168
blob_reset(&orig);
169
blob_reset(&target);
170
blob_reset(&delta);
171
}
172
173
174
/*
175
** COMMAND: test-delta
176
**
177
** Usage: %fossil test-delta FILE1 FILE2
178
**
179
** Read two files named on the command-line. Create and apply deltas
180
** going in both directions. Verify that the original files are
181
** correctly recovered.
182
*/
183
void cmd_test_delta(void){
184
Blob f1, f2; /* Original file content */
185
Blob d12, d21; /* Deltas from f1->f2 and f2->f1 */
186
Blob a1, a2; /* Recovered file content */
187
if( g.argc!=4 ) usage("FILE1 FILE2");
188
blob_read_from_file(&f1, g.argv[2], ExtFILE);
189
blob_read_from_file(&f2, g.argv[3], ExtFILE);
190
blob_delta_create(&f1, &f2, &d12);
191
blob_delta_create(&f2, &f1, &d21);
192
blob_delta_apply(&f1, &d12, &a2);
193
blob_delta_apply(&f2, &d21, &a1);
194
if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
195
fossil_fatal("delta test failed");
196
}
197
fossil_print("ok\n");
198
}
199

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button