diff options
Diffstat (limited to 'src/libgit2/index.c')
-rw-r--r-- | src/libgit2/index.c | 433 |
1 files changed, 316 insertions, 117 deletions
diff --git a/src/libgit2/index.c b/src/libgit2/index.c index 6777f0358..9d919093b 100644 --- a/src/libgit2/index.c +++ b/src/libgit2/index.c @@ -32,8 +32,6 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr unsigned int flags, git_index_matched_path_cb cb, void *payload); -#define minimal_entry_size (offsetof(struct entry_short, path)) - static const size_t INDEX_HEADER_SIZE = 12; static const unsigned int INDEX_VERSION_NUMBER_DEFAULT = 2; @@ -65,7 +63,7 @@ struct entry_time { uint32_t nanoseconds; }; -struct entry_short { +struct entry_common { struct entry_time ctime; struct entry_time mtime; uint32_t dev; @@ -74,25 +72,35 @@ struct entry_short { uint32_t uid; uint32_t gid; uint32_t file_size; - unsigned char oid[GIT_OID_SHA1_SIZE]; - uint16_t flags; - char path[1]; /* arbitrary length */ }; -struct entry_long { - struct entry_time ctime; - struct entry_time mtime; - uint32_t dev; - uint32_t ino; - uint32_t mode; - uint32_t uid; - uint32_t gid; - uint32_t file_size; - unsigned char oid[GIT_OID_SHA1_SIZE]; - uint16_t flags; - uint16_t flags_extended; - char path[1]; /* arbitrary length */ -}; +#define entry_short(oid_size) \ + struct { \ + struct entry_common common; \ + unsigned char oid[oid_size]; \ + uint16_t flags; \ + char path[1]; /* arbitrary length */ \ + } + +#define entry_long(oid_size) \ + struct { \ + struct entry_common common; \ + unsigned char oid[oid_size]; \ + uint16_t flags; \ + uint16_t flags_extended; \ + char path[1]; /* arbitrary length */ \ + } + +typedef entry_short(GIT_OID_SHA1_SIZE) index_entry_short_sha1; +typedef entry_long(GIT_OID_SHA1_SIZE) index_entry_long_sha1; + +#ifdef GIT_EXPERIMENTAL_SHA256 +typedef entry_short(GIT_OID_SHA256_SIZE) index_entry_short_sha256; +typedef entry_long(GIT_OID_SHA256_SIZE) index_entry_long_sha256; +#endif + +#undef entry_short +#undef entry_long struct entry_srch_key { const char *path; @@ -115,12 +123,12 @@ struct reuc_entry_internal { bool git_index__enforce_unsaved_safety = false; /* local declarations */ -static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size); +static int read_extension(size_t *read_len, git_index *index, size_t checksum_size, const char *buffer, size_t buffer_size); static int read_header(struct index_header *dest, const void *buffer); static int parse_index(git_index *index, const char *buffer, size_t buffer_size); static bool is_index_extended(git_index *index); -static int write_index(unsigned char checksum[GIT_HASH_SHA1_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file); +static int write_index(unsigned char checksum[GIT_HASH_MAX_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file); static void index_entry_free(git_index_entry *entry); static void index_entry_reuc_free(git_index_reuc_entry *reuc); @@ -401,7 +409,10 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case) git_vector_sort(&index->reuc); } -int git_index_open(git_index **index_out, const char *index_path) +int git_index__open( + git_index **index_out, + const char *index_path, + git_oid_t oid_type) { git_index *index; int error = -1; @@ -411,6 +422,8 @@ int git_index_open(git_index **index_out, const char *index_path) index = git__calloc(1, sizeof(git_index)); GIT_ERROR_CHECK_ALLOC(index); + index->oid_type = oid_type; + if (git_pool_init(&index->tree_pool, 1) < 0) goto fail; @@ -451,10 +464,34 @@ fail: return error; } +#ifdef GIT_EXPERIMENTAL_SHA256 +int git_index_open(git_index **index_out, const char *index_path, git_oid_t oid_type) +{ + return git_index__open(index_out, index_path, oid_type); +} +#else +int git_index_open(git_index **index_out, const char *index_path) +{ + return git_index__open(index_out, index_path, GIT_OID_SHA1); +} +#endif + +int git_index__new(git_index **out, git_oid_t oid_type) +{ + return git_index__open(out, NULL, oid_type); +} + +#ifdef GIT_EXPERIMENTAL_SHA256 +int git_index_new(git_index **out, git_oid_t oid_type) +{ + return git_index__new(out, oid_type); +} +#else int git_index_new(git_index **out) { - return git_index_open(out, NULL); + return git_index__new(out, GIT_OID_SHA1); } +#endif static void index_free(git_index *index) { @@ -620,8 +657,8 @@ static int compare_checksum(git_index *index) { int fd; ssize_t bytes_read; - unsigned char checksum[GIT_HASH_SHA1_SIZE]; - size_t checksum_size = GIT_HASH_SHA1_SIZE; + unsigned char checksum[GIT_HASH_MAX_SIZE]; + size_t checksum_size = git_oid_size(index->oid_type); if ((fd = p_open(index->index_file_path, O_RDONLY)) < 0) return fd; @@ -2306,6 +2343,7 @@ static int index_error_invalid(const char *message) static int read_reuc(git_index *index, const char *buffer, size_t size) { const char *endptr; + size_t oid_size = git_oid_size(index->oid_type); size_t len; int i; @@ -2354,16 +2392,16 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) for (i = 0; i < 3; i++) { if (!lost->mode[i]) continue; - if (size < GIT_OID_SHA1_SIZE) { + if (size < oid_size) { index_entry_reuc_free(lost); return index_error_invalid("reading reuc entry oid"); } - if (git_oid__fromraw(&lost->oid[i], (const unsigned char *) buffer, GIT_OID_SHA1) < 0) + if (git_oid__fromraw(&lost->oid[i], (const unsigned char *) buffer, index->oid_type) < 0) return -1; - size -= GIT_OID_SHA1_SIZE; - buffer += GIT_OID_SHA1_SIZE; + size -= oid_size; + buffer += oid_size; } /* entry was read successfully - insert into reuc vector */ @@ -2433,73 +2471,157 @@ out_err: return 0; } -static size_t index_entry_size(size_t path_len, size_t varint_len, uint32_t flags) +GIT_INLINE(size_t) index_entry_path_offset( + git_oid_t oid_type, + uint32_t flags) { + if (oid_type == GIT_OID_SHA1) + return (flags & GIT_INDEX_ENTRY_EXTENDED) ? + offsetof(index_entry_long_sha1, path) : + offsetof(index_entry_short_sha1, path); + +#ifdef GIT_EXPERIMENTAL_SHA256 + else if (oid_type == GIT_OID_SHA256) + return (flags & GIT_INDEX_ENTRY_EXTENDED) ? + offsetof(index_entry_long_sha256, path) : + offsetof(index_entry_short_sha256, path); +#endif + + git_error_set(GIT_ERROR_INTERNAL, "invalid oid type"); + return 0; +} + +GIT_INLINE(size_t) index_entry_flags_offset(git_oid_t oid_type) +{ + if (oid_type == GIT_OID_SHA1) + return offsetof(index_entry_long_sha1, flags_extended); + +#ifdef GIT_EXPERIMENTAL_SHA256 + else if (oid_type == GIT_OID_SHA256) + return offsetof(index_entry_long_sha256, flags_extended); +#endif + + git_error_set(GIT_ERROR_INTERNAL, "invalid oid type"); + return 0; +} + +static size_t index_entry_size( + size_t path_len, + size_t varint_len, + git_oid_t oid_type, + uint32_t flags) +{ + size_t offset, size; + + if (!(offset = index_entry_path_offset(oid_type, flags))) + return 0; + if (varint_len) { - if (flags & GIT_INDEX_ENTRY_EXTENDED) - return offsetof(struct entry_long, path) + path_len + 1 + varint_len; - else - return offsetof(struct entry_short, path) + path_len + 1 + varint_len; + if (GIT_ADD_SIZET_OVERFLOW(&size, offset, path_len) || + GIT_ADD_SIZET_OVERFLOW(&size, size, 1) || + GIT_ADD_SIZET_OVERFLOW(&size, size, varint_len)) + return 0; } else { -#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7) - if (flags & GIT_INDEX_ENTRY_EXTENDED) - return entry_size(struct entry_long, path_len); - else - return entry_size(struct entry_short, path_len); -#undef entry_size + if (GIT_ADD_SIZET_OVERFLOW(&size, offset, path_len) || + GIT_ADD_SIZET_OVERFLOW(&size, size, 8)) + return 0; + + size &= ~7; } + + return size; } static int read_entry( git_index_entry **out, size_t *out_size, git_index *index, + size_t checksum_size, const void *buffer, size_t buffer_size, const char *last) { - size_t path_length, entry_size; + size_t path_length, path_offset, entry_size; const char *path_ptr; - struct entry_short source; + struct entry_common *source_common; + index_entry_short_sha1 source_sha1; +#ifdef GIT_EXPERIMENTAL_SHA256 + index_entry_short_sha256 source_sha256; +#endif git_index_entry entry = {{0}}; bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP; char *tmp_path = NULL; - size_t checksum_size = GIT_HASH_SHA1_SIZE; + + size_t minimal_entry_size = index_entry_path_offset(index->oid_type, 0); if (checksum_size + minimal_entry_size > buffer_size) return -1; /* buffer is not guaranteed to be aligned */ - memcpy(&source, buffer, sizeof(struct entry_short)); - - entry.ctime.seconds = (git_time_t)ntohl(source.ctime.seconds); - entry.ctime.nanoseconds = ntohl(source.ctime.nanoseconds); - entry.mtime.seconds = (git_time_t)ntohl(source.mtime.seconds); - entry.mtime.nanoseconds = ntohl(source.mtime.nanoseconds); - entry.dev = ntohl(source.dev); - entry.ino = ntohl(source.ino); - entry.mode = ntohl(source.mode); - entry.uid = ntohl(source.uid); - entry.gid = ntohl(source.gid); - entry.file_size = ntohl(source.file_size); - entry.flags = ntohs(source.flags); - - if (git_oid__fromraw(&entry.id, source.oid, GIT_OID_SHA1) < 0) + switch (index->oid_type) { + case GIT_OID_SHA1: + source_common = &source_sha1.common; + memcpy(&source_sha1, buffer, sizeof(source_sha1)); + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + source_common = &source_sha256.common; + memcpy(&source_sha256, buffer, sizeof(source_sha256)); + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } + + entry.ctime.seconds = (git_time_t)ntohl(source_common->ctime.seconds); + entry.ctime.nanoseconds = ntohl(source_common->ctime.nanoseconds); + entry.mtime.seconds = (git_time_t)ntohl(source_common->mtime.seconds); + entry.mtime.nanoseconds = ntohl(source_common->mtime.nanoseconds); + entry.dev = ntohl(source_common->dev); + entry.ino = ntohl(source_common->ino); + entry.mode = ntohl(source_common->mode); + entry.uid = ntohl(source_common->uid); + entry.gid = ntohl(source_common->gid); + entry.file_size = ntohl(source_common->file_size); + + switch (index->oid_type) { + case GIT_OID_SHA1: + if (git_oid__fromraw(&entry.id, source_sha1.oid, + GIT_OID_SHA1) < 0) + return -1; + entry.flags = ntohs(source_sha1.flags); + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + if (git_oid__fromraw(&entry.id, source_sha256.oid, + GIT_OID_SHA256) < 0) + return -1; + entry.flags = ntohs(source_sha256.flags); + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } + + if (!(path_offset = index_entry_path_offset(index->oid_type, entry.flags))) return -1; + if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) { uint16_t flags_raw; size_t flags_offset; - flags_offset = offsetof(struct entry_long, flags_extended); - memcpy(&flags_raw, (const char *) buffer + flags_offset, - sizeof(flags_raw)); + if (!(flags_offset = index_entry_flags_offset(index->oid_type))) + return -1; + + memcpy(&flags_raw, (const char *)buffer + flags_offset, sizeof(flags_raw)); flags_raw = ntohs(flags_raw); memcpy(&entry.flags_extended, &flags_raw, sizeof(flags_raw)); - path_ptr = (const char *) buffer + offsetof(struct entry_long, path); - } else - path_ptr = (const char *) buffer + offsetof(struct entry_short, path); + path_ptr = (const char *)buffer + path_offset; + } else { + path_ptr = (const char *)buffer + path_offset; + } if (!compressed) { path_length = entry.flags & GIT_INDEX_ENTRY_NAMEMASK; @@ -2511,12 +2633,12 @@ static int read_entry( path_end = memchr(path_ptr, '\0', buffer_size); if (path_end == NULL) - return -1; + return index_error_invalid("invalid path name"); path_length = path_end - path_ptr; } - entry_size = index_entry_size(path_length, 0, entry.flags); + entry_size = index_entry_size(path_length, 0, index->oid_type, entry.flags); entry.path = (char *)path_ptr; } else { size_t varint_len, last_len, prefix_len, suffix_len, path_len; @@ -2542,15 +2664,18 @@ static int read_entry( memcpy(tmp_path, last, prefix_len); memcpy(tmp_path + prefix_len, path_ptr + varint_len, suffix_len + 1); - entry_size = index_entry_size(suffix_len, varint_len, entry.flags); + + entry_size = index_entry_size(suffix_len, varint_len, index->oid_type, entry.flags); entry.path = tmp_path; } if (entry_size == 0) return -1; - if (checksum_size + entry_size > buffer_size) + if (checksum_size + entry_size > buffer_size) { + git_error_set(GIT_ERROR_INTERNAL, "invalid index checksum"); return -1; + } if (index_entry_dup(out, index, &entry) < 0) { git__free(tmp_path); @@ -2579,11 +2704,10 @@ static int read_header(struct index_header *dest, const void *buffer) return 0; } -static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size) +static int read_extension(size_t *read_len, git_index *index, size_t checksum_size, const char *buffer, size_t buffer_size) { struct index_extension dest; size_t total_size; - size_t checksum_size = GIT_HASH_SHA1_SIZE; /* buffer is not guaranteed to be aligned */ memcpy(&dest, buffer, sizeof(struct index_extension)); @@ -2602,7 +2726,7 @@ static int read_extension(size_t *read_len, git_index *index, const char *buffer if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') { /* tree cache */ if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) { - if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, &index->tree_pool) < 0) + if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, index->oid_type, &index->tree_pool) < 0) return -1; } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) { if (read_reuc(index, buffer + 8, dest.extension_size) < 0) @@ -2630,8 +2754,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) int error = 0; unsigned int i; struct index_header header = { 0 }; - unsigned char checksum[GIT_HASH_SHA1_SIZE]; - size_t checksum_size = GIT_HASH_SHA1_SIZE; + unsigned char checksum[GIT_HASH_MAX_SIZE]; + size_t checksum_size = git_hash_size(git_oid_algorithm(index->oid_type)); const char *last = NULL; const char *empty = ""; @@ -2646,9 +2770,12 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) if (buffer_size < INDEX_HEADER_SIZE + checksum_size) return index_error_invalid("insufficient buffer space"); - /* Precalculate the SHA1 of the files's contents -- we'll match it to - * the provided SHA1 in the footer */ - git_hash_buf(checksum, buffer, buffer_size - checksum_size, GIT_HASH_ALGORITHM_SHA1); + /* + * Precalculate the hash of the files's contents -- we'll match + * it to the provided checksum in the footer. + */ + git_hash_buf(checksum, buffer, buffer_size - checksum_size, + git_oid_algorithm(index->oid_type)); /* Parse header */ if ((error = read_header(&header, buffer)) < 0) @@ -2670,7 +2797,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) git_index_entry *entry = NULL; size_t entry_size; - if ((error = read_entry(&entry, &entry_size, index, buffer, buffer_size, last)) < 0) { + if ((error = read_entry(&entry, &entry_size, index, checksum_size, buffer, buffer_size, last)) < 0) { error = index_error_invalid("invalid entry"); goto done; } @@ -2701,7 +2828,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) while (buffer_size > checksum_size) { size_t extension_size; - if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) { + if ((error = read_extension(&extension_size, index, checksum_size, buffer, buffer_size)) < 0) { goto done; } @@ -2714,7 +2841,10 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) goto done; } - /* 160-bit SHA-1 over the content of the index file before this checksum. */ + /* + * SHA-1 or SHA-256 (depending on the repository's object format) + * over the content of the index file before this checksum. + */ if (memcmp(checksum, buffer, checksum_size) != 0) { error = index_error_invalid( "calculated checksum does not match expected"); @@ -2754,16 +2884,40 @@ static bool is_index_extended(git_index *index) return (extended > 0); } -static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char *last) +static int write_disk_entry( + git_index *index, + git_filebuf *file, + git_index_entry *entry, + const char *last) { void *mem = NULL; - struct entry_short ondisk; - size_t path_len, disk_size; + struct entry_common *ondisk_common; + size_t path_len, path_offset, disk_size; int varint_len = 0; char *path; const char *path_start = entry->path; size_t same_len = 0; + index_entry_short_sha1 ondisk_sha1; + index_entry_long_sha1 ondisk_ext_sha1; +#ifdef GIT_EXPERIMENTAL_SHA256 + index_entry_short_sha256 ondisk_sha256; + index_entry_long_sha256 ondisk_ext_sha256; +#endif + + switch (index->oid_type) { + case GIT_OID_SHA1: + ondisk_common = &ondisk_sha1.common; + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + ondisk_common = &ondisk_sha256.common; + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } + path_len = ((struct entry_internal *)entry)->pathlen; if (last) { @@ -2780,9 +2934,9 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha varint_len = git_encode_varint(NULL, 0, strlen(last) - same_len); } - disk_size = index_entry_size(path_len, varint_len, entry->flags); + disk_size = index_entry_size(path_len, varint_len, index->oid_type, entry->flags); - if (git_filebuf_reserve(file, &mem, disk_size) < 0) + if (!disk_size || git_filebuf_reserve(file, &mem, disk_size) < 0) return -1; memset(mem, 0x0, disk_size); @@ -2797,35 +2951,77 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha * * In 2038 I will be either too dead or too rich to care about this */ - ondisk.ctime.seconds = htonl((uint32_t)entry->ctime.seconds); - ondisk.mtime.seconds = htonl((uint32_t)entry->mtime.seconds); - ondisk.ctime.nanoseconds = htonl(entry->ctime.nanoseconds); - ondisk.mtime.nanoseconds = htonl(entry->mtime.nanoseconds); - ondisk.dev = htonl(entry->dev); - ondisk.ino = htonl(entry->ino); - ondisk.mode = htonl(entry->mode); - ondisk.uid = htonl(entry->uid); - ondisk.gid = htonl(entry->gid); - ondisk.file_size = htonl((uint32_t)entry->file_size); - git_oid_raw_cpy(ondisk.oid, entry->id.id, GIT_OID_SHA1_SIZE); - ondisk.flags = htons(entry->flags); + ondisk_common->ctime.seconds = htonl((uint32_t)entry->ctime.seconds); + ondisk_common->mtime.seconds = htonl((uint32_t)entry->mtime.seconds); + ondisk_common->ctime.nanoseconds = htonl(entry->ctime.nanoseconds); + ondisk_common->mtime.nanoseconds = htonl(entry->mtime.nanoseconds); + ondisk_common->dev = htonl(entry->dev); + ondisk_common->ino = htonl(entry->ino); + ondisk_common->mode = htonl(entry->mode); + ondisk_common->uid = htonl(entry->uid); + ondisk_common->gid = htonl(entry->gid); + ondisk_common->file_size = htonl((uint32_t)entry->file_size); + + switch (index->oid_type) { + case GIT_OID_SHA1: + git_oid_raw_cpy(ondisk_sha1.oid, entry->id.id, GIT_OID_SHA1_SIZE); + ondisk_sha1.flags = htons(entry->flags); + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + git_oid_raw_cpy(ondisk_sha256.oid, entry->id.id, GIT_OID_SHA256_SIZE); + ondisk_sha256.flags = htons(entry->flags); + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } + + path_offset = index_entry_path_offset(index->oid_type, entry->flags); if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) { - const size_t path_offset = offsetof(struct entry_long, path); - struct entry_long ondisk_ext; - memcpy(&ondisk_ext, &ondisk, sizeof(struct entry_short)); - ondisk_ext.flags_extended = htons(entry->flags_extended & + struct entry_common *ondisk_ext; + uint16_t flags_extended = htons(entry->flags_extended & GIT_INDEX_ENTRY_EXTENDED_FLAGS); - memcpy(mem, &ondisk_ext, path_offset); - path = (char *)mem + path_offset; - disk_size -= path_offset; + + switch (index->oid_type) { + case GIT_OID_SHA1: + memcpy(&ondisk_ext_sha1, &ondisk_sha1, + sizeof(index_entry_short_sha1)); + ondisk_ext_sha1.flags_extended = flags_extended; + ondisk_ext = &ondisk_ext_sha1.common; + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + memcpy(&ondisk_ext_sha256, &ondisk_sha256, + sizeof(index_entry_short_sha256)); + ondisk_ext_sha256.flags_extended = flags_extended; + ondisk_ext = &ondisk_ext_sha256.common; + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } + + memcpy(mem, ondisk_ext, path_offset); } else { - const size_t path_offset = offsetof(struct entry_short, path); - memcpy(mem, &ondisk, path_offset); - path = (char *)mem + path_offset; - disk_size -= path_offset; + switch (index->oid_type) { + case GIT_OID_SHA1: + memcpy(mem, &ondisk_sha1, path_offset); + break; +#ifdef GIT_EXPERIMENTAL_SHA256 + case GIT_OID_SHA256: + memcpy(mem, &ondisk_sha256, path_offset); + break; +#endif + default: + GIT_ASSERT(!"invalid oid type"); + } } + path = (char *)mem + path_offset; + disk_size -= path_offset; + if (last) { varint_len = git_encode_varint((unsigned char *) path, disk_size, strlen(last) - same_len); @@ -2877,7 +3073,7 @@ static int write_entries(git_index *index, git_filebuf *file) last = ""; git_vector_foreach(entries, i, entry) { - if ((error = write_disk_entry(file, entry, last)) < 0) + if ((error = write_disk_entry(index, file, entry, last)) < 0) break; if (index->version >= INDEX_VERSION_NUMBER_COMP) last = entry->path; @@ -2955,8 +3151,9 @@ done: return error; } -static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *reuc) +static int create_reuc_extension_data(git_str *reuc_buf, git_index *index, git_index_reuc_entry *reuc) { + size_t oid_size = git_oid_size(index->oid_type); int i; int error = 0; @@ -2970,7 +3167,7 @@ static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *r } for (i = 0; i < 3; i++) { - if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_SHA1_SIZE)) < 0) + if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, oid_size)) < 0) return error; } @@ -2987,7 +3184,7 @@ static int write_reuc_extension(git_index *index, git_filebuf *file) int error = 0; git_vector_foreach(out, i, reuc) { - if ((error = create_reuc_extension_data(&reuc_buf, reuc)) < 0) + if ((error = create_reuc_extension_data(&reuc_buf, index, reuc)) < 0) goto done; } @@ -3036,7 +3233,7 @@ static void clear_uptodate(git_index *index) } static int write_index( - unsigned char checksum[GIT_HASH_SHA1_SIZE], + unsigned char checksum[GIT_HASH_MAX_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file) @@ -3048,7 +3245,9 @@ static int write_index( GIT_ASSERT_ARG(index); GIT_ASSERT_ARG(file); - *checksum_size = GIT_HASH_SHA1_SIZE; + GIT_ASSERT(index->oid_type); + + *checksum_size = git_hash_size(git_oid_algorithm(index->oid_type)); if (index->version <= INDEX_VERSION_NUMBER_EXT) { is_extended = is_index_extended(index); @@ -3209,7 +3408,7 @@ cleanup: if (error < 0) return error; - error = git_tree_cache_read_tree(&index->tree, tree, &index->tree_pool); + error = git_tree_cache_read_tree(&index->tree, tree, index->oid_type, &index->tree_pool); return error; } @@ -3674,7 +3873,7 @@ int git_indexwriter_init( writer->index = index; - filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(GIT_OID_SHA1)); + filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(index->oid_type)); GIT_ASSERT(filebuf_hash); if (!index->index_file_path) @@ -3716,7 +3915,7 @@ int git_indexwriter_init_for_operation( int git_indexwriter_commit(git_indexwriter *writer) { - unsigned char checksum[GIT_HASH_SHA1_SIZE]; + unsigned char checksum[GIT_HASH_MAX_SIZE]; size_t checksum_size; int error; |