| #include "git-compat-util.h" | |
| #include "oidset.h" | |
| #include "hex.h" | |
| #include "strbuf.h" | |
| void oidset_init(struct oidset *set, size_t initial_size) | |
| { | |
| memset(&set->set, 0, sizeof(set->set)); | |
| if (initial_size) | |
| kh_resize_oid_set(&set->set, initial_size); | |
| } | |
| int oidset_contains(const struct oidset *set, const struct object_id *oid) | |
| { | |
| khiter_t pos = kh_get_oid_set(&set->set, *oid); | |
| return pos != kh_end(&set->set); | |
| } | |
| bool oidset_equal(const struct oidset *a, const struct oidset *b) | |
| { | |
| struct oidset_iter iter; | |
| struct object_id *a_oid; | |
| if (oidset_size(a) != oidset_size(b)) | |
| return false; | |
| oidset_iter_init(a, &iter); | |
| while ((a_oid = oidset_iter_next(&iter))) | |
| if (!oidset_contains(b, a_oid)) | |
| return false; | |
| return true; | |
| } | |
| int oidset_insert(struct oidset *set, const struct object_id *oid) | |
| { | |
| int added; | |
| kh_put_oid_set(&set->set, *oid, &added); | |
| return !added; | |
| } | |
| void oidset_insert_from_set(struct oidset *dest, struct oidset *src) | |
| { | |
| struct oidset_iter iter; | |
| struct object_id *src_oid; | |
| oidset_iter_init(src, &iter); | |
| while ((src_oid = oidset_iter_next(&iter))) | |
| oidset_insert(dest, src_oid); | |
| } | |
| int oidset_remove(struct oidset *set, const struct object_id *oid) | |
| { | |
| khiter_t pos = kh_get_oid_set(&set->set, *oid); | |
| if (pos == kh_end(&set->set)) | |
| return 0; | |
| kh_del_oid_set(&set->set, pos); | |
| return 1; | |
| } | |
| void oidset_clear(struct oidset *set) | |
| { | |
| kh_release_oid_set(&set->set); | |
| oidset_init(set, 0); | |
| } | |
| void oidset_parse_file(struct oidset *set, const char *path, | |
| const struct git_hash_algo *algop) | |
| { | |
| oidset_parse_file_carefully(set, path, algop, NULL, NULL); | |
| } | |
| static void parse_oidset_line(struct oidset *set, struct strbuf *sb, | |
| const struct git_hash_algo *algop, | |
| oidset_parse_tweak_fn fn, void *cbdata) | |
| { | |
| const char *p; | |
| const char *name; | |
| struct object_id oid; | |
| if (memchr(sb->buf, '\0', sb->len)) | |
| die("invalid object name: %s", sb->buf); | |
| /* | |
| * Allow trailing comments, leading whitespace | |
| * (including before commits), and empty or whitespace | |
| * only lines. | |
| */ | |
| name = strchr(sb->buf, '#'); | |
| if (name) | |
| strbuf_setlen(sb, name - sb->buf); | |
| strbuf_trim(sb); | |
| if (!sb->len) | |
| return; | |
| if (parse_oid_hex_algop(sb->buf, &oid, &p, algop) || *p != '\0') | |
| die("invalid object name: %s", sb->buf); | |
| if (fn && fn(&oid, cbdata)) | |
| return; | |
| oidset_insert(set, &oid); | |
| } | |
| void oidset_parse_file_carefully(struct oidset *set, const char *path, | |
| const struct git_hash_algo *algop, | |
| oidset_parse_tweak_fn fn, void *cbdata) | |
| { | |
| FILE *fp; | |
| struct strbuf sb = STRBUF_INIT; | |
| fp = fopen(path, "r"); | |
| if (!fp) | |
| die("could not open object name list: %s", path); | |
| while (!strbuf_getline(&sb, fp)) | |
| parse_oidset_line(set, &sb, algop, fn, cbdata); | |
| if (ferror(fp)) | |
| die_errno("Could not read '%s'", path); | |
| fclose(fp); | |
| strbuf_release(&sb); | |
| } | |
| void oidset_parse_buffer_carefully(struct oidset *set, const char *buf, | |
| size_t size, | |
| const struct git_hash_algo *algop, | |
| oidset_parse_tweak_fn fn, void *cbdata) | |
| { | |
| struct strbuf sb = STRBUF_INIT; | |
| const char *p = buf, *end; | |
| if (!size) | |
| return; | |
| end = buf + size; | |
| while (p < end) { | |
| const char *nl = memchr(p, '\n', end - p); | |
| size_t len = (nl ? nl : end) - p; | |
| strbuf_reset(&sb); | |
| if (len && p[len - 1] == '\r') | |
| len--; | |
| strbuf_add(&sb, p, len); | |
| parse_oidset_line(set, &sb, algop, fn, cbdata); | |
| p = nl ? nl + 1 : end; | |
| } | |
| strbuf_release(&sb); | |
| } |