Upgrade Git to latest master
[navymail.git] / gbox-walk.c
blob19510f99777be8035cb883e992291328aa39dd86
1 /* walk through gbox
2 * Copyright (C) 2011 Kirill Smelkov <kirr@navytux.spb.ru>
4 * This program is free software: you can Use, Study, Modify and Redistribute it
5 * under the terms of the GNU General Public License version 2. This program is
6 * distributed WITHOUT ANY WARRANTY. See COPYING file for full License terms.
7 */
10 #include "navymail/gbox-walk.h"
11 #include "tag.h"
14 /* TODO die -> error codes */
15 void prepare_gbox_walk(struct gbox_walk *w)
17 /* TODO convert to argv_array */
18 const char *rev_argv[3];
19 int i, rev_argc=0;
21 rev_argv[rev_argc++] = NULL;
22 if (w->original_order)
23 rev_argv[rev_argc++] = "--reverse";
24 rev_argv[rev_argc++] = w->gbox;
27 init_revisions(&w->revs, NULL/*prefix - ok?*/);
28 if (setup_revisions(rev_argc, rev_argv, &w->revs, NULL) != 1)
29 die("gbox-walk: setup revision failed");
31 /* unmark revs.pending commits as seen, so gbox walking could be used
32 * several times (this mimics git/handle_commit() a bit
34 for (i = 0; i < w->revs.pending.nr; ++i) {
35 struct object *object = w->revs.pending.objects[i].item;
37 /* tag -> tagee */
38 while (object->type == OBJ_TAG) {
39 struct tag *tag = (struct tag *) object;
40 if (!tag->tagged)
41 die("bad tag");
42 object = parse_object(tag->tagged->sha1);
43 if (!object)
44 die("bad object %s", sha1_to_hex(tag->tagged->sha1));
47 if (object->type == OBJ_COMMIT)
48 clear_commit_marks((struct commit *)object, SEEN | UNINTERESTING | SHOWN | ADDED);
52 if (prepare_revision_walk(&w->revs))
53 die("gbox-walk: revision walk setup failed");
55 w->tree = NULL;
56 w->tree_entries.sha1 = NULL; /* = SHA1_ARRAY_INIT */
57 w->entry_idx = -1;
61 const unsigned char * /*sha1*/ next_gbox_entry(struct gbox_walk *w)
63 struct name_entry entry;
65 start:
66 /* see, if we need to fetch next commit */
67 if (!w->tree) {
68 struct commit *commit;
70 commit = get_revision(&w->revs);
71 if (!commit)
72 return NULL;
74 /* printf("%s\n", sha1_to_hex(commit->object.sha1)); */
75 w->tree = commit->tree;
76 if (parse_tree(w->tree))
77 die("gbox-walk: parse_tree failed");
79 init_tree_desc(&w->tree_desc, w->tree->buffer, w->tree->size);
82 /* preload the tree for original order */
83 if (w->original_order) {
84 while (tree_entry(&w->tree_desc, &entry))
85 sha1_array_append(&w->tree_entries, entry.sha1);
87 w->entry_idx = w->tree_entries.nr - 1;
92 /* fast case - walking gbox in reverse order */
93 if (!w->original_order) {
94 if (tree_entry(&w->tree_desc, &entry))
95 return entry.sha1;
98 /* slow case - exporting mbox in original order */
99 else {
100 if (w->entry_idx >= 0)
101 return w->tree_entries.sha1[w->entry_idx--];
103 sha1_array_clear(&w->tree_entries);
107 /* restart from next commit */
108 w->tree = NULL;
109 goto start;