Close and free the stack */
| 159 | |
| 160 | /* Close and free the stack */ |
| 161 | void reftable_stack_destroy(struct reftable_stack *st) |
| 162 | { |
| 163 | char **names = NULL; |
| 164 | int err = 0; |
| 165 | |
| 166 | if (!st) |
| 167 | return; |
| 168 | |
| 169 | if (st->merged) { |
| 170 | reftable_merged_table_free(st->merged); |
| 171 | st->merged = NULL; |
| 172 | } |
| 173 | |
| 174 | err = read_lines(st->list_file, &names); |
| 175 | if (err < 0) { |
| 176 | REFTABLE_FREE_AND_NULL(names); |
| 177 | } |
| 178 | |
| 179 | if (st->tables) { |
| 180 | struct reftable_buf filename = REFTABLE_BUF_INIT; |
| 181 | |
| 182 | for (size_t i = 0; i < st->tables_len; i++) { |
| 183 | const char *name = reftable_table_name(st->tables[i]); |
| 184 | int try_unlinking = 1; |
| 185 | |
| 186 | reftable_buf_reset(&filename); |
| 187 | if (names && !has_name(names, name)) { |
| 188 | if (stack_filename(&filename, st, name) < 0) |
| 189 | try_unlinking = 0; |
| 190 | } |
| 191 | reftable_table_decref(st->tables[i]); |
| 192 | |
| 193 | if (try_unlinking && filename.len) { |
| 194 | /* On Windows, can only unlink after closing. */ |
| 195 | unlink(filename.buf); |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | reftable_buf_release(&filename); |
| 200 | st->tables_len = 0; |
| 201 | REFTABLE_FREE_AND_NULL(st->tables); |
| 202 | } |
| 203 | |
| 204 | if (st->list_fd >= 0) { |
| 205 | close(st->list_fd); |
| 206 | st->list_fd = -1; |
| 207 | } |
| 208 | |
| 209 | REFTABLE_FREE_AND_NULL(st->list_file); |
| 210 | REFTABLE_FREE_AND_NULL(st->reftable_dir); |
| 211 | reftable_free(st); |
| 212 | free_names(names); |
| 213 | } |
| 214 | |
| 215 | static struct reftable_table **stack_copy_tables(struct reftable_stack *st, |
| 216 | size_t cur_len) |