annotate mercurial/mpatch.c @ 19966:7985e3469f58 stable

largefiles: systematic testing of merges to/from largefiles 427ce5633c1c fixed one problem with update and added a test case for it. The test coverage was thus insufficient before that. To make sure we have good test coverage in this area we add systematic testing of all cases of merges that may or may not change normal files to largefiles or vice versa. The tests shows some annoying extra merge prompts in some cases, but these prompts are hard to avoid and they are now "safe" - they do not leave the system in a confused inconsistent state.
author Mads Kiilerich <madski@unity3d.com>
date Mon, 28 Oct 2013 22:34:05 +0100
parents 9a8ab5c47f84
children 09e41ac6289d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
1 /*
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
2 mpatch.c - efficient binary patching for Mercurial
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
3
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
4 This implements a patch algorithm that's O(m + nlog n) where m is the
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
5 size of the output and n is the number of patches.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
6
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
7 Given a list of binary patches, it unpacks each into a hunk list,
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
8 then combines the hunk lists with a treewise recursion to form a
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
9 single hunk list. This hunk list is then applied to the original
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
10 text.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
11
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
12 The text (or binary) fragments are copied directly from their source
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
13 Python objects into a preallocated output string to avoid the
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
14 allocation of intermediate Python objects. Working memory is about 2x
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
15 the total number of hunks.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
16
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2543
diff changeset
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
18
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
19 This software may be used and distributed according to the terms
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
20 of the GNU General Public License, incorporated herein by reference.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
21 */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
22
16758
9a8ab5c47f84 mpatch: use Py_ssize_t for string length
Adrian Buehlmann <adrian@cadifra.com>
parents: 16757
diff changeset
23 #define PY_SSIZE_T_CLEAN
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
24 #include <Python.h>
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
25 #include <stdlib.h>
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
26 #include <string.h>
2468
1ac0574f1768 mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2083
diff changeset
27
11360
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
28 #include "util.h"
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
29
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
30 static char mpatch_doc[] = "Efficient binary patching.";
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
31 static PyObject *mpatch_Error;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
32
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
33 struct frag {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
34 int start, end, len;
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
35 const char *data;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
36 };
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
37
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
38 struct flist {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
39 struct frag *base, *head, *tail;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
40 };
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
41
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
42 static struct flist *lalloc(Py_ssize_t size)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
43 {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
44 struct flist *a = NULL;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
45
3138
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
46 if (size < 1)
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
47 size = 1;
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
48
1978
10606ee61107 do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents: 1746
diff changeset
49 a = (struct flist *)malloc(sizeof(struct flist));
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
50 if (a) {
1978
10606ee61107 do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents: 1746
diff changeset
51 a->base = (struct frag *)malloc(sizeof(struct frag) * size);
2048
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
52 if (a->base) {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
53 a->head = a->tail = a->base;
2048
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
54 return a;
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
55 }
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
56 free(a);
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
57 a = NULL;
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
58 }
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
59 if (!PyErr_Occurred())
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
60 PyErr_NoMemory();
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
61 return NULL;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
62 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
63
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
64 static void lfree(struct flist *a)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
65 {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
66 if (a) {
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
67 free(a->base);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
68 free(a);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
69 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
70 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
71
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
72 static Py_ssize_t lsize(struct flist *a)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
73 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
74 return a->tail - a->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
75 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
76
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
77 /* move hunks in source that are less cut to dest, compensating
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
78 for changes in offset. the last hunk may be split if necessary.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
79 */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
80 static int gather(struct flist *dest, struct flist *src, int cut, int offset)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
81 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
82 struct frag *d = dest->tail, *s = src->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
83 int postend, c, l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
84
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
85 while (s != src->tail) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
86 if (s->start + offset >= cut)
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
87 break; /* we've gone far enough */
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
88
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
89 postend = offset + s->start + s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
90 if (postend <= cut) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
91 /* save this hunk */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
92 offset += s->start + s->len - s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
93 *d++ = *s++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
94 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
95 else {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
96 /* break up this hunk */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
97 c = cut - offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
98 if (s->end < c)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
99 c = s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
100 l = cut - offset - s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
101 if (s->len < l)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
102 l = s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
103
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
104 offset += s->start + l - c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
105
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
106 d->start = s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
107 d->end = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
108 d->len = l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
109 d->data = s->data;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
110 d++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
111 s->start = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
112 s->len = s->len - l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
113 s->data = s->data + l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
114
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
115 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
116 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
117 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
118
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
119 dest->tail = d;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
120 src->head = s;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
121 return offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
122 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
123
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
124 /* like gather, but with no output list */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
125 static int discard(struct flist *src, int cut, int offset)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
126 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
127 struct frag *s = src->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
128 int postend, c, l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
129
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
130 while (s != src->tail) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
131 if (s->start + offset >= cut)
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
132 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
133
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
134 postend = offset + s->start + s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
135 if (postend <= cut) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
136 offset += s->start + s->len - s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
137 s++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
138 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
139 else {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
140 c = cut - offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
141 if (s->end < c)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
142 c = s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
143 l = cut - offset - s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
144 if (s->len < l)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
145 l = s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
146
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
147 offset += s->start + l - c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
148 s->start = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
149 s->len = s->len - l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
150 s->data = s->data + l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
151
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
152 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
153 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
154 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
155
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
156 src->head = s;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
157 return offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
158 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
159
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
160 /* combine hunk lists a and b, while adjusting b for offset changes in a/
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
161 this deletes a and b and returns the resultant list. */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
162 static struct flist *combine(struct flist *a, struct flist *b)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
163 {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
164 struct flist *c = NULL;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
165 struct frag *bh, *ct;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
166 int offset = 0, post;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
167
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
168 if (a && b)
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
169 c = lalloc((lsize(a) + lsize(b)) * 2);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
170
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
171 if (c) {
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
172
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
173 for (bh = b->head; bh != b->tail; bh++) {
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
174 /* save old hunks */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
175 offset = gather(c, a, bh->start, offset);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
176
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
177 /* discard replaced hunks */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
178 post = discard(a, bh->end, offset);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
179
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
180 /* insert new hunk */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
181 ct = c->tail;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
182 ct->start = bh->start - offset;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
183 ct->end = bh->end - post;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
184 ct->len = bh->len;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
185 ct->data = bh->data;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
186 c->tail++;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
187 offset = post;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
188 }
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
189
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
190 /* hold on to tail from a */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
191 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a));
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
192 c->tail += lsize(a);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
193 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
194
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
195 lfree(a);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
196 lfree(b);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
197 return c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
198 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
199
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
200 /* decode a binary patch into a hunk list */
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
201 static struct flist *decode(const char *bin, Py_ssize_t len)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
202 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
203 struct flist *l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
204 struct frag *lt;
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
205 const char *data = bin + 12, *end = bin + len;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
206
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
207 /* assume worst case size, we won't have many of these lists */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
208 l = lalloc(len / 12);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
209 if (!l)
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
210 return NULL;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
211
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
212 lt = l->tail;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
213
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
214 while (data <= end) {
16437
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
215 lt->start = getbe32(bin);
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
216 lt->end = getbe32(bin + 4);
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
217 lt->len = getbe32(bin + 8);
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
218 if (lt->start > lt->end)
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
219 break; /* sanity check */
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
220 bin = data + lt->len;
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
221 if (bin < data)
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
222 break; /* big data + big (bogus) len can wrap around */
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
223 lt->data = data;
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
224 data = bin + 12;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
225 lt++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
226 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
227
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
228 if (bin != end) {
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
229 if (!PyErr_Occurred())
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
230 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
231 lfree(l);
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
232 return NULL;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
233 }
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
234
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
235 l->tail = lt;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
236 return l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
237 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
238
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
239 /* calculate the size of resultant text */
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
240 static Py_ssize_t calcsize(Py_ssize_t len, struct flist *l)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
241 {
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
242 Py_ssize_t outlen = 0, last = 0;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
243 struct frag *f = l->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
244
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
245 while (f != l->tail) {
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
246 if (f->start < last || f->end > len) {
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
247 if (!PyErr_Occurred())
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
248 PyErr_SetString(mpatch_Error,
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
249 "invalid patch");
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
250 return -1;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
251 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
252 outlen += f->start - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
253 last = f->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
254 outlen += f->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
255 f++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
256 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
257
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
258 outlen += len - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
259 return outlen;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
260 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
261
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
262 static int apply(char *buf, const char *orig, Py_ssize_t len, struct flist *l)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
263 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
264 struct frag *f = l->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
265 int last = 0;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
266 char *p = buf;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
267
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
268 while (f != l->tail) {
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
269 if (f->start < last || f->end > len) {
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
270 if (!PyErr_Occurred())
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
271 PyErr_SetString(mpatch_Error,
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
272 "invalid patch");
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
273 return 0;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
274 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
275 memcpy(p, orig + last, f->start - last);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
276 p += f->start - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
277 memcpy(p, f->data, f->len);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
278 last = f->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
279 p += f->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
280 f++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
281 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
282 memcpy(p, orig + last, len - last);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
283 return 1;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
284 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
285
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
286 /* recursively generate a patch of all bins between start and end */
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
287 static struct flist *fold(PyObject *bins, Py_ssize_t start, Py_ssize_t end)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
288 {
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
289 Py_ssize_t len, blen;
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
290 const char *buffer;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
291
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
292 if (start + 1 == end) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
293 /* trivial case, output a decoded list */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
294 PyObject *tmp = PyList_GetItem(bins, start);
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
295 if (!tmp)
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
296 return NULL;
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
297 if (PyObject_AsCharBuffer(tmp, &buffer, &blen))
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
298 return NULL;
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
299 return decode(buffer, blen);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
300 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
301
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
302 /* divide and conquer, memory management is elsewhere */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
303 len = (end - start) / 2;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
304 return combine(fold(bins, start, start + len),
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
305 fold(bins, start + len, end));
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
306 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
307
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
308 static PyObject *
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
309 patches(PyObject *self, PyObject *args)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
310 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
311 PyObject *text, *bins, *result;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
312 struct flist *patch;
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
313 const char *in;
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
314 char *out;
16757
923bd97b86a0 mpatch: use Py_ssize_t
Adrian Buehlmann <adrian@cadifra.com>
parents: 16437
diff changeset
315 Py_ssize_t len, outlen, inlen;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
316
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
317 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
318 return NULL;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
319
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
320 len = PyList_Size(bins);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
321 if (!len) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
322 /* nothing to do */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
323 Py_INCREF(text);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
324 return text;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
325 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
326
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
327 if (PyObject_AsCharBuffer(text, &in, &inlen))
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
328 return NULL;
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
329
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
330 patch = fold(bins, 0, len);
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
331 if (!patch)
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
332 return NULL;
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
333
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
334 outlen = calcsize(inlen, patch);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
335 if (outlen < 0) {
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
336 result = NULL;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
337 goto cleanup;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
338 }
11360
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
339 result = PyBytes_FromStringAndSize(NULL, outlen);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
340 if (!result) {
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
341 result = NULL;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
342 goto cleanup;
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
343 }
11360
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
344 out = PyBytes_AsString(result);
5444
a0952e4e52eb mpatch: allow buffer objects for input
Matt Mackall <mpm@selenic.com>
parents: 4377
diff changeset
345 if (!apply(out, in, inlen, patch)) {
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
346 Py_DECREF(result);
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
347 result = NULL;
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
348 }
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
349 cleanup:
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
350 lfree(patch);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
351 return result;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
352 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
353
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
354 /* calculate size of a patched file directly */
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
355 static PyObject *
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
356 patchedsize(PyObject *self, PyObject *args)
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
357 {
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
358 long orig, start, end, len, outlen = 0, last = 0;
16758
9a8ab5c47f84 mpatch: use Py_ssize_t for string length
Adrian Buehlmann <adrian@cadifra.com>
parents: 16757
diff changeset
359 Py_ssize_t patchlen;
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
360 char *bin, *binend, *data;
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
361
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
362 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen))
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
363 return NULL;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
364
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
365 binend = bin + patchlen;
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
366 data = bin + 12;
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
367
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
368 while (data <= binend) {
16437
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
369 start = getbe32(bin);
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
370 end = getbe32(bin + 4);
d126a0d16856 util.h: replace ntohl/htonl with get/putbe32
Matt Mackall <mpm@selenic.com>
parents: 16385
diff changeset
371 len = getbe32(bin + 8);
4358
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
372 if (start > end)
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
373 break; /* sanity check */
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
374 bin = data + len;
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
375 if (bin < data)
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
376 break; /* big data + big (bogus) len can wrap around */
11dc22eb8e8d Fix segfaults when parsing bdiff hunks in mpatch.decode() and .patchedsize()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3138
diff changeset
377 data = bin + 12;
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
378 outlen += start - last;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
379 last = end;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
380 outlen += len;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
381 }
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
382
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
383 if (bin != binend) {
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
384 if (!PyErr_Occurred())
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
385 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
386 return NULL;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
387 }
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
388
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
389 outlen += orig - last;
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
390 return Py_BuildValue("l", outlen);
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
391 }
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
392
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
393 static PyMethodDef methods[] = {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
394 {"patches", patches, METH_VARARGS, "apply a series of patches\n"},
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1978
diff changeset
395 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"},
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
396 {NULL, NULL}
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
397 };
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
398
11360
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
399 #ifdef IS_PY3K
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
400 static struct PyModuleDef mpatch_module = {
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
401 PyModuleDef_HEAD_INIT,
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
402 "mpatch",
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
403 mpatch_doc,
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
404 -1,
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
405 methods
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
406 };
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
407
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
408 PyMODINIT_FUNC PyInit_mpatch(void)
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
409 {
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
410 PyObject *m;
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
411
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
412 m = PyModule_Create(&mpatch_module);
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
413 if (m == NULL)
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
414 return NULL;
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
415
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
416 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
417 Py_INCREF(mpatch_Error);
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
418 PyModule_AddObject(m, "mpatchError", mpatch_Error);
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
419
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
420 return m;
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
421 }
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
422 #else
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
423 PyMODINIT_FUNC
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
424 initmpatch(void)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
425 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
426 Py_InitModule3("mpatch", methods, mpatch_doc);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
427 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
428 }
11360
2ac98313b26c mpatch.c: Added preliminary support for py3k.
Renato Cunha <renatoc@gmail.com>
parents: 10282
diff changeset
429 #endif