]>
Commit | Line | Data |
---|---|---|
06160502 | 1 | /* |
50298f44 SP |
2 | * This file is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License, version 2, | |
4 | * as published by the Free Software Foundation. | |
06160502 | 5 | * |
50298f44 SP |
6 | * In addition to the permissions in the GNU General Public License, |
7 | * the authors give you unlimited permission to link the compiled | |
8 | * version of this file into combinations with other programs, | |
9 | * and to distribute those combinations without any restriction | |
10 | * coming from the use of this file. (The General Public License | |
11 | * restrictions do apply in other respects; for example, they cover | |
12 | * modification of the file, and distribution when not linked into | |
13 | * a combined executable.) | |
06160502 | 14 | * |
50298f44 SP |
15 | * This file is distributed in the hope that it will be useful, but |
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | * General Public License for more details. | |
06160502 | 19 | * |
50298f44 SP |
20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; see the file COPYING. If not, write to | |
22 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor, | |
23 | * Boston, MA 02110-1301, USA. | |
06160502 SP |
24 | */ |
25 | ||
64a47c01 | 26 | #include "common.h" |
08d5d000 | 27 | #include "commit.h" |
72a3fe42 | 28 | #include "odb.h" |
3315782c | 29 | #include "hashtable.h" |
71db842f | 30 | #include "pqueue.h" |
06160502 | 31 | |
b5c5f0f8 VM |
32 | #include "git2/revwalk.h" |
33 | ||
71db842f VM |
34 | typedef struct commit_object { |
35 | git_oid oid; | |
36 | uint32_t time; | |
37 | unsigned int seen:1, | |
38 | uninteresting:1, | |
39 | topo_delay:1, | |
40 | parsed:1; | |
41 | ||
42 | unsigned short in_degree; | |
43 | unsigned short out_degree; | |
44 | ||
45 | struct commit_object **parents; | |
46 | } commit_object; | |
47 | ||
48 | typedef struct commit_list { | |
49 | commit_object *item; | |
50 | struct commit_list *next; | |
51 | } commit_list; | |
52 | ||
53 | struct git_revwalk { | |
54 | git_repository *repo; | |
55 | ||
56 | git_hashtable *commits; | |
71db842f VM |
57 | |
58 | commit_list *iterator_topo; | |
59 | commit_list *iterator_rand; | |
60 | commit_list *iterator_reverse; | |
61 | git_pqueue iterator_time; | |
62 | ||
63 | int (*get_next)(commit_object **, git_revwalk *); | |
64 | int (*enqueue)(git_revwalk *, commit_object *); | |
65 | ||
66 | git_vector memory_alloc; | |
67 | size_t chunk_size; | |
68 | ||
69 | unsigned walking:1; | |
70 | unsigned int sorting; | |
71 | }; | |
72 | ||
73 | commit_list *commit_list_insert(commit_object *item, commit_list **list_p) | |
74 | { | |
75 | commit_list *new_list = git__malloc(sizeof(commit_list)); | |
76 | new_list->item = item; | |
77 | new_list->next = *list_p; | |
78 | *list_p = new_list; | |
79 | return new_list; | |
80 | } | |
81 | ||
36b31329 | 82 | void commit_list_free(commit_list **list_p) |
71db842f | 83 | { |
36b31329 VM |
84 | commit_list *list = *list_p; |
85 | ||
71db842f VM |
86 | while (list) { |
87 | commit_list *temp = list; | |
88 | list = temp->next; | |
89 | free(temp); | |
90 | } | |
36b31329 VM |
91 | |
92 | *list_p = NULL; | |
71db842f VM |
93 | } |
94 | ||
95 | commit_object *commit_list_pop(commit_list **stack) | |
96 | { | |
97 | commit_list *top = *stack; | |
98 | commit_object *item = top ? top->item : NULL; | |
99 | ||
100 | if (top) { | |
101 | *stack = top->next; | |
102 | free(top); | |
103 | } | |
104 | return item; | |
105 | } | |
106 | ||
107 | static int commit_time_cmp(void *a, void *b) | |
108 | { | |
109 | commit_object *commit_a = (commit_object *)a; | |
110 | commit_object *commit_b = (commit_object *)b; | |
111 | ||
112 | return (commit_a->time < commit_b->time); | |
113 | } | |
114 | ||
115 | static uint32_t object_table_hash(const void *key, int hash_id) | |
3315782c VM |
116 | { |
117 | uint32_t r; | |
71db842f | 118 | git_oid *id; |
5e15176d | 119 | |
71db842f VM |
120 | id = (git_oid *)key; |
121 | memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r)); | |
3315782c VM |
122 | return r; |
123 | } | |
124 | ||
71db842f VM |
125 | #define COMMITS_PER_CHUNK 128 |
126 | #define CHUNK_STEP 64 | |
127 | #define PARENTS_PER_COMMIT ((CHUNK_STEP - sizeof(commit_object)) / sizeof(commit_object *)) | |
128 | ||
129 | static int alloc_chunk(git_revwalk *walk) | |
06160502 | 130 | { |
71db842f VM |
131 | void *chunk; |
132 | ||
133 | chunk = git__calloc(COMMITS_PER_CHUNK, CHUNK_STEP); | |
134 | if (chunk == NULL) | |
135 | return GIT_ENOMEM; | |
136 | ||
137 | walk->chunk_size = 0; | |
138 | return git_vector_insert(&walk->memory_alloc, chunk); | |
139 | } | |
140 | ||
141 | static commit_object *alloc_commit(git_revwalk *walk) | |
142 | { | |
143 | unsigned char *chunk; | |
144 | ||
145 | if (walk->chunk_size == COMMITS_PER_CHUNK) | |
146 | alloc_chunk(walk); | |
147 | ||
148 | chunk = git_vector_get(&walk->memory_alloc, walk->memory_alloc.length - 1); | |
149 | chunk += (walk->chunk_size * CHUNK_STEP); | |
150 | walk->chunk_size++; | |
151 | ||
152 | return (commit_object *)chunk; | |
153 | } | |
154 | ||
155 | static commit_object **alloc_parents(commit_object *commit, size_t n_parents) | |
156 | { | |
157 | if (n_parents <= PARENTS_PER_COMMIT) | |
158 | return (commit_object **)((unsigned char *)commit + sizeof(commit_object)); | |
159 | ||
160 | return git__malloc(n_parents * sizeof(commit_object *)); | |
3315782c VM |
161 | } |
162 | ||
40721f6b | 163 | |
71db842f | 164 | static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid) |
3315782c | 165 | { |
71db842f | 166 | commit_object *commit; |
58b0cbea | 167 | |
71db842f | 168 | if ((commit = git_hashtable_lookup(walk->commits, oid)) != NULL) |
3315782c | 169 | return commit; |
40721f6b | 170 | |
71db842f | 171 | commit = alloc_commit(walk); |
3315782c VM |
172 | if (commit == NULL) |
173 | return NULL; | |
5e15176d | 174 | |
71db842f | 175 | git_oid_cpy(&commit->oid, oid); |
3315782c | 176 | |
71db842f VM |
177 | if (git_hashtable_insert(walk->commits, &commit->oid, commit) < GIT_SUCCESS) { |
178 | free(commit); | |
179 | return NULL; | |
180 | } | |
3315782c VM |
181 | |
182 | return commit; | |
06160502 | 183 | } |
08d5d000 | 184 | |
71db842f | 185 | static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawobj *raw) |
e5d1faef | 186 | { |
71db842f | 187 | const int parent_len = STRLEN("parent ") + GIT_OID_HEXSZ + 1; |
3315782c | 188 | |
71db842f VM |
189 | unsigned char *buffer = raw->data; |
190 | unsigned char *buffer_end = buffer + raw->len; | |
191 | unsigned char *parents_start; | |
3315782c | 192 | |
71db842f | 193 | int i, parents = 0; |
3315782c | 194 | |
71db842f | 195 | buffer += STRLEN("tree ") + GIT_OID_HEXSZ + 1; |
e5d1faef | 196 | |
71db842f VM |
197 | parents_start = buffer; |
198 | while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", STRLEN("parent ")) == 0) { | |
199 | parents++; | |
200 | buffer += parent_len; | |
201 | } | |
3315782c | 202 | |
71db842f VM |
203 | commit->parents = alloc_parents(commit, parents); |
204 | if (commit->parents == NULL) | |
205 | return GIT_ENOMEM; | |
3315782c | 206 | |
71db842f VM |
207 | buffer = parents_start; |
208 | for (i = 0; i < parents; ++i) { | |
209 | git_oid oid; | |
3315782c | 210 | |
71db842f VM |
211 | if (git_oid_mkstr(&oid, (char *)buffer + STRLEN("parent ")) < GIT_SUCCESS) |
212 | return GIT_EOBJCORRUPTED; | |
eec95235 | 213 | |
71db842f VM |
214 | commit->parents[i] = commit_lookup(walk, &oid); |
215 | if (commit->parents[i] == NULL) | |
216 | return GIT_ENOMEM; | |
3315782c | 217 | |
71db842f VM |
218 | buffer += parent_len; |
219 | } | |
3315782c | 220 | |
71db842f | 221 | commit->out_degree = (unsigned short)parents; |
3315782c | 222 | |
71db842f VM |
223 | if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) |
224 | return GIT_EOBJCORRUPTED; | |
3315782c | 225 | |
71db842f VM |
226 | buffer = memchr(buffer, '>', buffer_end - buffer); |
227 | if (buffer == NULL) | |
228 | return GIT_EOBJCORRUPTED; | |
3315782c | 229 | |
71db842f VM |
230 | commit->time = strtol((char *)buffer + 2, NULL, 10); |
231 | if (commit->time == 0) | |
232 | return GIT_EOBJCORRUPTED; | |
e5d1faef | 233 | |
71db842f VM |
234 | commit->parsed = 1; |
235 | return GIT_SUCCESS; | |
3315782c | 236 | } |
8add0153 | 237 | |
71db842f | 238 | static int commit_parse(git_revwalk *walk, commit_object *commit) |
3315782c | 239 | { |
72a3fe42 | 240 | git_odb_object *obj; |
71db842f | 241 | int error; |
3315782c | 242 | |
71db842f VM |
243 | if (commit->parsed) |
244 | return GIT_SUCCESS; | |
08d5d000 | 245 | |
72a3fe42 | 246 | if ((error = git_odb_read(&obj, walk->repo->db, &commit->oid)) < GIT_SUCCESS) |
71db842f | 247 | return error; |
52f2390b | 248 | |
72a3fe42 VM |
249 | if (obj->raw.type != GIT_OBJ_COMMIT) { |
250 | git_odb_object_close(obj); | |
71db842f | 251 | return GIT_EOBJTYPE; |
9b3577ed | 252 | } |
71db842f | 253 | |
72a3fe42 VM |
254 | error = commit_quick_parse(walk, commit, &obj->raw); |
255 | git_odb_object_close(obj); | |
71db842f | 256 | return error; |
3315782c VM |
257 | } |
258 | ||
71db842f | 259 | static void mark_uninteresting(commit_object *commit) |
3315782c | 260 | { |
71db842f VM |
261 | unsigned short i; |
262 | assert(commit); | |
1f080e2d | 263 | |
71db842f | 264 | commit->uninteresting = 1; |
08d5d000 | 265 | |
71db842f VM |
266 | for (i = 0; i < commit->out_degree; ++i) |
267 | if (!commit->parents[i]->uninteresting) | |
268 | mark_uninteresting(commit->parents[i]); | |
3315782c | 269 | } |
1a895dd7 | 270 | |
71db842f | 271 | static int process_commit(git_revwalk *walk, commit_object *commit) |
3315782c | 272 | { |
71db842f | 273 | int error; |
3315782c | 274 | |
71db842f VM |
275 | if (commit->seen) |
276 | return GIT_SUCCESS; | |
3315782c | 277 | |
71db842f | 278 | commit->seen = 1; |
1a895dd7 | 279 | |
71db842f VM |
280 | if ((error = commit_parse(walk, commit)) < GIT_SUCCESS) |
281 | return error; | |
e5d1faef | 282 | |
71db842f VM |
283 | if (commit->uninteresting) |
284 | mark_uninteresting(commit); | |
1f080e2d | 285 | |
71db842f VM |
286 | return walk->enqueue(walk, commit); |
287 | } | |
3315782c | 288 | |
71db842f VM |
289 | static int process_commit_parents(git_revwalk *walk, commit_object *commit) |
290 | { | |
291 | unsigned short i; | |
292 | int error = GIT_SUCCESS; | |
c836c332 | 293 | |
71db842f VM |
294 | for (i = 0; i < commit->out_degree && error == GIT_SUCCESS; ++i) { |
295 | error = process_commit(walk, commit->parents[i]); | |
3315782c VM |
296 | } |
297 | ||
71db842f | 298 | return error; |
08d5d000 VM |
299 | } |
300 | ||
71db842f | 301 | static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting) |
08d5d000 | 302 | { |
71db842f | 303 | commit_object *commit; |
1a895dd7 | 304 | |
71db842f VM |
305 | commit = commit_lookup(walk, oid); |
306 | if (commit == NULL) | |
307 | return GIT_ENOTFOUND; | |
1f080e2d | 308 | |
36aaf1ff | 309 | commit->uninteresting = uninteresting; |
1a895dd7 | 310 | |
36aaf1ff | 311 | return process_commit(walk, commit); |
3315782c VM |
312 | } |
313 | ||
71db842f VM |
314 | int git_revwalk_push(git_revwalk *walk, const git_oid *oid) |
315 | { | |
316 | assert(walk && oid); | |
317 | return push_commit(walk, oid, 0); | |
318 | } | |
3315782c | 319 | |
71db842f VM |
320 | int git_revwalk_hide(git_revwalk *walk, const git_oid *oid) |
321 | { | |
322 | assert(walk && oid); | |
323 | return push_commit(walk, oid, 1); | |
324 | } | |
3315782c | 325 | |
71db842f | 326 | static int revwalk_enqueue_timesort(git_revwalk *walk, commit_object *commit) |
3315782c | 327 | { |
71db842f VM |
328 | return git_pqueue_insert(&walk->iterator_time, commit); |
329 | } | |
3315782c | 330 | |
71db842f VM |
331 | static int revwalk_enqueue_unsorted(git_revwalk *walk, commit_object *commit) |
332 | { | |
333 | return commit_list_insert(commit, &walk->iterator_rand) ? GIT_SUCCESS : GIT_ENOMEM; | |
334 | } | |
3315782c | 335 | |
71db842f VM |
336 | static int revwalk_next_timesort(commit_object **object_out, git_revwalk *walk) |
337 | { | |
338 | int error; | |
339 | commit_object *next; | |
5e15176d | 340 | |
71db842f VM |
341 | while ((next = git_pqueue_pop(&walk->iterator_time)) != NULL) { |
342 | if ((error = process_commit_parents(walk, next)) < GIT_SUCCESS) | |
343 | return error; | |
6bb7aa13 | 344 | |
71db842f VM |
345 | if (!next->uninteresting) { |
346 | *object_out = next; | |
347 | return GIT_SUCCESS; | |
348 | } | |
9b3577ed | 349 | } |
08d5d000 | 350 | |
71db842f | 351 | return GIT_EREVWALKOVER; |
3315782c VM |
352 | } |
353 | ||
71db842f | 354 | static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk) |
3315782c | 355 | { |
71db842f VM |
356 | int error; |
357 | commit_object *next; | |
3315782c | 358 | |
71db842f VM |
359 | while ((next = commit_list_pop(&walk->iterator_rand)) != NULL) { |
360 | if ((error = process_commit_parents(walk, next)) < GIT_SUCCESS) | |
361 | return error; | |
6bb7aa13 | 362 | |
71db842f VM |
363 | if (!next->uninteresting) { |
364 | *object_out = next; | |
365 | return GIT_SUCCESS; | |
366 | } | |
3315782c VM |
367 | } |
368 | ||
71db842f | 369 | return GIT_EREVWALKOVER; |
a7c182c5 | 370 | } |
1a895dd7 | 371 | |
71db842f | 372 | static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk) |
a7c182c5 | 373 | { |
71db842f VM |
374 | commit_object *next; |
375 | unsigned short i; | |
1a895dd7 | 376 | |
71db842f VM |
377 | for (;;) { |
378 | next = commit_list_pop(&walk->iterator_topo); | |
379 | if (next == NULL) | |
380 | return GIT_EREVWALKOVER; | |
5e15176d | 381 | |
71db842f VM |
382 | if (next->in_degree > 0) { |
383 | next->topo_delay = 1; | |
384 | continue; | |
385 | } | |
655d381a | 386 | |
71db842f VM |
387 | for (i = 0; i < next->out_degree; ++i) { |
388 | commit_object *parent = next->parents[i]; | |
5e15176d | 389 | |
71db842f VM |
390 | if (--parent->in_degree == 0 && parent->topo_delay) { |
391 | parent->topo_delay = 0; | |
392 | commit_list_insert(parent, &walk->iterator_topo); | |
393 | } | |
394 | } | |
5e15176d | 395 | |
71db842f VM |
396 | *object_out = next; |
397 | return GIT_SUCCESS; | |
398 | } | |
5e15176d VM |
399 | } |
400 | ||
71db842f | 401 | static int revwalk_next_reverse(commit_object **object_out, git_revwalk *walk) |
5e15176d | 402 | { |
71db842f VM |
403 | *object_out = commit_list_pop(&walk->iterator_reverse); |
404 | return *object_out ? GIT_SUCCESS : GIT_EREVWALKOVER; | |
405 | } | |
5e15176d | 406 | |
3315782c | 407 | |
71db842f VM |
408 | static int prepare_walk(git_revwalk *walk) |
409 | { | |
71db842f | 410 | int error; |
36aaf1ff | 411 | commit_object *next; |
08d5d000 | 412 | |
71db842f | 413 | if (walk->sorting & GIT_SORT_TOPOLOGICAL) { |
71db842f | 414 | unsigned short i; |
08d5d000 | 415 | |
71db842f VM |
416 | while ((error = walk->get_next(&next, walk)) == GIT_SUCCESS) { |
417 | for (i = 0; i < next->out_degree; ++i) { | |
418 | commit_object *parent = next->parents[i]; | |
419 | parent->in_degree++; | |
420 | } | |
3315782c | 421 | |
71db842f VM |
422 | commit_list_insert(next, &walk->iterator_topo); |
423 | } | |
3315782c | 424 | |
71db842f VM |
425 | if (error != GIT_EREVWALKOVER) |
426 | return error; | |
3315782c | 427 | |
71db842f VM |
428 | walk->get_next = &revwalk_next_toposort; |
429 | } | |
3315782c | 430 | |
71db842f | 431 | if (walk->sorting & GIT_SORT_REVERSE) { |
3315782c | 432 | |
71db842f VM |
433 | while ((error = walk->get_next(&next, walk)) == GIT_SUCCESS) |
434 | commit_list_insert(next, &walk->iterator_reverse); | |
3315782c | 435 | |
71db842f VM |
436 | if (error != GIT_EREVWALKOVER) |
437 | return error; | |
9bdb7594 | 438 | |
71db842f VM |
439 | walk->get_next = &revwalk_next_reverse; |
440 | } | |
40721f6b | 441 | |
71db842f VM |
442 | walk->walking = 1; |
443 | return GIT_SUCCESS; | |
444 | } | |
3315782c | 445 | |
3315782c | 446 | |
36aaf1ff VM |
447 | |
448 | ||
449 | ||
450 | int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo) | |
451 | { | |
452 | git_revwalk *walk; | |
453 | ||
454 | walk = git__malloc(sizeof(git_revwalk)); | |
455 | if (walk == NULL) | |
456 | return GIT_ENOMEM; | |
457 | ||
458 | memset(walk, 0x0, sizeof(git_revwalk)); | |
459 | ||
460 | walk->commits = git_hashtable_alloc(64, | |
461 | object_table_hash, | |
462 | (git_hash_keyeq_ptr)git_oid_cmp); | |
463 | ||
464 | if (walk->commits == NULL) { | |
465 | free(walk); | |
466 | return GIT_ENOMEM; | |
467 | } | |
468 | ||
469 | git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp); | |
470 | git_vector_init(&walk->memory_alloc, 8, NULL); | |
471 | alloc_chunk(walk); | |
472 | ||
473 | walk->get_next = &revwalk_next_unsorted; | |
474 | walk->enqueue = &revwalk_enqueue_unsorted; | |
475 | ||
476 | walk->repo = repo; | |
477 | ||
478 | *revwalk_out = walk; | |
479 | return GIT_SUCCESS; | |
480 | } | |
481 | ||
482 | void git_revwalk_free(git_revwalk *walk) | |
483 | { | |
484 | unsigned int i; | |
485 | ||
486 | if (walk == NULL) | |
487 | return; | |
488 | ||
489 | git_revwalk_reset(walk); | |
490 | git_hashtable_free(walk->commits); | |
491 | git_pqueue_free(&walk->iterator_time); | |
492 | ||
493 | for (i = 0; i < walk->memory_alloc.length; ++i) | |
494 | free(git_vector_get(&walk->memory_alloc, i)); | |
495 | ||
496 | git_vector_free(&walk->memory_alloc); | |
497 | free(walk); | |
498 | } | |
499 | ||
500 | git_repository *git_revwalk_repository(git_revwalk *walk) | |
501 | { | |
502 | assert(walk); | |
503 | return walk->repo; | |
504 | } | |
505 | ||
506 | void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode) | |
507 | { | |
508 | assert(walk); | |
509 | ||
510 | if (walk->walking) | |
511 | git_revwalk_reset(walk); | |
512 | ||
513 | walk->sorting = sort_mode; | |
514 | ||
515 | if (walk->sorting & GIT_SORT_TIME) { | |
516 | walk->get_next = &revwalk_next_timesort; | |
517 | walk->enqueue = &revwalk_enqueue_timesort; | |
518 | } else { | |
519 | walk->get_next = &revwalk_next_unsorted; | |
520 | walk->enqueue = &revwalk_enqueue_unsorted; | |
521 | } | |
522 | } | |
523 | ||
71db842f VM |
524 | int git_revwalk_next(git_oid *oid, git_revwalk *walk) |
525 | { | |
526 | int error; | |
527 | commit_object *next; | |
3315782c | 528 | |
71db842f | 529 | assert(walk && oid); |
3315782c | 530 | |
71db842f VM |
531 | if (!walk->walking) { |
532 | if ((error = prepare_walk(walk)) < GIT_SUCCESS) | |
533 | return error; | |
534 | } | |
3315782c | 535 | |
71db842f | 536 | error = walk->get_next(&next, walk); |
36aaf1ff VM |
537 | if (error < GIT_SUCCESS) { |
538 | if (error == GIT_EREVWALKOVER) | |
539 | git_revwalk_reset(walk); | |
71db842f | 540 | return error; |
36aaf1ff | 541 | } |
3315782c | 542 | |
71db842f VM |
543 | git_oid_cpy(oid, &next->oid); |
544 | return GIT_SUCCESS; | |
3315782c VM |
545 | } |
546 | ||
71db842f | 547 | void git_revwalk_reset(git_revwalk *walk) |
3315782c | 548 | { |
71db842f VM |
549 | const void *_unused; |
550 | commit_object *commit; | |
3315782c | 551 | |
71db842f | 552 | assert(walk); |
9bdb7594 | 553 | |
71db842f VM |
554 | GIT_HASHTABLE_FOREACH(walk->commits, _unused, commit, |
555 | commit->seen = 0; | |
556 | commit->in_degree = 0; | |
557 | commit->topo_delay = 0; | |
558 | ); | |
9bdb7594 | 559 | |
36aaf1ff | 560 | git_pqueue_clear(&walk->iterator_time); |
36b31329 VM |
561 | commit_list_free(&walk->iterator_topo); |
562 | commit_list_free(&walk->iterator_rand); | |
563 | commit_list_free(&walk->iterator_reverse); | |
71db842f | 564 | walk->walking = 0; |
08d5d000 | 565 | } |
36b7cdb6 | 566 |