X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=fast-import.c;h=d5e4cf0bad411dad859dbe421ab7583cfb0f1561;hb=19ea3f4652253344938d2045dc0e9533c89495fe;hp=b141535e11b0740e8382e23a3c749c252550b493;hpb=9e7267d8c0bcaef799876ed6353b2d02c9cb910e;p=platform%2Fupstream%2Fgit.git diff --git a/fast-import.c b/fast-import.c index b141535..d5e4cf0 100644 --- a/fast-import.c +++ b/fast-import.c @@ -154,6 +154,7 @@ Format of STDIN stream: #include "builtin.h" #include "cache.h" +#include "config.h" #include "lockfile.h" #include "object.h" #include "blob.h" @@ -164,8 +165,9 @@ Format of STDIN stream: #include "refs.h" #include "csum-file.h" #include "quote.h" -#include "exec_cmd.h" #include "dir.h" +#include "run-command.h" +#include "packfile.h" #define PACK_ID_BITS 16 #define MAX_PACK_ID ((1<branch_tree.tree) fputs(" loaded", rpt); - if (is_null_sha1(b->branch_tree.versions[1].sha1)) + if (is_null_oid(&b->branch_tree.versions[1].oid)) fputs(" dirty", rpt); fputc('\n', rpt); - fprintf(rpt, " tip commit : %s\n", sha1_to_hex(b->sha1)); - fprintf(rpt, " old tree : %s\n", sha1_to_hex(b->branch_tree.versions[0].sha1)); - fprintf(rpt, " cur tree : %s\n", sha1_to_hex(b->branch_tree.versions[1].sha1)); + fprintf(rpt, " tip commit : %s\n", oid_to_hex(&b->oid)); + fprintf(rpt, " old tree : %s\n", + oid_to_hex(&b->branch_tree.versions[0].oid)); + fprintf(rpt, " cur tree : %s\n", + oid_to_hex(&b->branch_tree.versions[1].oid)); fprintf(rpt, " commit clock: %" PRIuMAX "\n", b->last_commit); fputs(" last pack : ", rpt); @@ -414,7 +418,7 @@ static void write_crash_report(const char *err) struct recent_command *rc; if (!rpt) { - error("can't write crash report %s: %s", loc, strerror(errno)); + error_errno("can't write crash report %s", loc); free(loc); return; } @@ -424,7 +428,7 @@ static void write_crash_report(const char *err) fprintf(rpt, "fast-import crash report:\n"); fprintf(rpt, " fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid()); fprintf(rpt, " parent process : %"PRIuMAX"\n", (uintmax_t) getppid()); - fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_MODE(LOCAL))); + fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_MODE(ISO8601))); fputc('\n', rpt); fputs("fatal: ", rpt); @@ -470,7 +474,7 @@ static void write_crash_report(const char *err) fputs("Annotated Tags\n", rpt); fputs("--------------\n", rpt); for (tg = first_tag; tg; tg = tg->next_tag) { - fputs(sha1_to_hex(tg->sha1), rpt); + fputs(oid_to_hex(&tg->oid), rpt); fputc(' ', rpt); fputs(tg->name, rpt); fputc('\n', rpt); @@ -555,7 +559,7 @@ static void alloc_objects(unsigned int cnt) alloc_count += cnt; } -static struct object_entry *new_object(unsigned char *sha1) +static struct object_entry *new_object(struct object_id *oid) { struct object_entry *e; @@ -563,38 +567,65 @@ static struct object_entry *new_object(unsigned char *sha1) alloc_objects(object_entry_alloc); e = blocks->next_free++; - hashcpy(e->idx.sha1, sha1); + oidcpy(&e->idx.oid, oid); return e; } -static struct object_entry *find_object(unsigned char *sha1) +static struct object_entry *find_object(struct object_id *oid) { - unsigned int h = sha1[0] << 8 | sha1[1]; + unsigned int h = oid->hash[0] << 8 | oid->hash[1]; struct object_entry *e; for (e = object_table[h]; e; e = e->next) - if (!hashcmp(sha1, e->idx.sha1)) + if (!oidcmp(oid, &e->idx.oid)) return e; return NULL; } -static struct object_entry *insert_object(unsigned char *sha1) +static struct object_entry *insert_object(struct object_id *oid) { - unsigned int h = sha1[0] << 8 | sha1[1]; + unsigned int h = oid->hash[0] << 8 | oid->hash[1]; struct object_entry *e = object_table[h]; while (e) { - if (!hashcmp(sha1, e->idx.sha1)) + if (!oidcmp(oid, &e->idx.oid)) return e; e = e->next; } - e = new_object(sha1); + e = new_object(oid); e->next = object_table[h]; e->idx.offset = 0; object_table[h] = e; return e; } +static void invalidate_pack_id(unsigned int id) +{ + unsigned int h; + unsigned long lu; + struct tag *t; + + for (h = 0; h < ARRAY_SIZE(object_table); h++) { + struct object_entry *e; + + for (e = object_table[h]; e; e = e->next) + if (e->pack_id == id) + e->pack_id = MAX_PACK_ID; + } + + for (lu = 0; lu < branch_table_sz; lu++) { + struct branch *b; + + for (b = branch_table[lu]; b; b = b->table_next_branch) + if (b->pack_id == id) + b->pack_id = MAX_PACK_ID; + } + + for (t = first_tag; t; t = t->next_tag) + if (t->pack_id == id) + t->pack_id = MAX_PACK_ID; +} + static unsigned int hc_str(const char *s, size_t len) { unsigned int r = 0; @@ -622,7 +653,7 @@ static void *pool_alloc(size_t len) return xmalloc(len); } total_allocd += sizeof(struct mem_pool) + mem_pool_alloc; - p = xmalloc(sizeof(struct mem_pool) + mem_pool_alloc); + p = xmalloc(st_add(sizeof(struct mem_pool), mem_pool_alloc)); p->next_pool = mem_pool; p->next_free = (char *) p->space; p->end = p->next_free + mem_pool_alloc; @@ -644,8 +675,9 @@ static void *pool_calloc(size_t count, size_t size) static char *pool_strdup(const char *s) { - char *r = pool_alloc(strlen(s) + 1); - strcpy(r, s); + size_t len = strlen(s) + 1; + char *r = pool_alloc(len); + memcpy(r, s, len); return r; } @@ -702,7 +734,7 @@ static struct atom_str *to_atom(const char *s, unsigned short len) c = pool_alloc(sizeof(struct atom_str) + len + 1); c->str_len = len; - strncpy(c->str_dat, s, len); + memcpy(c->str_dat, s, len); c->str_dat[len] = 0; c->next_atom = atom_table[hc]; atom_table[hc] = c; @@ -813,7 +845,8 @@ static struct tree_entry *new_tree_entry(void) if (!avail_tree_entry) { unsigned int n = tree_entry_alloc; total_allocd += n * sizeof(struct tree_entry); - avail_tree_entry = e = xmalloc(n * sizeof(struct tree_entry)); + ALLOC_ARRAY(e, n); + avail_tree_entry = e; while (n-- > 1) { *((void**)e) = e + 1; e++; @@ -847,7 +880,7 @@ static struct tree_content *dup_tree_content(struct tree_content *s) a = s->entries[i]; b = new_tree_entry(); memcpy(b, a, sizeof(*a)); - if (a->tree && is_null_sha1(b->versions[1].sha1)) + if (a->tree && is_null_oid(&b->versions[1].oid)) b->tree = dup_tree_content(a->tree); else b->tree = NULL; @@ -861,15 +894,15 @@ static struct tree_content *dup_tree_content(struct tree_content *s) static void start_packfile(void) { - static char tmp_file[PATH_MAX]; + struct strbuf tmp_file = STRBUF_INIT; struct packed_git *p; struct pack_header hdr; int pack_fd; - pack_fd = odb_mkstemp(tmp_file, sizeof(tmp_file), - "pack/tmp_pack_XXXXXX"); - p = xcalloc(1, sizeof(*p) + strlen(tmp_file) + 2); - strcpy(p->pack_name, tmp_file); + pack_fd = odb_mkstemp(&tmp_file, "pack/tmp_pack_XXXXXX"); + FLEX_ALLOC_STR(p, pack_name, tmp_file.buf); + strbuf_release(&tmp_file); + p->pack_fd = pack_fd; p->do_not_close = 1; pack_file = sha1fd(pack_fd, p->pack_name); @@ -895,7 +928,7 @@ static const char *create_index(void) struct object_entry_pool *o; /* Build the table of object IDs. */ - idx = xmalloc(object_count * sizeof(*idx)); + ALLOC_ARRAY(idx, object_count); c = idx; for (o = blocks; o; o = o->next_pool) for (e = o->next_free; e-- != o->entries;) @@ -912,41 +945,57 @@ static const char *create_index(void) static char *keep_pack(const char *curr_index_name) { - static char name[PATH_MAX]; static const char *keep_msg = "fast-import"; + struct strbuf name = STRBUF_INIT; int keep_fd; - keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1); + odb_pack_name(&name, pack_data->sha1, "keep"); + keep_fd = odb_pack_keep(name.buf); if (keep_fd < 0) die_errno("cannot create keep file"); write_or_die(keep_fd, keep_msg, strlen(keep_msg)); if (close(keep_fd)) die_errno("failed to write keep file"); - snprintf(name, sizeof(name), "%s/pack/pack-%s.pack", - get_object_directory(), sha1_to_hex(pack_data->sha1)); - if (finalize_object_file(pack_data->pack_name, name)) + odb_pack_name(&name, pack_data->sha1, "pack"); + if (finalize_object_file(pack_data->pack_name, name.buf)) die("cannot store pack file"); - snprintf(name, sizeof(name), "%s/pack/pack-%s.idx", - get_object_directory(), sha1_to_hex(pack_data->sha1)); - if (finalize_object_file(curr_index_name, name)) + odb_pack_name(&name, pack_data->sha1, "idx"); + if (finalize_object_file(curr_index_name, name.buf)) die("cannot store index file"); free((void *)curr_index_name); - return name; + return strbuf_detach(&name, NULL); } static void unkeep_all_packs(void) { - static char name[PATH_MAX]; + struct strbuf name = STRBUF_INIT; int k; for (k = 0; k < pack_id; k++) { struct packed_git *p = all_packs[k]; - snprintf(name, sizeof(name), "%s/pack/pack-%s.keep", - get_object_directory(), sha1_to_hex(p->sha1)); - unlink_or_warn(name); + odb_pack_name(&name, p->sha1, "keep"); + unlink_or_warn(name.buf); } + strbuf_release(&name); +} + +static int loosen_small_pack(const struct packed_git *p) +{ + struct child_process unpack = CHILD_PROCESS_INIT; + + if (lseek(p->pack_fd, 0, SEEK_SET) < 0) + die_errno("Failed seeking to start of '%s'", p->pack_name); + + unpack.in = p->pack_fd; + unpack.git_cmd = 1; + unpack.stdout_to_stderr = 1; + argv_array_push(&unpack.args, "unpack-objects"); + if (!show_stats) + argv_array_push(&unpack.args, "-q"); + + return run_command(&unpack); } static void end_packfile(void) @@ -960,17 +1009,25 @@ static void end_packfile(void) clear_delta_base_cache(); if (object_count) { struct packed_git *new_p; - unsigned char cur_pack_sha1[20]; + struct object_id cur_pack_oid; char *idx_name; int i; struct branch *b; struct tag *t; close_pack_windows(pack_data); - sha1close(pack_file, cur_pack_sha1, 0); + sha1close(pack_file, cur_pack_oid.hash, 0); fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1, pack_data->pack_name, object_count, - cur_pack_sha1, pack_size); + cur_pack_oid.hash, pack_size); + + if (object_count <= unpack_limit) { + if (!loosen_small_pack(pack_data)) { + invalidate_pack_id(pack_id); + goto discard_pack; + } + } + close(pack_data->pack_fd); idx_name = keep_pack(create_index()); @@ -980,6 +1037,7 @@ static void end_packfile(void) die("core git rejected index %s", idx_name); all_packs[pack_id] = new_p; install_packed_git(new_p); + free(idx_name); /* Print the boundary */ if (pack_edges) { @@ -987,12 +1045,14 @@ static void end_packfile(void) for (i = 0; i < branch_table_sz; i++) { for (b = branch_table[i]; b; b = b->table_next_branch) { if (b->pack_id == pack_id) - fprintf(pack_edges, " %s", sha1_to_hex(b->sha1)); + fprintf(pack_edges, " %s", + oid_to_hex(&b->oid)); } } for (t = first_tag; t; t = t->next_tag) { if (t->pack_id == pack_id) - fprintf(pack_edges, " %s", sha1_to_hex(t->sha1)); + fprintf(pack_edges, " %s", + oid_to_hex(&t->oid)); } fputc('\n', pack_edges); fflush(pack_edges); @@ -1001,11 +1061,11 @@ static void end_packfile(void) pack_id++; } else { +discard_pack: close(pack_data->pack_fd); unlink_or_warn(pack_data->pack_name); } - free(pack_data); - pack_data = NULL; + FREE_AND_NULL(pack_data); running = 0; /* We can't carry a delta across packfiles. */ @@ -1024,33 +1084,33 @@ static int store_object( enum object_type type, struct strbuf *dat, struct last_object *last, - unsigned char *sha1out, + struct object_id *oidout, uintmax_t mark) { void *out, *delta; struct object_entry *e; unsigned char hdr[96]; - unsigned char sha1[20]; + struct object_id oid; unsigned long hdrlen, deltalen; git_SHA_CTX c; git_zstream s; - hdrlen = sprintf((char *)hdr,"%s %lu", typename(type), - (unsigned long)dat->len) + 1; + hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu", + typename(type), (unsigned long)dat->len) + 1; git_SHA1_Init(&c); git_SHA1_Update(&c, hdr, hdrlen); git_SHA1_Update(&c, dat->buf, dat->len); - git_SHA1_Final(sha1, &c); - if (sha1out) - hashcpy(sha1out, sha1); + git_SHA1_Final(oid.hash, &c); + if (oidout) + oidcpy(oidout, &oid); - e = insert_object(sha1); + e = insert_object(&oid); if (mark) insert_mark(mark, e); if (e->idx.offset) { duplicate_count_by_type[type]++; return 1; - } else if (find_sha1_pack(sha1, packed_git)) { + } else if (find_sha1_pack(oid.hash, packed_git)) { e->type = type; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1090,8 +1150,7 @@ static int store_object( /* We cannot carry a delta into the new pack. */ if (delta) { - free(delta); - delta = NULL; + FREE_AND_NULL(delta); git_deflate_init(&s, pack_compression_level); s.next_in = (void *)dat->buf; @@ -1119,7 +1178,8 @@ static int store_object( delta_count_by_type[type]++; e->depth = last->depth + 1; - hdrlen = encode_in_pack_object_header(OBJ_OFS_DELTA, deltalen, hdr); + hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr), + OBJ_OFS_DELTA, deltalen); sha1write(pack_file, hdr, hdrlen); pack_size += hdrlen; @@ -1130,7 +1190,8 @@ static int store_object( pack_size += sizeof(hdr) - pos; } else { e->depth = 0; - hdrlen = encode_in_pack_object_header(type, dat->len, hdr); + hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr), + type, dat->len); sha1write(pack_file, hdr, hdrlen); pack_size += hdrlen; } @@ -1161,13 +1222,13 @@ static void truncate_pack(struct sha1file_checkpoint *checkpoint) pack_size = checkpoint->offset; } -static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) +static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) { size_t in_sz = 64 * 1024, out_sz = 64 * 1024; unsigned char *in_buf = xmalloc(in_sz); unsigned char *out_buf = xmalloc(out_sz); struct object_entry *e; - unsigned char sha1[20]; + struct object_id oid; unsigned long hdrlen; off_t offset; git_SHA_CTX c; @@ -1183,9 +1244,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) sha1file_checkpoint(pack_file, &checkpoint); offset = checkpoint.offset; - hdrlen = snprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1; - if (out_sz <= hdrlen) - die("impossibly large object header"); + hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1; git_SHA1_Init(&c); git_SHA1_Update(&c, out_buf, hdrlen); @@ -1194,9 +1253,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) git_deflate_init(&s, pack_compression_level); - hdrlen = encode_in_pack_object_header(OBJ_BLOB, len, out_buf); - if (out_sz <= hdrlen) - die("impossibly large object header"); + hdrlen = encode_in_pack_object_header(out_buf, out_sz, OBJ_BLOB, len); s.next_out = out_buf + hdrlen; s.avail_out = out_sz - hdrlen; @@ -1234,12 +1291,12 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) } } git_deflate_end(&s); - git_SHA1_Final(sha1, &c); + git_SHA1_Final(oid.hash, &c); - if (sha1out) - hashcpy(sha1out, sha1); + if (oidout) + oidcpy(oidout, &oid); - e = insert_object(sha1); + e = insert_object(&oid); if (mark) insert_mark(mark, e); @@ -1248,7 +1305,7 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark) duplicate_count_by_type[OBJ_BLOB]++; truncate_pack(&checkpoint); - } else if (find_sha1_pack(sha1, packed_git)) { + } else if (find_sha1_pack(oid.hash, packed_git)) { e->type = OBJ_BLOB; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1332,7 +1389,7 @@ static const char *get_mode(const char *str, uint16_t *modep) static void load_tree(struct tree_entry *root) { - unsigned char *sha1 = root->versions[1].sha1; + struct object_id *oid = &root->versions[1].oid; struct object_entry *myoe; struct tree_content *t; unsigned long size; @@ -1340,22 +1397,22 @@ static void load_tree(struct tree_entry *root) const char *c; root->tree = t = new_tree_content(8); - if (is_null_sha1(sha1)) + if (is_null_oid(oid)) return; - myoe = find_object(sha1); + myoe = find_object(oid); if (myoe && myoe->pack_id != MAX_PACK_ID) { if (myoe->type != OBJ_TREE) - die("Not a tree: %s", sha1_to_hex(sha1)); + die("Not a tree: %s", oid_to_hex(oid)); t->delta_depth = myoe->depth; buf = gfi_unpack_entry(myoe, &size); if (!buf) - die("Can't load tree %s", sha1_to_hex(sha1)); + die("Can't load tree %s", oid_to_hex(oid)); } else { enum object_type type; - buf = read_sha1_file(sha1, &type, &size); + buf = read_sha1_file(oid->hash, &type, &size); if (!buf || type != OBJ_TREE) - die("Can't load tree %s", sha1_to_hex(sha1)); + die("Can't load tree %s", oid_to_hex(oid)); } c = buf; @@ -1369,13 +1426,13 @@ static void load_tree(struct tree_entry *root) e->tree = NULL; c = get_mode(c, &e->versions[1].mode); if (!c) - die("Corrupt mode in %s", sha1_to_hex(sha1)); + die("Corrupt mode in %s", oid_to_hex(oid)); e->versions[0].mode = e->versions[1].mode; e->name = to_atom(c, strlen(c)); c += e->name->str_len + 1; - hashcpy(e->versions[0].sha1, (unsigned char *)c); - hashcpy(e->versions[1].sha1, (unsigned char *)c); - c += 20; + hashcpy(e->versions[0].oid.hash, (unsigned char *)c); + hashcpy(e->versions[1].oid.hash, (unsigned char *)c); + c += GIT_SHA1_RAWSZ; } free(buf); } @@ -1404,9 +1461,9 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b) unsigned int i; if (!v) - qsort(t->entries,t->entry_count,sizeof(t->entries[0]),tecmp0); + QSORT(t->entries, t->entry_count, tecmp0); else - qsort(t->entries,t->entry_count,sizeof(t->entries[0]),tecmp1); + QSORT(t->entries, t->entry_count, tecmp1); for (i = 0; i < t->entry_count; i++) { if (t->entries[i]->versions[v].mode) @@ -1422,7 +1479,7 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b) strbuf_addf(b, "%o %s%c", (unsigned int)(e->versions[v].mode & ~NO_DELTA), e->name->str_dat, '\0'); - strbuf_add(b, e->versions[v].sha1, 20); + strbuf_add(b, e->versions[v].oid.hash, GIT_SHA1_RAWSZ); } } @@ -1433,7 +1490,7 @@ static void store_tree(struct tree_entry *root) struct last_object lo = { STRBUF_INIT, 0, 0, /* no_swap */ 1 }; struct object_entry *le = NULL; - if (!is_null_sha1(root->versions[1].sha1)) + if (!is_null_oid(&root->versions[1].oid)) return; if (!root->tree) @@ -1446,7 +1503,7 @@ static void store_tree(struct tree_entry *root) } if (!(root->versions[0].mode & NO_DELTA)) - le = find_object(root->versions[0].sha1); + le = find_object(&root->versions[0].oid); if (S_ISDIR(root->versions[0].mode) && le && le->pack_id == pack_id) { mktree(t, 0, &old_tree); lo.data = old_tree; @@ -1455,14 +1512,14 @@ static void store_tree(struct tree_entry *root) } mktree(t, 1, &new_tree); - store_object(OBJ_TREE, &new_tree, &lo, root->versions[1].sha1, 0); + store_object(OBJ_TREE, &new_tree, &lo, &root->versions[1].oid, 0); t->delta_depth = lo.depth; for (i = 0, j = 0, del = 0; i < t->entry_count; i++) { struct tree_entry *e = t->entries[i]; if (e->versions[1].mode) { e->versions[0].mode = e->versions[1].mode; - hashcpy(e->versions[0].sha1, e->versions[1].sha1); + oidcpy(&e->versions[0].oid, &e->versions[1].oid); t->entries[j++] = e; } else { release_tree_entry(e); @@ -1474,14 +1531,14 @@ static void store_tree(struct tree_entry *root) static void tree_content_replace( struct tree_entry *root, - const unsigned char *sha1, + const struct object_id *oid, const uint16_t mode, struct tree_content *newtree) { if (!S_ISDIR(mode)) die("Root cannot be a non-directory"); - hashclr(root->versions[0].sha1); - hashcpy(root->versions[1].sha1, sha1); + oidclr(&root->versions[0].oid); + oidcpy(&root->versions[1].oid, oid); if (root->tree) release_tree_content_recursive(root->tree); root->tree = newtree; @@ -1490,7 +1547,7 @@ static void tree_content_replace( static int tree_content_set( struct tree_entry *root, const char *p, - const unsigned char *sha1, + const struct object_id *oid, const uint16_t mode, struct tree_content *subtree) { @@ -1511,14 +1568,14 @@ static int tree_content_set( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) { if (!S_ISDIR(mode) && e->versions[1].mode == mode - && !hashcmp(e->versions[1].sha1, sha1)) + && !oidcmp(&e->versions[1].oid, oid)) return 0; e->versions[1].mode = mode; - hashcpy(e->versions[1].sha1, sha1); + oidcpy(&e->versions[1].oid, oid); if (e->tree) release_tree_content_recursive(e->tree); e->tree = subtree; @@ -1539,7 +1596,7 @@ static int tree_content_set( if (S_ISDIR(e->versions[0].mode)) e->versions[0].mode |= NO_DELTA; - hashclr(root->versions[1].sha1); + oidclr(&root->versions[1].oid); return 1; } if (!S_ISDIR(e->versions[1].mode)) { @@ -1548,8 +1605,8 @@ static int tree_content_set( } if (!e->tree) load_tree(e); - if (tree_content_set(e, slash1 + 1, sha1, mode, subtree)) { - hashclr(root->versions[1].sha1); + if (tree_content_set(e, slash1 + 1, oid, mode, subtree)) { + oidclr(&root->versions[1].oid); return 1; } return 0; @@ -1561,18 +1618,18 @@ static int tree_content_set( e = new_tree_entry(); e->name = to_atom(p, n); e->versions[0].mode = 0; - hashclr(e->versions[0].sha1); + oidclr(&e->versions[0].oid); t->entries[t->entry_count++] = e; if (*slash1) { e->tree = new_tree_content(8); e->versions[1].mode = S_IFDIR; - tree_content_set(e, slash1 + 1, sha1, mode, subtree); + tree_content_set(e, slash1 + 1, oid, mode, subtree); } else { e->tree = subtree; e->versions[1].mode = mode; - hashcpy(e->versions[1].sha1, sha1); + oidcpy(&e->versions[1].oid, oid); } - hashclr(root->versions[1].sha1); + oidclr(&root->versions[1].oid); return 1; } @@ -1601,7 +1658,7 @@ static int tree_content_remove( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (*slash1 && !S_ISDIR(e->versions[1].mode)) /* * If p names a file in some subdirectory, and a @@ -1617,7 +1674,7 @@ static int tree_content_remove( if (tree_content_remove(e, slash1 + 1, backup_leaf, 0)) { for (n = 0; n < e->tree->entry_count; n++) { if (e->tree->entries[n]->versions[1].mode) { - hashclr(root->versions[1].sha1); + oidclr(&root->versions[1].oid); return 1; } } @@ -1636,8 +1693,8 @@ del_entry: release_tree_content_recursive(e->tree); e->tree = NULL; e->versions[1].mode = 0; - hashclr(e->versions[1].sha1); - hashclr(root->versions[1].sha1); + oidclr(&e->versions[1].oid); + oidclr(&root->versions[1].oid); return 1; } @@ -1668,7 +1725,7 @@ static int tree_content_get( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) goto found_entry; if (!S_ISDIR(e->versions[1].mode)) @@ -1682,7 +1739,7 @@ static int tree_content_get( found_entry: memcpy(leaf, e, sizeof(*leaf)); - if (e->tree && is_null_sha1(e->versions[1].sha1)) + if (e->tree && is_null_oid(&e->versions[1].oid)) leaf->tree = dup_tree_content(e->tree); else leaf->tree = NULL; @@ -1693,34 +1750,35 @@ static int update_branch(struct branch *b) { static const char *msg = "fast-import"; struct ref_transaction *transaction; - unsigned char old_sha1[20]; + struct object_id old_oid; struct strbuf err = STRBUF_INIT; - if (is_null_sha1(b->sha1)) { + if (is_null_oid(&b->oid)) { if (b->delete) - delete_ref(b->name, NULL, 0); + delete_ref(NULL, b->name, NULL, 0); return 0; } - if (read_ref(b->name, old_sha1)) - hashclr(old_sha1); - if (!force_update && !is_null_sha1(old_sha1)) { + if (read_ref(b->name, old_oid.hash)) + oidclr(&old_oid); + if (!force_update && !is_null_oid(&old_oid)) { struct commit *old_cmit, *new_cmit; - old_cmit = lookup_commit_reference_gently(old_sha1, 0); - new_cmit = lookup_commit_reference_gently(b->sha1, 0); + old_cmit = lookup_commit_reference_gently(&old_oid, 0); + new_cmit = lookup_commit_reference_gently(&b->oid, 0); if (!old_cmit || !new_cmit) return error("Branch %s is missing commits.", b->name); if (!in_merge_bases(old_cmit, new_cmit)) { warning("Not updating %s" " (new tip %s does not contain %s)", - b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1)); + b->name, oid_to_hex(&b->oid), + oid_to_hex(&old_oid)); return -1; } } transaction = ref_transaction_begin(&err); if (!transaction || - ref_transaction_update(transaction, b->name, b->sha1, old_sha1, + ref_transaction_update(transaction, b->name, b->oid.hash, old_oid.hash, 0, msg, &err) || ref_transaction_commit(transaction, &err)) { ref_transaction_free(transaction); @@ -1762,7 +1820,7 @@ static void dump_tags(void) strbuf_addf(&ref_name, "refs/tags/%s", t->name); if (ref_transaction_update(transaction, ref_name.buf, - t->sha1, NULL, 0, msg, &err)) { + t->oid.hash, NULL, 0, msg, &err)) { failure |= error("%s", err.buf); goto cleanup; } @@ -1791,7 +1849,7 @@ static void dump_marks_helper(FILE *f, for (k = 0; k < 1024; k++) { if (m->data.marked[k]) fprintf(f, ":%" PRIuMAX " %s\n", base + k, - sha1_to_hex(m->data.marked[k]->idx.sha1)); + oid_to_hex(&m->data.marked[k]->idx.oid)); } } } @@ -1801,12 +1859,12 @@ static void dump_marks(void) static struct lock_file mark_lock; FILE *f; - if (!export_marks_file) + if (!export_marks_file || (import_marks_file && !import_marks_file_done)) return; if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) { - failure |= error("Unable to write marks file %s: %s", - export_marks_file, strerror(errno)); + failure |= error_errno("Unable to write marks file %s", + export_marks_file); return; } @@ -1821,8 +1879,8 @@ static void dump_marks(void) dump_marks_helper(f, 0, marks); if (commit_lock_file(&mark_lock)) { - failure |= error("Unable to write file %s: %s", - export_marks_file, strerror(errno)); + failure |= error_errno("Unable to write file %s", + export_marks_file); return; } } @@ -1834,13 +1892,13 @@ static void read_marks(void) if (f) ; else if (import_marks_file_ignore_missing && errno == ENOENT) - return; /* Marks file does not exist */ + goto done; /* Marks file does not exist */ else die_errno("cannot read '%s'", import_marks_file); while (fgets(line, sizeof(line), f)) { uintmax_t mark; char *end; - unsigned char sha1[20]; + struct object_id oid; struct object_entry *e; end = strchr(line, '\n'); @@ -1849,14 +1907,14 @@ static void read_marks(void) *end = 0; mark = strtoumax(line + 1, &end, 10); if (!mark || end == line + 1 - || *end != ' ' || get_sha1_hex(end + 1, sha1)) + || *end != ' ' || get_oid_hex(end + 1, &oid)) die("corrupt mark line: %s", line); - e = find_object(sha1); + e = find_object(&oid); if (!e) { - enum object_type type = sha1_object_info(sha1, NULL); + enum object_type type = sha1_object_info(oid.hash, NULL); if (type < 0) - die("object not found: %s", sha1_to_hex(sha1)); - e = insert_object(sha1); + die("object not found: %s", oid_to_hex(&oid)); + e = insert_object(&oid); e->type = type; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1864,6 +1922,8 @@ static void read_marks(void) insert_mark(mark, e); } fclose(f); +done: + import_marks_file_done = 1; } @@ -1885,7 +1945,7 @@ static int read_next_command(void) struct recent_command *rc; strbuf_detach(&command_buf, NULL); - stdin_eof = strbuf_getline(&command_buf, stdin, '\n'); + stdin_eof = strbuf_getline_lf(&command_buf, stdin); if (stdin_eof) return EOF; @@ -1957,7 +2017,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res) strbuf_detach(&command_buf, NULL); for (;;) { - if (strbuf_getline(&command_buf, stdin, '\n') == EOF) + if (strbuf_getline_lf(&command_buf, stdin) == EOF) die("EOF in data (terminator '%s' not found)", term); if (term_len == command_buf.len && !strcmp(term, command_buf.buf)) @@ -2062,21 +2122,21 @@ static char *parse_ident(const char *buf) static void parse_and_store_blob( struct last_object *last, - unsigned char *sha1out, + struct object_id *oidout, uintmax_t mark) { static struct strbuf buf = STRBUF_INIT; uintmax_t len; if (parse_data(&buf, big_file_threshold, &len)) - store_object(OBJ_BLOB, &buf, last, sha1out, mark); + store_object(OBJ_BLOB, &buf, last, oidout, mark); else { if (last) { strbuf_release(&last->data); last->offset = 0; last->depth = 0; } - stream_blob(len, sha1out, mark); + stream_blob(len, oidout, mark); skip_optional_lf(); } } @@ -2152,26 +2212,30 @@ static void construct_path_with_fanout(const char *hex_sha1, path[i++] = '/'; fanout--; } - memcpy(path + i, hex_sha1 + j, 40 - j); - path[i + 40 - j] = '\0'; + memcpy(path + i, hex_sha1 + j, GIT_SHA1_HEXSZ - j); + path[i + GIT_SHA1_HEXSZ - j] = '\0'; } static uintmax_t do_change_note_fanout( struct tree_entry *orig_root, struct tree_entry *root, - char *hex_sha1, unsigned int hex_sha1_len, + char *hex_oid, unsigned int hex_oid_len, char *fullpath, unsigned int fullpath_len, unsigned char fanout) { - struct tree_content *t = root->tree; + struct tree_content *t; struct tree_entry *e, leaf; - unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len; + unsigned int i, tmp_hex_oid_len, tmp_fullpath_len; uintmax_t num_notes = 0; - unsigned char sha1[20]; + struct object_id oid; char realpath[60]; + if (!root->tree) + load_tree(root); + t = root->tree; + for (i = 0; t && i < t->entry_count; i++) { e = t->entries[i]; - tmp_hex_sha1_len = hex_sha1_len + e->name->str_len; + tmp_hex_oid_len = hex_oid_len + e->name->str_len; tmp_fullpath_len = fullpath_len; /* @@ -2183,12 +2247,12 @@ static uintmax_t do_change_note_fanout( * of 2 chars. */ if (!e->versions[1].mode || - tmp_hex_sha1_len > 40 || + tmp_hex_oid_len > GIT_SHA1_HEXSZ || e->name->str_len % 2) continue; /* This _may_ be a note entry, or a subdir containing notes */ - memcpy(hex_sha1 + hex_sha1_len, e->name->str_dat, + memcpy(hex_oid + hex_oid_len, e->name->str_dat, e->name->str_len); if (tmp_fullpath_len) fullpath[tmp_fullpath_len++] = '/'; @@ -2197,14 +2261,14 @@ static uintmax_t do_change_note_fanout( tmp_fullpath_len += e->name->str_len; fullpath[tmp_fullpath_len] = '\0'; - if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) { + if (tmp_hex_oid_len == GIT_SHA1_HEXSZ && !get_oid_hex(hex_oid, &oid)) { /* This is a note entry */ if (fanout == 0xff) { /* Counting mode, no rename */ num_notes++; continue; } - construct_path_with_fanout(hex_sha1, fanout, realpath); + construct_path_with_fanout(hex_oid, fanout, realpath); if (!strcmp(fullpath, realpath)) { /* Note entry is in correct location */ num_notes++; @@ -2215,15 +2279,13 @@ static uintmax_t do_change_note_fanout( if (!tree_content_remove(orig_root, fullpath, &leaf, 0)) die("Failed to remove path %s", fullpath); tree_content_set(orig_root, realpath, - leaf.versions[1].sha1, + &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); } else if (S_ISDIR(e->versions[1].mode)) { /* This is a subdir that may contain note entries */ - if (!e->tree) - load_tree(e); num_notes += do_change_note_fanout(orig_root, e, - hex_sha1, tmp_hex_sha1_len, + hex_oid, tmp_hex_oid_len, fullpath, tmp_fullpath_len, fanout); } @@ -2236,8 +2298,14 @@ static uintmax_t do_change_note_fanout( static uintmax_t change_note_fanout(struct tree_entry *root, unsigned char fanout) { - char hex_sha1[40], path[60]; - return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout); + /* + * The size of path is due to one slash between every two hex digits, + * plus the terminating NUL. Note that there is no slash at the end, so + * the number of slashes is one less than half the number of hex + * characters. + */ + char hex_oid[GIT_MAX_HEXSZ], path[GIT_MAX_HEXSZ + (GIT_MAX_HEXSZ / 2) - 1 + 1]; + return do_change_note_fanout(root, root, hex_oid, 0, path, 0, fanout); } /* @@ -2298,7 +2366,7 @@ static void file_change_m(const char *p, struct branch *b) static struct strbuf uq = STRBUF_INIT; const char *endp; struct object_entry *oe; - unsigned char sha1[20]; + struct object_id oid; uint16_t mode, inline_data = 0; p = get_mode(p, &mode); @@ -2321,15 +2389,14 @@ static void file_change_m(const char *p, struct branch *b) if (*p == ':') { oe = find_mark(parse_mark_ref_space(&p)); - hashcpy(sha1, oe->idx.sha1); + oidcpy(&oid, &oe->idx.oid); } else if (skip_prefix(p, "inline ", &p)) { inline_data = 1; oe = NULL; /* not used with inline_data, but makes gcc happy */ } else { - if (get_sha1_hex(p, sha1)) + if (parse_oid_hex(p, &oid, &p)) die("Invalid dataref: %s", command_buf.buf); - oe = find_object(sha1); - p += 40; + oe = find_object(&oid); if (*p++ != ' ') die("Missing space after SHA1: %s", command_buf.buf); } @@ -2342,7 +2409,7 @@ static void file_change_m(const char *p, struct branch *b) } /* Git does not track empty, non-toplevel directories. */ - if (S_ISDIR(mode) && !hashcmp(sha1, EMPTY_TREE_SHA1_BIN) && *p) { + if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *p) { tree_content_remove(&b->branch_tree, p, NULL, 0); return; } @@ -2369,12 +2436,12 @@ static void file_change_m(const char *p, struct branch *b) p = uq.buf; } read_next_command(); - parse_and_store_blob(&last_blob, sha1, 0); + parse_and_store_blob(&last_blob, &oid, 0); } else { enum object_type expected = S_ISDIR(mode) ? OBJ_TREE: OBJ_BLOB; enum object_type type = oe ? oe->type : - sha1_object_info(sha1, NULL); + sha1_object_info(oid.hash, NULL); if (type < 0) die("%s not found: %s", S_ISDIR(mode) ? "Tree" : "Blob", @@ -2386,10 +2453,10 @@ static void file_change_m(const char *p, struct branch *b) } if (!*p) { - tree_content_replace(&b->branch_tree, sha1, mode, NULL); + tree_content_replace(&b->branch_tree, &oid, mode, NULL); return; } - tree_content_set(&b->branch_tree, p, sha1, mode, NULL); + tree_content_set(&b->branch_tree, p, &oid, mode, NULL); } static void file_change_d(const char *p, struct branch *b) @@ -2447,13 +2514,13 @@ static void file_change_cr(const char *s, struct branch *b, int rename) die("Path %s not in branch", s); if (!*d) { /* C "path/to/subdir" "" */ tree_content_replace(&b->branch_tree, - leaf.versions[1].sha1, + &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); return; } tree_content_set(&b->branch_tree, d, - leaf.versions[1].sha1, + &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); } @@ -2463,7 +2530,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa static struct strbuf uq = STRBUF_INIT; struct object_entry *oe; struct branch *s; - unsigned char sha1[20], commit_sha1[20]; + struct object_id oid, commit_oid; char path[60]; uint16_t inline_data = 0; unsigned char new_fanout; @@ -2488,15 +2555,14 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa /* or 'inline' */ if (*p == ':') { oe = find_mark(parse_mark_ref_space(&p)); - hashcpy(sha1, oe->idx.sha1); + oidcpy(&oid, &oe->idx.oid); } else if (skip_prefix(p, "inline ", &p)) { inline_data = 1; oe = NULL; /* not used with inline_data, but makes gcc happy */ } else { - if (get_sha1_hex(p, sha1)) + if (parse_oid_hex(p, &oid, &p)) die("Invalid dataref: %s", command_buf.buf); - oe = find_object(sha1); - p += 40; + oe = find_object(&oid); if (*p++ != ' ') die("Missing space after SHA1: %s", command_buf.buf); } @@ -2504,19 +2570,19 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa /* */ s = lookup_branch(p); if (s) { - if (is_null_sha1(s->sha1)) + if (is_null_oid(&s->oid)) die("Can't add a note on empty branch."); - hashcpy(commit_sha1, s->sha1); + oidcpy(&commit_oid, &s->oid); } else if (*p == ':') { uintmax_t commit_mark = parse_mark_ref_eol(p); struct object_entry *commit_oe = find_mark(commit_mark); if (commit_oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", commit_mark); - hashcpy(commit_sha1, commit_oe->idx.sha1); - } else if (!get_sha1(p, commit_sha1)) { + oidcpy(&commit_oid, &commit_oe->idx.oid); + } else if (!get_oid(p, &commit_oid)) { unsigned long size; - char *buf = read_object_with_reference(commit_sha1, - commit_type, &size, commit_sha1); + char *buf = read_object_with_reference(commit_oid.hash, + commit_type, &size, commit_oid.hash); if (!buf || size < 46) die("Not a valid commit: %s", p); free(buf); @@ -2529,13 +2595,13 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa p = uq.buf; } read_next_command(); - parse_and_store_blob(&last_blob, sha1, 0); + parse_and_store_blob(&last_blob, &oid, 0); } else if (oe) { if (oe->type != OBJ_BLOB) die("Not a blob (actually a %s): %s", typename(oe->type), command_buf.buf); - } else if (!is_null_sha1(sha1)) { - enum object_type type = sha1_object_info(sha1, NULL); + } else if (!is_null_oid(&oid)) { + enum object_type type = sha1_object_info(oid.hash, NULL); if (type < 0) die("Blob not found: %s", command_buf.buf); if (type != OBJ_BLOB) @@ -2543,50 +2609,51 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa typename(type), command_buf.buf); } - construct_path_with_fanout(sha1_to_hex(commit_sha1), *old_fanout, path); + construct_path_with_fanout(oid_to_hex(&commit_oid), *old_fanout, path); if (tree_content_remove(&b->branch_tree, path, NULL, 0)) b->num_notes--; - if (is_null_sha1(sha1)) + if (is_null_oid(&oid)) return; /* nothing to insert */ b->num_notes++; new_fanout = convert_num_notes_to_fanout(b->num_notes); - construct_path_with_fanout(sha1_to_hex(commit_sha1), new_fanout, path); - tree_content_set(&b->branch_tree, path, sha1, S_IFREG | 0644, NULL); + construct_path_with_fanout(oid_to_hex(&commit_oid), new_fanout, path); + tree_content_set(&b->branch_tree, path, &oid, S_IFREG | 0644, NULL); } static void file_change_deleteall(struct branch *b) { release_tree_content_recursive(b->branch_tree.tree); - hashclr(b->branch_tree.versions[0].sha1); - hashclr(b->branch_tree.versions[1].sha1); + oidclr(&b->branch_tree.versions[0].oid); + oidclr(&b->branch_tree.versions[1].oid); load_tree(&b->branch_tree); b->num_notes = 0; } static void parse_from_commit(struct branch *b, char *buf, unsigned long size) { - if (!buf || size < 46) - die("Not a valid commit: %s", sha1_to_hex(b->sha1)); + if (!buf || size < GIT_SHA1_HEXSZ + 6) + die("Not a valid commit: %s", oid_to_hex(&b->oid)); if (memcmp("tree ", buf, 5) - || get_sha1_hex(buf + 5, b->branch_tree.versions[1].sha1)) - die("The commit %s is corrupt", sha1_to_hex(b->sha1)); - hashcpy(b->branch_tree.versions[0].sha1, - b->branch_tree.versions[1].sha1); + || get_oid_hex(buf + 5, &b->branch_tree.versions[1].oid)) + die("The commit %s is corrupt", oid_to_hex(&b->oid)); + oidcpy(&b->branch_tree.versions[0].oid, + &b->branch_tree.versions[1].oid); } static void parse_from_existing(struct branch *b) { - if (is_null_sha1(b->sha1)) { - hashclr(b->branch_tree.versions[0].sha1); - hashclr(b->branch_tree.versions[1].sha1); + if (is_null_oid(&b->oid)) { + oidclr(&b->branch_tree.versions[0].oid); + oidclr(&b->branch_tree.versions[1].oid); } else { unsigned long size; char *buf; - buf = read_object_with_reference(b->sha1, - commit_type, &size, b->sha1); + buf = read_object_with_reference(b->oid.hash, + commit_type, &size, + b->oid.hash); parse_from_commit(b, buf, size); free(buf); } @@ -2596,28 +2663,28 @@ static int parse_from(struct branch *b) { const char *from; struct branch *s; - unsigned char sha1[20]; + struct object_id oid; if (!skip_prefix(command_buf.buf, "from ", &from)) return 0; - hashcpy(sha1, b->branch_tree.versions[1].sha1); + oidcpy(&oid, &b->branch_tree.versions[1].oid); s = lookup_branch(from); if (b == s) die("Can't create a branch from itself: %s", b->name); else if (s) { - unsigned char *t = s->branch_tree.versions[1].sha1; - hashcpy(b->sha1, s->sha1); - hashcpy(b->branch_tree.versions[0].sha1, t); - hashcpy(b->branch_tree.versions[1].sha1, t); + struct object_id *t = &s->branch_tree.versions[1].oid; + oidcpy(&b->oid, &s->oid); + oidcpy(&b->branch_tree.versions[0].oid, t); + oidcpy(&b->branch_tree.versions[1].oid, t); } else if (*from == ':') { uintmax_t idnum = parse_mark_ref_eol(from); struct object_entry *oe = find_mark(idnum); if (oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", idnum); - if (hashcmp(b->sha1, oe->idx.sha1)) { - hashcpy(b->sha1, oe->idx.sha1); + if (oidcmp(&b->oid, &oe->idx.oid)) { + oidcpy(&b->oid, &oe->idx.oid); if (oe->pack_id != MAX_PACK_ID) { unsigned long size; char *buf = gfi_unpack_entry(oe, &size); @@ -2626,15 +2693,15 @@ static int parse_from(struct branch *b) } else parse_from_existing(b); } - } else if (!get_sha1(from, b->sha1)) { + } else if (!get_oid(from, &b->oid)) { parse_from_existing(b); - if (is_null_sha1(b->sha1)) + if (is_null_oid(&b->oid)) b->delete = 1; } else die("Invalid ref name or SHA1 expression: %s", from); - if (b->branch_tree.tree && hashcmp(sha1, b->branch_tree.versions[1].sha1)) { + if (b->branch_tree.tree && oidcmp(&oid, &b->branch_tree.versions[1].oid)) { release_tree_content_recursive(b->branch_tree.tree); b->branch_tree.tree = NULL; } @@ -2654,17 +2721,17 @@ static struct hash_list *parse_merge(unsigned int *count) n = xmalloc(sizeof(*n)); s = lookup_branch(from); if (s) - hashcpy(n->sha1, s->sha1); + oidcpy(&n->oid, &s->oid); else if (*from == ':') { uintmax_t idnum = parse_mark_ref_eol(from); struct object_entry *oe = find_mark(idnum); if (oe->type != OBJ_COMMIT) die("Mark :%" PRIuMAX " not a commit", idnum); - hashcpy(n->sha1, oe->idx.sha1); - } else if (!get_sha1(from, n->sha1)) { + oidcpy(&n->oid, &oe->idx.oid); + } else if (!get_oid(from, &n->oid)) { unsigned long size; - char *buf = read_object_with_reference(n->sha1, - commit_type, &size, n->sha1); + char *buf = read_object_with_reference(n->oid.hash, + commit_type, &size, n->oid.hash); if (!buf || size < 46) die("Not a valid commit: %s", from); free(buf); @@ -2751,17 +2818,19 @@ static void parse_new_commit(const char *arg) /* build the tree and the commit */ store_tree(&b->branch_tree); - hashcpy(b->branch_tree.versions[0].sha1, - b->branch_tree.versions[1].sha1); + oidcpy(&b->branch_tree.versions[0].oid, + &b->branch_tree.versions[1].oid); strbuf_reset(&new_data); strbuf_addf(&new_data, "tree %s\n", - sha1_to_hex(b->branch_tree.versions[1].sha1)); - if (!is_null_sha1(b->sha1)) - strbuf_addf(&new_data, "parent %s\n", sha1_to_hex(b->sha1)); + oid_to_hex(&b->branch_tree.versions[1].oid)); + if (!is_null_oid(&b->oid)) + strbuf_addf(&new_data, "parent %s\n", + oid_to_hex(&b->oid)); while (merge_list) { struct hash_list *next = merge_list->next; - strbuf_addf(&new_data, "parent %s\n", sha1_to_hex(merge_list->sha1)); + strbuf_addf(&new_data, "parent %s\n", + oid_to_hex(&merge_list->oid)); free(merge_list); merge_list = next; } @@ -2774,7 +2843,7 @@ static void parse_new_commit(const char *arg) free(author); free(committer); - if (!store_object(OBJ_COMMIT, &new_data, NULL, b->sha1, next_mark)) + if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark)) b->pack_id = pack_id; b->last_commit = object_count_by_type[OBJ_COMMIT]; } @@ -2787,7 +2856,7 @@ static void parse_new_tag(const char *arg) struct branch *s; struct tag *t; uintmax_t from_mark = 0; - unsigned char sha1[20]; + struct object_id oid; enum object_type type; const char *v; @@ -2806,20 +2875,20 @@ static void parse_new_tag(const char *arg) die("Expected from command, got %s", command_buf.buf); s = lookup_branch(from); if (s) { - if (is_null_sha1(s->sha1)) + if (is_null_oid(&s->oid)) die("Can't tag an empty branch."); - hashcpy(sha1, s->sha1); + oidcpy(&oid, &s->oid); type = OBJ_COMMIT; } else if (*from == ':') { struct object_entry *oe; from_mark = parse_mark_ref_eol(from); oe = find_mark(from_mark); type = oe->type; - hashcpy(sha1, oe->idx.sha1); - } else if (!get_sha1(from, sha1)) { - struct object_entry *oe = find_object(sha1); + oidcpy(&oid, &oe->idx.oid); + } else if (!get_oid(from, &oid)) { + struct object_entry *oe = find_object(&oid); if (!oe) { - type = sha1_object_info(sha1, NULL); + type = sha1_object_info(oid.hash, NULL); if (type < 0) die("Not a valid object: %s", from); } else @@ -2845,7 +2914,7 @@ static void parse_new_tag(const char *arg) "object %s\n" "type %s\n" "tag %s\n", - sha1_to_hex(sha1), typename(type), t->name); + oid_to_hex(&oid), typename(type), t->name); if (tagger) strbuf_addf(&new_data, "tagger %s\n", tagger); @@ -2853,7 +2922,7 @@ static void parse_new_tag(const char *arg) strbuf_addbuf(&new_data, &msg); free(tagger); - if (store_object(OBJ_TAG, &new_data, NULL, t->sha1, 0)) + if (store_object(OBJ_TAG, &new_data, NULL, &t->oid, 0)) t->pack_id = MAX_PACK_ID; else t->pack_id = pack_id; @@ -2865,9 +2934,9 @@ static void parse_reset_branch(const char *arg) b = lookup_branch(arg); if (b) { - hashclr(b->sha1); - hashclr(b->branch_tree.versions[0].sha1); - hashclr(b->branch_tree.versions[1].sha1); + oidclr(&b->oid); + oidclr(&b->branch_tree.versions[0].oid); + oidclr(&b->branch_tree.versions[1].oid); if (b->branch_tree.tree) { release_tree_content_recursive(b->branch_tree.tree); b->branch_tree.tree = NULL; @@ -2883,11 +2952,11 @@ static void parse_reset_branch(const char *arg) static void cat_blob_write(const char *buf, unsigned long size) { - if (write_in_full(cat_blob_fd, buf, size) != size) + if (write_in_full(cat_blob_fd, buf, size) < 0) die_errno("Write to frontend failed"); } -static void cat_blob(struct object_entry *oe, unsigned char sha1[20]) +static void cat_blob(struct object_entry *oe, struct object_id *oid) { struct strbuf line = STRBUF_INIT; unsigned long size; @@ -2895,7 +2964,7 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20]) char *buf; if (!oe || oe->pack_id == MAX_PACK_ID) { - buf = read_sha1_file(sha1, &type, &size); + buf = read_sha1_file(oid->hash, &type, &size); } else { type = oe->type; buf = gfi_unpack_entry(oe, &size); @@ -2906,19 +2975,19 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20]) */ if (type <= 0) { strbuf_reset(&line); - strbuf_addf(&line, "%s missing\n", sha1_to_hex(sha1)); + strbuf_addf(&line, "%s missing\n", oid_to_hex(oid)); cat_blob_write(line.buf, line.len); strbuf_release(&line); free(buf); return; } if (!buf) - die("Can't read object %s", sha1_to_hex(sha1)); + die("Can't read object %s", oid_to_hex(oid)); if (type != OBJ_BLOB) die("Object %s is a %s but a blob was expected.", - sha1_to_hex(sha1), typename(type)); + oid_to_hex(oid), typename(type)); strbuf_reset(&line); - strbuf_addf(&line, "%s %s %lu\n", sha1_to_hex(sha1), + strbuf_addf(&line, "%s %s %lu\n", oid_to_hex(oid), typename(type), size); cat_blob_write(line.buf, line.len); strbuf_release(&line); @@ -2935,7 +3004,7 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20]) static void parse_get_mark(const char *p) { struct object_entry *oe = oe; - char output[42]; + char output[GIT_MAX_HEXSZ + 2]; /* get-mark SP LF */ if (*p != ':') @@ -2945,43 +3014,43 @@ static void parse_get_mark(const char *p) if (!oe) die("Unknown mark: %s", command_buf.buf); - snprintf(output, sizeof(output), "%s\n", sha1_to_hex(oe->idx.sha1)); - cat_blob_write(output, 41); + xsnprintf(output, sizeof(output), "%s\n", oid_to_hex(&oe->idx.oid)); + cat_blob_write(output, GIT_SHA1_HEXSZ + 1); } static void parse_cat_blob(const char *p) { struct object_entry *oe = oe; - unsigned char sha1[20]; + struct object_id oid; /* cat-blob SP LF */ if (*p == ':') { oe = find_mark(parse_mark_ref_eol(p)); if (!oe) die("Unknown mark: %s", command_buf.buf); - hashcpy(sha1, oe->idx.sha1); + oidcpy(&oid, &oe->idx.oid); } else { - if (get_sha1_hex(p, sha1)) + if (parse_oid_hex(p, &oid, &p)) die("Invalid dataref: %s", command_buf.buf); - if (p[40]) + if (*p) die("Garbage after SHA1: %s", command_buf.buf); - oe = find_object(sha1); + oe = find_object(&oid); } - cat_blob(oe, sha1); + cat_blob(oe, &oid); } static struct object_entry *dereference(struct object_entry *oe, - unsigned char sha1[20]) + struct object_id *oid) { unsigned long size; char *buf = NULL; if (!oe) { - enum object_type type = sha1_object_info(sha1, NULL); + enum object_type type = sha1_object_info(oid->hash, NULL); if (type < 0) - die("object not found: %s", sha1_to_hex(sha1)); + die("object not found: %s", oid_to_hex(oid)); /* cache it! */ - oe = insert_object(sha1); + oe = insert_object(oid); oe->type = type; oe->pack_id = MAX_PACK_ID; oe->idx.offset = 1; @@ -3000,49 +3069,48 @@ static struct object_entry *dereference(struct object_entry *oe, buf = gfi_unpack_entry(oe, &size); } else { enum object_type unused; - buf = read_sha1_file(sha1, &unused, &size); + buf = read_sha1_file(oid->hash, &unused, &size); } if (!buf) - die("Can't load object %s", sha1_to_hex(sha1)); + die("Can't load object %s", oid_to_hex(oid)); /* Peel one layer. */ switch (oe->type) { case OBJ_TAG: - if (size < 40 + strlen("object ") || - get_sha1_hex(buf + strlen("object "), sha1)) + if (size < GIT_SHA1_HEXSZ + strlen("object ") || + get_oid_hex(buf + strlen("object "), oid)) die("Invalid SHA1 in tag: %s", command_buf.buf); break; case OBJ_COMMIT: - if (size < 40 + strlen("tree ") || - get_sha1_hex(buf + strlen("tree "), sha1)) + if (size < GIT_SHA1_HEXSZ + strlen("tree ") || + get_oid_hex(buf + strlen("tree "), oid)) die("Invalid SHA1 in commit: %s", command_buf.buf); } free(buf); - return find_object(sha1); + return find_object(oid); } static struct object_entry *parse_treeish_dataref(const char **p) { - unsigned char sha1[20]; + struct object_id oid; struct object_entry *e; if (**p == ':') { /* */ e = find_mark(parse_mark_ref_space(p)); if (!e) die("Unknown mark: %s", command_buf.buf); - hashcpy(sha1, e->idx.sha1); + oidcpy(&oid, &e->idx.oid); } else { /* */ - if (get_sha1_hex(*p, sha1)) + if (parse_oid_hex(*p, &oid, p)) die("Invalid dataref: %s", command_buf.buf); - e = find_object(sha1); - *p += 40; + e = find_object(&oid); if (*(*p)++ != ' ') die("Missing space after tree-ish: %s", command_buf.buf); } while (!e || e->type != OBJ_TREE) - e = dereference(e, sha1); + e = dereference(e, &oid); return e; } @@ -3086,8 +3154,8 @@ static void parse_ls(const char *p, struct branch *b) } else { struct object_entry *e = parse_treeish_dataref(&p); root = new_tree_entry(); - hashcpy(root->versions[1].sha1, e->idx.sha1); - if (!is_null_sha1(root->versions[1].sha1)) + oidcpy(&root->versions[1].oid, &e->idx.oid); + if (!is_null_oid(&root->versions[1].oid)) root->versions[1].mode = S_IFDIR; load_tree(root); } @@ -3109,7 +3177,7 @@ static void parse_ls(const char *p, struct branch *b) if (S_ISDIR(leaf.versions[1].mode)) store_tree(&leaf); - print_ls(leaf.versions[1].mode, leaf.versions[1].sha1, p); + print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, p); if (leaf.tree) release_tree_content_recursive(leaf.tree); if (!b || root != &b->branch_tree) @@ -3121,10 +3189,10 @@ static void checkpoint(void) checkpoint_requested = 0; if (object_count) { cycle_packfile(); - dump_branches(); - dump_tags(); - dump_marks(); } + dump_branches(); + dump_tags(); + dump_marks(); } static void parse_checkpoint(void) @@ -3145,7 +3213,7 @@ static char* make_fast_import_path(const char *path) { if (!relative_marks_paths || is_absolute_path(path)) return xstrdup(path); - return xstrdup(git_path("info/fast-import/%s", path)); + return git_pathdup("info/fast-import/%s", path); } static void option_import_marks(const char *marks, @@ -3217,9 +3285,7 @@ static void option_export_pack_edges(const char *edges) { if (pack_edges) fclose(pack_edges); - pack_edges = fopen(edges, "a"); - if (!pack_edges) - die_errno("Cannot open '%s'", edges); + pack_edges = xfopen(edges, "a"); } static int parse_one_option(const char *option) @@ -3316,21 +3382,13 @@ static void parse_option(const char *option) static void git_pack_config(void) { int indexversion_value; + int limit; unsigned long packsizelimit_value; if (!git_config_get_ulong("pack.depth", &max_depth)) { if (max_depth > MAX_DEPTH) max_depth = MAX_DEPTH; } - if (!git_config_get_int("pack.compression", &pack_compression_level)) { - if (pack_compression_level == -1) - pack_compression_level = Z_DEFAULT_COMPRESSION; - else if (pack_compression_level < 0 || - pack_compression_level > Z_BEST_COMPRESSION) - git_die_config("pack.compression", - "bad pack compression level %d", pack_compression_level); - pack_compression_seen = 1; - } if (!git_config_get_int("pack.indexversion", &indexversion_value)) { pack_idx_opts.version = indexversion_value; if (pack_idx_opts.version > 2) @@ -3340,6 +3398,11 @@ static void git_pack_config(void) if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value)) max_packsize = packsizelimit_value; + if (!git_config_get_int("fastimport.unpacklimit", &limit)) + unpack_limit = limit; + else if (!git_config_get_int("transfer.unpacklimit", &limit)) + unpack_limit = limit; + git_config(git_default_config, NULL); } @@ -3380,22 +3443,16 @@ static void parse_argv(void) read_marks(); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { unsigned int i; - git_extract_argv0_path(argv[0]); - - git_setup_gettext(); - if (argc == 2 && !strcmp(argv[1], "-h")) usage(fast_import_usage); setup_git_directory(); reset_pack_idx_option(&pack_idx_opts); git_pack_config(); - if (!pack_compression_seen && core_compression_seen) - pack_compression_level = core_compression_level; alloc_objects(object_entry_alloc); strbuf_init(&command_buf, 0);