Git fork

odb: introduce `odb_write_object()`

We do not have a backend-agnostic way to write objects into an object
database. While there is `write_object_file()`, this function is rather
specific to the loose object format.

Introduce `odb_write_object()` to plug this gap. For now, this function
is a simple wrapper around `write_object_file()` and doesn't even use
the passed-in object database yet. This will change in subsequent
commits, where `write_object_file()` is converted so that it works on
top of an `odb_source`. `odb_write_object()` will then become
responsible for deciding which source an object shall be written to.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
ab1c6e1d 0f9b1893

+106 -67
+7 -4
apply.c
··· 3621 3621 3622 3622 /* Preimage the patch was prepared for */ 3623 3623 if (patch->is_new) 3624 - write_object_file("", 0, OBJ_BLOB, &pre_oid); 3624 + odb_write_object(the_repository->objects, "", 0, OBJ_BLOB, &pre_oid); 3625 3625 else if (repo_get_oid(the_repository, patch->old_oid_prefix, &pre_oid) || 3626 3626 read_blob_object(&buf, &pre_oid, patch->old_mode)) 3627 3627 return error(_("repository lacks the necessary blob to perform 3-way merge.")); ··· 3637 3637 return -1; 3638 3638 } 3639 3639 /* post_oid is theirs */ 3640 - write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &post_oid); 3640 + odb_write_object(the_repository->objects, tmp_image.buf.buf, 3641 + tmp_image.buf.len, OBJ_BLOB, &post_oid); 3641 3642 image_clear(&tmp_image); 3642 3643 3643 3644 /* our_oid is ours */ ··· 3650 3651 return error(_("cannot read the current contents of '%s'"), 3651 3652 patch->old_name); 3652 3653 } 3653 - write_object_file(tmp_image.buf.buf, tmp_image.buf.len, OBJ_BLOB, &our_oid); 3654 + odb_write_object(the_repository->objects, tmp_image.buf.buf, 3655 + tmp_image.buf.len, OBJ_BLOB, &our_oid); 3654 3656 image_clear(&tmp_image); 3655 3657 3656 3658 /* in-core three-way merge between post and our using pre as base */ ··· 4360 4362 } 4361 4363 fill_stat_cache_info(state->repo->index, ce, &st); 4362 4364 } 4363 - if (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) { 4365 + if (odb_write_object(the_repository->objects, buf, size, 4366 + OBJ_BLOB, &ce->oid) < 0) { 4364 4367 discard_cache_entry(ce); 4365 4368 return error(_("unable to create backing store " 4366 4369 "for newly created file %s"), path);
+1 -1
builtin/checkout.c
··· 320 320 * (it also writes the merge result to the object database even 321 321 * when it may contain conflicts). 322 322 */ 323 - if (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid)) 323 + if (odb_write_object(the_repository->objects, result_buf.ptr, result_buf.size, OBJ_BLOB, &oid)) 324 324 die(_("Unable to add merge result for '%s'"), path); 325 325 free(result_buf.ptr); 326 326 ce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool);
+2 -1
builtin/merge-file.c
··· 155 155 if (object_id && !to_stdout) { 156 156 struct object_id oid; 157 157 if (result.size) { 158 - if (write_object_file(result.ptr, result.size, OBJ_BLOB, &oid) < 0) 158 + if (odb_write_object(the_repository->objects, result.ptr, 159 + result.size, OBJ_BLOB, &oid) < 0) 159 160 ret = error(_("Could not write object file")); 160 161 } else { 161 162 oidcpy(&oid, the_hash_algo->empty_blob);
+1 -1
builtin/mktag.c
··· 106 106 if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0) 107 107 die(_("tag on stdin did not refer to a valid object")); 108 108 109 - if (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0) 109 + if (odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TAG, &result) < 0) 110 110 die(_("unable to write tag file")); 111 111 112 112 strbuf_release(&buf);
+1 -1
builtin/mktree.c
··· 63 63 strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz); 64 64 } 65 65 66 - write_object_file(buf.buf, buf.len, OBJ_TREE, oid); 66 + odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TREE, oid); 67 67 strbuf_release(&buf); 68 68 } 69 69
+2 -1
builtin/notes.c
··· 229 229 230 230 static void write_note_data(struct note_data *d, struct object_id *oid) 231 231 { 232 - if (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) { 232 + if (odb_write_object(the_repository->objects, d->buf.buf, 233 + d->buf.len, OBJ_BLOB, oid)) { 233 234 int status = die_message(_("unable to write note object")); 234 235 235 236 if (d->edit_path)
+2 -2
builtin/receive-pack.c
··· 760 760 int bogs /* beginning_of_gpg_sig */; 761 761 762 762 already_done = 1; 763 - if (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB, 764 - &push_cert_oid)) 763 + if (odb_write_object(the_repository->objects, push_cert.buf, 764 + push_cert.len, OBJ_BLOB, &push_cert_oid)) 765 765 oidclr(&push_cert_oid, the_repository->hash_algo); 766 766 767 767 memset(&sigcheck, '\0', sizeof(sigcheck));
+2 -1
builtin/replace.c
··· 488 488 return -1; 489 489 } 490 490 491 - if (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) { 491 + if (odb_write_object(the_repository->objects, buf.buf, 492 + buf.len, OBJ_COMMIT, &new_oid)) { 492 493 strbuf_release(&buf); 493 494 return error(_("could not write replacement commit for: '%s'"), 494 495 old_ref);
+2 -2
builtin/tag.c
··· 271 271 struct object_id *compat_oid = NULL, compat_oid_buf; 272 272 if (sign && do_sign(buf, &compat_oid, &compat_oid_buf) < 0) 273 273 return error(_("unable to sign the tag")); 274 - if (write_object_file_flags(buf->buf, buf->len, OBJ_TAG, result, 275 - compat_oid, 0) < 0) 274 + if (odb_write_object_ext(the_repository->objects, buf->buf, 275 + buf->len, OBJ_TAG, result, compat_oid, 0) < 0) 276 276 return error(_("unable to write tag file")); 277 277 return 0; 278 278 }
+6 -6
builtin/unpack-objects.c
··· 204 204 { 205 205 struct object_id oid; 206 206 207 - if (write_object_file(obj_buf->buffer, obj_buf->size, 208 - obj->type, &oid) < 0) 207 + if (odb_write_object(the_repository->objects, obj_buf->buffer, obj_buf->size, 208 + obj->type, &oid) < 0) 209 209 die("failed to write object %s", oid_to_hex(&obj->oid)); 210 210 obj->flags |= FLAG_WRITTEN; 211 211 } ··· 272 272 void *buf, unsigned long size) 273 273 { 274 274 if (!strict) { 275 - if (write_object_file(buf, size, type, 276 - &obj_list[nr].oid) < 0) 275 + if (odb_write_object(the_repository->objects, buf, size, type, 276 + &obj_list[nr].oid) < 0) 277 277 die("failed to write object"); 278 278 added_object(nr, type, buf, size); 279 279 free(buf); 280 280 obj_list[nr].obj = NULL; 281 281 } else if (type == OBJ_BLOB) { 282 282 struct blob *blob; 283 - if (write_object_file(buf, size, type, 284 - &obj_list[nr].oid) < 0) 283 + if (odb_write_object(the_repository->objects, buf, size, type, 284 + &obj_list[nr].oid) < 0) 285 285 die("failed to write object"); 286 286 added_object(nr, type, buf, size); 287 287 free(buf);
+2 -3
cache-tree.c
··· 456 456 } else if (dryrun) { 457 457 hash_object_file(the_hash_algo, buffer.buf, buffer.len, 458 458 OBJ_TREE, &it->oid); 459 - } else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE, 460 - &it->oid, NULL, flags & WRITE_TREE_SILENT 461 - ? WRITE_OBJECT_FILE_SILENT : 0)) { 459 + } else if (odb_write_object_ext(the_repository->objects, buffer.buf, buffer.len, OBJ_TREE, 460 + &it->oid, NULL, flags & WRITE_TREE_SILENT ? WRITE_OBJECT_SILENT : 0)) { 462 461 strbuf_release(&buffer); 463 462 return -1; 464 463 }
+2 -2
commit.c
··· 1797 1797 compat_oid = &compat_oid_buf; 1798 1798 } 1799 1799 1800 - result = write_object_file_flags(buffer.buf, buffer.len, OBJ_COMMIT, 1801 - ret, compat_oid, 0); 1800 + result = odb_write_object_ext(the_repository->objects, buffer.buf, buffer.len, 1801 + OBJ_COMMIT, ret, compat_oid, 0); 1802 1802 out: 1803 1803 free(parent_buf); 1804 1804 strbuf_release(&buffer);
+1 -1
match-trees.c
··· 246 246 rewrite_with = oid2; 247 247 } 248 248 hashcpy(rewrite_here, rewrite_with->hash, r->hash_algo); 249 - status = write_object_file(buf, sz, OBJ_TREE, result); 249 + status = odb_write_object(r->objects, buf, sz, OBJ_TREE, result); 250 250 free(buf); 251 251 return status; 252 252 }
+4 -3
merge-ort.c
··· 2216 2216 } 2217 2217 2218 2218 if (!ret && record_object && 2219 - write_object_file(result_buf.ptr, result_buf.size, 2220 - OBJ_BLOB, &result->oid)) { 2219 + odb_write_object(the_repository->objects, result_buf.ptr, result_buf.size, 2220 + OBJ_BLOB, &result->oid)) { 2221 2221 path_msg(opt, ERROR_OBJECT_WRITE_FAILED, 0, 2222 2222 pathnames[0], pathnames[1], pathnames[2], NULL, 2223 2223 _("error: unable to add %s to database"), path); ··· 3772 3772 } 3773 3773 3774 3774 /* Write this object file out, and record in result_oid */ 3775 - if (write_object_file(buf.buf, buf.len, OBJ_TREE, result_oid)) 3775 + if (odb_write_object(the_repository->objects, buf.buf, 3776 + buf.len, OBJ_TREE, result_oid)) 3776 3777 ret = -1; 3777 3778 strbuf_release(&buf); 3778 3779 return ret;
+2 -1
notes-cache.c
··· 98 98 { 99 99 struct object_id value_oid; 100 100 101 - if (write_object_file(data, size, OBJ_BLOB, &value_oid) < 0) 101 + if (odb_write_object(the_repository->objects, data, 102 + size, OBJ_BLOB, &value_oid) < 0) 102 103 return -1; 103 104 return add_note(&c->tree, key_oid, &value_oid, NULL); 104 105 }
+8 -4
notes.c
··· 682 682 ret = tree_write_stack_finish_subtree(n); 683 683 if (ret) 684 684 return ret; 685 - ret = write_object_file(n->buf.buf, n->buf.len, OBJ_TREE, &s); 685 + ret = odb_write_object(the_repository->objects, n->buf.buf, 686 + n->buf.len, OBJ_TREE, &s); 686 687 if (ret) 687 688 return ret; 688 689 strbuf_release(&n->buf); ··· 847 848 free(new_msg); 848 849 849 850 /* create a new blob object from buf */ 850 - ret = write_object_file(buf, buf_len, OBJ_BLOB, cur_oid); 851 + ret = odb_write_object(the_repository->objects, buf, 852 + buf_len, OBJ_BLOB, cur_oid); 851 853 free(buf); 852 854 return ret; 853 855 } ··· 927 929 string_list_join_lines_helper, &buf)) 928 930 goto out; 929 931 930 - ret = write_object_file(buf.buf, buf.len, OBJ_BLOB, cur_oid); 932 + ret = odb_write_object(the_repository->objects, buf.buf, 933 + buf.len, OBJ_BLOB, cur_oid); 931 934 932 935 out: 933 936 strbuf_release(&buf); ··· 1215 1218 ret = for_each_note(t, flags, write_each_note, &cb_data) || 1216 1219 write_each_non_note_until(NULL, &cb_data) || 1217 1220 tree_write_stack_finish_subtree(&root) || 1218 - write_object_file(root.buf.buf, root.buf.len, OBJ_TREE, result); 1221 + odb_write_object(the_repository->objects, root.buf.buf, 1222 + root.buf.len, OBJ_TREE, result); 1219 1223 strbuf_release(&root.buf); 1220 1224 return ret; 1221 1225 }
+9 -9
object-file.c
··· 755 755 756 756 fd = create_tmpfile(tmp_file, filename); 757 757 if (fd < 0) { 758 - if (flags & WRITE_OBJECT_FILE_SILENT) 758 + if (flags & WRITE_OBJECT_SILENT) 759 759 return -1; 760 760 else if (errno == EACCES) 761 761 return error(_("insufficient permission for adding " ··· 887 887 utb.actime = mtime; 888 888 utb.modtime = mtime; 889 889 if (utime(tmp_file.buf, &utb) < 0 && 890 - !(flags & WRITE_OBJECT_FILE_SILENT)) 890 + !(flags & WRITE_OBJECT_SILENT)) 891 891 warning_errno(_("failed utime() on %s"), tmp_file.buf); 892 892 } 893 893 ··· 1032 1032 return err; 1033 1033 } 1034 1034 1035 - int write_object_file_flags(const void *buf, unsigned long len, 1036 - enum object_type type, struct object_id *oid, 1037 - struct object_id *compat_oid_in, unsigned flags) 1035 + int write_object_file(const void *buf, unsigned long len, 1036 + enum object_type type, struct object_id *oid, 1037 + struct object_id *compat_oid_in, unsigned flags) 1038 1038 { 1039 1039 struct repository *repo = the_repository; 1040 1040 const struct git_hash_algo *algo = repo->hash_algo; ··· 1159 1159 } 1160 1160 1161 1161 if (write_object) 1162 - ret = write_object_file(buf, size, type, oid); 1162 + ret = odb_write_object(istate->repo->objects, buf, size, type, oid); 1163 1163 else 1164 1164 hash_object_file(istate->repo->hash_algo, buf, size, type, oid); 1165 1165 ··· 1184 1184 get_conv_flags(flags)); 1185 1185 1186 1186 if (write_object) 1187 - ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB, 1188 - oid); 1187 + ret = odb_write_object(istate->repo->objects, sbuf.buf, sbuf.len, OBJ_BLOB, 1188 + oid); 1189 1189 else 1190 1190 hash_object_file(istate->repo->hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB, 1191 1191 oid); ··· 1287 1287 if (!(flags & INDEX_WRITE_OBJECT)) 1288 1288 hash_object_file(istate->repo->hash_algo, sb.buf, sb.len, 1289 1289 OBJ_BLOB, oid); 1290 - else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid)) 1290 + else if (odb_write_object(the_repository->objects, sb.buf, sb.len, OBJ_BLOB, oid)) 1291 1291 rc = error(_("%s: failed to insert into database"), path); 1292 1292 strbuf_release(&sb); 1293 1293 break;
+3 -23
object-file.h
··· 157 157 struct object_info; 158 158 int parse_loose_header(const char *hdr, struct object_info *oi); 159 159 160 - enum { 161 - /* 162 - * By default, `write_object_file()` does not actually write 163 - * anything into the object store, but only computes the object ID. 164 - * This flag changes that so that the object will be written as a loose 165 - * object and persisted. 166 - */ 167 - WRITE_OBJECT_FILE_PERSIST = (1 << 0), 168 - 169 - /* 170 - * Do not print an error in case something gose wrong. 171 - */ 172 - WRITE_OBJECT_FILE_SILENT = (1 << 1), 173 - }; 174 - 175 - int write_object_file_flags(const void *buf, unsigned long len, 176 - enum object_type type, struct object_id *oid, 177 - struct object_id *compat_oid_in, unsigned flags); 178 - static inline int write_object_file(const void *buf, unsigned long len, 179 - enum object_type type, struct object_id *oid) 180 - { 181 - return write_object_file_flags(buf, len, type, oid, NULL, 0); 182 - } 160 + int write_object_file(const void *buf, unsigned long len, 161 + enum object_type type, struct object_id *oid, 162 + struct object_id *compat_oid_in, unsigned flags); 183 163 184 164 struct input_stream { 185 165 const void *(*read)(struct input_stream *, unsigned long *len);
+10
odb.c
··· 980 980 type_name(expect)); 981 981 } 982 982 983 + int odb_write_object_ext(struct object_database *odb UNUSED, 984 + const void *buf, unsigned long len, 985 + enum object_type type, 986 + struct object_id *oid, 987 + struct object_id *compat_oid, 988 + unsigned flags) 989 + { 990 + return write_object_file(buf, len, type, oid, compat_oid, flags); 991 + } 992 + 983 993 struct object_database *odb_new(struct repository *repo) 984 994 { 985 995 struct object_database *o = xmalloc(sizeof(*o));
+38
odb.h
··· 437 437 FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), 438 438 }; 439 439 440 + enum { 441 + /* 442 + * By default, `odb_write_object()` does not actually write anything 443 + * into the object store, but only computes the object ID. This flag 444 + * changes that so that the object will be written as a loose object 445 + * and persisted. 446 + */ 447 + WRITE_OBJECT_PERSIST = (1 << 0), 448 + 449 + /* 450 + * Do not print an error in case something goes wrong. 451 + */ 452 + WRITE_OBJECT_SILENT = (1 << 1), 453 + }; 454 + 455 + /* 456 + * Write an object into the object database. The object is being written into 457 + * the local alternate of the repository. If provided, the converted object ID 458 + * as well as the compatibility object ID are written to the respective 459 + * pointers. 460 + * 461 + * Returns 0 on success, a negative error code otherwise. 462 + */ 463 + int odb_write_object_ext(struct object_database *odb, 464 + const void *buf, unsigned long len, 465 + enum object_type type, 466 + struct object_id *oid, 467 + struct object_id *compat_oid, 468 + unsigned flags); 469 + 470 + static inline int odb_write_object(struct object_database *odb, 471 + const void *buf, unsigned long len, 472 + enum object_type type, 473 + struct object_id *oid) 474 + { 475 + return odb_write_object_ext(odb, buf, len, type, oid, NULL, 0); 476 + } 477 + 440 478 /* Compatibility wrappers, to be removed once Git 2.51 has been released. */ 441 479 #include "repository.h" 442 480
+1 -1
read-cache.c
··· 690 690 void set_object_name_for_intent_to_add_entry(struct cache_entry *ce) 691 691 { 692 692 struct object_id oid; 693 - if (write_object_file("", 0, OBJ_BLOB, &oid)) 693 + if (odb_write_object(the_repository->objects, "", 0, OBJ_BLOB, &oid)) 694 694 die(_("cannot create an empty blob in the object database")); 695 695 oidcpy(&ce->oid, &oid); 696 696 }