]> git.ipfire.org Git - thirdparty/git.git/blob - reftable/iter.c
Merge branch 'jk/libcurl-8.7-regression-workaround'
[thirdparty/git.git] / reftable / iter.c
1 /*
2 Copyright 2020 Google LLC
3
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://developers.google.com/open-source/licenses/bsd
7 */
8
9 #include "iter.h"
10
11 #include "system.h"
12
13 #include "block.h"
14 #include "generic.h"
15 #include "constants.h"
16 #include "reader.h"
17 #include "reftable-error.h"
18
19 static void filtering_ref_iterator_close(void *iter_arg)
20 {
21 struct filtering_ref_iterator *fri = iter_arg;
22 strbuf_release(&fri->oid);
23 reftable_iterator_destroy(&fri->it);
24 }
25
26 static int filtering_ref_iterator_next(void *iter_arg,
27 struct reftable_record *rec)
28 {
29 struct filtering_ref_iterator *fri = iter_arg;
30 struct reftable_ref_record *ref = &rec->u.ref;
31 int err = 0;
32 while (1) {
33 err = reftable_iterator_next_ref(&fri->it, ref);
34 if (err != 0) {
35 break;
36 }
37
38 if (fri->double_check) {
39 struct reftable_iterator it = { NULL };
40
41 err = reftable_table_seek_ref(&fri->tab, &it,
42 ref->refname);
43 if (err == 0) {
44 err = reftable_iterator_next_ref(&it, ref);
45 }
46
47 reftable_iterator_destroy(&it);
48
49 if (err < 0) {
50 break;
51 }
52
53 if (err > 0) {
54 continue;
55 }
56 }
57
58 if (ref->value_type == REFTABLE_REF_VAL2 &&
59 (!memcmp(fri->oid.buf, ref->value.val2.target_value,
60 fri->oid.len) ||
61 !memcmp(fri->oid.buf, ref->value.val2.value,
62 fri->oid.len)))
63 return 0;
64
65 if (ref->value_type == REFTABLE_REF_VAL1 &&
66 !memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
67 return 0;
68 }
69 }
70
71 reftable_ref_record_release(ref);
72 return err;
73 }
74
75 static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
76 .next = &filtering_ref_iterator_next,
77 .close = &filtering_ref_iterator_close,
78 };
79
80 void iterator_from_filtering_ref_iterator(struct reftable_iterator *it,
81 struct filtering_ref_iterator *fri)
82 {
83 assert(!it->ops);
84 it->iter_arg = fri;
85 it->ops = &filtering_ref_iterator_vtable;
86 }
87
88 static void indexed_table_ref_iter_close(void *p)
89 {
90 struct indexed_table_ref_iter *it = p;
91 block_iter_close(&it->cur);
92 reftable_block_done(&it->block_reader.block);
93 reftable_free(it->offsets);
94 strbuf_release(&it->oid);
95 }
96
97 static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
98 {
99 uint64_t off;
100 int err = 0;
101 if (it->offset_idx == it->offset_len) {
102 it->is_finished = 1;
103 return 1;
104 }
105
106 reftable_block_done(&it->block_reader.block);
107
108 off = it->offsets[it->offset_idx++];
109 err = reader_init_block_reader(it->r, &it->block_reader, off,
110 BLOCK_TYPE_REF);
111 if (err < 0) {
112 return err;
113 }
114 if (err > 0) {
115 /* indexed block does not exist. */
116 return REFTABLE_FORMAT_ERROR;
117 }
118 block_reader_start(&it->block_reader, &it->cur);
119 return 0;
120 }
121
122 static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
123 {
124 struct indexed_table_ref_iter *it = p;
125 struct reftable_ref_record *ref = &rec->u.ref;
126
127 while (1) {
128 int err = block_iter_next(&it->cur, rec);
129 if (err < 0) {
130 return err;
131 }
132
133 if (err > 0) {
134 err = indexed_table_ref_iter_next_block(it);
135 if (err < 0) {
136 return err;
137 }
138
139 if (it->is_finished) {
140 return 1;
141 }
142 continue;
143 }
144 /* BUG */
145 if (!memcmp(it->oid.buf, ref->value.val2.target_value,
146 it->oid.len) ||
147 !memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
148 return 0;
149 }
150 }
151 }
152
153 int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
154 struct reftable_reader *r, uint8_t *oid,
155 int oid_len, uint64_t *offsets, int offset_len)
156 {
157 struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT;
158 struct indexed_table_ref_iter *itr = reftable_calloc(1, sizeof(*itr));
159 int err = 0;
160
161 *itr = empty;
162 itr->r = r;
163 strbuf_add(&itr->oid, oid, oid_len);
164
165 itr->offsets = offsets;
166 itr->offset_len = offset_len;
167
168 err = indexed_table_ref_iter_next_block(itr);
169 if (err < 0) {
170 reftable_free(itr);
171 } else {
172 *dest = itr;
173 }
174 return err;
175 }
176
177 static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
178 .next = &indexed_table_ref_iter_next,
179 .close = &indexed_table_ref_iter_close,
180 };
181
182 void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it,
183 struct indexed_table_ref_iter *itr)
184 {
185 assert(!it->ops);
186 it->iter_arg = itr;
187 it->ops = &indexed_table_ref_iter_vtable;
188 }