Git fork

Merge branch 'ps/reftable-detach'

Isolates the reftable subsystem from the rest of Git's codebase by
using fewer pieces of Git's infrastructure.

* ps/reftable-detach:
reftable/system: provide thin wrapper for lockfile subsystem
reftable/stack: drop only use of `get_locked_file_path()`
reftable/system: provide thin wrapper for tempfile subsystem
reftable/stack: stop using `fsync_component()` directly
reftable/system: stop depending on "hash.h"
reftable: explicitly handle hash format IDs
reftable/system: move "dir.h" to its only user

+506 -229
+1
Makefile
··· 2722 REFTABLE_OBJS += reftable/reader.o 2723 REFTABLE_OBJS += reftable/record.o 2724 REFTABLE_OBJS += reftable/stack.o 2725 REFTABLE_OBJS += reftable/tree.o 2726 REFTABLE_OBJS += reftable/writer.o 2727
··· 2722 REFTABLE_OBJS += reftable/reader.o 2723 REFTABLE_OBJS += reftable/record.o 2724 REFTABLE_OBJS += reftable/stack.o 2725 + REFTABLE_OBJS += reftable/system.o 2726 REFTABLE_OBJS += reftable/tree.o 2727 REFTABLE_OBJS += reftable/writer.o 2728
+18 -1
refs/reftable-backend.c
··· 15 #include "../object.h" 16 #include "../path.h" 17 #include "../refs.h" 18 #include "../reftable/reftable-stack.h" 19 #include "../reftable/reftable-record.h" 20 #include "../reftable/reftable-error.h" ··· 23 #include "../setup.h" 24 #include "../strmap.h" 25 #include "../trace2.h" 26 #include "parse.h" 27 #include "refs-internal.h" 28 ··· 272 return 0; 273 } 274 275 static struct ref_store *reftable_be_init(struct repository *repo, 276 const char *gitdir, 277 unsigned int store_flags) ··· 289 refs->store_flags = store_flags; 290 refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); 291 292 - refs->write_options.hash_id = repo->hash_algo->format_id; 293 refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); 294 refs->write_options.disable_auto_compact = 295 !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); 296 refs->write_options.lock_timeout_ms = 100; 297 298 git_config(reftable_be_config, &refs->write_options); 299
··· 15 #include "../object.h" 16 #include "../path.h" 17 #include "../refs.h" 18 + #include "../reftable/reftable-basics.h" 19 #include "../reftable/reftable-stack.h" 20 #include "../reftable/reftable-record.h" 21 #include "../reftable/reftable-error.h" ··· 24 #include "../setup.h" 25 #include "../strmap.h" 26 #include "../trace2.h" 27 + #include "../write-or-die.h" 28 #include "parse.h" 29 #include "refs-internal.h" 30 ··· 274 return 0; 275 } 276 277 + static int reftable_be_fsync(int fd) 278 + { 279 + return fsync_component(FSYNC_COMPONENT_REFERENCE, fd); 280 + } 281 + 282 static struct ref_store *reftable_be_init(struct repository *repo, 283 const char *gitdir, 284 unsigned int store_flags) ··· 296 refs->store_flags = store_flags; 297 refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo); 298 299 + switch (repo->hash_algo->format_id) { 300 + case GIT_SHA1_FORMAT_ID: 301 + refs->write_options.hash_id = REFTABLE_HASH_SHA1; 302 + break; 303 + case GIT_SHA256_FORMAT_ID: 304 + refs->write_options.hash_id = REFTABLE_HASH_SHA256; 305 + break; 306 + default: 307 + BUG("unknown hash algorithm %d", repo->hash_algo->format_id); 308 + } 309 refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); 310 refs->write_options.disable_auto_compact = 311 !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); 312 refs->write_options.lock_timeout_ms = 100; 313 + refs->write_options.fsync = reftable_be_fsync; 314 315 git_config(reftable_be_config, &refs->write_options); 316
+7 -6
reftable/basics.c
··· 271 return p; 272 } 273 274 - int hash_size(uint32_t id) 275 { 276 switch (id) { 277 - case 0: 278 - case GIT_SHA1_FORMAT_ID: 279 - return GIT_SHA1_RAWSZ; 280 - case GIT_SHA256_FORMAT_ID: 281 - return GIT_SHA256_RAWSZ; 282 } 283 abort(); 284 }
··· 271 return p; 272 } 273 274 + int hash_size(enum reftable_hash id) 275 { 276 + if (!id) 277 + return REFTABLE_HASH_SIZE_SHA1; 278 switch (id) { 279 + case REFTABLE_HASH_SHA1: 280 + return REFTABLE_HASH_SIZE_SHA1; 281 + case REFTABLE_HASH_SHA256: 282 + return REFTABLE_HASH_SIZE_SHA256; 283 } 284 abort(); 285 }
+9 -1
reftable/basics.h
··· 148 /* Find the longest shared prefix size of `a` and `b` */ 149 int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); 150 151 - int hash_size(uint32_t id); 152 153 #endif
··· 148 /* Find the longest shared prefix size of `a` and `b` */ 149 int common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); 150 151 + int hash_size(enum reftable_hash id); 152 + 153 + /* 154 + * Format IDs that identify the hash function used by a reftable. Note that 155 + * these constants end up on disk and thus mustn't change. The format IDs are 156 + * "sha1" and "s256" in big endian, respectively. 157 + */ 158 + #define REFTABLE_FORMAT_ID_SHA1 ((uint32_t) 0x73686131) 159 + #define REFTABLE_FORMAT_ID_SHA256 ((uint32_t) 0x73323536) 160 161 #endif
+2 -2
reftable/merged.c
··· 181 182 int reftable_merged_table_new(struct reftable_merged_table **dest, 183 struct reftable_reader **readers, size_t n, 184 - uint32_t hash_id) 185 { 186 struct reftable_merged_table *m = NULL; 187 uint64_t last_max = 0; ··· 293 return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); 294 } 295 296 - uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt) 297 { 298 return mt->hash_id; 299 }
··· 181 182 int reftable_merged_table_new(struct reftable_merged_table **dest, 183 struct reftable_reader **readers, size_t n, 184 + enum reftable_hash hash_id) 185 { 186 struct reftable_merged_table *m = NULL; 187 uint64_t last_max = 0; ··· 293 return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); 294 } 295 296 + enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *mt) 297 { 298 return mt->hash_id; 299 }
+2 -1
reftable/merged.h
··· 10 #define MERGED_H 11 12 #include "system.h" 13 14 struct reftable_merged_table { 15 struct reftable_reader **readers; 16 size_t readers_len; 17 - uint32_t hash_id; 18 19 /* If unset, produce deletions. This is useful for compaction. For the 20 * full stack, deletions should be produced. */
··· 10 #define MERGED_H 11 12 #include "system.h" 13 + #include "reftable-basics.h" 14 15 struct reftable_merged_table { 16 struct reftable_reader **readers; 17 size_t readers_len; 18 + enum reftable_hash hash_id; 19 20 /* If unset, produce deletions. This is useful for compaction. For the 21 * full stack, deletions should be produced. */
+8 -6
reftable/reader.c
··· 67 return block_source_read_block(&r->source, dest, off, sz); 68 } 69 70 - uint32_t reftable_reader_hash_id(struct reftable_reader *r) 71 { 72 return r->hash_id; 73 } ··· 107 f += 8; 108 109 if (r->version == 1) { 110 - r->hash_id = GIT_SHA1_FORMAT_ID; 111 } else { 112 - r->hash_id = get_be32(f); 113 - switch (r->hash_id) { 114 - case GIT_SHA1_FORMAT_ID: 115 break; 116 - case GIT_SHA256_FORMAT_ID: 117 break; 118 default: 119 err = REFTABLE_FORMAT_ERROR; 120 goto done; 121 } 122 f += 4; 123 } 124
··· 67 return block_source_read_block(&r->source, dest, off, sz); 68 } 69 70 + enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r) 71 { 72 return r->hash_id; 73 } ··· 107 f += 8; 108 109 if (r->version == 1) { 110 + r->hash_id = REFTABLE_HASH_SHA1; 111 } else { 112 + switch (get_be32(f)) { 113 + case REFTABLE_FORMAT_ID_SHA1: 114 + r->hash_id = REFTABLE_HASH_SHA1; 115 break; 116 + case REFTABLE_FORMAT_ID_SHA256: 117 + r->hash_id = REFTABLE_HASH_SHA256; 118 break; 119 default: 120 err = REFTABLE_FORMAT_ERROR; 121 goto done; 122 } 123 + 124 f += 4; 125 } 126
+2 -2
reftable/reader.h
··· 37 /* Size of the file, excluding the footer. */ 38 uint64_t size; 39 40 - /* 'sha1' for SHA1, 's256' for SHA-256 */ 41 - uint32_t hash_id; 42 43 uint32_t block_size; 44 uint64_t min_update_index;
··· 37 /* Size of the file, excluding the footer. */ 38 uint64_t size; 39 40 + /* The hash function used for ref records. */ 41 + enum reftable_hash hash_id; 42 43 uint32_t block_size; 44 uint64_t min_update_index;
+13
reftable/reftable-basics.h
··· 11 12 #include <stddef.h> 13 14 /* Overrides the functions to use for memory management. */ 15 void reftable_set_alloc(void *(*malloc)(size_t), 16 void *(*realloc)(void *, size_t), void (*free)(void *));
··· 11 12 #include <stddef.h> 13 14 + /* 15 + * Hash functions understood by the reftable library. Note that the values are 16 + * arbitrary and somewhat random such that we can easily detect cases where the 17 + * hash hasn't been properly set up. 18 + */ 19 + enum reftable_hash { 20 + REFTABLE_HASH_SHA1 = 89, 21 + REFTABLE_HASH_SHA256 = 247, 22 + }; 23 + #define REFTABLE_HASH_SIZE_SHA1 20 24 + #define REFTABLE_HASH_SIZE_SHA256 32 25 + #define REFTABLE_HASH_SIZE_MAX REFTABLE_HASH_SIZE_SHA256 26 + 27 /* Overrides the functions to use for memory management. */ 28 void reftable_set_alloc(void *(*malloc)(size_t), 29 void *(*realloc)(void *, size_t), void (*free)(void *));
+2 -2
reftable/reftable-merged.h
··· 34 */ 35 int reftable_merged_table_new(struct reftable_merged_table **dest, 36 struct reftable_reader **readers, size_t n, 37 - uint32_t hash_id); 38 39 /* Initialize a merged table iterator for reading refs. */ 40 int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, ··· 56 void reftable_merged_table_free(struct reftable_merged_table *m); 57 58 /* return the hash ID of the merged table. */ 59 - uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *m); 60 61 #endif
··· 34 */ 35 int reftable_merged_table_new(struct reftable_merged_table **dest, 36 struct reftable_reader **readers, size_t n, 37 + enum reftable_hash hash_id); 38 39 /* Initialize a merged table iterator for reading refs. */ 40 int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, ··· 56 void reftable_merged_table_free(struct reftable_merged_table *m); 57 58 /* return the hash ID of the merged table. */ 59 + enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *m); 60 61 #endif
+1 -1
reftable/reftable-reader.h
··· 54 struct reftable_iterator *it); 55 56 /* returns the hash ID used in this table. */ 57 - uint32_t reftable_reader_hash_id(struct reftable_reader *r); 58 59 /* return an iterator for the refs pointing to `oid`. */ 60 int reftable_reader_refs_for(struct reftable_reader *r,
··· 54 struct reftable_iterator *it); 55 56 /* returns the hash ID used in this table. */ 57 + enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r); 58 59 /* return an iterator for the refs pointing to `oid`. */ 60 int reftable_reader_refs_for(struct reftable_reader *r,
+6 -6
reftable/reftable-record.h
··· 9 #ifndef REFTABLE_RECORD_H 10 #define REFTABLE_RECORD_H 11 12 - #include "hash.h" 13 #include <stdint.h> 14 15 /* ··· 40 #define REFTABLE_NR_REF_VALUETYPES 4 41 } value_type; 42 union { 43 - unsigned char val1[GIT_MAX_RAWSZ]; 44 struct { 45 - unsigned char value[GIT_MAX_RAWSZ]; /* first hash */ 46 - unsigned char target_value[GIT_MAX_RAWSZ]; /* second hash */ 47 } val2; 48 char *symref; /* referent, malloced 0-terminated string */ 49 } value; ··· 85 86 union { 87 struct { 88 - unsigned char new_hash[GIT_MAX_RAWSZ]; 89 - unsigned char old_hash[GIT_MAX_RAWSZ]; 90 char *name; 91 char *email; 92 uint64_t time;
··· 9 #ifndef REFTABLE_RECORD_H 10 #define REFTABLE_RECORD_H 11 12 + #include "reftable-basics.h" 13 #include <stdint.h> 14 15 /* ··· 40 #define REFTABLE_NR_REF_VALUETYPES 4 41 } value_type; 42 union { 43 + unsigned char val1[REFTABLE_HASH_SIZE_MAX]; 44 struct { 45 + unsigned char value[REFTABLE_HASH_SIZE_MAX]; /* first hash */ 46 + unsigned char target_value[REFTABLE_HASH_SIZE_MAX]; /* second hash */ 47 } val2; 48 char *symref; /* referent, malloced 0-terminated string */ 49 } value; ··· 85 86 union { 87 struct { 88 + unsigned char new_hash[REFTABLE_HASH_SIZE_MAX]; 89 + unsigned char old_hash[REFTABLE_HASH_SIZE_MAX]; 90 char *name; 91 char *email; 92 uint64_t time;
+7 -1
reftable/reftable-writer.h
··· 33 /* 4-byte identifier ("sha1", "s256") of the hash. 34 * Defaults to SHA1 if unset 35 */ 36 - uint32_t hash_id; 37 38 /* Default mode for creating files. If unset, use 0666 (+umask) */ 39 unsigned int default_permissions; ··· 62 * negative value will cause us to block indefinitely. 63 */ 64 long lock_timeout_ms; 65 }; 66 67 /* reftable_block_stats holds statistics for a single block type */
··· 33 /* 4-byte identifier ("sha1", "s256") of the hash. 34 * Defaults to SHA1 if unset 35 */ 36 + enum reftable_hash hash_id; 37 38 /* Default mode for creating files. If unset, use 0666 (+umask) */ 39 unsigned int default_permissions; ··· 62 * negative value will cause us to block indefinitely. 63 */ 64 long lock_timeout_ms; 65 + 66 + /* 67 + * Optional callback used to fsync files to disk. Falls back to using 68 + * fsync(3P) when unset. 69 + */ 70 + int (*fsync)(int fd); 71 }; 72 73 /* reftable_block_stats holds statistics for a single block type */
+86 -85
reftable/stack.c
··· 8 9 #include "stack.h" 10 11 - #include "../write-or-die.h" 12 #include "system.h" 13 #include "constants.h" 14 #include "merged.h" ··· 17 #include "reftable-record.h" 18 #include "reftable-merged.h" 19 #include "writer.h" 20 - #include "tempfile.h" 21 22 static int stack_try_add(struct reftable_stack *st, 23 int (*write_table)(struct reftable_writer *wr, ··· 43 return 0; 44 } 45 46 - static ssize_t reftable_fd_write(void *arg, const void *data, size_t sz) 47 { 48 - int *fdp = (int *)arg; 49 - return write_in_full(*fdp, data, sz); 50 } 51 52 - static int reftable_fd_flush(void *arg) 53 { 54 - int *fdp = (int *)arg; 55 56 - return fsync_component(FSYNC_COMPONENT_REFERENCE, *fdp); 57 } 58 59 int reftable_new_stack(struct reftable_stack **dest, const char *dir, ··· 73 if (_opts) 74 opts = *_opts; 75 if (opts.hash_id == 0) 76 - opts.hash_id = GIT_SHA1_FORMAT_ID; 77 78 *dest = NULL; 79 ··· 648 } 649 650 struct reftable_addition { 651 - struct lock_file tables_list_lock; 652 struct reftable_stack *stack; 653 654 char **new_tables; ··· 667 668 add->stack = st; 669 670 - err = hold_lock_file_for_update_timeout(&add->tables_list_lock, 671 - st->list_file, 672 - LOCK_NO_DEREF, 673 - st->opts.lock_timeout_ms); 674 if (err < 0) { 675 if (errno == EEXIST) { 676 err = REFTABLE_LOCK_ERROR; ··· 680 goto done; 681 } 682 if (st->opts.default_permissions) { 683 - if (chmod(get_lock_file_path(&add->tables_list_lock), 684 st->opts.default_permissions) < 0) { 685 err = REFTABLE_IO_ERROR; 686 goto done; ··· 724 add->new_tables_len = 0; 725 add->new_tables_cap = 0; 726 727 - rollback_lock_file(&add->tables_list_lock); 728 reftable_buf_release(&nm); 729 } 730 ··· 740 int reftable_addition_commit(struct reftable_addition *add) 741 { 742 struct reftable_buf table_list = REFTABLE_BUF_INIT; 743 - int lock_file_fd = get_lock_file_fd(&add->tables_list_lock); 744 int err = 0; 745 size_t i; 746 ··· 758 goto done; 759 } 760 761 - err = write_in_full(lock_file_fd, table_list.buf, table_list.len); 762 reftable_buf_release(&table_list); 763 if (err < 0) { 764 err = REFTABLE_IO_ERROR; 765 goto done; 766 } 767 768 - err = fsync_component(FSYNC_COMPONENT_REFERENCE, lock_file_fd); 769 if (err < 0) { 770 err = REFTABLE_IO_ERROR; 771 goto done; 772 } 773 774 - err = commit_lock_file(&add->tables_list_lock); 775 if (err < 0) { 776 err = REFTABLE_IO_ERROR; 777 goto done; ··· 857 struct reftable_buf tab_file_name = REFTABLE_BUF_INIT; 858 struct reftable_buf next_name = REFTABLE_BUF_INIT; 859 struct reftable_writer *wr = NULL; 860 - struct tempfile *tab_file = NULL; 861 int err = 0; 862 - int tab_fd; 863 864 reftable_buf_reset(&next_name); 865 ··· 875 if (err < 0) 876 goto done; 877 878 - tab_file = mks_tempfile(temp_tab_file_name.buf); 879 - if (!tab_file) { 880 - err = REFTABLE_IO_ERROR; 881 goto done; 882 - } 883 if (add->stack->opts.default_permissions) { 884 - if (chmod(get_tempfile_path(tab_file), 885 add->stack->opts.default_permissions)) { 886 err = REFTABLE_IO_ERROR; 887 goto done; 888 } 889 } 890 - tab_fd = get_tempfile_fd(tab_file); 891 892 - err = reftable_writer_new(&wr, reftable_fd_write, reftable_fd_flush, 893 - &tab_fd, &add->stack->opts); 894 if (err < 0) 895 goto done; 896 ··· 906 if (err < 0) 907 goto done; 908 909 - err = close_tempfile_gently(tab_file); 910 - if (err < 0) { 911 - err = REFTABLE_IO_ERROR; 912 goto done; 913 - } 914 915 if (wr->min_update_index < add->next_update_index) { 916 err = REFTABLE_API_ERROR; ··· 933 On windows, this relies on rand() picking a unique destination name. 934 Maybe we should do retry loop as well? 935 */ 936 - err = rename_tempfile(&tab_file, tab_file_name.buf); 937 - if (err < 0) { 938 - err = REFTABLE_IO_ERROR; 939 goto done; 940 - } 941 942 REFTABLE_ALLOC_GROW(add->new_tables, add->new_tables_len + 1, 943 add->new_tables_cap); ··· 948 add->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name); 949 950 done: 951 - delete_tempfile(&tab_file); 952 reftable_buf_release(&temp_tab_file_name); 953 reftable_buf_release(&tab_file_name); 954 reftable_buf_release(&next_name); ··· 968 static int stack_compact_locked(struct reftable_stack *st, 969 size_t first, size_t last, 970 struct reftable_log_expiry_config *config, 971 - struct tempfile **tab_file_out) 972 { 973 struct reftable_buf next_name = REFTABLE_BUF_INIT; 974 struct reftable_buf tab_file_path = REFTABLE_BUF_INIT; 975 struct reftable_writer *wr = NULL; 976 - struct tempfile *tab_file; 977 - int tab_fd, err = 0; 978 979 err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]), 980 reftable_reader_max_update_index(st->readers[last])); ··· 989 if (err < 0) 990 goto done; 991 992 - tab_file = mks_tempfile(tab_file_path.buf); 993 - if (!tab_file) { 994 - err = REFTABLE_IO_ERROR; 995 goto done; 996 - } 997 - tab_fd = get_tempfile_fd(tab_file); 998 999 if (st->opts.default_permissions && 1000 - chmod(get_tempfile_path(tab_file), st->opts.default_permissions) < 0) { 1001 err = REFTABLE_IO_ERROR; 1002 goto done; 1003 } 1004 1005 - err = reftable_writer_new(&wr, reftable_fd_write, reftable_fd_flush, 1006 - &tab_fd, &st->opts); 1007 if (err < 0) 1008 goto done; 1009 ··· 1015 if (err < 0) 1016 goto done; 1017 1018 - err = close_tempfile_gently(tab_file); 1019 if (err < 0) 1020 goto done; 1021 1022 *tab_file_out = tab_file; 1023 - tab_file = NULL; 1024 1025 done: 1026 - delete_tempfile(&tab_file); 1027 reftable_writer_free(wr); 1028 reftable_buf_release(&next_name); 1029 reftable_buf_release(&tab_file_path); ··· 1154 struct reftable_buf new_table_name = REFTABLE_BUF_INIT; 1155 struct reftable_buf new_table_path = REFTABLE_BUF_INIT; 1156 struct reftable_buf table_name = REFTABLE_BUF_INIT; 1157 - struct lock_file tables_list_lock = LOCK_INIT; 1158 - struct lock_file *table_locks = NULL; 1159 - struct tempfile *new_table = NULL; 1160 int is_empty_table = 0, err = 0; 1161 size_t first_to_replace, last_to_replace; 1162 size_t i, nlocks = 0; ··· 1173 * Hold the lock so that we can read "tables.list" and lock all tables 1174 * which are part of the user-specified range. 1175 */ 1176 - err = hold_lock_file_for_update_timeout(&tables_list_lock, 1177 - st->list_file, 1178 - LOCK_NO_DEREF, 1179 - st->opts.lock_timeout_ms); 1180 if (err < 0) { 1181 if (errno == EEXIST) 1182 err = REFTABLE_LOCK_ERROR; ··· 1199 * older process is still busy compacting tables which are preexisting 1200 * from the point of view of the newer process. 1201 */ 1202 - REFTABLE_CALLOC_ARRAY(table_locks, last - first + 1); 1203 if (!table_locks) { 1204 err = REFTABLE_OUT_OF_MEMORY_ERROR; 1205 goto done; 1206 } 1207 1208 for (i = last + 1; i > first; i--) { 1209 err = stack_filename(&table_name, st, reader_name(st->readers[i - 1])); 1210 if (err < 0) 1211 goto done; 1212 1213 - err = hold_lock_file_for_update(&table_locks[nlocks], 1214 - table_name.buf, LOCK_NO_DEREF); 1215 if (err < 0) { 1216 /* 1217 * When the table is locked already we may do a ··· 1247 * run into file descriptor exhaustion when we compress a lot 1248 * of tables. 1249 */ 1250 - err = close_lock_file_gently(&table_locks[nlocks++]); 1251 if (err < 0) { 1252 err = REFTABLE_IO_ERROR; 1253 goto done; ··· 1259 * "tables.list" lock while compacting the locked tables. This allows 1260 * concurrent updates to the stack to proceed. 1261 */ 1262 - err = rollback_lock_file(&tables_list_lock); 1263 if (err < 0) { 1264 err = REFTABLE_IO_ERROR; 1265 goto done; ··· 1282 * "tables.list". We'll then replace the compacted range of tables with 1283 * the new table. 1284 */ 1285 - err = hold_lock_file_for_update_timeout(&tables_list_lock, 1286 - st->list_file, 1287 - LOCK_NO_DEREF, 1288 - st->opts.lock_timeout_ms); 1289 if (err < 0) { 1290 if (errno == EEXIST) 1291 err = REFTABLE_LOCK_ERROR; ··· 1295 } 1296 1297 if (st->opts.default_permissions) { 1298 - if (chmod(get_lock_file_path(&tables_list_lock), 1299 st->opts.default_permissions) < 0) { 1300 err = REFTABLE_IO_ERROR; 1301 goto done; ··· 1424 if (err < 0) 1425 goto done; 1426 1427 - err = rename_tempfile(&new_table, new_table_path.buf); 1428 - if (err < 0) { 1429 - err = REFTABLE_IO_ERROR; 1430 goto done; 1431 - } 1432 } 1433 1434 /* ··· 1452 goto done; 1453 } 1454 1455 - err = write_in_full(get_lock_file_fd(&tables_list_lock), 1456 tables_list_buf.buf, tables_list_buf.len); 1457 if (err < 0) { 1458 err = REFTABLE_IO_ERROR; ··· 1460 goto done; 1461 } 1462 1463 - err = fsync_component(FSYNC_COMPONENT_REFERENCE, get_lock_file_fd(&tables_list_lock)); 1464 if (err < 0) { 1465 err = REFTABLE_IO_ERROR; 1466 unlink(new_table_path.buf); 1467 goto done; 1468 } 1469 1470 - err = commit_lock_file(&tables_list_lock); 1471 if (err < 0) { 1472 err = REFTABLE_IO_ERROR; 1473 unlink(new_table_path.buf); ··· 1488 * readers, so it is expected that unlinking tables may fail. 1489 */ 1490 for (i = 0; i < nlocks; i++) { 1491 - struct lock_file *table_lock = &table_locks[i]; 1492 - char *table_path = get_locked_file_path(table_lock); 1493 - unlink(table_path); 1494 - reftable_free(table_path); 1495 } 1496 1497 done: 1498 - rollback_lock_file(&tables_list_lock); 1499 for (i = 0; table_locks && i < nlocks; i++) 1500 - rollback_lock_file(&table_locks[i]); 1501 reftable_free(table_locks); 1502 1503 - delete_tempfile(&new_table); 1504 reftable_buf_release(&new_table_name); 1505 reftable_buf_release(&new_table_path); 1506 reftable_buf_release(&tables_list_buf); ··· 1603 1604 static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) 1605 { 1606 - int version = (st->opts.hash_id == GIT_SHA1_FORMAT_ID) ? 1 : 2; 1607 int overhead = header_size(version) - 1; 1608 uint64_t *sizes; 1609
··· 8 9 #include "stack.h" 10 11 #include "system.h" 12 #include "constants.h" 13 #include "merged.h" ··· 16 #include "reftable-record.h" 17 #include "reftable-merged.h" 18 #include "writer.h" 19 20 static int stack_try_add(struct reftable_stack *st, 21 int (*write_table)(struct reftable_writer *wr, ··· 41 return 0; 42 } 43 44 + static int stack_fsync(const struct reftable_write_options *opts, int fd) 45 { 46 + if (opts->fsync) 47 + return opts->fsync(fd); 48 + return fsync(fd); 49 } 50 51 + struct fd_writer { 52 + const struct reftable_write_options *opts; 53 + int fd; 54 + }; 55 + 56 + static ssize_t fd_writer_write(void *arg, const void *data, size_t sz) 57 { 58 + struct fd_writer *writer = arg; 59 + return write_in_full(writer->fd, data, sz); 60 + } 61 62 + static int fd_writer_flush(void *arg) 63 + { 64 + struct fd_writer *writer = arg; 65 + return stack_fsync(writer->opts, writer->fd); 66 } 67 68 int reftable_new_stack(struct reftable_stack **dest, const char *dir, ··· 82 if (_opts) 83 opts = *_opts; 84 if (opts.hash_id == 0) 85 + opts.hash_id = REFTABLE_HASH_SHA1; 86 87 *dest = NULL; 88 ··· 657 } 658 659 struct reftable_addition { 660 + struct reftable_flock tables_list_lock; 661 struct reftable_stack *stack; 662 663 char **new_tables; ··· 676 677 add->stack = st; 678 679 + err = flock_acquire(&add->tables_list_lock, st->list_file, 680 + st->opts.lock_timeout_ms); 681 if (err < 0) { 682 if (errno == EEXIST) { 683 err = REFTABLE_LOCK_ERROR; ··· 687 goto done; 688 } 689 if (st->opts.default_permissions) { 690 + if (chmod(add->tables_list_lock.path, 691 st->opts.default_permissions) < 0) { 692 err = REFTABLE_IO_ERROR; 693 goto done; ··· 731 add->new_tables_len = 0; 732 add->new_tables_cap = 0; 733 734 + flock_release(&add->tables_list_lock); 735 reftable_buf_release(&nm); 736 } 737 ··· 747 int reftable_addition_commit(struct reftable_addition *add) 748 { 749 struct reftable_buf table_list = REFTABLE_BUF_INIT; 750 int err = 0; 751 size_t i; 752 ··· 764 goto done; 765 } 766 767 + err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len); 768 reftable_buf_release(&table_list); 769 if (err < 0) { 770 err = REFTABLE_IO_ERROR; 771 goto done; 772 } 773 774 + err = stack_fsync(&add->stack->opts, add->tables_list_lock.fd); 775 if (err < 0) { 776 err = REFTABLE_IO_ERROR; 777 goto done; 778 } 779 780 + err = flock_commit(&add->tables_list_lock); 781 if (err < 0) { 782 err = REFTABLE_IO_ERROR; 783 goto done; ··· 863 struct reftable_buf tab_file_name = REFTABLE_BUF_INIT; 864 struct reftable_buf next_name = REFTABLE_BUF_INIT; 865 struct reftable_writer *wr = NULL; 866 + struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; 867 + struct fd_writer writer = { 868 + .opts = &add->stack->opts, 869 + }; 870 int err = 0; 871 872 reftable_buf_reset(&next_name); 873 ··· 883 if (err < 0) 884 goto done; 885 886 + err = tmpfile_from_pattern(&tab_file, temp_tab_file_name.buf); 887 + if (err < 0) 888 goto done; 889 if (add->stack->opts.default_permissions) { 890 + if (chmod(tab_file.path, 891 add->stack->opts.default_permissions)) { 892 err = REFTABLE_IO_ERROR; 893 goto done; 894 } 895 } 896 897 + writer.fd = tab_file.fd; 898 + err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, 899 + &writer, &add->stack->opts); 900 if (err < 0) 901 goto done; 902 ··· 912 if (err < 0) 913 goto done; 914 915 + err = tmpfile_close(&tab_file); 916 + if (err < 0) 917 goto done; 918 919 if (wr->min_update_index < add->next_update_index) { 920 err = REFTABLE_API_ERROR; ··· 937 On windows, this relies on rand() picking a unique destination name. 938 Maybe we should do retry loop as well? 939 */ 940 + err = tmpfile_rename(&tab_file, tab_file_name.buf); 941 + if (err < 0) 942 goto done; 943 944 REFTABLE_ALLOC_GROW(add->new_tables, add->new_tables_len + 1, 945 add->new_tables_cap); ··· 950 add->new_tables[add->new_tables_len++] = reftable_buf_detach(&next_name); 951 952 done: 953 + tmpfile_delete(&tab_file); 954 reftable_buf_release(&temp_tab_file_name); 955 reftable_buf_release(&tab_file_name); 956 reftable_buf_release(&next_name); ··· 970 static int stack_compact_locked(struct reftable_stack *st, 971 size_t first, size_t last, 972 struct reftable_log_expiry_config *config, 973 + struct reftable_tmpfile *tab_file_out) 974 { 975 struct reftable_buf next_name = REFTABLE_BUF_INIT; 976 struct reftable_buf tab_file_path = REFTABLE_BUF_INIT; 977 struct reftable_writer *wr = NULL; 978 + struct fd_writer writer= { 979 + .opts = &st->opts, 980 + }; 981 + struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; 982 + int err = 0; 983 984 err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]), 985 reftable_reader_max_update_index(st->readers[last])); ··· 994 if (err < 0) 995 goto done; 996 997 + err = tmpfile_from_pattern(&tab_file, tab_file_path.buf); 998 + if (err < 0) 999 goto done; 1000 1001 if (st->opts.default_permissions && 1002 + chmod(tab_file.path, st->opts.default_permissions) < 0) { 1003 err = REFTABLE_IO_ERROR; 1004 goto done; 1005 } 1006 1007 + writer.fd = tab_file.fd; 1008 + err = reftable_writer_new(&wr, fd_writer_write, fd_writer_flush, 1009 + &writer, &st->opts); 1010 if (err < 0) 1011 goto done; 1012 ··· 1018 if (err < 0) 1019 goto done; 1020 1021 + err = tmpfile_close(&tab_file); 1022 if (err < 0) 1023 goto done; 1024 1025 *tab_file_out = tab_file; 1026 + tab_file = REFTABLE_TMPFILE_INIT; 1027 1028 done: 1029 + tmpfile_delete(&tab_file); 1030 reftable_writer_free(wr); 1031 reftable_buf_release(&next_name); 1032 reftable_buf_release(&tab_file_path); ··· 1157 struct reftable_buf new_table_name = REFTABLE_BUF_INIT; 1158 struct reftable_buf new_table_path = REFTABLE_BUF_INIT; 1159 struct reftable_buf table_name = REFTABLE_BUF_INIT; 1160 + struct reftable_flock tables_list_lock = REFTABLE_FLOCK_INIT; 1161 + struct reftable_flock *table_locks = NULL; 1162 + struct reftable_tmpfile new_table = REFTABLE_TMPFILE_INIT; 1163 int is_empty_table = 0, err = 0; 1164 size_t first_to_replace, last_to_replace; 1165 size_t i, nlocks = 0; ··· 1176 * Hold the lock so that we can read "tables.list" and lock all tables 1177 * which are part of the user-specified range. 1178 */ 1179 + err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); 1180 if (err < 0) { 1181 if (errno == EEXIST) 1182 err = REFTABLE_LOCK_ERROR; ··· 1199 * older process is still busy compacting tables which are preexisting 1200 * from the point of view of the newer process. 1201 */ 1202 + REFTABLE_ALLOC_ARRAY(table_locks, last - first + 1); 1203 if (!table_locks) { 1204 err = REFTABLE_OUT_OF_MEMORY_ERROR; 1205 goto done; 1206 } 1207 + for (i = 0; i < last - first + 1; i++) 1208 + table_locks[i] = REFTABLE_FLOCK_INIT; 1209 1210 for (i = last + 1; i > first; i--) { 1211 err = stack_filename(&table_name, st, reader_name(st->readers[i - 1])); 1212 if (err < 0) 1213 goto done; 1214 1215 + err = flock_acquire(&table_locks[nlocks], table_name.buf, 0); 1216 if (err < 0) { 1217 /* 1218 * When the table is locked already we may do a ··· 1248 * run into file descriptor exhaustion when we compress a lot 1249 * of tables. 1250 */ 1251 + err = flock_close(&table_locks[nlocks++]); 1252 if (err < 0) { 1253 err = REFTABLE_IO_ERROR; 1254 goto done; ··· 1260 * "tables.list" lock while compacting the locked tables. This allows 1261 * concurrent updates to the stack to proceed. 1262 */ 1263 + err = flock_release(&tables_list_lock); 1264 if (err < 0) { 1265 err = REFTABLE_IO_ERROR; 1266 goto done; ··· 1283 * "tables.list". We'll then replace the compacted range of tables with 1284 * the new table. 1285 */ 1286 + err = flock_acquire(&tables_list_lock, st->list_file, st->opts.lock_timeout_ms); 1287 if (err < 0) { 1288 if (errno == EEXIST) 1289 err = REFTABLE_LOCK_ERROR; ··· 1293 } 1294 1295 if (st->opts.default_permissions) { 1296 + if (chmod(tables_list_lock.path, 1297 st->opts.default_permissions) < 0) { 1298 err = REFTABLE_IO_ERROR; 1299 goto done; ··· 1422 if (err < 0) 1423 goto done; 1424 1425 + err = tmpfile_rename(&new_table, new_table_path.buf); 1426 + if (err < 0) 1427 goto done; 1428 } 1429 1430 /* ··· 1448 goto done; 1449 } 1450 1451 + err = write_in_full(tables_list_lock.fd, 1452 tables_list_buf.buf, tables_list_buf.len); 1453 if (err < 0) { 1454 err = REFTABLE_IO_ERROR; ··· 1456 goto done; 1457 } 1458 1459 + err = stack_fsync(&st->opts, tables_list_lock.fd); 1460 if (err < 0) { 1461 err = REFTABLE_IO_ERROR; 1462 unlink(new_table_path.buf); 1463 goto done; 1464 } 1465 1466 + err = flock_commit(&tables_list_lock); 1467 if (err < 0) { 1468 err = REFTABLE_IO_ERROR; 1469 unlink(new_table_path.buf); ··· 1484 * readers, so it is expected that unlinking tables may fail. 1485 */ 1486 for (i = 0; i < nlocks; i++) { 1487 + struct reftable_flock *table_lock = &table_locks[i]; 1488 + 1489 + reftable_buf_reset(&table_name); 1490 + err = reftable_buf_add(&table_name, table_lock->path, 1491 + strlen(table_lock->path) - strlen(".lock")); 1492 + if (err) 1493 + continue; 1494 + 1495 + unlink(table_name.buf); 1496 } 1497 1498 done: 1499 + flock_release(&tables_list_lock); 1500 for (i = 0; table_locks && i < nlocks; i++) 1501 + flock_release(&table_locks[i]); 1502 reftable_free(table_locks); 1503 1504 + tmpfile_delete(&new_table); 1505 reftable_buf_release(&new_table_name); 1506 reftable_buf_release(&new_table_path); 1507 reftable_buf_release(&tables_list_buf); ··· 1604 1605 static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) 1606 { 1607 + int version = (st->opts.hash_id == REFTABLE_HASH_SHA1) ? 1 : 2; 1608 int overhead = header_size(version) - 1; 1609 uint64_t *sizes; 1610
+126
reftable/system.c
···
··· 1 + #include "system.h" 2 + #include "basics.h" 3 + #include "reftable-error.h" 4 + #include "../lockfile.h" 5 + #include "../tempfile.h" 6 + 7 + int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern) 8 + { 9 + struct tempfile *tempfile; 10 + 11 + tempfile = mks_tempfile(pattern); 12 + if (!tempfile) 13 + return REFTABLE_IO_ERROR; 14 + 15 + out->path = tempfile->filename.buf; 16 + out->fd = tempfile->fd; 17 + out->priv = tempfile; 18 + 19 + return 0; 20 + } 21 + 22 + int tmpfile_close(struct reftable_tmpfile *t) 23 + { 24 + struct tempfile *tempfile = t->priv; 25 + int ret = close_tempfile_gently(tempfile); 26 + t->fd = -1; 27 + if (ret < 0) 28 + return REFTABLE_IO_ERROR; 29 + return 0; 30 + } 31 + 32 + int tmpfile_delete(struct reftable_tmpfile *t) 33 + { 34 + struct tempfile *tempfile = t->priv; 35 + int ret = delete_tempfile(&tempfile); 36 + *t = REFTABLE_TMPFILE_INIT; 37 + if (ret < 0) 38 + return REFTABLE_IO_ERROR; 39 + return 0; 40 + } 41 + 42 + int tmpfile_rename(struct reftable_tmpfile *t, const char *path) 43 + { 44 + struct tempfile *tempfile = t->priv; 45 + int ret = rename_tempfile(&tempfile, path); 46 + *t = REFTABLE_TMPFILE_INIT; 47 + if (ret < 0) 48 + return REFTABLE_IO_ERROR; 49 + return 0; 50 + } 51 + 52 + int flock_acquire(struct reftable_flock *l, const char *target_path, 53 + long timeout_ms) 54 + { 55 + struct lock_file *lockfile; 56 + int err; 57 + 58 + lockfile = reftable_malloc(sizeof(*lockfile)); 59 + if (!lockfile) 60 + return REFTABLE_OUT_OF_MEMORY_ERROR; 61 + 62 + err = hold_lock_file_for_update_timeout(lockfile, target_path, LOCK_NO_DEREF, 63 + timeout_ms); 64 + if (err < 0) { 65 + reftable_free(lockfile); 66 + if (errno == EEXIST) 67 + return REFTABLE_LOCK_ERROR; 68 + return -1; 69 + } 70 + 71 + l->fd = get_lock_file_fd(lockfile); 72 + l->path = get_lock_file_path(lockfile); 73 + l->priv = lockfile; 74 + 75 + return 0; 76 + } 77 + 78 + int flock_close(struct reftable_flock *l) 79 + { 80 + struct lock_file *lockfile = l->priv; 81 + int ret; 82 + 83 + if (!lockfile) 84 + return REFTABLE_API_ERROR; 85 + 86 + ret = close_lock_file_gently(lockfile); 87 + l->fd = -1; 88 + if (ret < 0) 89 + return REFTABLE_IO_ERROR; 90 + 91 + return 0; 92 + } 93 + 94 + int flock_release(struct reftable_flock *l) 95 + { 96 + struct lock_file *lockfile = l->priv; 97 + int ret; 98 + 99 + if (!lockfile) 100 + return 0; 101 + 102 + ret = rollback_lock_file(lockfile); 103 + reftable_free(lockfile); 104 + *l = REFTABLE_FLOCK_INIT; 105 + if (ret < 0) 106 + return REFTABLE_IO_ERROR; 107 + 108 + return 0; 109 + } 110 + 111 + int flock_commit(struct reftable_flock *l) 112 + { 113 + struct lock_file *lockfile = l->priv; 114 + int ret; 115 + 116 + if (!lockfile) 117 + return REFTABLE_API_ERROR; 118 + 119 + ret = commit_lock_file(lockfile); 120 + reftable_free(lockfile); 121 + *l = REFTABLE_FLOCK_INIT; 122 + if (ret < 0) 123 + return REFTABLE_IO_ERROR; 124 + 125 + return 0; 126 + }
+84 -5
reftable/system.h
··· 12 /* This header glues the reftable library to the rest of Git */ 13 14 #include "git-compat-util.h" 15 - #include "lockfile.h" 16 - #include "tempfile.h" 17 - #include "hash.h" /* hash ID, sizes.*/ 18 - #include "dir.h" /* remove_dir_recursively, for tests.*/ 19 20 - int hash_size(uint32_t id); 21 22 #endif
··· 12 /* This header glues the reftable library to the rest of Git */ 13 14 #include "git-compat-util.h" 15 + 16 + /* 17 + * An implementation-specific temporary file. By making this specific to the 18 + * implementation it becomes possible to tie temporary files into any kind of 19 + * signal or atexit handlers for cleanup on abnormal situations. 20 + */ 21 + struct reftable_tmpfile { 22 + const char *path; 23 + int fd; 24 + void *priv; 25 + }; 26 + #define REFTABLE_TMPFILE_INIT ((struct reftable_tmpfile) { .fd = -1, }) 27 + 28 + /* 29 + * Create a temporary file from a pattern similar to how mkstemp(3p) would. 30 + * The `pattern` shall not be modified. On success, the structure at `out` has 31 + * been initialized such that it is ready for use. Returns 0 on success, a 32 + * reftable error code on error. 33 + */ 34 + int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern); 35 + 36 + /* 37 + * Close the temporary file's file descriptor without removing the file itself. 38 + * This is a no-op in case the file has already been closed beforehand. Returns 39 + * 0 on success, a reftable error code on error. 40 + */ 41 + int tmpfile_close(struct reftable_tmpfile *t); 42 + 43 + /* 44 + * Close the temporary file and delete it. This is a no-op in case the file has 45 + * already been deleted or renamed beforehand. Returns 0 on success, a reftable 46 + * error code on error. 47 + */ 48 + int tmpfile_delete(struct reftable_tmpfile *t); 49 + 50 + /* 51 + * Rename the temporary file to the provided path. The temporary file must be 52 + * active. Return 0 on success, a reftable error code on error. Deactivates the 53 + * temporary file. 54 + */ 55 + int tmpfile_rename(struct reftable_tmpfile *t, const char *path); 56 + 57 + /* 58 + * An implementation-specific file lock. Same as with `reftable_tmpfile`, 59 + * making this specific to the implementation makes it possible to tie this 60 + * into signal or atexit handlers such that we know to clean up stale locks on 61 + * abnormal exits. 62 + */ 63 + struct reftable_flock { 64 + const char *path; 65 + int fd; 66 + void *priv; 67 + }; 68 + #define REFTABLE_FLOCK_INIT ((struct reftable_flock){ .fd = -1, }) 69 70 + /* 71 + * Acquire the lock for the given target path by exclusively creating a file 72 + * with ".lock" appended to it. If that lock exists, we wait up to `timeout_ms` 73 + * to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative 74 + * we block indefinitely. 75 + * 76 + * Retrun 0 on success, a reftable error code on error. 77 + */ 78 + int flock_acquire(struct reftable_flock *l, const char *target_path, 79 + long timeout_ms); 80 + 81 + /* 82 + * Close the lockfile's file descriptor without removing the lock itself. This 83 + * is a no-op in case the lockfile has already been closed beforehand. Returns 84 + * 0 on success, a reftable error code on error. 85 + */ 86 + int flock_close(struct reftable_flock *l); 87 + 88 + /* 89 + * Release the lock by unlinking the lockfile. This is a no-op in case the 90 + * lockfile has already been released or committed beforehand. Returns 0 on 91 + * success, a reftable error code on error. 92 + */ 93 + int flock_release(struct reftable_flock *l); 94 + 95 + /* 96 + * Commit the lock by renaming the lockfile into place. Returns 0 on success, a 97 + * reftable error code on error. 98 + */ 99 + int flock_commit(struct reftable_flock *l); 100 101 #endif
+17 -3
reftable/writer.c
··· 79 } 80 81 if (opts->hash_id == 0) { 82 - opts->hash_id = GIT_SHA1_FORMAT_ID; 83 } 84 if (opts->block_size == 0) { 85 opts->block_size = DEFAULT_BLOCK_SIZE; ··· 88 89 static int writer_version(struct reftable_writer *w) 90 { 91 - return (w->opts.hash_id == 0 || w->opts.hash_id == GIT_SHA1_FORMAT_ID) ? 92 1 : 93 2; 94 } ··· 103 put_be64(dest + 8, w->min_update_index); 104 put_be64(dest + 16, w->max_update_index); 105 if (writer_version(w) == 2) { 106 - put_be32(dest + 24, w->opts.hash_id); 107 } 108 return header_size(writer_version(w)); 109 } 110
··· 79 } 80 81 if (opts->hash_id == 0) { 82 + opts->hash_id = REFTABLE_HASH_SHA1; 83 } 84 if (opts->block_size == 0) { 85 opts->block_size = DEFAULT_BLOCK_SIZE; ··· 88 89 static int writer_version(struct reftable_writer *w) 90 { 91 + return (w->opts.hash_id == 0 || w->opts.hash_id == REFTABLE_HASH_SHA1) ? 92 1 : 93 2; 94 } ··· 103 put_be64(dest + 8, w->min_update_index); 104 put_be64(dest + 16, w->max_update_index); 105 if (writer_version(w) == 2) { 106 + uint32_t hash_id; 107 + 108 + switch (w->opts.hash_id) { 109 + case REFTABLE_HASH_SHA1: 110 + hash_id = REFTABLE_FORMAT_ID_SHA1; 111 + break; 112 + case REFTABLE_HASH_SHA256: 113 + hash_id = REFTABLE_FORMAT_ID_SHA256; 114 + break; 115 + default: 116 + return -1; 117 + } 118 + 119 + put_be32(dest + 24, hash_id); 120 } 121 + 122 return header_size(writer_version(w)); 123 } 124
+2 -2
t/helper/test-reftable.c
··· 156 int opt_dump_blocks = 0; 157 int opt_dump_table = 0; 158 int opt_dump_stack = 0; 159 - uint32_t opt_hash_id = GIT_SHA1_FORMAT_ID; 160 const char *arg = NULL, *argv0 = argv[0]; 161 162 for (; argc > 1; argv++, argc--) ··· 167 else if (!strcmp("-t", argv[1])) 168 opt_dump_table = 1; 169 else if (!strcmp("-6", argv[1])) 170 - opt_hash_id = GIT_SHA256_FORMAT_ID; 171 else if (!strcmp("-s", argv[1])) 172 opt_dump_stack = 1; 173 else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) {
··· 156 int opt_dump_blocks = 0; 157 int opt_dump_table = 0; 158 int opt_dump_stack = 0; 159 + uint32_t opt_hash_id = REFTABLE_HASH_SHA1; 160 const char *arg = NULL, *argv0 = argv[0]; 161 162 for (; argc > 1; argv++, argc--) ··· 167 else if (!strcmp("-t", argv[1])) 168 opt_dump_table = 1; 169 else if (!strcmp("-6", argv[1])) 170 + opt_hash_id = REFTABLE_HASH_SHA256; 171 else if (!strcmp("-s", argv[1])) 172 opt_dump_stack = 1; 173 else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) {
+3 -2
t/unit-tests/lib-reftable.c
··· 2 #include "test-lib.h" 3 #include "reftable/constants.h" 4 #include "reftable/writer.h" 5 6 - void t_reftable_set_hash(uint8_t *p, int i, uint32_t id) 7 { 8 memset(p, (uint8_t)i, hash_size(id)); 9 } ··· 82 size_t off = i * (opts.block_size ? opts.block_size 83 : DEFAULT_BLOCK_SIZE); 84 if (!off) 85 - off = header_size(opts.hash_id == GIT_SHA256_FORMAT_ID ? 2 : 1); 86 check_char(buf->buf[off], ==, 'r'); 87 } 88
··· 2 #include "test-lib.h" 3 #include "reftable/constants.h" 4 #include "reftable/writer.h" 5 + #include "strbuf.h" 6 7 + void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id) 8 { 9 memset(p, (uint8_t)i, hash_size(id)); 10 } ··· 83 size_t off = i * (opts.block_size ? opts.block_size 84 : DEFAULT_BLOCK_SIZE); 85 if (!off) 86 + off = header_size(opts.hash_id == REFTABLE_HASH_SHA256 ? 2 : 1); 87 check_char(buf->buf[off], ==, 'r'); 88 } 89
+1 -1
t/unit-tests/lib-reftable.h
··· 6 7 struct reftable_buf; 8 9 - void t_reftable_set_hash(uint8_t *p, int i, uint32_t id); 10 11 struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, 12 struct reftable_write_options *opts);
··· 6 7 struct reftable_buf; 8 9 + void t_reftable_set_hash(uint8_t *p, int i, enum reftable_hash id); 10 11 struct reftable_writer *t_reftable_strbuf_writer(struct reftable_buf *buf, 12 struct reftable_write_options *opts);
+21 -20
t/unit-tests/t-reftable-block.c
··· 11 #include "reftable/blocksource.h" 12 #include "reftable/constants.h" 13 #include "reftable/reftable-error.h" 14 15 static void t_ref_block_read_write(void) 16 { ··· 36 block.len = block_size; 37 block_source_from_buf(&block.source ,&buf); 38 ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, 39 - header_off, hash_size(GIT_SHA1_FORMAT_ID)); 40 check(!ret); 41 42 rec.u.ref.refname = (char *) ""; ··· 47 for (i = 0; i < N; i++) { 48 rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 49 rec.u.ref.value_type = REFTABLE_REF_VAL1; 50 - memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ); 51 52 recs[i] = rec; 53 ret = block_writer_add(&bw, &rec); ··· 61 62 block_writer_release(&bw); 63 64 - block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); 65 66 block_iter_seek_start(&it, &br); 67 ··· 72 check_int(i, ==, N); 73 break; 74 } 75 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 76 } 77 78 for (i = 0; i < N; i++) { ··· 85 ret = block_iter_next(&it, &rec); 86 check_int(ret, ==, 0); 87 88 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 89 90 want.len--; 91 ret = block_iter_seek_key(&it, &br, &want); ··· 93 94 ret = block_iter_next(&it, &rec); 95 check_int(ret, ==, 0); 96 - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); 97 } 98 99 block_reader_release(&br); ··· 130 block.len = block_size; 131 block_source_from_buf(&block.source ,&buf); 132 ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, 133 - header_off, hash_size(GIT_SHA1_FORMAT_ID)); 134 check(!ret); 135 136 for (i = 0; i < N; i++) { ··· 150 151 block_writer_release(&bw); 152 153 - block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); 154 155 block_iter_seek_start(&it, &br); 156 ··· 161 check_int(i, ==, N); 162 break; 163 } 164 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 165 } 166 167 for (i = 0; i < N; i++) { ··· 175 ret = block_iter_next(&it, &rec); 176 check_int(ret, ==, 0); 177 178 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 179 180 want.len--; 181 ret = block_iter_seek_key(&it, &br, &want); ··· 183 184 ret = block_iter_next(&it, &rec); 185 check_int(ret, ==, 0); 186 - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); 187 } 188 189 block_reader_release(&br); ··· 220 block.len = block_size; 221 block_source_from_buf(&block.source, &buf); 222 ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, 223 - header_off, hash_size(GIT_SHA1_FORMAT_ID)); 224 check(!ret); 225 226 for (i = 0; i < N; i++) { ··· 242 243 block_writer_release(&bw); 244 245 - block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); 246 247 block_iter_seek_start(&it, &br); 248 ··· 253 check_int(i, ==, N); 254 break; 255 } 256 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 257 } 258 259 for (i = 0; i < N; i++) { ··· 266 ret = block_iter_next(&it, &rec); 267 check_int(ret, ==, 0); 268 269 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 270 } 271 272 block_reader_release(&br); ··· 304 block.len = block_size; 305 block_source_from_buf(&block.source, &buf); 306 ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, 307 - header_off, hash_size(GIT_SHA1_FORMAT_ID)); 308 check(!ret); 309 310 for (i = 0; i < N; i++) { ··· 326 327 block_writer_release(&bw); 328 329 - block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); 330 331 block_iter_seek_start(&it, &br); 332 ··· 337 check_int(i, ==, N); 338 break; 339 } 340 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 341 } 342 343 for (i = 0; i < N; i++) { ··· 350 ret = block_iter_next(&it, &rec); 351 check_int(ret, ==, 0); 352 353 - check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); 354 355 want.len--; 356 ret = block_iter_seek_key(&it, &br, &want); ··· 358 359 ret = block_iter_next(&it, &rec); 360 check_int(ret, ==, 0); 361 - check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); 362 } 363 364 block_reader_release(&br);
··· 11 #include "reftable/blocksource.h" 12 #include "reftable/constants.h" 13 #include "reftable/reftable-error.h" 14 + #include "strbuf.h" 15 16 static void t_ref_block_read_write(void) 17 { ··· 37 block.len = block_size; 38 block_source_from_buf(&block.source ,&buf); 39 ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, 40 + header_off, hash_size(REFTABLE_HASH_SHA1)); 41 check(!ret); 42 43 rec.u.ref.refname = (char *) ""; ··· 48 for (i = 0; i < N; i++) { 49 rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 50 rec.u.ref.value_type = REFTABLE_REF_VAL1; 51 + memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); 52 53 recs[i] = rec; 54 ret = block_writer_add(&bw, &rec); ··· 62 63 block_writer_release(&bw); 64 65 + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 66 67 block_iter_seek_start(&it, &br); 68 ··· 73 check_int(i, ==, N); 74 break; 75 } 76 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 77 } 78 79 for (i = 0; i < N; i++) { ··· 86 ret = block_iter_next(&it, &rec); 87 check_int(ret, ==, 0); 88 89 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 90 91 want.len--; 92 ret = block_iter_seek_key(&it, &br, &want); ··· 94 95 ret = block_iter_next(&it, &rec); 96 check_int(ret, ==, 0); 97 + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 98 } 99 100 block_reader_release(&br); ··· 131 block.len = block_size; 132 block_source_from_buf(&block.source ,&buf); 133 ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, 134 + header_off, hash_size(REFTABLE_HASH_SHA1)); 135 check(!ret); 136 137 for (i = 0; i < N; i++) { ··· 151 152 block_writer_release(&bw); 153 154 + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 155 156 block_iter_seek_start(&it, &br); 157 ··· 162 check_int(i, ==, N); 163 break; 164 } 165 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 166 } 167 168 for (i = 0; i < N; i++) { ··· 176 ret = block_iter_next(&it, &rec); 177 check_int(ret, ==, 0); 178 179 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 180 181 want.len--; 182 ret = block_iter_seek_key(&it, &br, &want); ··· 184 185 ret = block_iter_next(&it, &rec); 186 check_int(ret, ==, 0); 187 + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 188 } 189 190 block_reader_release(&br); ··· 221 block.len = block_size; 222 block_source_from_buf(&block.source, &buf); 223 ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, 224 + header_off, hash_size(REFTABLE_HASH_SHA1)); 225 check(!ret); 226 227 for (i = 0; i < N; i++) { ··· 243 244 block_writer_release(&bw); 245 246 + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 247 248 block_iter_seek_start(&it, &br); 249 ··· 254 check_int(i, ==, N); 255 break; 256 } 257 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 258 } 259 260 for (i = 0; i < N; i++) { ··· 267 ret = block_iter_next(&it, &rec); 268 check_int(ret, ==, 0); 269 270 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 271 } 272 273 block_reader_release(&br); ··· 305 block.len = block_size; 306 block_source_from_buf(&block.source, &buf); 307 ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, 308 + header_off, hash_size(REFTABLE_HASH_SHA1)); 309 check(!ret); 310 311 for (i = 0; i < N; i++) { ··· 327 328 block_writer_release(&bw); 329 330 + block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); 331 332 block_iter_seek_start(&it, &br); 333 ··· 338 check_int(i, ==, N); 339 break; 340 } 341 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 342 } 343 344 for (i = 0; i < N; i++) { ··· 351 ret = block_iter_next(&it, &rec); 352 check_int(ret, ==, 0); 353 354 + check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); 355 356 want.len--; 357 ret = block_iter_seek_key(&it, &br, &want); ··· 359 360 ret = block_iter_next(&it, &rec); 361 check_int(ret, ==, 0); 362 + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); 363 } 364 365 block_reader_release(&br);
+13 -13
t/unit-tests/t-reftable-merged.c
··· 42 check(!err); 43 } 44 45 - err = reftable_merged_table_new(&mt, *readers, n, GIT_SHA1_FORMAT_ID); 46 check(!err); 47 return mt; 48 } ··· 91 92 err = reftable_iterator_next_ref(&it, &ref); 93 check(!err); 94 - check(reftable_ref_record_equal(&r2[0], &ref, GIT_SHA1_RAWSZ)); 95 reftable_ref_record_release(&ref); 96 reftable_iterator_destroy(&it); 97 readers_destroy(readers, 3); ··· 168 check(!err); 169 err = reftable_iterator_seek_ref(&it, "a"); 170 check(!err); 171 - check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID); 172 check_int(reftable_merged_table_min_update_index(mt), ==, 1); 173 check_int(reftable_merged_table_max_update_index(mt), ==, 3); 174 ··· 186 check_int(ARRAY_SIZE(want), ==, len); 187 for (i = 0; i < len; i++) 188 check(reftable_ref_record_equal(want[i], &out[i], 189 - GIT_SHA1_RAWSZ)); 190 for (i = 0; i < len; i++) 191 reftable_ref_record_release(&out[i]); 192 reftable_free(out); ··· 252 253 err = reftable_iterator_next_ref(&it, &rec); 254 check(!err); 255 - err = reftable_ref_record_equal(&rec, &r1[1], GIT_SHA1_RAWSZ); 256 check(err == 1); 257 258 err = reftable_iterator_next_ref(&it, &rec); 259 check(!err); 260 - err = reftable_ref_record_equal(&rec, &r2[1], GIT_SHA1_RAWSZ); 261 check(err == 1); 262 263 err = reftable_iterator_next_ref(&it, &rec); ··· 300 check(!err); 301 } 302 303 - err = reftable_merged_table_new(&mt, *readers, n, GIT_SHA1_FORMAT_ID); 304 check(!err); 305 return mt; 306 } ··· 377 check(!err); 378 err = reftable_iterator_seek_log(&it, "a"); 379 check(!err); 380 - check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID); 381 check_int(reftable_merged_table_min_update_index(mt), ==, 1); 382 check_int(reftable_merged_table_max_update_index(mt), ==, 3); 383 ··· 395 check_int(ARRAY_SIZE(want), ==, len); 396 for (i = 0; i < len; i++) 397 check(reftable_log_record_equal(want[i], &out[i], 398 - GIT_SHA1_RAWSZ)); 399 400 err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); 401 check(!err); ··· 404 reftable_log_record_release(&out[0]); 405 err = reftable_iterator_next_log(&it, &out[0]); 406 check(!err); 407 - check(reftable_log_record_equal(&out[0], &r3[0], GIT_SHA1_RAWSZ)); 408 reftable_iterator_destroy(&it); 409 410 for (i = 0; i < len; i++) ··· 448 check(!err); 449 450 hash_id = reftable_reader_hash_id(rd); 451 - check_int(hash_id, ==, GIT_SHA1_FORMAT_ID); 452 453 - err = reftable_merged_table_new(&merged, &rd, 1, GIT_SHA256_FORMAT_ID); 454 check_int(err, ==, REFTABLE_FORMAT_ERROR); 455 - err = reftable_merged_table_new(&merged, &rd, 1, GIT_SHA1_FORMAT_ID); 456 check(!err); 457 458 reftable_reader_decref(rd);
··· 42 check(!err); 43 } 44 45 + err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); 46 check(!err); 47 return mt; 48 } ··· 91 92 err = reftable_iterator_next_ref(&it, &ref); 93 check(!err); 94 + check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); 95 reftable_ref_record_release(&ref); 96 reftable_iterator_destroy(&it); 97 readers_destroy(readers, 3); ··· 168 check(!err); 169 err = reftable_iterator_seek_ref(&it, "a"); 170 check(!err); 171 + check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); 172 check_int(reftable_merged_table_min_update_index(mt), ==, 1); 173 check_int(reftable_merged_table_max_update_index(mt), ==, 3); 174 ··· 186 check_int(ARRAY_SIZE(want), ==, len); 187 for (i = 0; i < len; i++) 188 check(reftable_ref_record_equal(want[i], &out[i], 189 + REFTABLE_HASH_SIZE_SHA1)); 190 for (i = 0; i < len; i++) 191 reftable_ref_record_release(&out[i]); 192 reftable_free(out); ··· 252 253 err = reftable_iterator_next_ref(&it, &rec); 254 check(!err); 255 + err = reftable_ref_record_equal(&rec, &r1[1], REFTABLE_HASH_SIZE_SHA1); 256 check(err == 1); 257 258 err = reftable_iterator_next_ref(&it, &rec); 259 check(!err); 260 + err = reftable_ref_record_equal(&rec, &r2[1], REFTABLE_HASH_SIZE_SHA1); 261 check(err == 1); 262 263 err = reftable_iterator_next_ref(&it, &rec); ··· 300 check(!err); 301 } 302 303 + err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); 304 check(!err); 305 return mt; 306 } ··· 377 check(!err); 378 err = reftable_iterator_seek_log(&it, "a"); 379 check(!err); 380 + check_int(reftable_merged_table_hash_id(mt), ==, REFTABLE_HASH_SHA1); 381 check_int(reftable_merged_table_min_update_index(mt), ==, 1); 382 check_int(reftable_merged_table_max_update_index(mt), ==, 3); 383 ··· 395 check_int(ARRAY_SIZE(want), ==, len); 396 for (i = 0; i < len; i++) 397 check(reftable_log_record_equal(want[i], &out[i], 398 + REFTABLE_HASH_SIZE_SHA1)); 399 400 err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); 401 check(!err); ··· 404 reftable_log_record_release(&out[0]); 405 err = reftable_iterator_next_log(&it, &out[0]); 406 check(!err); 407 + check(reftable_log_record_equal(&out[0], &r3[0], REFTABLE_HASH_SIZE_SHA1)); 408 reftable_iterator_destroy(&it); 409 410 for (i = 0; i < len; i++) ··· 448 check(!err); 449 450 hash_id = reftable_reader_hash_id(rd); 451 + check_int(hash_id, ==, REFTABLE_HASH_SHA1); 452 453 + err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA256); 454 check_int(err, ==, REFTABLE_FORMAT_ERROR); 455 + err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA1); 456 check(!err); 457 458 reftable_reader_decref(rd);
+2 -1
t/unit-tests/t-reftable-pq.c
··· 9 #include "test-lib.h" 10 #include "reftable/constants.h" 11 #include "reftable/pq.h" 12 13 static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) 14 { ··· 132 133 merged_iter_pqueue_check(&pq); 134 check(pq_entry_equal(&top, &e)); 135 - check(reftable_record_equal(top.rec, &recs[i], GIT_SHA1_RAWSZ)); 136 for (size_t j = 0; i < pq.len; j++) { 137 check(pq_less(&top, &pq.heap[j])); 138 check_int(top.index, >, j);
··· 9 #include "test-lib.h" 10 #include "reftable/constants.h" 11 #include "reftable/pq.h" 12 + #include "strbuf.h" 13 14 static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) 15 { ··· 133 134 merged_iter_pqueue_check(&pq); 135 check(pq_entry_equal(&top, &e)); 136 + check(reftable_record_equal(top.rec, &recs[i], REFTABLE_HASH_SIZE_SHA1)); 137 for (size_t j = 0; i < pq.len; j++) { 138 check(pq_less(&top, &pq.heap[j])); 139 check_int(top.index, >, j);
+2 -2
t/unit-tests/t-reftable-reader.c
··· 31 ret = reftable_iterator_next_ref(&it, &ref); 32 check(!ret); 33 34 - ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ); 35 check_int(ret, ==, 1); 36 37 ret = reftable_iterator_next_ref(&it, &ref); ··· 74 ret = reftable_iterator_next_ref(&it, &ref); 75 check(!ret); 76 77 - ret = reftable_ref_record_equal(&ref, &records[0], GIT_SHA1_RAWSZ); 78 check_int(ret, ==, 1); 79 80 ret = reftable_iterator_next_ref(&it, &ref);
··· 31 ret = reftable_iterator_next_ref(&it, &ref); 32 check(!ret); 33 34 + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); 35 check_int(ret, ==, 1); 36 37 ret = reftable_iterator_next_ref(&it, &ref); ··· 74 ret = reftable_iterator_next_ref(&it, &ref); 75 check(!ret); 76 77 + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); 78 check_int(ret, ==, 1); 79 80 ret = reftable_iterator_next_ref(&it, &ref);
+21 -20
t/unit-tests/t-reftable-readwrite.c
··· 13 #include "reftable/reader.h" 14 #include "reftable/reftable-error.h" 15 #include "reftable/reftable-writer.h" 16 17 static const int update_index = 5; 18 ··· 41 } 42 43 static void write_table(char ***names, struct reftable_buf *buf, int N, 44 - int block_size, uint32_t hash_id) 45 { 46 struct reftable_write_options opts = { 47 .block_size = block_size, ··· 62 refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i); 63 refs[i].update_index = update_index; 64 refs[i].value_type = REFTABLE_REF_VAL1; 65 - t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID); 66 } 67 68 for (i = 0; i < N; i++) { ··· 70 logs[i].update_index = update_index; 71 logs[i].value_type = REFTABLE_LOG_UPDATE; 72 t_reftable_set_hash(logs[i].value.update.new_hash, i, 73 - GIT_SHA1_FORMAT_ID); 74 logs[i].value.update.message = (char *) "message"; 75 } 76 ··· 104 /* This tests buffer extension for log compression. Must use a random 105 hash, to ensure that the compressed part is larger than the original. 106 */ 107 - for (i = 0; i < GIT_SHA1_RAWSZ; i++) { 108 log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); 109 log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); 110 } ··· 191 log.update_index = i; 192 log.value_type = REFTABLE_LOG_UPDATE; 193 t_reftable_set_hash(log.value.update.old_hash, i, 194 - GIT_SHA1_FORMAT_ID); 195 t_reftable_set_hash(log.value.update.new_hash, i + 1, 196 - GIT_SHA1_FORMAT_ID); 197 198 err = reftable_writer_add_log(w, &log); 199 check(!err); ··· 326 int err = 0; 327 int j = 0; 328 329 - write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID); 330 331 block_source_from_buf(&source, &buf); 332 ··· 361 char **names; 362 struct reftable_buf buf = REFTABLE_BUF_INIT; 363 int N = 1; 364 - write_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID); 365 check_int(buf.len, <, 200); 366 reftable_buf_release(&buf); 367 free_names(names); ··· 378 struct reftable_log_record log = { 0 }; 379 struct reftable_iterator it = { 0 }; 380 381 - write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID); 382 383 block_source_from_buf(&source, &buf); 384 ··· 400 reftable_buf_release(&buf); 401 } 402 403 - static void t_table_read_write_seek(int index, int hash_id) 404 { 405 char **names; 406 struct reftable_buf buf = REFTABLE_BUF_INIT; ··· 467 468 static void t_table_read_write_seek_linear(void) 469 { 470 - t_table_read_write_seek(0, GIT_SHA1_FORMAT_ID); 471 } 472 473 static void t_table_read_write_seek_linear_sha256(void) 474 { 475 - t_table_read_write_seek(0, GIT_SHA256_FORMAT_ID); 476 } 477 478 static void t_table_read_write_seek_index(void) 479 { 480 - t_table_read_write_seek(1, GIT_SHA1_FORMAT_ID); 481 } 482 483 static void t_table_refs_for(int indexed) 484 { 485 char **want_names; 486 int want_names_len = 0; 487 - uint8_t want_hash[GIT_SHA1_RAWSZ]; 488 489 struct reftable_write_options opts = { 490 .block_size = 256, ··· 500 want_names = reftable_calloc(N + 1, sizeof(*want_names)); 501 check(want_names != NULL); 502 503 - t_reftable_set_hash(want_hash, 4, GIT_SHA1_FORMAT_ID); 504 505 for (i = 0; i < N; i++) { 506 - uint8_t hash[GIT_SHA1_RAWSZ]; 507 char fill[51] = { 0 }; 508 char name[100]; 509 struct reftable_ref_record ref = { 0 }; ··· 517 518 ref.value_type = REFTABLE_REF_VAL2; 519 t_reftable_set_hash(ref.value.val2.value, i / 4, 520 - GIT_SHA1_FORMAT_ID); 521 t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4, 522 - GIT_SHA1_FORMAT_ID); 523 524 /* 80 bytes / entry, so 3 entries per block. Yields 17 525 */ ··· 527 n = reftable_writer_add_ref(w, &ref); 528 check_int(n, ==, 0); 529 530 - if (!memcmp(ref.value.val2.value, want_hash, GIT_SHA1_RAWSZ) || 531 - !memcmp(ref.value.val2.target_value, want_hash, GIT_SHA1_RAWSZ)) 532 want_names[want_names_len++] = xstrdup(name); 533 } 534
··· 13 #include "reftable/reader.h" 14 #include "reftable/reftable-error.h" 15 #include "reftable/reftable-writer.h" 16 + #include "strbuf.h" 17 18 static const int update_index = 5; 19 ··· 42 } 43 44 static void write_table(char ***names, struct reftable_buf *buf, int N, 45 + int block_size, enum reftable_hash hash_id) 46 { 47 struct reftable_write_options opts = { 48 .block_size = block_size, ··· 63 refs[i].refname = (*names)[i] = xstrfmt("refs/heads/branch%02d", i); 64 refs[i].update_index = update_index; 65 refs[i].value_type = REFTABLE_REF_VAL1; 66 + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); 67 } 68 69 for (i = 0; i < N; i++) { ··· 71 logs[i].update_index = update_index; 72 logs[i].value_type = REFTABLE_LOG_UPDATE; 73 t_reftable_set_hash(logs[i].value.update.new_hash, i, 74 + REFTABLE_HASH_SHA1); 75 logs[i].value.update.message = (char *) "message"; 76 } 77 ··· 105 /* This tests buffer extension for log compression. Must use a random 106 hash, to ensure that the compressed part is larger than the original. 107 */ 108 + for (i = 0; i < REFTABLE_HASH_SIZE_SHA1; i++) { 109 log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); 110 log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); 111 } ··· 192 log.update_index = i; 193 log.value_type = REFTABLE_LOG_UPDATE; 194 t_reftable_set_hash(log.value.update.old_hash, i, 195 + REFTABLE_HASH_SHA1); 196 t_reftable_set_hash(log.value.update.new_hash, i + 1, 197 + REFTABLE_HASH_SHA1); 198 199 err = reftable_writer_add_log(w, &log); 200 check(!err); ··· 327 int err = 0; 328 int j = 0; 329 330 + write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); 331 332 block_source_from_buf(&source, &buf); 333 ··· 362 char **names; 363 struct reftable_buf buf = REFTABLE_BUF_INIT; 364 int N = 1; 365 + write_table(&names, &buf, N, 4096, REFTABLE_HASH_SHA1); 366 check_int(buf.len, <, 200); 367 reftable_buf_release(&buf); 368 free_names(names); ··· 379 struct reftable_log_record log = { 0 }; 380 struct reftable_iterator it = { 0 }; 381 382 + write_table(&names, &buf, N, 256, REFTABLE_HASH_SHA1); 383 384 block_source_from_buf(&source, &buf); 385 ··· 401 reftable_buf_release(&buf); 402 } 403 404 + static void t_table_read_write_seek(int index, enum reftable_hash hash_id) 405 { 406 char **names; 407 struct reftable_buf buf = REFTABLE_BUF_INIT; ··· 468 469 static void t_table_read_write_seek_linear(void) 470 { 471 + t_table_read_write_seek(0, REFTABLE_HASH_SHA1); 472 } 473 474 static void t_table_read_write_seek_linear_sha256(void) 475 { 476 + t_table_read_write_seek(0, REFTABLE_HASH_SHA256); 477 } 478 479 static void t_table_read_write_seek_index(void) 480 { 481 + t_table_read_write_seek(1, REFTABLE_HASH_SHA1); 482 } 483 484 static void t_table_refs_for(int indexed) 485 { 486 char **want_names; 487 int want_names_len = 0; 488 + uint8_t want_hash[REFTABLE_HASH_SIZE_SHA1]; 489 490 struct reftable_write_options opts = { 491 .block_size = 256, ··· 501 want_names = reftable_calloc(N + 1, sizeof(*want_names)); 502 check(want_names != NULL); 503 504 + t_reftable_set_hash(want_hash, 4, REFTABLE_HASH_SHA1); 505 506 for (i = 0; i < N; i++) { 507 + uint8_t hash[REFTABLE_HASH_SIZE_SHA1]; 508 char fill[51] = { 0 }; 509 char name[100]; 510 struct reftable_ref_record ref = { 0 }; ··· 518 519 ref.value_type = REFTABLE_REF_VAL2; 520 t_reftable_set_hash(ref.value.val2.value, i / 4, 521 + REFTABLE_HASH_SHA1); 522 t_reftable_set_hash(ref.value.val2.target_value, 3 + i / 4, 523 + REFTABLE_HASH_SHA1); 524 525 /* 80 bytes / entry, so 3 entries per block. Yields 17 526 */ ··· 528 n = reftable_writer_add_ref(w, &ref); 529 check_int(n, ==, 0); 530 531 + if (!memcmp(ref.value.val2.value, want_hash, REFTABLE_HASH_SIZE_SHA1) || 532 + !memcmp(ref.value.val2.target_value, want_hash, REFTABLE_HASH_SIZE_SHA1)) 533 want_names[want_names_len++] = xstrdup(name); 534 } 535
+30 -29
t/unit-tests/t-reftable-record.c
··· 7 */ 8 9 #include "test-lib.h" 10 #include "reftable/constants.h" 11 #include "reftable/record.h" 12 ··· 17 18 typ = reftable_record_type(rec); 19 reftable_record_init(&copy, typ); 20 - reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ); 21 /* do it twice to catch memory leaks */ 22 - reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ); 23 - check(reftable_record_equal(rec, &copy, GIT_SHA1_RAWSZ)); 24 25 reftable_record_release(&copy); 26 } ··· 59 60 static void set_hash(uint8_t *h, int j) 61 { 62 - for (int i = 0; i < hash_size(GIT_SHA1_FORMAT_ID); i++) 63 h[i] = (j >> i) & 0xff; 64 } 65 ··· 84 }, 85 }; 86 87 - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 88 check(!reftable_record_cmp(&in[0], &in[1])); 89 90 - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); 91 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 92 93 in[1].u.ref.value_type = in[0].u.ref.value_type; 94 - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 95 check(!reftable_record_cmp(&in[0], &in[1])); 96 } 97 ··· 155 check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION); 156 157 reftable_record_key(&in, &key); 158 - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); 159 check_int(n, >, 0); 160 161 /* decode into a non-zero reftable_record to test for leaks. */ 162 - m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch); 163 check_int(n, ==, m); 164 165 check(reftable_ref_record_equal(&in.u.ref, &out.u.ref, 166 - GIT_SHA1_RAWSZ)); 167 reftable_record_release(&in); 168 169 reftable_buf_release(&key); ··· 193 }, 194 }; 195 196 - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 197 - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); 198 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 199 /* comparison should be reversed for equal keys, because 200 * comparison is now performed on the basis of update indices */ 201 check_int(reftable_record_cmp(&in[0], &in[1]), <, 0); 202 203 in[1].u.log.update_index = in[0].u.log.update_index; 204 - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 205 check(!reftable_record_cmp(&in[0], &in[1])); 206 } 207 ··· 303 304 reftable_record_key(&rec, &key); 305 306 - n = reftable_record_encode(&rec, dest, GIT_SHA1_RAWSZ); 307 check_int(n, >=, 0); 308 valtype = reftable_record_val_type(&rec); 309 m = reftable_record_decode(&out, key, valtype, dest, 310 - GIT_SHA1_RAWSZ, &scratch); 311 check_int(n, ==, m); 312 313 check(reftable_log_record_equal(&in[i], &out.u.log, 314 - GIT_SHA1_RAWSZ)); 315 reftable_log_record_release(&in[i]); 316 reftable_buf_release(&key); 317 reftable_record_release(&out); ··· 380 }, 381 }; 382 383 - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 384 check(!reftable_record_cmp(&in[0], &in[1])); 385 386 - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); 387 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 388 389 in[1].u.obj.offset_len = in[0].u.obj.offset_len; 390 - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 391 check(!reftable_record_cmp(&in[0], &in[1])); 392 } 393 394 static void t_reftable_obj_record_roundtrip(void) 395 { 396 - uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 }; 397 uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; 398 struct reftable_obj_record recs[3] = { 399 { ··· 435 check(!reftable_record_is_deletion(&in)); 436 t_copy(&in); 437 reftable_record_key(&in, &key); 438 - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); 439 check_int(n, >, 0); 440 extra = reftable_record_val_type(&in); 441 m = reftable_record_decode(&out, key, extra, dest, 442 - GIT_SHA1_RAWSZ, &scratch); 443 check_int(n, ==, m); 444 445 - check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); 446 reftable_buf_release(&key); 447 reftable_record_release(&out); 448 } ··· 473 check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); 474 check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); 475 476 - check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 477 check(!reftable_record_cmp(&in[0], &in[1])); 478 479 - check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ)); 480 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 481 482 in[1].u.idx.offset = in[0].u.idx.offset; 483 - check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ)); 484 check(!reftable_record_cmp(&in[0], &in[1])); 485 486 for (size_t i = 0; i < ARRAY_SIZE(in); i++) ··· 516 517 check(!reftable_record_is_deletion(&in)); 518 check(!reftable_buf_cmp(&key, &in.u.idx.last_key)); 519 - n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ); 520 check_int(n, >, 0); 521 522 extra = reftable_record_val_type(&in); 523 - m = reftable_record_decode(&out, key, extra, dest, GIT_SHA1_RAWSZ, 524 &scratch); 525 check_int(m, ==, n); 526 527 - check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); 528 529 reftable_record_release(&out); 530 reftable_buf_release(&key);
··· 7 */ 8 9 #include "test-lib.h" 10 + #include "reftable/basics.h" 11 #include "reftable/constants.h" 12 #include "reftable/record.h" 13 ··· 18 19 typ = reftable_record_type(rec); 20 reftable_record_init(&copy, typ); 21 + reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1); 22 /* do it twice to catch memory leaks */ 23 + reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1); 24 + check(reftable_record_equal(rec, &copy, REFTABLE_HASH_SIZE_SHA1)); 25 26 reftable_record_release(&copy); 27 } ··· 60 61 static void set_hash(uint8_t *h, int j) 62 { 63 + for (int i = 0; i < hash_size(REFTABLE_HASH_SHA1); i++) 64 h[i] = (j >> i) & 0xff; 65 } 66 ··· 85 }, 86 }; 87 88 + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 89 check(!reftable_record_cmp(&in[0], &in[1])); 90 91 + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); 92 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 93 94 in[1].u.ref.value_type = in[0].u.ref.value_type; 95 + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 96 check(!reftable_record_cmp(&in[0], &in[1])); 97 } 98 ··· 156 check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION); 157 158 reftable_record_key(&in, &key); 159 + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); 160 check_int(n, >, 0); 161 162 /* decode into a non-zero reftable_record to test for leaks. */ 163 + m = reftable_record_decode(&out, key, i, dest, REFTABLE_HASH_SIZE_SHA1, &scratch); 164 check_int(n, ==, m); 165 166 check(reftable_ref_record_equal(&in.u.ref, &out.u.ref, 167 + REFTABLE_HASH_SIZE_SHA1)); 168 reftable_record_release(&in); 169 170 reftable_buf_release(&key); ··· 194 }, 195 }; 196 197 + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 198 + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); 199 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 200 /* comparison should be reversed for equal keys, because 201 * comparison is now performed on the basis of update indices */ 202 check_int(reftable_record_cmp(&in[0], &in[1]), <, 0); 203 204 in[1].u.log.update_index = in[0].u.log.update_index; 205 + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 206 check(!reftable_record_cmp(&in[0], &in[1])); 207 } 208 ··· 304 305 reftable_record_key(&rec, &key); 306 307 + n = reftable_record_encode(&rec, dest, REFTABLE_HASH_SIZE_SHA1); 308 check_int(n, >=, 0); 309 valtype = reftable_record_val_type(&rec); 310 m = reftable_record_decode(&out, key, valtype, dest, 311 + REFTABLE_HASH_SIZE_SHA1, &scratch); 312 check_int(n, ==, m); 313 314 check(reftable_log_record_equal(&in[i], &out.u.log, 315 + REFTABLE_HASH_SIZE_SHA1)); 316 reftable_log_record_release(&in[i]); 317 reftable_buf_release(&key); 318 reftable_record_release(&out); ··· 381 }, 382 }; 383 384 + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 385 check(!reftable_record_cmp(&in[0], &in[1])); 386 387 + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); 388 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 389 390 in[1].u.obj.offset_len = in[0].u.obj.offset_len; 391 + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 392 check(!reftable_record_cmp(&in[0], &in[1])); 393 } 394 395 static void t_reftable_obj_record_roundtrip(void) 396 { 397 + uint8_t testHash1[REFTABLE_HASH_SIZE_SHA1] = { 1, 2, 3, 4, 0 }; 398 uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; 399 struct reftable_obj_record recs[3] = { 400 { ··· 436 check(!reftable_record_is_deletion(&in)); 437 t_copy(&in); 438 reftable_record_key(&in, &key); 439 + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); 440 check_int(n, >, 0); 441 extra = reftable_record_val_type(&in); 442 m = reftable_record_decode(&out, key, extra, dest, 443 + REFTABLE_HASH_SIZE_SHA1, &scratch); 444 check_int(n, ==, m); 445 446 + check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); 447 reftable_buf_release(&key); 448 reftable_record_release(&out); 449 } ··· 474 check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); 475 check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); 476 477 + check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 478 check(!reftable_record_cmp(&in[0], &in[1])); 479 480 + check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); 481 check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); 482 483 in[1].u.idx.offset = in[0].u.idx.offset; 484 + check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); 485 check(!reftable_record_cmp(&in[0], &in[1])); 486 487 for (size_t i = 0; i < ARRAY_SIZE(in); i++) ··· 517 518 check(!reftable_record_is_deletion(&in)); 519 check(!reftable_buf_cmp(&key, &in.u.idx.last_key)); 520 + n = reftable_record_encode(&in, dest, REFTABLE_HASH_SIZE_SHA1); 521 check_int(n, >, 0); 522 523 extra = reftable_record_val_type(&in); 524 + m = reftable_record_decode(&out, key, extra, dest, REFTABLE_HASH_SIZE_SHA1, 525 &scratch); 526 check_int(m, ==, n); 527 528 + check(reftable_record_equal(&in, &out, REFTABLE_HASH_SIZE_SHA1)); 529 530 reftable_record_release(&out); 531 reftable_buf_release(&key);
+20 -17
t/unit-tests/t-reftable-stack.c
··· 8 9 #include "test-lib.h" 10 #include "lib-reftable.h" 11 #include "reftable/merged.h" 12 #include "reftable/reader.h" 13 #include "reftable/reftable-error.h" 14 #include "reftable/stack.h" 15 #include <dirent.h> 16 17 static void clear_dir(const char *dirname) ··· 120 121 snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i); 122 ref.refname = buf; 123 - t_reftable_set_hash(ref.value.val1, i, GIT_SHA1_FORMAT_ID); 124 125 err = reftable_stack_add(st, &write_test_ref, &ref); 126 check(!err); ··· 168 169 err = reftable_stack_read_ref(st, ref.refname, &dest); 170 check(!err); 171 - check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ)); 172 check_int(st->readers_len, >, 0); 173 174 #ifndef GIT_WINDOWS_NATIVE ··· 279 err = reftable_stack_read_ref(st, ref.refname, &dest); 280 check(!err); 281 check_int(REFTABLE_REF_SYMREF, ==, dest.value_type); 282 - check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ)); 283 284 reftable_ref_record_release(&dest); 285 reftable_stack_destroy(st); ··· 339 for (size_t i = 0; i < ARRAY_SIZE(refs); i++) { 340 err = reftable_stack_read_ref(st2, refs[i].refname, &ref); 341 check(!err); 342 - check(reftable_ref_record_equal(&refs[i], &ref, GIT_SHA1_RAWSZ)); 343 } 344 345 reftable_ref_record_release(&ref); ··· 529 refs[i].refname = xstrdup(buf); 530 refs[i].update_index = i + 1; 531 refs[i].value_type = REFTABLE_REF_VAL1; 532 - t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID); 533 534 logs[i].refname = xstrdup(buf); 535 logs[i].update_index = N + i + 1; 536 logs[i].value_type = REFTABLE_LOG_UPDATE; 537 logs[i].value.update.email = xstrdup("identity@invalid"); 538 - t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID); 539 } 540 541 for (i = 0; i < N; i++) { ··· 561 int err = reftable_stack_read_ref(st, refs[i].refname, &dest); 562 check(!err); 563 check(reftable_ref_record_equal(&dest, refs + i, 564 - GIT_SHA1_RAWSZ)); 565 reftable_ref_record_release(&dest); 566 } 567 ··· 570 int err = reftable_stack_read_log(st, refs[i].refname, &dest); 571 check(!err); 572 check(reftable_log_record_equal(&dest, logs + i, 573 - GIT_SHA1_RAWSZ)); 574 reftable_log_record_release(&dest); 575 } 576 ··· 621 refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 622 refs[i].update_index = i + 1; 623 refs[i].value_type = REFTABLE_REF_VAL1; 624 - t_reftable_set_hash(refs[i].value.val1, i, GIT_SHA1_FORMAT_ID); 625 626 logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 627 logs[i].update_index = i + 1; 628 logs[i].value_type = REFTABLE_LOG_UPDATE; 629 logs[i].value.update.email = xstrdup("johndoe@invalid"); 630 logs[i].value.update.message = xstrdup("commit\n"); 631 - t_reftable_set_hash(logs[i].value.update.new_hash, i, GIT_SHA1_FORMAT_ID); 632 } 633 634 for (i = 0; i < N; i++) { ··· 655 if (err > 0) 656 break; 657 check(!err); 658 - check(reftable_ref_record_equal(&ref, &refs[i], GIT_SHA1_RAWSZ)); 659 reftable_ref_record_release(&ref); 660 } 661 check_int(i, ==, N); ··· 673 if (err > 0) 674 break; 675 check(!err); 676 - check(reftable_log_record_equal(&log, &logs[i], GIT_SHA1_RAWSZ)); 677 reftable_log_record_release(&log); 678 } 679 check_int(i, ==, N); ··· 766 if (i % 2 == 0) { 767 refs[i].value_type = REFTABLE_REF_VAL1; 768 t_reftable_set_hash(refs[i].value.val1, i, 769 - GIT_SHA1_FORMAT_ID); 770 } 771 772 logs[i].refname = xstrdup(buf); ··· 775 if (i % 2 == 0) { 776 logs[i].value_type = REFTABLE_LOG_UPDATE; 777 t_reftable_set_hash(logs[i].value.update.new_hash, i, 778 - GIT_SHA1_FORMAT_ID); 779 logs[i].value.update.email = 780 xstrdup("identity@invalid"); 781 } ··· 835 .value.symref = (char *) "target", 836 .update_index = 1, 837 }; 838 - struct reftable_write_options opts32 = { .hash_id = GIT_SHA256_FORMAT_ID }; 839 struct reftable_stack *st32 = NULL; 840 struct reftable_write_options opts_default = { 0 }; 841 struct reftable_stack *st_default = NULL; ··· 858 err = reftable_stack_read_ref(st_default, "master", &dest); 859 check(!err); 860 861 - check(reftable_ref_record_equal(&ref, &dest, GIT_SHA1_RAWSZ)); 862 reftable_ref_record_release(&dest); 863 reftable_stack_destroy(st); 864 reftable_stack_destroy(st_default); ··· 908 logs[i].value.update.time = i; 909 logs[i].value.update.email = xstrdup("identity@invalid"); 910 t_reftable_set_hash(logs[i].value.update.new_hash, i, 911 - GIT_SHA1_FORMAT_ID); 912 } 913 914 for (i = 1; i <= N; i++) {
··· 8 9 #include "test-lib.h" 10 #include "lib-reftable.h" 11 + #include "dir.h" 12 #include "reftable/merged.h" 13 #include "reftable/reader.h" 14 #include "reftable/reftable-error.h" 15 #include "reftable/stack.h" 16 + #include "strbuf.h" 17 + #include "tempfile.h" 18 #include <dirent.h> 19 20 static void clear_dir(const char *dirname) ··· 123 124 snprintf(buf, sizeof(buf), "refs/heads/branch-%04"PRIuMAX, (uintmax_t)i); 125 ref.refname = buf; 126 + t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1); 127 128 err = reftable_stack_add(st, &write_test_ref, &ref); 129 check(!err); ··· 171 172 err = reftable_stack_read_ref(st, ref.refname, &dest); 173 check(!err); 174 + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); 175 check_int(st->readers_len, >, 0); 176 177 #ifndef GIT_WINDOWS_NATIVE ··· 282 err = reftable_stack_read_ref(st, ref.refname, &dest); 283 check(!err); 284 check_int(REFTABLE_REF_SYMREF, ==, dest.value_type); 285 + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); 286 287 reftable_ref_record_release(&dest); 288 reftable_stack_destroy(st); ··· 342 for (size_t i = 0; i < ARRAY_SIZE(refs); i++) { 343 err = reftable_stack_read_ref(st2, refs[i].refname, &ref); 344 check(!err); 345 + check(reftable_ref_record_equal(&refs[i], &ref, REFTABLE_HASH_SIZE_SHA1)); 346 } 347 348 reftable_ref_record_release(&ref); ··· 532 refs[i].refname = xstrdup(buf); 533 refs[i].update_index = i + 1; 534 refs[i].value_type = REFTABLE_REF_VAL1; 535 + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); 536 537 logs[i].refname = xstrdup(buf); 538 logs[i].update_index = N + i + 1; 539 logs[i].value_type = REFTABLE_LOG_UPDATE; 540 logs[i].value.update.email = xstrdup("identity@invalid"); 541 + t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); 542 } 543 544 for (i = 0; i < N; i++) { ··· 564 int err = reftable_stack_read_ref(st, refs[i].refname, &dest); 565 check(!err); 566 check(reftable_ref_record_equal(&dest, refs + i, 567 + REFTABLE_HASH_SIZE_SHA1)); 568 reftable_ref_record_release(&dest); 569 } 570 ··· 573 int err = reftable_stack_read_log(st, refs[i].refname, &dest); 574 check(!err); 575 check(reftable_log_record_equal(&dest, logs + i, 576 + REFTABLE_HASH_SIZE_SHA1)); 577 reftable_log_record_release(&dest); 578 } 579 ··· 624 refs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 625 refs[i].update_index = i + 1; 626 refs[i].value_type = REFTABLE_REF_VAL1; 627 + t_reftable_set_hash(refs[i].value.val1, i, REFTABLE_HASH_SHA1); 628 629 logs[i].refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 630 logs[i].update_index = i + 1; 631 logs[i].value_type = REFTABLE_LOG_UPDATE; 632 logs[i].value.update.email = xstrdup("johndoe@invalid"); 633 logs[i].value.update.message = xstrdup("commit\n"); 634 + t_reftable_set_hash(logs[i].value.update.new_hash, i, REFTABLE_HASH_SHA1); 635 } 636 637 for (i = 0; i < N; i++) { ··· 658 if (err > 0) 659 break; 660 check(!err); 661 + check(reftable_ref_record_equal(&ref, &refs[i], REFTABLE_HASH_SIZE_SHA1)); 662 reftable_ref_record_release(&ref); 663 } 664 check_int(i, ==, N); ··· 676 if (err > 0) 677 break; 678 check(!err); 679 + check(reftable_log_record_equal(&log, &logs[i], REFTABLE_HASH_SIZE_SHA1)); 680 reftable_log_record_release(&log); 681 } 682 check_int(i, ==, N); ··· 769 if (i % 2 == 0) { 770 refs[i].value_type = REFTABLE_REF_VAL1; 771 t_reftable_set_hash(refs[i].value.val1, i, 772 + REFTABLE_HASH_SHA1); 773 } 774 775 logs[i].refname = xstrdup(buf); ··· 778 if (i % 2 == 0) { 779 logs[i].value_type = REFTABLE_LOG_UPDATE; 780 t_reftable_set_hash(logs[i].value.update.new_hash, i, 781 + REFTABLE_HASH_SHA1); 782 logs[i].value.update.email = 783 xstrdup("identity@invalid"); 784 } ··· 838 .value.symref = (char *) "target", 839 .update_index = 1, 840 }; 841 + struct reftable_write_options opts32 = { .hash_id = REFTABLE_HASH_SHA256 }; 842 struct reftable_stack *st32 = NULL; 843 struct reftable_write_options opts_default = { 0 }; 844 struct reftable_stack *st_default = NULL; ··· 861 err = reftable_stack_read_ref(st_default, "master", &dest); 862 check(!err); 863 864 + check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); 865 reftable_ref_record_release(&dest); 866 reftable_stack_destroy(st); 867 reftable_stack_destroy(st_default); ··· 911 logs[i].value.update.time = i; 912 logs[i].value.update.email = xstrdup("identity@invalid"); 913 t_reftable_set_hash(logs[i].value.update.new_hash, i, 914 + REFTABLE_HASH_SHA1); 915 } 916 917 for (i = 1; i <= N; i++) {