1 | |
2 | |
3 | |
4 | #include "cache.h" |
5 | #include "diff.h" |
6 | #include "diffcore.h" |
7 | |
8 | static int should_break(struct diff_filespec *src, |
9 | struct diff_filespec *dst, |
10 | int break_score, |
11 | int *merge_score_p) |
12 | { |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | unsigned long delta_size, max_size; |
49 | unsigned long src_copied, literal_added, src_removed; |
50 | |
51 | *merge_score_p = 0; |
52 | |
53 | |
54 | |
55 | if (S_ISREG(src->mode)(((src->mode) & 0170000) == 0100000) != S_ISREG(dst->mode)(((dst->mode) & 0170000) == 0100000)) { |
56 | *merge_score_p = (int)MAX_SCORE60000.0; |
57 | return 1; |
58 | } |
59 | |
60 | if (src->oid_valid && dst->oid_valid && |
61 | !oidcmp(&src->oid, &dst->oid)) |
62 | return 0; |
63 | |
64 | if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) |
65 | return 0; |
66 | |
67 | max_size = ((src->size > dst->size) ? src->size : dst->size); |
68 | if (max_size < MINIMUM_BREAK_SIZE400) |
69 | return 0; |
70 | |
71 | if (!src->size) |
72 | return 0; |
73 | |
74 | if (diffcore_count_changes(src, dst, |
75 | &src->cnt_data, &dst->cnt_data, |
76 | &src_copied, &literal_added)) |
77 | return 0; |
78 | |
79 | |
80 | if (src->size < src_copied) |
81 | src_copied = src->size; |
82 | if (dst->size < literal_added + src_copied) { |
83 | if (src_copied < dst->size) |
84 | literal_added = dst->size - src_copied; |
85 | else |
86 | literal_added = 0; |
87 | } |
88 | src_removed = src->size - src_copied; |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | *merge_score_p = (int)(src_removed * MAX_SCORE60000.0 / src->size); |
96 | if (*merge_score_p > break_score) |
97 | return 1; |
98 | |
99 | |
100 | |
101 | |
102 | delta_size = src_removed + literal_added; |
103 | if (delta_size * MAX_SCORE60000.0 / max_size < break_score) |
104 | return 0; |
105 | |
106 | |
107 | |
108 | |
109 | if ((src->size * break_score < src_removed * MAX_SCORE60000.0) && |
110 | (literal_added * 20 < src_removed) && |
111 | (literal_added * 20 < src_copied)) |
112 | return 0; |
113 | |
114 | return 1; |
115 | } |
116 | |
117 | void diffcore_break(int break_score) |
118 | { |
119 | struct diff_queue_struct *q = &diff_queued_diff; |
120 | struct diff_queue_struct outq; |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | int merge_score; |
154 | int i; |
155 | |
156 | |
157 | |
158 | |
159 | merge_score = (break_score >> 16) & 0xFFFF; |
160 | break_score = (break_score & 0xFFFF); |
161 | |
162 | if (!break_score) |
163 | break_score = DEFAULT_BREAK_SCORE30000; |
164 | if (!merge_score) |
165 | merge_score = DEFAULT_MERGE_SCORE36000; |
166 | |
167 | DIFF_QUEUE_CLEAR(&outq)do { (&outq)->queue = ((void*)0); (&outq)->nr = (&outq)->alloc = 0; } while (0); |
168 | |
169 | for (i = 0; i < q->nr; i++) { |
170 | struct diff_filepair *p = q->queue[i]; |
171 | int score; |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | if (DIFF_FILE_VALID(p->one)(((p->one)->mode) != 0) && DIFF_FILE_VALID(p->two)(((p->two)->mode) != 0) && |
178 | object_type(p->one->mode) == OBJ_BLOB && |
179 | object_type(p->two->mode) == OBJ_BLOB && |
180 | !strcmp(p->one->path, p->two->path)) { |
181 | if (should_break(p->one, p->two, |
182 | break_score, &score)) { |
183 | |
184 | struct diff_filespec *null_one, *null_two; |
185 | struct diff_filepair *dp; |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | if (score < merge_score) |
194 | score = 0; |
195 | |
196 | |
197 | null_one = alloc_filespec(p->one->path); |
198 | dp = diff_queue(&outq, p->one, null_one); |
199 | dp->score = score; |
200 | dp->broken_pair = 1; |
201 | |
202 | |
203 | null_two = alloc_filespec(p->two->path); |
204 | dp = diff_queue(&outq, null_two, p->two); |
205 | dp->score = score; |
206 | dp->broken_pair = 1; |
207 | |
208 | diff_free_filespec_blob(p->one); |
209 | diff_free_filespec_blob(p->two); |
210 | free(p); |
211 | |
212 | |
213 | continue; |
214 | } |
215 | } |
216 | diff_free_filespec_data(p->one); |
217 | diff_free_filespec_data(p->two); |
218 | diff_q(&outq, p); |
219 | } |
220 | free(q->queue); |
221 | *q = outq; |
222 | |
223 | return; |
224 | } |
225 | |
226 | static void merge_broken(struct diff_filepair *p, |
227 | struct diff_filepair *pp, |
228 | struct diff_queue_struct *outq) |
229 | { |
230 | |
231 | struct diff_filepair *c = p, *d = pp, *dp; |
232 | if (DIFF_FILE_VALID(p->one)(((p->one)->mode) != 0)) { |
| |
233 | |
234 | d = p; c = pp; |
235 | } |
236 | |
237 | if (!DIFF_FILE_VALID(d->one)(((d->one)->mode) != 0)) |
| |
238 | die("internal error in merge #1"); |
239 | if (DIFF_FILE_VALID(d->two)(((d->two)->mode) != 0)) |
| |
240 | die("internal error in merge #2"); |
241 | if (DIFF_FILE_VALID(c->one)(((c->one)->mode) != 0)) |
| |
242 | die("internal error in merge #3"); |
243 | if (!DIFF_FILE_VALID(c->two)(((c->two)->mode) != 0)) |
| |
244 | die("internal error in merge #4"); |
245 | |
246 | dp = diff_queue(outq, d->one, c->two); |
247 | dp->score = p->score; |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | d->one->rename_used++; |
255 | diff_free_filespec_data(d->two); |
256 | diff_free_filespec_data(c->one); |
257 | free(d); |
258 | free(c); |
| |
259 | } |
260 | |
261 | void diffcore_merge_broken(void) |
262 | { |
263 | struct diff_queue_struct *q = &diff_queued_diff; |
264 | struct diff_queue_struct outq; |
265 | int i, j; |
266 | |
267 | DIFF_QUEUE_CLEAR(&outq)do { (&outq)->queue = ((void*)0); (&outq)->nr = (&outq)->alloc = 0; } while (0); |
268 | |
269 | for (i = 0; i < q->nr; i++) { |
| 1 | Loop condition is true. Entering loop body | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 7 | | Loop condition is true. Entering loop body | |
|
| 10 | | Loop condition is true. Entering loop body | |
|
270 | struct diff_filepair *p = q->queue[i]; |
271 | if (!p) |
| 2 | | Assuming 'p' is non-null | |
|
| |
| 5 | | Assuming 'p' is non-null | |
|
| |
| 8 | | Assuming 'p' is non-null | |
|
| |
| 11 | | Assuming 'p' is non-null | |
|
| |
272 | |
273 | continue; |
274 | else if (p->broken_pair && |
| |
275 | !strcmp(p->one->path, p->two->path)) { |
276 | |
277 | |
278 | |
279 | for (j = i + 1; j < q->nr; j++) { |
| 14 | | Loop condition is true. Entering loop body | |
|
280 | struct diff_filepair *pp = q->queue[j]; |
281 | if (pp->broken_pair && |
| |
282 | !strcmp(pp->one->path, pp->two->path) && |
283 | !strcmp(p->one->path, pp->two->path)) { |
284 | |
285 | merge_broken(p, pp, &outq); |
| |
| 23 | | Returning; memory was released via 1st parameter | |
|
286 | q->queue[j] = NULL((void*)0); |
287 | break; |
| 24 | | Execution continues on line 290 | |
|
288 | } |
289 | } |
290 | if (q->nr <= j) |
| |
291 | |
292 | |
293 | |
294 | diff_q(&outq, p); |
| 26 | | Use of memory after it is freed |
|
295 | } |
296 | else |
297 | diff_q(&outq, p); |
298 | } |
299 | free(q->queue); |
300 | *q = outq; |
301 | |
302 | return; |
303 | } |